From 657cc2045ee46922b00d4fd7c126f57d1e8ecc43 Mon Sep 17 00:00:00 2001 From: Monis Khan Date: Tue, 5 Sep 2023 12:27:55 -0400 Subject: [PATCH] kmsv2: enable KMSv2KDF feature gate by default Signed-off-by: Monis Khan --- .../apiserver/pkg/features/kube_features.go | 2 +- .../options/encryptionconfig/config_test.go | 81 ++++++++++++++++--- .../kmsv2_transformation_test.go | 11 ++- 3 files changed, 80 insertions(+), 14 deletions(-) diff --git a/staging/src/k8s.io/apiserver/pkg/features/kube_features.go b/staging/src/k8s.io/apiserver/pkg/features/kube_features.go index 18b04d234cc..5d1c144f5d1 100644 --- a/staging/src/k8s.io/apiserver/pkg/features/kube_features.go +++ b/staging/src/k8s.io/apiserver/pkg/features/kube_features.go @@ -260,7 +260,7 @@ var defaultKubernetesFeatureGates = map[featuregate.Feature]featuregate.FeatureS KMSv2: {Default: true, PreRelease: featuregate.Beta}, - KMSv2KDF: {Default: false, PreRelease: featuregate.Beta}, // default and lock to true in 1.29, remove in 1.31 + KMSv2KDF: {Default: true, PreRelease: featuregate.Beta}, // lock to true in 1.29 once KMSv2 is GA, remove in 1.31 OpenAPIEnums: {Default: true, PreRelease: featuregate.Beta}, diff --git a/staging/src/k8s.io/apiserver/pkg/server/options/encryptionconfig/config_test.go b/staging/src/k8s.io/apiserver/pkg/server/options/encryptionconfig/config_test.go index 6380269782e..704c10e5ed5 100644 --- a/staging/src/k8s.io/apiserver/pkg/server/options/encryptionconfig/config_test.go +++ b/staging/src/k8s.io/apiserver/pkg/server/options/encryptionconfig/config_test.go @@ -1839,6 +1839,8 @@ func TestComputeEncryptionConfigHash(t *testing.T) { } func Test_kmsv2PluginProbe_rotateDEKOnKeyIDChange(t *testing.T) { + defaultUseSeed := utilfeature.DefaultFeatureGate.Enabled(features.KMSv2KDF) + origNowFunc := envelopekmsv2.NowFunc now := origNowFunc() // freeze time t.Cleanup(func() { envelopekmsv2.NowFunc = origNowFunc }) @@ -1888,7 +1890,7 @@ func Test_kmsv2PluginProbe_rotateDEKOnKeyIDChange(t *testing.T) { { name: "happy path, with previous state", service: &testKMSv2EnvelopeService{err: fmt.Errorf("broken")}, // not called - state: validState(t, "2", now), + state: validState(t, "2", now, false), statusKeyID: "2", wantState: envelopekmsv2.State{ EncryptedObject: kmstypes.EncryptedObject{KeyID: "2"}, @@ -1901,7 +1903,7 @@ func Test_kmsv2PluginProbe_rotateDEKOnKeyIDChange(t *testing.T) { { name: "happy path, with previous state, useSeed=true", service: &testKMSv2EnvelopeService{keyID: "2"}, - state: validState(t, "2", now), + state: validState(t, "2", now, false), useSeed: true, statusKeyID: "2", wantState: envelopekmsv2.State{ @@ -1916,10 +1918,73 @@ func Test_kmsv2PluginProbe_rotateDEKOnKeyIDChange(t *testing.T) { }, wantErr: "", }, + { + name: "happy path, with previous useSeed=true state", + service: &testKMSv2EnvelopeService{keyID: "2"}, + state: validState(t, "2", now, true), + statusKeyID: "2", + wantState: envelopekmsv2.State{ + EncryptedObject: kmstypes.EncryptedObject{KeyID: "2"}, + ExpirationTimestamp: now.Add(3 * time.Minute), + }, + wantEncryptCalls: 1, + wantLogs: []string{ + `"encrypting content using envelope service" uid="panda"`, + fmt.Sprintf(`"successfully rotated DEK" uid="panda" useSeed=false newKeyIDHash="sha256:d4735e3a265e16eee03f59718b9b5d03019c07d8b6c51f90da3a666eec13ab35" oldKeyIDHash="sha256:d4735e3a265e16eee03f59718b9b5d03019c07d8b6c51f90da3a666eec13ab35" expirationTimestamp="%s"`, + now.Add(3*time.Minute).Format(time.RFC3339)), + }, + wantErr: "", + }, + { + name: "happy path, with previous useSeed=true state, useSeed=true", + service: &testKMSv2EnvelopeService{keyID: "2"}, + state: validState(t, "2", now, true), + useSeed: true, + statusKeyID: "2", + wantState: envelopekmsv2.State{ + EncryptedObject: kmstypes.EncryptedObject{KeyID: "2", EncryptedDEKSourceType: kmstypes.EncryptedDEKSourceType_HKDF_SHA256_XNONCE_AES_GCM_SEED}, + ExpirationTimestamp: now.Add(3 * time.Minute), + }, + wantEncryptCalls: 0, + wantLogs: nil, + wantErr: "", + }, + { + name: "happy path, with previous state, useSeed=default", + service: &testKMSv2EnvelopeService{keyID: "2"}, + state: validState(t, "2", now, false), + useSeed: defaultUseSeed, + statusKeyID: "2", + wantState: envelopekmsv2.State{ + EncryptedObject: kmstypes.EncryptedObject{KeyID: "2", EncryptedDEKSourceType: kmstypes.EncryptedDEKSourceType_HKDF_SHA256_XNONCE_AES_GCM_SEED}, + ExpirationTimestamp: now.Add(3 * time.Minute), + }, + wantEncryptCalls: 1, + wantLogs: []string{ + `"encrypting content using envelope service" uid="panda"`, + fmt.Sprintf(`"successfully rotated DEK" uid="panda" useSeed=true newKeyIDHash="sha256:d4735e3a265e16eee03f59718b9b5d03019c07d8b6c51f90da3a666eec13ab35" oldKeyIDHash="sha256:d4735e3a265e16eee03f59718b9b5d03019c07d8b6c51f90da3a666eec13ab35" expirationTimestamp="%s"`, + now.Add(3*time.Minute).Format(time.RFC3339)), + }, + wantErr: "", + }, + { + name: "happy path, with previous useSeed=true state, useSeed=default", + service: &testKMSv2EnvelopeService{keyID: "2"}, + state: validState(t, "2", now, true), + useSeed: defaultUseSeed, + statusKeyID: "2", + wantState: envelopekmsv2.State{ + EncryptedObject: kmstypes.EncryptedObject{KeyID: "2", EncryptedDEKSourceType: kmstypes.EncryptedDEKSourceType_HKDF_SHA256_XNONCE_AES_GCM_SEED}, + ExpirationTimestamp: now.Add(3 * time.Minute), + }, + wantEncryptCalls: 0, + wantLogs: nil, + wantErr: "", + }, { name: "previous state expired but key ID matches", service: &testKMSv2EnvelopeService{err: fmt.Errorf("broken")}, // not called - state: validState(t, "3", now.Add(-time.Hour)), + state: validState(t, "3", now.Add(-time.Hour), false), statusKeyID: "3", wantState: envelopekmsv2.State{ EncryptedObject: kmstypes.EncryptedObject{KeyID: "3"}, @@ -1932,7 +1997,7 @@ func Test_kmsv2PluginProbe_rotateDEKOnKeyIDChange(t *testing.T) { { name: "previous state expired but key ID does not match", service: &testKMSv2EnvelopeService{keyID: "4"}, - state: validState(t, "3", now.Add(-time.Hour)), + state: validState(t, "3", now.Add(-time.Hour), false), statusKeyID: "4", wantState: envelopekmsv2.State{ EncryptedObject: kmstypes.EncryptedObject{KeyID: "4"}, @@ -1949,7 +2014,7 @@ func Test_kmsv2PluginProbe_rotateDEKOnKeyIDChange(t *testing.T) { { name: "service down but key ID does not match", service: &testKMSv2EnvelopeService{err: fmt.Errorf("broken")}, - state: validState(t, "4", now.Add(7*time.Minute)), + state: validState(t, "4", now.Add(7*time.Minute), false), statusKeyID: "5", wantState: envelopekmsv2.State{ EncryptedObject: kmstypes.EncryptedObject{KeyID: "4"}, @@ -1981,7 +2046,7 @@ func Test_kmsv2PluginProbe_rotateDEKOnKeyIDChange(t *testing.T) { { name: "invalid service response, with previous state", service: &testKMSv2EnvelopeService{keyID: "3", encryptAnnotations: map[string][]byte{"panda": nil}}, - state: validState(t, "2", now), + state: validState(t, "2", now, false), statusKeyID: "3", wantState: envelopekmsv2.State{ EncryptedObject: kmstypes.EncryptedObject{KeyID: "2"}, @@ -2083,11 +2148,9 @@ func Test_kmsv2PluginProbe_rotateDEKOnKeyIDChange(t *testing.T) { } } -func validState(t *testing.T, keyID string, exp time.Time) envelopekmsv2.State { +func validState(t *testing.T, keyID string, exp time.Time, useSeed bool) envelopekmsv2.State { t.Helper() - useSeed := utilfeature.DefaultFeatureGate.Enabled(features.KMSv2KDF) // match the current default behavior - transformer, encObject, cacheKey, err := envelopekmsv2.GenerateTransformer(testContext(t), "", &testKMSv2EnvelopeService{keyID: keyID}, useSeed) if err != nil { t.Fatal(err) diff --git a/test/integration/controlplane/transformation/kmsv2_transformation_test.go b/test/integration/controlplane/transformation/kmsv2_transformation_test.go index 3881b865e36..5c10e85025b 100644 --- a/test/integration/controlplane/transformation/kmsv2_transformation_test.go +++ b/test/integration/controlplane/transformation/kmsv2_transformation_test.go @@ -171,18 +171,20 @@ func (r envelopekmsv2) plainTextPayload(secretETCDPath string) ([]byte, error) { // 4. The cipherTextPayload (ex. Secret) should be encrypted via AES GCM transform / extended nonce GCM // 5. kmstypes.EncryptedObject structure should be serialized and deposited in ETCD func TestKMSv2Provider(t *testing.T) { + defaultUseSeed := utilfeature.DefaultFeatureGate.Enabled(features.KMSv2KDF) + t.Run("regular gcm", func(t *testing.T) { defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.KMSv2KDF, false)() - testKMSv2Provider(t) + testKMSv2Provider(t, !defaultUseSeed) }) t.Run("extended nonce gcm", func(t *testing.T) { defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.KMSv2KDF, true)() - testKMSv2Provider(t) + testKMSv2Provider(t, defaultUseSeed) }) } -func testKMSv2Provider(t *testing.T) { +func testKMSv2Provider(t *testing.T, useSeed bool) { defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.KMSv2, true)() encryptionConfig := ` @@ -271,7 +273,7 @@ resources: providerName: providerName, rawEnvelope: rawEnvelope, plainTextDEKSource: plainTextDEKSource, - useSeed: utilfeature.DefaultFeatureGate.Enabled(features.KMSv2KDF), + useSeed: useSeed, } wantPrefix := envelopeData.prefix() @@ -953,6 +955,7 @@ resources: providerName: providerName, rawEnvelope: rawEnvelope, plainTextDEKSource: plainTextDEKSource, + useSeed: true, // expect KMSv2KDF to be enabled by default for this test } wantPrefix := envelopeData.prefix()