@@ -327,10 +327,10 @@ func (r *ClientRotation) CertificateType() pki.CertificateType {
327327}
328328
329329func (r * ClientRotation ) NewCertificate (signer * crypto.CA , validity time.Duration , keyGen crypto.KeyPairGenerator ) (* crypto.TLSCertificateConfig , error ) {
330- if keyGen ! = nil {
331- return signer .NewClientCertificate (r .UserInfo , keyGen , crypto . WithLifetime ( validity ) )
330+ if keyGen = = nil {
331+ return signer .MakeClientCertificateForDuration (r .UserInfo , validity )
332332 }
333- return signer .MakeClientCertificateForDuration (r .UserInfo , validity )
333+ return signer .NewClientCertificate (r .UserInfo , keyGen , crypto . WithLifetime ( validity ) )
334334}
335335
336336func (r * ClientRotation ) NeedNewTargetCertKeyPair (currentCertSecret * corev1.Secret , signer * crypto.CA , caBundleCerts []* x509.Certificate , refresh time.Duration , refreshOnlyWhenExpired , exists bool ) string {
@@ -356,14 +356,13 @@ func (r *ServingRotation) NewCertificate(signer *crypto.CA, validity time.Durati
356356 if len (hostnames ) == 0 {
357357 return nil , fmt .Errorf ("no hostnames set" )
358358 }
359- if keyGen != nil {
360- return signer .NewServerCertificate (
361- sets .New (hostnames ... ), keyGen ,
362- crypto .WithLifetime (validity ),
363- crypto .WithExtensions (r .CertificateExtensionFn ... ),
364- )
359+ if keyGen == nil {
360+ return signer .MakeServerCertForDuration (sets .New (hostnames ... ), validity , r .CertificateExtensionFn ... )
365361 }
366- return signer .MakeServerCertForDuration (sets .New (hostnames ... ), validity , r .CertificateExtensionFn ... )
362+ return signer .NewServerCertificate (sets .New (hostnames ... ), keyGen ,
363+ crypto .WithLifetime (validity ),
364+ crypto .WithExtensions (r .CertificateExtensionFn ... ),
365+ )
367366}
368367
369368func (r * ServingRotation ) RecheckChannel () <- chan struct {} {
@@ -423,23 +422,25 @@ func (r *SignerRotation) CertificateType() pki.CertificateType {
423422
424423func (r * SignerRotation ) NewCertificate (signer * crypto.CA , validity time.Duration , keyGen crypto.KeyPairGenerator ) (* crypto.TLSCertificateConfig , error ) {
425424 signerName := fmt .Sprintf ("%s_@%d" , r .SignerName , time .Now ().Unix ())
426- if keyGen != nil {
427- return crypto .NewSigningCertificate (signerName , keyGen ,
428- crypto .WithSigner (signer ),
429- crypto .WithLifetime (validity ),
430- )
425+ if keyGen == nil {
426+ return crypto .MakeCAConfigForDuration (signerName , validity , signer )
431427 }
432- return crypto .MakeCAConfigForDuration (signerName , validity , signer )
428+ return crypto .NewSigningCertificate (signerName , keyGen ,
429+ crypto .WithSigner (signer ),
430+ crypto .WithLifetime (validity ),
431+ )
433432}
434433
435434// PeerRotation creates certificates used for both server and client authentication
436435// (e.g., etcd peer certificates). It uses CertificateTypePeer for PKI profile
437436// resolution, which selects the stronger of the serving and client key configurations.
438437//
439- // When keyGen is non-nil (ConfigurablePKI enabled), it calls NewPeerCertificate
440- // which requires UserInfo for the client identity. When keyGen is nil (legacy),
441- // it falls back to MakeServerCertForDuration with an extension function that
442- // sets both ClientAuth and ServerAuth ExtKeyUsages.
438+ // UserInfo is always required. When keyGen is non-nil (ConfigurablePKI enabled),
439+ // NewPeerCertificate encodes UserInfo as the client identity in the certificate
440+ // subject. When keyGen is nil (legacy), UserInfo.Name must match the sorted first
441+ // hostname (used as CN by MakeServerCertForDuration), and the certificate falls
442+ // back to MakeServerCertForDuration with an extension function that sets both
443+ // ClientAuth and ServerAuth ExtKeyUsages.
443444type PeerRotation struct {
444445 Hostnames ServingHostnameFunc
445446 UserInfo user.Info
@@ -456,24 +457,28 @@ func (r *PeerRotation) NewCertificate(signer *crypto.CA, validity time.Duration,
456457 if len (hostnames ) == 0 {
457458 return nil , fmt .Errorf ("no hostnames set" )
458459 }
459- if keyGen != nil {
460- if r .UserInfo == nil {
461- return nil , fmt .Errorf ("PeerRotation requires UserInfo for configurable PKI certificates" )
460+ if r .UserInfo == nil {
461+ return nil , fmt .Errorf ("PeerRotation requires UserInfo" )
462+ }
463+ if keyGen == nil {
464+ // Legacy path: use server cert template with extension fn to add both ExtKeyUsages.
465+ // MakeServerCertForDuration sorts hostnames and uses the first sorted value as CN.
466+ sortedHostnames := sets .List (sets .New (hostnames ... ))
467+ if cn := sortedHostnames [0 ]; r .UserInfo .GetName () != cn {
468+ return nil , fmt .Errorf ("PeerRotation legacy path uses sorted first hostname %q as CN; UserInfo.Name %q conflicts — set UserInfo.Name to match or enable ConfigurablePKI" , cn , r .UserInfo .GetName ())
469+ }
470+ peerExtFn := func (cert * x509.Certificate ) error {
471+ cert .ExtKeyUsage = []x509.ExtKeyUsage {x509 .ExtKeyUsageClientAuth , x509 .ExtKeyUsageServerAuth }
472+ return nil
462473 }
463- return signer .NewPeerCertificate (
464- sets .New (hostnames ... ), r .UserInfo , keyGen ,
465- crypto .WithLifetime (validity ),
466- crypto .WithExtensions (r .CertificateExtensionFn ... ),
467- )
468- }
469- // Legacy path: use server cert template with extension fn to add both ExtKeyUsages.
470- // The subject CN comes from the first hostname (preserves current behavior).
471- peerExtFn := func (cert * x509.Certificate ) error {
472- cert .ExtKeyUsage = []x509.ExtKeyUsage {x509 .ExtKeyUsageClientAuth , x509 .ExtKeyUsageServerAuth }
473- return nil
474- }
475- extensions := append (append ([]crypto.CertificateExtensionFunc {}, r .CertificateExtensionFn ... ), peerExtFn )
476- return signer .MakeServerCertForDuration (sets .New (hostnames ... ), validity , extensions ... )
474+ extensions := append (append ([]crypto.CertificateExtensionFunc {}, r .CertificateExtensionFn ... ), peerExtFn )
475+ return signer .MakeServerCertForDuration (sets .New (hostnames ... ), validity , extensions ... )
476+ }
477+ return signer .NewPeerCertificate (
478+ sets .New (hostnames ... ), r .UserInfo , keyGen ,
479+ crypto .WithLifetime (validity ),
480+ crypto .WithExtensions (r .CertificateExtensionFn ... ),
481+ )
477482}
478483
479484func (r * PeerRotation ) RecheckChannel () <- chan struct {} {
0 commit comments