@@ -201,7 +201,7 @@ func (c *keyController) checkAndCreateKeys(ctx context.Context, syncContext fact
201201
202202 var commonReason * string
203203 for gr , grKeys := range desiredEncryptionState {
204- latestKeyID , internalReason , needed := needsNewKey (grKeys , currentMode , externalReason , encryptedGRs )
204+ latestKeyID , internalReason , needed := needsNewKey (grKeys , currentMode , externalReason , encryptedGRs , apiEncryptionConfiguration )
205205 if ! needed {
206206 continue
207207 }
@@ -265,6 +265,63 @@ func (c *keyController) validateExistingSecret(ctx context.Context, keySecret *c
265265 return nil // we made this key earlier
266266}
267267
268+ // kmsProviderConfig abstracts provider-specific KMS logic so that every
269+ // provider-type switch lives in a single factory (newKMSProviderConfig).
270+ type kmsProviderConfig interface {
271+ referencedSecretName () (string , []string , error )
272+ referencedConfigMapName () (string , []string , error )
273+ // migrationRequired reports whether switching from latest (stored in
274+ // the key secret) to this provider config requires a new encryption key.
275+ migrationRequired (latest configv1.KMSPluginConfig ) bool
276+ }
277+
278+ func newKMSProviderConfig (plugin configv1.KMSPluginConfig ) (kmsProviderConfig , error ) {
279+ switch plugin .Type {
280+ case configv1 .VaultKMSProvider :
281+ return & vaultProviderConfig {plugin .Vault }, nil
282+ default :
283+ return nil , fmt .Errorf ("unsupported KMS provider type %q" , plugin .Type )
284+ }
285+ }
286+
287+ type vaultProviderConfig struct {
288+ vault configv1.VaultKMSPluginConfig
289+ }
290+
291+ // referencedSecretName returns the name of the secret referenced by the KMS plugin
292+ // config and the specific data keys to carry from that secret. Only the listed keys
293+ // are copied into the Key Secret; any other data in the referenced secret is ignored.
294+ func (v * vaultProviderConfig ) referencedSecretName () (string , []string , error ) {
295+ switch v .vault .Authentication .Type {
296+ case configv1 .VaultAuthenticationTypeAppRole :
297+ // The Vault AppRole secret must contain "role-id" and "secret-id" keys.
298+ // These are the only keys carried into the encryption key secret.
299+ return v .vault .Authentication .AppRole .Secret .Name , []string {"role-id" , "secret-id" }, nil
300+ default :
301+ return "" , nil , fmt .Errorf ("unsupported Vault authentication type %q" , v .vault .Authentication .Type )
302+ }
303+ }
304+
305+ // referencedConfigMapName returns the name of the configmap referenced by the KMS plugin
306+ // config and the specific data keys to carry from that configmap. Only the listed keys
307+ // are copied into the Key Secret; any other data in the referenced configmap is ignored.
308+ func (v * vaultProviderConfig ) referencedConfigMapName () (string , []string , error ) {
309+ if v .vault .TLS .CABundle .Name == "" {
310+ return "" , nil , nil
311+ }
312+ return v .vault .TLS .CABundle .Name , []string {"ca-bundle.crt" }, nil
313+ }
314+
315+ func (v * vaultProviderConfig ) migrationRequired (latest configv1.KMSPluginConfig ) bool {
316+ if latest .Type != configv1 .VaultKMSProvider {
317+ return true
318+ }
319+ return v .vault .VaultAddress != latest .Vault .VaultAddress ||
320+ v .vault .VaultNamespace != latest .Vault .VaultNamespace ||
321+ v .vault .TransitMount != latest .Vault .TransitMount ||
322+ v .vault .TransitKey != latest .Vault .TransitKey
323+ }
324+
268325func (c * keyController ) generateKeySecret (ctx context.Context , keyID uint64 , currentMode state.Mode , apiServerEncryption configv1.APIServerEncryption , internalReason , externalReason string ) (* corev1.Secret , error ) {
269326 bs := crypto .ModeToNewKeyFunc [currentMode ]()
270327 ks := state.KeyState {
@@ -287,7 +344,12 @@ func (c *keyController) generateKeySecret(ctx context.Context, keyID uint64, cur
287344 Plugin : apiServerEncryption .KMS ,
288345 }
289346
290- if secretName , expectedKeys , err := referencedSecretName (apiServerEncryption .KMS ); err != nil {
347+ providerCfg , err := newKMSProviderConfig (apiServerEncryption .KMS )
348+ if err != nil {
349+ return nil , err
350+ }
351+
352+ if secretName , expectedKeys , err := providerCfg .referencedSecretName (); err != nil {
291353 return nil , err
292354 } else if len (secretName ) > 0 {
293355 refSecret , err := c .secretClient .Secrets (openshiftConfigNS ).Get (ctx , secretName , metav1.GetOptions {})
@@ -305,7 +367,7 @@ func (c *keyController) generateKeySecret(ctx context.Context, keyID uint64, cur
305367 }
306368 }
307369
308- if cmName , expectedKeys , err := referencedConfigMapName (apiServerEncryption . KMS ); err != nil {
370+ if cmName , expectedKeys , err := providerCfg . referencedConfigMapName (); err != nil {
309371 return nil , err
310372 } else if len (cmName ) > 0 {
311373 refCM , err := c .configMapClient .ConfigMaps (openshiftConfigNS ).Get (ctx , cmName , metav1.GetOptions {})
@@ -358,7 +420,7 @@ func (c *keyController) getCurrentModeReasonAndEncryptionConfig(ctx context.Cont
358420
359421// needsNewKey checks whether a new key must be created for the given resource. If true, it also returns the latest
360422// used key ID and a reason string.
361- func needsNewKey (grKeys state.GroupResourceState , currentMode state.Mode , externalReason string , encryptedGRs []schema.GroupResource ) (uint64 , string , bool ) {
423+ func needsNewKey (grKeys state.GroupResourceState , currentMode state.Mode , externalReason string , encryptedGRs []schema.GroupResource , apiServerEncryption configv1. APIServerEncryption ) (uint64 , string , bool ) {
362424 // we always need to have some encryption keys unless we are turned off
363425 if len (grKeys .ReadKeys ) == 0 {
364426 return 0 , "key-does-not-exist" , currentMode != state .Identity
@@ -403,13 +465,18 @@ func needsNewKey(grKeys state.GroupResourceState, currentMode state.Mode, extern
403465
404466 if currentMode == state .KMS {
405467 // We are here because Encryption Mode is not changed
468+ // However, we need to create a new key if migration-triggering fields
469+ // in the KMS provider configuration have changed.
470+ currentProviderCfg , err := newKMSProviderConfig (apiServerEncryption .KMS )
471+ if err != nil {
472+ return latestKeyID , fmt .Sprintf ("unsupported-kms-provider-%s" , apiServerEncryption .KMS .Type ), true
473+ }
474+ if currentProviderCfg .migrationRequired (latestKey .KMS .Plugin ) {
475+ return latestKeyID , "kms-provider-changed" , true
476+ }
406477
407- // For now in Tech Preview v1, we don't support configurational changes. Therefore,
408- // it is pointless comparing the secrets.
409-
410- // For KMS mode, we don't do time-based rotation. Therefore, we shortcut here
411- // KMS keys are rotated externally by the KMS system.
412- // Moreover, we don't trigger new key when external reason is changed.
478+ // For KMS mode, we don't do time-based rotation. KMS keys are rotated
479+ // externally by the KMS provider. Moreover, we don't trigger new key when external reason is changed.
413480 // Because it would lead to duplicate providers which is not allowed.
414481 return 0 , "" , false
415482 }
@@ -424,40 +491,6 @@ func needsNewKey(grKeys state.GroupResourceState, currentMode state.Mode, extern
424491 return latestKeyID , "rotation-interval-has-passed" , time .Since (latestKey .Migrated .Timestamp ) > encryptionSecretMigrationInterval
425492}
426493
427- // referencedSecretName returns the name of the secret referenced by the KMS plugin
428- // config and the specific data keys to carry from that secret. Only the listed keys
429- // are copied into the Key Secret; any other data in the referenced secret is ignored.
430- func referencedSecretName (plugin configv1.KMSPluginConfig ) (string , []string , error ) {
431- switch plugin .Type {
432- case configv1 .VaultKMSProvider :
433- switch plugin .Vault .Authentication .Type {
434- case configv1 .VaultAuthenticationTypeAppRole :
435- // The Vault AppRole secret must contain "role-id" and "secret-id" keys.
436- // These are the only keys carried into the encryption key secret.
437- return plugin .Vault .Authentication .AppRole .Secret .Name , []string {"role-id" , "secret-id" }, nil
438- default :
439- return "" , nil , fmt .Errorf ("unsupported Vault authentication type %q" , plugin .Vault .Authentication .Type )
440- }
441- default :
442- return "" , nil , fmt .Errorf ("unsupported KMS provider type %q" , plugin .Type )
443- }
444- }
445-
446- // referencedConfigMapName returns the name of the configmap referenced by the KMS plugin
447- // config and the specific data keys to carry from that configmap. Only the listed keys
448- // are copied into the Key Secret; any other data in the referenced configmap is ignored.
449- func referencedConfigMapName (plugin configv1.KMSPluginConfig ) (string , []string , error ) {
450- switch plugin .Type {
451- case configv1 .VaultKMSProvider :
452- if plugin .Vault .TLS .CABundle .Name == "" {
453- return "" , nil , nil
454- }
455- return plugin .Vault .TLS .CABundle .Name , []string {"ca-bundle.crt" }, nil
456- default :
457- return "" , nil , fmt .Errorf ("unsupported KMS provider type %q" , plugin .Type )
458- }
459- }
460-
461494// TODO make this un-settable once set
462495// ex: we could require the tech preview no upgrade flag to be set before we will honor this field
463496type unsupportedEncryptionConfig struct {
0 commit comments