@@ -37,6 +37,7 @@ func hasSigningKey(a interface{}) bool {
37
37
// Creates a cross-signed intermediate and new api.RootRotation object.
38
38
// This function assumes that the root cert and key and the external CAs have already been validated.
39
39
func 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" )
40
41
var (
41
42
rootCert , rootKey , crossSignedCert []byte
42
43
newRootHasSigner bool
@@ -53,6 +54,7 @@ func newRootRotationObject(ctx context.Context, securityConfig *ca.SecurityConfi
53
54
// a root rotation is already in progress)
54
55
switch {
55
56
case hasSigningKey (apiRootCA ):
57
+ log .G (ctx ).Info ("takes hasSigningKey branch" )
56
58
var oldRootCA ca.RootCA
57
59
oldRootCA , err = ca .NewRootCA (apiRootCA .CACert , apiRootCA .CACert , apiRootCA .CAKey , ca .DefaultNodeCertExpiration , nil )
58
60
if err == nil {
@@ -175,8 +177,14 @@ func getNormalizedExtCAs(caConfig *api.CAConfig, normalizedCurrentRootCACert []b
175
177
// object as is
176
178
// - we want to generate a new internal CA cert and key (force rotation value has changed), and we return the updated RootCA
177
179
// 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:
180
188
// - If the desired cert is the same as the current CA cert then abort any outstanding rotations. The current signing key
181
189
// is replaced with the desired signing key (this could lets us switch between external->internal or internal->external
182
190
// 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
289
297
return copied , nil
290
298
}
291
299
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
+
292
306
// check if this is the same desired cert as an existing root rotation
293
307
if r := cluster .RootCA .RootRotation ; r != nil && bytes .Equal (ca .NormalizePEMs (r .CACert ), newConfig .SigningCACert ) {
294
308
copied := cluster .RootCA .Copy ()
0 commit comments