@@ -37,6 +37,7 @@ func hasSigningKey(a interface{}) bool {
3737// Creates a cross-signed intermediate and new api.RootRotation object.
3838// This function assumes that the root cert and key and the external CAs have already been validated.
3939func newRootRotationObject (ctx context.Context , securityConfig * ca.SecurityConfig , apiRootCA * api.RootCA , newCARootCA ca.RootCA , extCAs []* api.ExternalCA , version uint64 ) (* api.RootCA , error ) {
40+ log .G (ctx ).Info ("calls newRootRotationObject" )
4041 var (
4142 rootCert , rootKey , crossSignedCert []byte
4243 newRootHasSigner bool
@@ -53,6 +54,7 @@ func newRootRotationObject(ctx context.Context, securityConfig *ca.SecurityConfi
5354 // a root rotation is already in progress)
5455 switch {
5556 case hasSigningKey (apiRootCA ):
57+ log .G (ctx ).Info ("takes hasSigningKey branch" )
5658 var oldRootCA ca.RootCA
5759 oldRootCA , err = ca .NewRootCA (apiRootCA .CACert , apiRootCA .CACert , apiRootCA .CAKey , ca .DefaultNodeCertExpiration , nil )
5860 if err == nil {
@@ -175,8 +177,14 @@ func getNormalizedExtCAs(caConfig *api.CAConfig, normalizedCurrentRootCACert []b
175177// object as is
176178// - we want to generate a new internal CA cert and key (force rotation value has changed), and we return the updated RootCA
177179// object
178- // 3. Signing cert and key have been provided: validate that these match (the cert and key match). Otherwise, return an error.
179- // 4. Return the updated RootCA object according to the following criteria:
180+ // 3. Check if the cert is the same key. We cannot rotate to a cert with the same key. As of go 1.19, the logic for certificate
181+ // trust chain validation changed, and a chain including two certs with the same key will not validate. This case would
182+ // usually occur when reissuing the same cert with a later expiration date. Because of this validation failure, our root
183+ // rotation algorithm fails. While it might be possible to adjust the rotation procedure to accommodate such a cert change,
184+ // it is somewhat of an edge case, and, more importantly, we do not currently possess the cryptographic expertise to safely
185+ // make such a change. So, as a result, this operation is disallowed. The new root cert must have a new key.
186+ // 4. Signing cert and key have been provided: validate that these match (the cert and key match). Otherwise, return an error.
187+ // 5. Return the updated RootCA object according to the following criteria:
180188// - If the desired cert is the same as the current CA cert then abort any outstanding rotations. The current signing key
181189// is replaced with the desired signing key (this could lets us switch between external->internal or internal->external
182190// without an actual CA rotation, which is not needed because any leaf cert issued with one CA cert can be validated using
@@ -289,6 +297,12 @@ func validateCAConfig(ctx context.Context, securityConfig *ca.SecurityConfig, cl
289297 return copied , nil
290298 }
291299
300+ // See step 3 in the doc comment. We cannot upgrade a cert with the same
301+ // key.
302+ if len (newConfig .SigningCAKey ) > 0 && bytes .Equal (newConfig .SigningCAKey , cluster .RootCA .CAKey ) {
303+ return nil , status .Errorf (codes .InvalidArgument , "Cannot update to a cert with an identical key" )
304+ }
305+
292306 // check if this is the same desired cert as an existing root rotation
293307 if r := cluster .RootCA .RootRotation ; r != nil && bytes .Equal (ca .NormalizePEMs (r .CACert ), newConfig .SigningCACert ) {
294308 copied := cluster .RootCA .Copy ()
0 commit comments