Skip to content

Commit a41ad19

Browse files
committed
configimage: migrate IngressOperatorSignerCertKey to library-go
Replace the forked selfSignedCertificate, generateSelfSignedCertificate, generateSubjectKeyID, and rsaPublicKey with a single call to libcrypto.NewSigningCertificate. The forked code existed to allow empty OU in the Subject, which library-go handles natively. This removes ~80 lines of duplicated crypto code including a SHA-1 SubjectKeyId implementation.
1 parent 89640d9 commit a41ad19

1 file changed

Lines changed: 15 additions & 101 deletions

File tree

pkg/asset/imagebased/configimage/ingressoperatorsigner.go

Lines changed: 15 additions & 101 deletions
Original file line numberDiff line numberDiff line change
@@ -2,21 +2,12 @@ package configimage
22

33
import (
44
"context"
5-
"crypto"
6-
"crypto/ecdsa"
7-
"crypto/elliptic"
8-
"crypto/rand"
9-
"crypto/rsa"
10-
"crypto/sha1" //nolint: gosec
11-
"crypto/x509"
125
"crypto/x509/pkix"
13-
"encoding/asn1"
14-
"errors"
156
"fmt"
16-
"math"
17-
"math/big"
187
"time"
198

9+
libcrypto "github.com/openshift/library-go/pkg/crypto"
10+
2011
"github.com/openshift/installer/pkg/asset"
2112
"github.com/openshift/installer/pkg/asset/installconfig"
2213
"github.com/openshift/installer/pkg/asset/tls"
@@ -47,23 +38,24 @@ func (a *IngressOperatorSignerCertKey) Generate(ctx context.Context, dependencie
4738
installConfig := &installconfig.InstallConfig{}
4839
dependencies.Get(installConfig)
4940

50-
cfg := &tls.CertCfg{
51-
Subject: pkix.Name{CommonName: signerName},
52-
KeyUsages: x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature | x509.KeyUsageCertSign,
53-
Validity: tls.ValidityOneYear(installConfig) * 2,
54-
IsCA: true,
55-
}
56-
57-
key, crt, err := generateSelfSignedCertificate(cfg)
41+
keyGen := libcrypto.RSAKeyPairGenerator{Bits: 2048}
42+
tlsCfg, err := libcrypto.NewSigningCertificate(
43+
signerName,
44+
keyGen,
45+
libcrypto.WithLifetime(tls.ValidityOneYear(installConfig)*2),
46+
libcrypto.WithSubject(pkix.Name{CommonName: signerName}),
47+
)
5848
if err != nil {
59-
return err
49+
return fmt.Errorf("failed to generate ingress operator signer certificate: %w", err)
6050
}
6151

62-
a.KeyRaw, err = tls.PrivateKeyToPem(key)
52+
certPEM, keyPEM, err := tlsCfg.GetPEMBytes()
6353
if err != nil {
64-
return fmt.Errorf("failed to encode private key to PEM: %w", err)
54+
return fmt.Errorf("failed to encode ingress operator signer to PEM: %w", err)
6555
}
66-
a.CertRaw = tls.CertToPem(crt)
56+
57+
a.CertRaw = certPEM
58+
a.KeyRaw = keyPEM
6759

6860
return nil
6961
}
@@ -97,81 +89,3 @@ func (a *IngressOperatorCABundle) Generate(ctx context.Context, deps asset.Paren
9789
func (a *IngressOperatorCABundle) Name() string {
9890
return "Certificate (ingress-operator-ca-bundle)"
9991
}
100-
101-
// selfSignedCertificate creates a self signed certificate.
102-
//
103-
// TODO: this is a modified tls.SelfSignedCertificate function to allow the
104-
// certificate's Subject.OU to be empty. We should revisit this by sharing as
105-
// much code as possible with the tls package.
106-
//
107-
// https://github.com/openshift/installer/blob/6723dfd18056a6d002f792afce5547fc24874908/pkg/asset/tls/tls.go
108-
func selfSignedCertificate(cfg *tls.CertCfg, key *rsa.PrivateKey) (*x509.Certificate, error) {
109-
serial, err := rand.Int(rand.Reader, new(big.Int).SetInt64(math.MaxInt64))
110-
if err != nil {
111-
return nil, err
112-
}
113-
cert := x509.Certificate{
114-
BasicConstraintsValid: true,
115-
IsCA: cfg.IsCA,
116-
KeyUsage: cfg.KeyUsages,
117-
NotAfter: time.Now().Add(cfg.Validity),
118-
NotBefore: time.Now(),
119-
SerialNumber: serial,
120-
Subject: cfg.Subject,
121-
}
122-
// verifies that the CN for the cert is set
123-
if len(cfg.Subject.CommonName) == 0 {
124-
return nil, errors.New("certification's subject is not set, or invalid")
125-
}
126-
pub := key.Public()
127-
cert.SubjectKeyId, err = generateSubjectKeyID(pub)
128-
if err != nil {
129-
return nil, fmt.Errorf("failed to set subject key identifier: %w", err)
130-
}
131-
certBytes, err := x509.CreateCertificate(rand.Reader, &cert, &cert, key.Public(), key)
132-
if err != nil {
133-
return nil, fmt.Errorf("failed to create certificate: %w", err)
134-
}
135-
return x509.ParseCertificate(certBytes)
136-
}
137-
138-
// generateSelfSignedCertificate generates a key/cert pair defined by CertCfg.
139-
func generateSelfSignedCertificate(cfg *tls.CertCfg) (*rsa.PrivateKey, *x509.Certificate, error) {
140-
key, err := tls.PrivateKey()
141-
if err != nil {
142-
return nil, nil, fmt.Errorf("failed to generate private key: %w", err)
143-
}
144-
145-
crt, err := selfSignedCertificate(cfg, key)
146-
if err != nil {
147-
return nil, nil, fmt.Errorf("failed to create self-signed certificate: %w", err)
148-
}
149-
return key, crt, nil
150-
}
151-
152-
// rsaPublicKey reflects the ASN.1 structure of a PKCS#1 public key.
153-
type rsaPublicKey struct {
154-
N *big.Int
155-
E int
156-
}
157-
158-
// generateSubjectKeyID generates a SHA-1 hash of the subject public key.
159-
func generateSubjectKeyID(pub crypto.PublicKey) ([]byte, error) {
160-
var publicKeyBytes []byte
161-
var err error
162-
163-
switch pub := pub.(type) {
164-
case *rsa.PublicKey:
165-
publicKeyBytes, err = asn1.Marshal(rsaPublicKey{N: pub.N, E: pub.E})
166-
if err != nil {
167-
return nil, fmt.Errorf("failed to Marshal ans1 public key: %w", err)
168-
}
169-
case *ecdsa.PublicKey:
170-
publicKeyBytes = elliptic.Marshal(pub.Curve, pub.X, pub.Y) //nolint: staticcheck
171-
default:
172-
return nil, errors.New("only RSA and ECDSA public keys supported")
173-
}
174-
175-
hash := sha1.Sum(publicKeyBytes) //nolint: gosec
176-
return hash[:], nil
177-
}

0 commit comments

Comments
 (0)