Skip to content

Commit 7ff079b

Browse files
committed
tls: refactor TLS cert generation to support configurable key algorithms
Refactor pkg/asset/tls/ to support generating signer certificates with configurable key algorithms (RSA or ECDSA). PrivateKeyToPem now returns ([]byte, error) instead of calling logrus.Fatalf, and GenerateSelfSignedCertificate accepts PrivateKeyParams to control key generation. KeyUsage flags are set based on the algorithm since ECDSA keys cannot perform key encipherment. All signer certs pass nil for pkiConfig in this commit, preserving the existing RSA-2048 behavior. Wiring signers to read PKI config is deferred to a follow-up to avoid breaking codepaths that generate signer certs without an install-config on disk (e.g. agent create certificates, node-joiner add-nodes). Assisted-by: Claude Code (Opus 4.6)
1 parent ebacca8 commit 7ff079b

16 files changed

Lines changed: 719 additions & 127 deletions

pkg/asset/imagebased/configimage/ingressoperatorsigner.go

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,10 @@ func (a *IngressOperatorSignerCertKey) Generate(ctx context.Context, dependencie
5959
return err
6060
}
6161

62-
a.KeyRaw = tls.PrivateKeyToPem(key)
62+
a.KeyRaw, err = tls.PrivateKeyToPem(key)
63+
if err != nil {
64+
return fmt.Errorf("failed to encode private key to PEM: %w", err)
65+
}
6366
a.CertRaw = tls.CertToPem(crt)
6467

6568
return nil

pkg/asset/tls/adminkubeconfig.go

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -23,13 +23,13 @@ func (c *AdminKubeConfigSignerCertKey) Dependencies() []asset.Asset {
2323
// Generate generates the root-ca key and cert pair.
2424
func (c *AdminKubeConfigSignerCertKey) Generate(ctx context.Context, parents asset.Parents) error {
2525
cfg := &CertCfg{
26-
Subject: pkix.Name{CommonName: "admin-kubeconfig-signer", OrganizationalUnit: []string{"openshift"}},
27-
KeyUsages: x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature | x509.KeyUsageCertSign,
28-
Validity: ValidityTenYears(),
29-
IsCA: true,
26+
Subject: pkix.Name{CommonName: "admin-kubeconfig-signer", OrganizationalUnit: []string{"openshift"}},
27+
// KeyUsages is set by GenerateSelfSignedCertificate based on the key algorithm.
28+
Validity: ValidityTenYears(),
29+
IsCA: true,
3030
}
3131

32-
return c.SelfSignedCertKey.Generate(ctx, cfg, "admin-kubeconfig-signer")
32+
return c.SelfSignedCertKey.Generate(ctx, cfg, "admin-kubeconfig-signer", nil)
3333
}
3434

3535
// Load reads the asset files from disk.

pkg/asset/tls/aggregator.go

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -32,13 +32,13 @@ func (a *AggregatorCA) Generate(ctx context.Context, dependencies asset.Parents)
3232
dependencies.Get(installConfig)
3333

3434
cfg := &CertCfg{
35-
Subject: pkix.Name{CommonName: "aggregator", OrganizationalUnit: []string{"bootkube"}},
36-
KeyUsages: x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature | x509.KeyUsageCertSign,
37-
Validity: ValidityOneDay(installConfig),
38-
IsCA: true,
35+
Subject: pkix.Name{CommonName: "aggregator", OrganizationalUnit: []string{"bootkube"}},
36+
// KeyUsages is set by GenerateSelfSignedCertificate based on the key algorithm.
37+
Validity: ValidityOneDay(installConfig),
38+
IsCA: true,
3939
}
4040

41-
return a.SelfSignedCertKey.Generate(ctx, cfg, "aggregator-ca")
41+
return a.SelfSignedCertKey.Generate(ctx, cfg, "aggregator-ca", nil)
4242
}
4343

