Skip to content

Commit a8fd407

Browse files
authored
Merge pull request kubernetes#128136 from enj/enj/t/non_global_kms_kdf_via_name
kmsv2: run KDF tests in parallel
2 parents b7fb82f + 43740c0 commit a8fd407

File tree

4 files changed

+121
-79
lines changed

4 files changed

+121
-79
lines changed

staging/src/k8s.io/apiserver/pkg/server/options/encryptionconfig/config.go

Lines changed: 20 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -107,24 +107,35 @@ const (
107107

108108
var codecs serializer.CodecFactory
109109

110-
// this atomic bool allows us to swap enablement of the KMSv2KDF feature in tests
110+
// this map allows us to swap enablement of the KMSv2KDF feature in tests
111111
// as the feature gate is now locked to true starting with v1.29
112112
// Note: it cannot be set by an end user
113-
var kdfDisabled atomic.Bool
113+
// KDF enablement is tracked per KMS provider to allow tests to run in parallel.
114+
var kdfEnabledPerKMS sync.Map // map[string]bool, KMS name -> KDF enabled
114115

115116
// this function should only be called in tests to swap enablement of the KMSv2KDF feature
116-
func SetKDFForTests(b bool) func() {
117-
kdfDisabled.Store(!b)
118-
return func() {
119-
kdfDisabled.Store(false)
117+
// Caller must guarantee that all KMS providers have distinct names across all tests.
118+
func SetKDFForTests(kmsName string, b bool) func() {
119+
if len(kmsName) == 0 { // guarantee that GetKDF("") returns the default value
120+
panic("empty KMS name used in test")
120121
}
122+
if _, loaded := kdfEnabledPerKMS.LoadOrStore(kmsName, b); loaded {
123+
panic("duplicate KMS name used in test")
124+
}
125+
return func() { kdfEnabledPerKMS.Delete(kmsName) }
121126
}
122127

123128
// this function should be used to determine enablement of the KMSv2KDF feature
124129
// instead of getting it from DefaultFeatureGate as the feature gate is now locked
125130
// to true starting with v1.29
126-
func GetKDF() bool {
127-
return !kdfDisabled.Load()
131+
// to allow integration tests to run in parallel, this "feature flag" can be set
132+
// per KMS provider as long as all providers use distinct names.
133+
func GetKDF(kmsName string) bool {
134+
kdfEnabled, ok := kdfEnabledPerKMS.Load(kmsName)
135+
if !ok {
136+
return true // explicit config is missing, but KDF is enabled by default
137+
}
138+
return kdfEnabled.(bool) // this will panic if a non-bool ever gets stored, which should never happen
128139
}
129140

130141
func init() {
@@ -390,7 +401,7 @@ func (h *kmsv2PluginProbe) rotateDEKOnKeyIDChange(ctx context.Context, statusKey
390401
// this gate can only change during tests, but the check is cheap enough to always make
391402
// this allows us to easily exercise both modes without restarting the API server
392403
// TODO integration test that this dynamically takes effect
393-
useSeed := GetKDF()
404+
useSeed := GetKDF(h.name)
394405
stateUseSeed := state.EncryptedObject.EncryptedDEKSourceType == kmstypes.EncryptedDEKSourceType_HKDF_SHA256_XNONCE_AES_GCM_SEED
395406

396407
// state is valid and status keyID is unchanged from when we generated this DEK/seed so there is no need to rotate it

staging/src/k8s.io/apiserver/pkg/server/options/encryptionconfig/config_test.go

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1851,7 +1851,7 @@ func TestComputeEncryptionConfigHash(t *testing.T) {
18511851
}
18521852

18531853
func Test_kmsv2PluginProbe_rotateDEKOnKeyIDChange(t *testing.T) {
1854-
defaultUseSeed := GetKDF()
1854+
defaultUseSeed := GetKDF("")
18551855

18561856
origNowFunc := envelopekmsv2.NowFunc
18571857
now := origNowFunc() // freeze time
@@ -2074,17 +2074,18 @@ func Test_kmsv2PluginProbe_rotateDEKOnKeyIDChange(t *testing.T) {
20742074
`encryptKeyIDHash="", stateKeyIDHash="sha256:d4735e3a265e16eee03f59718b9b5d03019c07d8b6c51f90da3a666eec13ab35", expirationTimestamp=` + now.Format(time.RFC3339),
20752075
},
20762076
}
2077-
for _, tt := range tests {
2077+
for i, tt := range tests {
20782078
t.Run(tt.name, func(t *testing.T) {
2079-
defer SetKDFForTests(tt.useSeed)()
2079+
kmsName := fmt.Sprintf("panda-%d", i)
2080+
defer SetKDFForTests(kmsName, tt.useSeed)()
20802081

20812082
var buf bytes.Buffer
20822083
klog.SetOutput(&buf)
20832084

20842085
ctx := testContext(t)
20852086

20862087
h := &kmsv2PluginProbe{
2087-
name: "panda",
2088+
name: kmsName,
20882089
service: tt.service,
20892090
}
20902091
h.state.Store(&tt.state)
@@ -2133,7 +2134,7 @@ func Test_kmsv2PluginProbe_rotateDEKOnKeyIDChange(t *testing.T) {
21332134
if _, stateErr := h.getCurrentState(); stateErr == nil || err == nil {
21342135
transformer := envelopekmsv2.NewEnvelopeTransformer(
21352136
&testKMSv2EnvelopeService{err: fmt.Errorf("broken")}, // not called
2136-
"panda",
2137+
kmsName,
21372138
h.getCurrentState,
21382139
"",
21392140
)

0 commit comments

Comments
 (0)