Skip to content

Commit 377c3cb

Browse files
committed
Add KMS encryption mode into library-go encryption controllers
1 parent dc3a1c8 commit 377c3cb

16 files changed

Lines changed: 1710 additions & 22 deletions

File tree

pkg/operator/encryption/controllers/key_controller.go

Lines changed: 39 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -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

161162
func (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

Comments
 (0)