From e087acc7917d77bd3a54c1f3b77188fe30b0d7ca Mon Sep 17 00:00:00 2001 From: James Munnelly Date: Tue, 6 Feb 2024 14:03:50 +0000 Subject: [PATCH] refuse to allow apiserver to startup if ServiceAccountTokenNodeBinding is enabled without ServiceAccountTokenNodeBindingValidation --- pkg/kubeapiserver/options/authentication.go | 5 ++++ .../options/authentication_test.go | 28 ++++++++++++++----- 2 files changed, 26 insertions(+), 7 deletions(-) diff --git a/pkg/kubeapiserver/options/authentication.go b/pkg/kubeapiserver/options/authentication.go index 11501a2f3cb..a7914af535d 100644 --- a/pkg/kubeapiserver/options/authentication.go +++ b/pkg/kubeapiserver/options/authentication.go @@ -260,6 +260,11 @@ func (o *BuiltInAuthenticationOptions) Validate() []error { } } + // verify that if ServiceAccountTokenNodeBinding is enabled, ServiceAccountTokenNodeBindingValidation is also enabled. + if utilfeature.DefaultFeatureGate.Enabled(features.ServiceAccountTokenNodeBinding) && !utilfeature.DefaultFeatureGate.Enabled(features.ServiceAccountTokenNodeBindingValidation) { + allErrors = append(allErrors, fmt.Errorf("the %q feature gate can only be enabled if the %q feature gate is also enabled", features.ServiceAccountTokenNodeBinding, features.ServiceAccountTokenNodeBindingValidation)) + } + if o.WebHook != nil { retryBackoff := o.WebHook.RetryBackoff if retryBackoff != nil && retryBackoff.Steps <= 0 { diff --git a/pkg/kubeapiserver/options/authentication_test.go b/pkg/kubeapiserver/options/authentication_test.go index eed32f1cab8..e2a8f5b874e 100644 --- a/pkg/kubeapiserver/options/authentication_test.go +++ b/pkg/kubeapiserver/options/authentication_test.go @@ -35,19 +35,22 @@ import ( "k8s.io/apiserver/pkg/features" apiserveroptions "k8s.io/apiserver/pkg/server/options" utilfeature "k8s.io/apiserver/pkg/util/feature" + "k8s.io/component-base/featuregate" featuregatetesting "k8s.io/component-base/featuregate/testing" + kubefeatures "k8s.io/kubernetes/pkg/features" kubeauthenticator "k8s.io/kubernetes/pkg/kubeapiserver/authenticator" "k8s.io/utils/pointer" ) func TestAuthenticationValidate(t *testing.T) { testCases := []struct { - name string - testOIDC *OIDCAuthenticationOptions - testSA *ServiceAccountAuthenticationOptions - testWebHook *WebHookAuthenticationOptions - testAuthenticationConfigFile string - expectErr string + name string + testOIDC *OIDCAuthenticationOptions + testSA *ServiceAccountAuthenticationOptions + testWebHook *WebHookAuthenticationOptions + testAuthenticationConfigFile string + expectErr string + enabledFeatures, disabledFeatures []featuregate.Feature }{ { name: "test when OIDC and ServiceAccounts are nil", @@ -226,6 +229,12 @@ func TestAuthenticationValidate(t *testing.T) { }, expectErr: "authentication-config file and oidc-* flags are mutually exclusive", }, + { + name: "fails to validate if ServiceAccountTokenNodeBindingValidation is disabled and ServiceAccountTokenNodeBinding is enabled", + enabledFeatures: []featuregate.Feature{kubefeatures.ServiceAccountTokenNodeBinding}, + disabledFeatures: []featuregate.Feature{kubefeatures.ServiceAccountTokenNodeBindingValidation}, + expectErr: "the \"ServiceAccountTokenNodeBinding\" feature gate can only be enabled if the \"ServiceAccountTokenNodeBindingValidation\" feature gate is also enabled", + }, } for _, testcase := range testCases { @@ -235,7 +244,12 @@ func TestAuthenticationValidate(t *testing.T) { options.ServiceAccounts = testcase.testSA options.WebHook = testcase.testWebHook options.AuthenticationConfigFile = testcase.testAuthenticationConfigFile - + for _, f := range testcase.enabledFeatures { + defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, f, true)() + } + for _, f := range testcase.disabledFeatures { + defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, f, false)() + } errs := options.Validate() if len(errs) > 0 && (!strings.Contains(utilerrors.NewAggregate(errs).Error(), testcase.expectErr) || testcase.expectErr == "") { t.Errorf("Got err: %v, Expected err: %s", errs, testcase.expectErr)