4444
// Name returns the human-friendly name of the asset.
@@ -102,13 +102,13 @@ func (c *AggregatorSignerCertKey) Generate(ctx context.Context, parents asset.Pa
102102
installConfig := &installconfig.InstallConfig{}
103103
parents.Get(installConfig)
104104
cfg := &CertCfg{
105-
Subject: pkix.Name{CommonName: "aggregator-signer", OrganizationalUnit: []string{"openshift"}},
106-
KeyUsages: x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature | x509.KeyUsageCertSign,
107-
Validity: ValidityOneDay(installConfig),
108-
IsCA: true,
105+
Subject: pkix.Name{CommonName: "aggregator-signer", OrganizationalUnit: []string{"openshift"}},
106+
// KeyUsages is set by GenerateSelfSignedCertificate based on the key algorithm.
107+
Validity: ValidityOneDay(installConfig),
108+
IsCA: true,
109109
}
110110

111-
return c.SelfSignedCertKey.Generate(ctx, cfg, "aggregator-signer")
111+
return c.SelfSignedCertKey.Generate(ctx, cfg, "aggregator-signer", nil)
112112
}
113113

114114
// Name returns the human-friendly name of the asset.

pkg/asset/tls/apiserver.go

Lines changed: 20 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -29,13 +29,13 @@ func (c *KubeAPIServerToKubeletSignerCertKey) Generate(ctx context.Context, pare
2929
installConfig := &installconfig.InstallConfig{}
3030
parents.Get(installConfig)
3131
cfg := &CertCfg{
32-
Subject: pkix.Name{CommonName: "kube-apiserver-to-kubelet-signer", OrganizationalUnit: []string{"openshift"}},
33-
KeyUsages: x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature | x509.KeyUsageCertSign,
34-
Validity: ValidityOneYear(installConfig),
35-
IsCA: true,
32+
Subject: pkix.Name{CommonName: "kube-apiserver-to-kubelet-signer", OrganizationalUnit: []string{"openshift"}},
33+
// KeyUsages is set by GenerateSelfSignedCertificate based on the key algorithm.
34+
Validity: ValidityOneYear(installConfig),
35+
IsCA: true,
3636
}
3737

38-
return c.SelfSignedCertKey.Generate(ctx, cfg, "kube-apiserver-to-kubelet-signer")
38+
return c.SelfSignedCertKey.Generate(ctx, cfg, "kube-apiserver-to-kubelet-signer", nil)
3939
}
4040

