Skip to content

Commit 394ad47

Browse files
committed
Improved key state controllers to use both pluginhash and generation
* generation id is canonical to aes keyID but also applicable for remotely managed KMS config keys, helps uniquely identify `KeyState.Generation` over time for various local and remote kms keys applied * hash of the kmsconfig used to uniquely identify the plugin socket path on the host, to determine which plugin be used on the encryption config Signed-off-by: Swarup Ghosh <[email protected]>
1 parent 13e97b8 commit 394ad47

File tree

12 files changed

+309
-141
lines changed

12 files changed

+309
-141
lines changed

pkg/operator/encryption/controllers/key_controller.go

Lines changed: 27 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -185,7 +185,6 @@ func (c *keyController) checkAndCreateKeys(ctx context.Context, syncContext fact
185185
newKeyRequired bool
186186
newKeyID uint64
187187
latestKeyID uint64
188-
ok bool
189188
reasons []string
190189
)
191190

@@ -196,17 +195,12 @@ func (c *keyController) checkAndCreateKeys(ctx context.Context, syncContext fact
196195
var commonReason *string
197196
for gr, grKeys := range desiredEncryptionState {
198197
// if kmsKeyID in GR ReadKey is not the same as current kmsKeyID, needed is true.
199-
ks, needed := needsNewKeyWithInternalReason(grKeys, currentKeyState.Mode, currentKeyState.KMSKeyID, currentKeyState.ExternalReason, encryptedGRs)
198+
ks, needed := needsNewKeyWithInternalReason(grKeys, currentKeyState.Mode, currentKeyState.KMSPluginHash, currentKeyState.ExternalReason, encryptedGRs)
200199
if !needed {
201200
continue
202201
}
203202

204-
if ks.Mode != state.KMS {
205-
latestKeyID, ok = state.NameToKeyID(ks.Key.Name)
206-
if !ok {
207-
latestKeyID = 0
208-
}
209-
}
203+
latestKeyID = ks.Generation
210204

211205
if commonReason == nil {
212206
commonReason = &ks.InternalReason
@@ -216,9 +210,8 @@ func (c *keyController) checkAndCreateKeys(ctx context.Context, syncContext fact
216210

217211
newKeyRequired = true
218212

219-
// tracking the newKeyID is only required for non-KMS
220213
nextKeyID := latestKeyID + 1
221-
if ks.Mode != state.KMS && newKeyID < nextKeyID {
214+
if newKeyID < nextKeyID {
222215
newKeyID = nextKeyID
223216
}
224217

@@ -236,7 +229,7 @@ func (c *keyController) checkAndCreateKeys(ctx context.Context, syncContext fact
236229

237230
var keySecret *corev1.Secret
238231
if currentKeyState.Mode == state.KMS {
239-
keySecret, err = c.generateKMSKeySecret(currentKeyState.KMSConfig, currentKeyState.InternalReason, currentKeyState.ExternalReason)
232+
keySecret, err = c.generateKMSKeySecret(newKeyID, currentKeyState.KMSConfig, currentKeyState.InternalReason, currentKeyState.ExternalReason)
240233
} else {
241234
keySecret, err = c.generateLocalKeySecret(newKeyID, currentKeyState.Mode, currentKeyState.InternalReason, currentKeyState.ExternalReason)
242235
}
@@ -270,16 +263,19 @@ func (c *keyController) validateExistingSecret(ctx context.Context, keySecret *c
270263
return fmt.Errorf("secret %s/%s is invalid, new keys cannot be created for encryption target", keySecret.Namespace, keySecret.Name)
271264
}
272265

273-
if ks.Mode == state.KMS && ks.KMSKeyID != "" {
266+
if ks.Generation == 0 {
267+
return fmt.Errorf("secret %s/%s is invalid, key generation id cannot be zero", keySecret.Namespace, keySecret.Name)
268+
}
269+
270+
if ks.Mode == state.KMS && ks.KMSPluginHash != "" {
274271
return nil
275272
}
276273

277-
if ks.Mode == state.KMS && ks.KMSKeyID == "" {
274+
if ks.Mode == state.KMS && ks.KMSPluginHash == "" {
278275
// kmsKeyID is mandatory in case of KMS
279-
return fmt.Errorf("secret %s/%s is invalid, new KMS keys cannot be created for encryption target", keySecret.Namespace, keySecret.Name)
276+
return fmt.Errorf("secret %s/%s is invalid, new KMS config keys cannot be created for encryption target", keySecret.Namespace, keySecret.Name)
280277
}
281278

282-
// checks for local aes (non-KMS) keys only
283279
actualKeyID, ok := state.NameToKeyID(actualKeySecret.Name)
284280
if !ok || actualKeyID != keyID {
285281
// TODO we can just get stuck in degraded here ...
@@ -292,6 +288,7 @@ func (c *keyController) validateExistingSecret(ctx context.Context, keySecret *c
292288
func (c *keyController) generateLocalKeySecret(keyID uint64, currentMode state.Mode, internalReason, externalReason string) (*corev1.Secret, error) {
293289
bs := crypto.ModeToNewKeyFunc[currentMode]()
294290
ks := state.KeyState{
291+
Generation: keyID,
295292
Key: apiserverv1.Key{
296293
Name: fmt.Sprintf("%d", keyID),
297294
Secret: base64.StdEncoding.EncodeToString(bs),
@@ -303,19 +300,20 @@ func (c *keyController) generateLocalKeySecret(keyID uint64, currentMode state.M
303300
return secrets.FromKeyState(c.instanceName, ks)
304301
}
305302

306-
func (c *keyController) generateKMSKeySecret(kmsConfig *configv1.KMSConfig, internalReason, externalReason string) (*corev1.Secret, error) {
303+
func (c *keyController) generateKMSKeySecret(keyID uint64, kmsConfig *configv1.KMSConfig, internalReason, externalReason string) (*corev1.Secret, error) {
307304
kmsConfig = kmsConfig.DeepCopy()
308305

309-
kmsKeyID, err := encryptionconfig.HashKMSConfig(*kmsConfig)
306+
kmsPluginHash, err := encryptionconfig.HashKMSConfig(*kmsConfig)
310307
if err != nil {
311308
return nil, err
312309
}
313310

314311
ks := state.KeyState{
312+
Generation: keyID,
315313
Mode: state.KMS,
316314
InternalReason: internalReason,
317315
ExternalReason: externalReason,
318-
KMSKeyID: kmsKeyID,
316+
KMSPluginHash: kmsPluginHash,
319317
KMSConfig: kmsConfig,
320318
}
321319
return secrets.FromKeyState(c.instanceName, ks)
@@ -344,16 +342,17 @@ func (c *keyController) getCurrentEncryptionModeWithExternalReason(ctx context.C
344342
case state.KMS:
345343
kmsConfig := apiServer.Spec.Encryption.KMS.DeepCopy()
346344

347-
kmsKeyID, err := encryptionconfig.HashKMSConfig(*kmsConfig)
345+
kmsPluginHash, err := encryptionconfig.HashKMSConfig(*kmsConfig)
348346
if err != nil {
349-
return state.KeyState{}, fmt.Errorf("encryption mode configured: %s, but provided kms config could not generate required kms key id %v", currentMode, err)
347+
return state.KeyState{}, fmt.Errorf("encryption mode configured: %s, but provided kms config could not generate required kms plugin hash %v", currentMode, err)
350348
}
351349

352350
ks := state.KeyState{
353351
Mode: state.KMS,
354-
KMSKeyID: kmsKeyID,
355-
KMSConfig: kmsConfig,
356352
ExternalReason: reason,
353+
354+
KMSPluginHash: kmsPluginHash,
355+
KMSConfig: kmsConfig,
357356
}
358357
return ks, nil
359358
case "": // unspecified means use the default (which can change over time)
@@ -365,15 +364,16 @@ func (c *keyController) getCurrentEncryptionModeWithExternalReason(ctx context.C
365364

366365
// needsNewKeyWithInternalReason checks whether a new key must be created for the given resource. If true, it also returns the latest
367366
// used key ID and a reason string.
368-
func needsNewKeyWithInternalReason(grKeys state.GroupResourceState, currentMode state.Mode, optionalCurrentKMSKeyID string, externalReason string, encryptedGRs []schema.GroupResource) (state.KeyState, bool) {
367+
func needsNewKeyWithInternalReason(grKeys state.GroupResourceState, currentMode state.Mode, optionalCurrentKMSHash string, externalReason string, encryptedGRs []schema.GroupResource) (state.KeyState, bool) {
369368
// we always need to have some encryption keys unless we are turned off
370369
if len(grKeys.ReadKeys) == 0 {
371370
return state.KeyState{InternalReason: "key-does-not-exist"}, currentMode != state.Identity
372371
}
373372

374373
latestKey := grKeys.ReadKeys[0]
375-
latestKeyID, ok := state.NameToKeyID(latestKey.Key.Name)
376-
if !ok {
374+
latestKeyID := latestKey.Generation
375+
376+
if latestKeyID == 0 {
377377
latestKey.InternalReason = fmt.Sprintf("key-secret-%d-is-invalid", latestKeyID)
378378
return latestKey, true
379379
}
@@ -411,8 +411,8 @@ func needsNewKeyWithInternalReason(grKeys state.GroupResourceState, currentMode
411411
return state.KeyState{}, false
412412
}
413413

414-
// if the hash of the kms config (kmsKeyID) has updated, we need a new KMS backing secret
415-
if currentMode == state.KMS && latestKey.KMSKeyID != optionalCurrentKMSKeyID {
414+
// if the hash of the kms config has updated, we need a new KMS backing secret
415+
if currentMode == state.KMS && latestKey.KMSPluginHash != optionalCurrentKMSHash {
416416
latestKey.InternalReason = "kms-config-changed"
417417
return latestKey, true
418418
}

pkg/operator/encryption/encryptionconfig/config.go

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -116,15 +116,22 @@ func ToEncryptionState(encryptionConfig *apiserverconfigv1.EncryptionConfigurati
116116
}
117117

118118
ks = state.KeyState{
119-
Mode: state.KMS,
120-
KMSKeyID: extractKMSKeyIdFromProviderName(provider.KMS.Name),
119+
Mode: state.KMS,
121120
}
122121

122+
ks.KMSPluginHash, ks.Generation, _ = extractKMSFromProviderName(provider.KMS.Name)
123+
123124
default:
124125
klog.Infof("skipping invalid provider index %d for resource %s", i, resourceConfig.Resources[0])
125126
continue // should never happen
126127
}
127128

129+
// fill generation for non-KMS,
130+
// KMS already has filled in above
131+
if ks.Mode != state.KMS {
132+
ks.Generation, _ = state.NameToKeyID(ks.Key.Name)
133+
}
134+
128135
// enrich KeyState with values from secrets
129136
for _, k := range backedKeys {
130137
if state.EqualKeyAndEqualID(&ks, &k) {
@@ -210,8 +217,8 @@ func stateToProviders(gr schema.GroupResource, desired state.GroupResourceState)
210217
providers = append(providers, apiserverconfigv1.ProviderConfiguration{
211218
KMS: &apiserverconfigv1.KMSConfiguration{
212219
APIVersion: "v2",
213-
Name: generateKMSProviderName(key.KMSKeyID, gr),
214-
Endpoint: fmt.Sprintf(KMSPluginEndpoint, key.KMSKeyID),
220+
Name: generateKMSProviderName(key.Generation, key.KMSPluginHash, gr),
221+
Endpoint: fmt.Sprintf(KMSPluginEndpoint, key.KMSPluginHash),
215222
Timeout: &metav1.Duration{
216223
Duration: KMSPluginTimeout,
217224
},

0 commit comments

Comments
 (0)