@@ -27,6 +27,7 @@ import (
2727
2828 "github.com/openshift/library-go/pkg/controller/factory"
2929 "github.com/openshift/library-go/pkg/operator/encryption/crypto"
30+ "github.com/openshift/library-go/pkg/operator/encryption/kms"
3031 "github.com/openshift/library-go/pkg/operator/encryption/secrets"
3132 "github.com/openshift/library-go/pkg/operator/encryption/state"
3233 "github.com/openshift/library-go/pkg/operator/encryption/statemachine"
@@ -159,7 +160,7 @@ func (c *keyController) sync(ctx context.Context, syncCtx factory.SyncContext) (
159160}
160161
161162func (c * keyController ) checkAndCreateKeys (ctx context.Context , syncContext factory.SyncContext , encryptedGRs []schema.GroupResource ) error {
162- currentMode , externalReason , err := c .getCurrentModeAndExternalReason (ctx )
163+ currentMode , externalReason , kmsConfig , err := c .getCurrentModeAndExternalReason (ctx )
163164 if err != nil {
164165 return err
165166 }
@@ -191,7 +192,7 @@ func (c *keyController) checkAndCreateKeys(ctx context.Context, syncContext fact
191192
192193 var commonReason * string
193194 for gr , grKeys := range desiredEncryptionState {
194- latestKeyID , internalReason , needed := needsNewKey (grKeys , currentMode , externalReason , encryptedGRs )
195+ latestKeyID , internalReason , needed := needsNewKey (grKeys , currentMode , externalReason , encryptedGRs , kmsConfig )
195196 if ! needed {
196197 continue
197198 }
@@ -218,7 +219,8 @@ func (c *keyController) checkAndCreateKeys(ctx context.Context, syncContext fact
218219
219220 sort .Sort (sort .StringSlice (reasons ))
220221 internalReason := strings .Join (reasons , ", " )
221- keySecret , err := c .generateKeySecret (newKeyID , currentMode , internalReason , externalReason )
222+
223+ keySecret , err := c .generateKeySecret (newKeyID , currentMode , internalReason , externalReason , kmsConfig )
222224 if err != nil {
223225 return fmt .Errorf ("failed to create key: %v" , err )
224226 }
@@ -255,8 +257,8 @@ func (c *keyController) validateExistingSecret(ctx context.Context, keySecret *c
255257 return nil // we made this key earlier
256258}
257259
258- func (c * keyController ) generateKeySecret (keyID uint64 , currentMode state.Mode , internalReason , externalReason string ) (* corev1.Secret , error ) {
259- bs := crypto .ModeToNewKeyFunc [currentMode ]()
260+ func (c * keyController ) generateKeySecret (keyID uint64 , currentMode state.Mode , internalReason , externalReason string , kmsConfig [] byte ) (* corev1.Secret , error ) {
261+ bs := crypto.ModeToNewKeyFunc [currentMode ](kmsConfig )
260262 ks := state.KeyState {
261263 Key : apiserverv1.Key {
262264 Name : fmt .Sprintf ("%d" , keyID ),
@@ -265,40 +267,51 @@ func (c *keyController) generateKeySecret(keyID uint64, currentMode state.Mode,
265267 Mode : currentMode ,
266268 InternalReason : internalReason ,
267269 ExternalReason : externalReason ,
270+ KMSConfig : kmsConfig ,
268271 }
269272 return secrets .FromKeyState (c .instanceName , ks )
270273}
271274
272- func (c * keyController ) getCurrentModeAndExternalReason (ctx context.Context ) (state.Mode , string , error ) {
275+ func (c * keyController ) getCurrentModeAndExternalReason (ctx context.Context ) (state.Mode , string , [] byte , error ) {
273276 apiServer , err := c .apiServerClient .Get (ctx , "cluster" , metav1.GetOptions {})
274277 if err != nil {
275- return "" , "" , err
278+ return "" , "" , nil , err
276279 }
277280
278281 operatorSpec , _ , _ , err := c .operatorClient .GetOperatorState ()
279282 if err != nil {
280- return "" , "" , err
283+ return "" , "" , nil , err
281284 }
282285
283286 encryptionConfig , err := structuredUnsupportedConfigFrom (operatorSpec .UnsupportedConfigOverrides .Raw , c .unsupportedConfigPrefix )
284287 if err != nil {
285- return "" , "" , err
288+ return "" , "" , nil , err
286289 }
287290
288291 reason := encryptionConfig .Encryption .Reason
289292 switch currentMode := state .Mode (apiServer .Spec .Encryption .Type ); currentMode {
290293 case state .AESCBC , state .AESGCM , state .Identity : // secretbox is disabled for now
291- return currentMode , reason , nil
294+ return currentMode , reason , nil , nil
295+ case state .KMS :
296+ // KMS object is used to track any configurational changes to detect KMS to KMS migration.
297+ // This object is generated from the configurable fields in APIServer config to store;
298+ // * Endpoint is used in EncryptionConfiguration to be passed to apiservers. Currently, it is statically set to DefaultEndpoint
299+ // * Other plugin specific configurations that are considered to trigger KMS migration
300+ kmsConfig , err := kms .NewKMS (kms .DefaultEndpoint ).ToBytes ()
301+ if err != nil {
302+ return "" , "" , nil , err
303+ }
304+ return currentMode , reason , kmsConfig , nil
292305 case "" : // unspecified means use the default (which can change over time)
293- return state .DefaultMode , reason , nil
306+ return state .DefaultMode , reason , nil , nil
294307 default :
295- return "" , "" , fmt .Errorf ("unknown encryption mode configured: %s" , currentMode )
308+ return "" , "" , nil , fmt .Errorf ("unknown encryption mode configured: %s" , currentMode )
296309 }
297310}
298311
299312// needsNewKey checks whether a new key must be created for the given resource. If true, it also returns the latest
300313// used key ID and a reason string.
301- func needsNewKey (grKeys state.GroupResourceState , currentMode state.Mode , externalReason string , encryptedGRs []schema.GroupResource ) (uint64 , string , bool ) {
314+ func needsNewKey (grKeys state.GroupResourceState , currentMode state.Mode , externalReason string , encryptedGRs []schema.GroupResource , kmsConfig [] byte ) (uint64 , string , bool ) {
302315 // we always need to have some encryption keys unless we are turned off
303316 if len (grKeys .ReadKeys ) == 0 {
304317 return 0 , "key-does-not-exist" , currentMode != state .Identity
@@ -346,6 +359,19 @@ func needsNewKey(grKeys state.GroupResourceState, currentMode state.Mode, extern
346359 return latestKeyID , "external-reason-changed" , true
347360 }
348361
362+ if currentMode == state .KMS {
363+ // We are here because Encryption Mode is not changed
364+ secret := crypto.ModeToNewKeyFunc [state.KMS ](kmsConfig )
365+ if latestKey .Key .Secret != base64 .StdEncoding .EncodeToString (secret ) {
366+ // If the current secret differs from the latestKey secret, that means KMS config is updated.
367+ // Therefore, we need to initiate migration.
368+ return latestKeyID , "kms-config-changed" , true
369+ }
370+ // For KMS mode, we don't do time-based rotation. Therefore, we shortcut here
371+ // KMS keys are rotated externally by the KMS system
372+ return 0 , "" , false
373+ }
374+
349375 // we check for encryptionSecretMigratedTimestamp set by migration controller to determine when migration completed
350376 // this also generates back pressure for key rotation when migration takes a long time or was recently completed
351377 return latestKeyID , "rotation-interval-has-passed" , time .Since (latestKey .Migrated .Timestamp ) > encryptionSecretMigrationInterval
0 commit comments