4141
// Name returns the human-friendly name of the asset.
@@ -124,13 +124,13 @@ func (c *KubeAPIServerLocalhostSignerCertKey) Dependencies() []asset.Asset {
124124
// Generate generates the root-ca key and cert pair.
125125
func (c *KubeAPIServerLocalhostSignerCertKey) Generate(ctx context.Context, parents asset.Parents) error {
126126
cfg := &CertCfg{
127-
Subject: pkix.Name{CommonName: "kube-apiserver-localhost-signer", OrganizationalUnit: []string{"openshift"}},
128-
KeyUsages: x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature | x509.KeyUsageCertSign,
129-
Validity: ValidityTenYears(),
130-
IsCA: true,
127+
Subject: pkix.Name{CommonName: "kube-apiserver-localhost-signer", OrganizationalUnit: []string{"openshift"}},
128+
// KeyUsages is set by GenerateSelfSignedCertificate based on the key algorithm.
129+
Validity: ValidityTenYears(),
130+
IsCA: true,
131131
}
132132

133-
return c.SelfSignedCertKey.Generate(ctx, cfg, "kube-apiserver-localhost-signer")
133+
return c.SelfSignedCertKey.Generate(ctx, cfg, "kube-apiserver-localhost-signer", nil)
134134
}
135135

136136
// Load reads the asset files from disk.
@@ -228,13 +228,13 @@ func (c *KubeAPIServerServiceNetworkSignerCertKey) Dependencies() []asset.Asset
228228
// Generate generates the root-ca key and cert pair.
229229
func (c *KubeAPIServerServiceNetworkSignerCertKey) Generate(ctx context.Context, parents asset.Parents) error {
230230
cfg := &CertCfg{
231-
Subject: pkix.Name{CommonName: "kube-apiserver-service-network-signer", OrganizationalUnit: []string{"openshift"}},
232-
KeyUsages: x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature | x509.KeyUsageCertSign,
233-
Validity: ValidityTenYears(),
234-
IsCA: true,
231+
Subject: pkix.Name{CommonName: "kube-apiserver-service-network-signer", OrganizationalUnit: []string{"openshift"}},
232+
// KeyUsages is set by GenerateSelfSignedCertificate based on the key algorithm.
233+
Validity: ValidityTenYears(),
234+
IsCA: true,
235235
}
236236

237-
return c.SelfSignedCertKey.Generate(ctx, cfg, "kube-apiserver-service-network-signer")
237+
return c.SelfSignedCertKey.Generate(ctx, cfg, "kube-apiserver-service-network-signer", nil)
238238
}
239239

240240
// Load reads the asset files from disk.
@@ -341,13 +341,13 @@ func (c *KubeAPIServerLBSignerCertKey) Dependencies() []asset.Asset {
341341
// Generate generates the root-ca key and cert pair.
342342
func (c *KubeAPIServerLBSignerCertKey) Generate(ctx context.Context, parents asset.Parents) error {
343343
cfg := &CertCfg{
344-
Subject: pkix.Name{CommonName: "kube-apiserver-lb-signer", OrganizationalUnit: []string{"openshift"}},
345-
KeyUsages: x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature | x509.KeyUsageCertSign,
346-
Validity: ValidityTenYears(),
347-
IsCA: true,
344+
Subject: pkix.Name{CommonName: "kube-apiserver-lb-signer", OrganizationalUnit: []string{"openshift"}},
345+
// KeyUsages is set by GenerateSelfSignedCertificate based on the key algorithm.
346+
Validity: ValidityTenYears(),
347+
IsCA: true,
348348
}
349349

350-
return c.SelfSignedCertKey.Generate(ctx, cfg, "kube-apiserver-lb-signer")
350+
return c.SelfSignedCertKey.Generate(ctx, cfg, "kube-apiserver-lb-signer", nil)
351351
}
352352

353353
// Load reads the asset files from disk.

pkg/asset/tls/boundsasigningkey.go

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@ package tls
22

33
import (
44
"context"
5+
"crypto/rsa"
6+
"fmt"
57
"os"
68

79
"github.com/pkg/errors"
@@ -50,10 +52,14 @@ func (sk *BoundSASigningKey) Load(f asset.FileFetcher) (bool, error) {
5052
return false, err
5153
}
5254

53-
rsaKey, err := PemToPrivateKey(keyFile.Data)
55+
key, err := PemToPrivateKey(keyFile.Data)
5456
if err != nil {
55-
logrus.Debugf("Failed to load rsa.PrivateKey from file: %s", err)
56-
return false, errors.Wrap(err, "failed to load rsa.PrivateKey from the file")
57+
logrus.Debugf("Failed to load private key from file: %s", err)
58+
return false, fmt.Errorf("failed to load private key from the file: %w", err)
59+
}
60+
rsaKey, ok := key.(*rsa.PrivateKey)
61+
if !ok {
62+
return false, fmt.Errorf("bound service account signing key must be RSA")
5763
}
5864
pubData, err := PublicKeyToPem(&rsaKey.PublicKey)
5965
if err != nil {

pkg/asset/tls/certkey.go

Lines changed: 32 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,13 @@ package tls
33
import (
44
"bytes"
55
"context"
6-
"crypto/rsa"
7-
"crypto/x509"
6+
"fmt"
87
"os"
98

10-
"github.com/pkg/errors"
119
"github.com/sirupsen/logrus"
1210

1311
"github.com/openshift/installer/pkg/asset"
12+
"github.com/openshift/installer/pkg/types"
1413
)
1514

1615
// CertInterface contains cert.
@@ -128,29 +127,28 @@ func (c *SignedCertKey) Generate(_ context.Context,
128127
filenameBase string,
129128
appendParent AppendParentChoice,
130129
) error {
131-
var key *rsa.PrivateKey
132-
var crt *x509.Certificate
133-
var err error
134-
135130
caKey, err := PemToPrivateKey(parentCA.Key())
136131
if err != nil {
137-
logrus.Debugf("Failed to parse RSA private key: %s", err)
138-
return errors.Wrap(err, "failed to parse rsa private key")
132+
logrus.Debugf("Failed to parse private key: %s", err)
133+
return fmt.Errorf("failed to parse private key: %w", err)
139134
}
140135

141136
caCert, err := PemToCertificate(parentCA.Cert())
142137
if err != nil {
143138
logrus.Debugf("Failed to parse x509 certificate: %s", err)
144-
return errors.Wrap(err, "failed to parse x509 certificate")
139+
return fmt.Errorf("failed to parse x509 certificate: %w", err)
145140
}
146141

147-
key, crt, err = GenerateSignedCertificate(caKey, caCert, cfg)
142+
key, crt, err := GenerateSignedCertificate(caKey, caCert, cfg)
148143
if err != nil {
149144
logrus.Debugf("Failed to generate signed cert/key pair: %s", err)
150-
return errors.Wrap(err, "failed to generate signed cert/key pair")
145+
return fmt.Errorf("failed to generate signed cert/key pair: %w", err)
151146
}
152147

153-
c.KeyRaw = PrivateKeyToPem(key)
148+
c.KeyRaw, err = PrivateKeyToPem(key)
149+
if err != nil {
150+
return fmt.Errorf("failed to encode private key to PEM: %w", err)
151+
}
154152
c.CertRaw = CertToPem(crt)
155153

156154
if appendParent {
@@ -167,17 +165,23 @@ type SelfSignedCertKey struct {
167165
CertKey
168166
}
169167

170-
// Generate generates a cert/key pair signed by the specified parent CA.
168+
// Generate generates a self-signed cert/key pair using the specified PKI profile.
171169
func (c *SelfSignedCertKey) Generate(_ context.Context,
172170
cfg *CertCfg,
173171
filenameBase string,
172+
pkiConfig *types.PKIConfig,
174173
) error {
175-
key, crt, err := GenerateSelfSignedCertificate(cfg)
174+
params := PKIConfigToKeyParams(pkiConfig)
175+
176+
key, crt, err := GenerateSelfSignedCertificate(cfg, params)
176177
if err != nil {
177-
return errors.Wrap(err, "failed to generate self-signed cert/key pair")
178+
return fmt.Errorf("failed to generate self-signed cert/key pair: %w", err)
178179
}
179180

180-
c.KeyRaw = PrivateKeyToPem(key)
181+
c.KeyRaw, err = PrivateKeyToPem(key)
182+
if err != nil {
183+
return fmt.Errorf("failed to encode private key to PEM: %w", err)
184+
}
181185
c.CertRaw = CertToPem(crt)
182186

183187
c.generateFiles(filenameBase)
@@ -192,29 +196,28 @@ func RegenerateSignedCertKey(
192196
parentCA CertKeyInterface,
193197
appendParent AppendParentChoice,
194198
) ([]byte, []byte, error) {
195-
var key *rsa.PrivateKey
196-
var crt *x509.Certificate
197-
var err error
198-
199199
caKey, err := PemToPrivateKey(parentCA.Key())
200200
if err != nil {
201-
logrus.Debugf("Failed to parse RSA private key: %s", err)
202-
return nil, nil, errors.Wrap(err, "failed to parse rsa private key")
201+
logrus.Debugf("Failed to parse private key: %s", err)
202+
return nil, nil, fmt.Errorf("failed to parse private key: %w", err)
203203
}
204204

205205
caCert, err := PemToCertificate(parentCA.Cert())
206206
if err != nil {
207207
logrus.Debugf("Failed to parse x509 certificate: %s", err)
208-
return nil, nil, errors.Wrap(err, "failed to parse x509 certificate")
208+
return nil, nil, fmt.Errorf("failed to parse x509 certificate: %w", err)
209209
}
210210

211-
key, crt, err = GenerateSignedCertificate(caKey, caCert, cfg)
212-
if err != nil {
213-
logrus.Debugf("Failed to generate signed cert/key pair: %s", err)
214-
return nil, nil, errors.Wrap(err, "failed to generate signed cert/key pair")
211+
key, crt, generateErr := GenerateSignedCertificate(caKey, caCert, cfg)
212+
if generateErr != nil {
213+
logrus.Debugf("Failed to generate signed cert/key pair: %s", generateErr)
214+
return nil, nil, fmt.Errorf("failed to generate signed cert/key pair: %w", generateErr)
215215
}
216216

217-
keyRaw := PrivateKeyToPem(key)
217+
keyRaw, err := PrivateKeyToPem(key)
218+
if err != nil {
219+
return nil, nil, fmt.Errorf("failed to encode private key to PEM: %w", err)
220+
}
218221
certRaw := CertToPem(crt)
219222

220223
if appendParent {

0 commit comments

Comments
 (0)