From a15b22cd9892388f59053c153668402875c95ded Mon Sep 17 00:00:00 2001 From: Mangirdas Judeikis Date: Mon, 1 Jul 2024 18:09:46 +0300 Subject: [PATCH 1/2] wire in optional tokenGetter provider --- pkg/kubeapiserver/options/authentication.go | 38 ++++++++++++++++----- 1 file changed, 30 insertions(+), 8 deletions(-) diff --git a/pkg/kubeapiserver/options/authentication.go b/pkg/kubeapiserver/options/authentication.go index 7e54bed46a1..a0e64fa3e45 100644 --- a/pkg/kubeapiserver/options/authentication.go +++ b/pkg/kubeapiserver/options/authentication.go @@ -132,6 +132,9 @@ type ServiceAccountAuthenticationOptions struct { JWKSURI string MaxExpiration time.Duration ExtendExpiration bool + // OptionalTokenGetter is a function that returns a service account token getter. + // If not set, the default token getter will be used. + OptionalTokenGetter func(factory informers.SharedInformerFactory) serviceaccount.ServiceAccountTokenGetter } // TokenFileAuthenticationOptions contains token file authentication options for API Server @@ -207,7 +210,20 @@ func (o *BuiltInAuthenticationOptions) WithRequestHeader() *BuiltInAuthenticatio // WithServiceAccounts set default value for service account authentication func (o *BuiltInAuthenticationOptions) WithServiceAccounts() *BuiltInAuthenticationOptions { - o.ServiceAccounts = &ServiceAccountAuthenticationOptions{Lookup: true, ExtendExpiration: true} + if o.ServiceAccounts == nil { + o.ServiceAccounts = &ServiceAccountAuthenticationOptions{} + } + o.ServiceAccounts.Lookup = true + o.ServiceAccounts.ExtendExpiration = true + return o +} + +// WithTokenGetterFunction set optional service account token getter function +func (o *BuiltInAuthenticationOptions) WithTokenGetterFunction(f func(factory informers.SharedInformerFactory) serviceaccount.ServiceAccountTokenGetter) *BuiltInAuthenticationOptions { + if o.ServiceAccounts == nil { + o.ServiceAccounts = &ServiceAccountAuthenticationOptions{} + } + o.ServiceAccounts.OptionalTokenGetter = f return o } @@ -673,13 +689,19 @@ func (o *BuiltInAuthenticationOptions) ApplyTo( if utilfeature.DefaultFeatureGate.Enabled(features.ServiceAccountTokenNodeBindingValidation) { nodeLister = versionedInformer.Core().V1().Nodes().Lister() } - authenticatorConfig.ServiceAccountTokenGetter = serviceaccountcontroller.NewGetterFromClient( - extclient, - versionedInformer.Core().V1().Secrets().Lister(), - versionedInformer.Core().V1().ServiceAccounts().Lister(), - versionedInformer.Core().V1().Pods().Lister(), - nodeLister, - ) + + // If the optional token getter function is set, use it. Otherwise, use the default token getter. + if o.ServiceAccounts.OptionalTokenGetter != nil { + authenticatorConfig.ServiceAccountTokenGetter = o.ServiceAccounts.OptionalTokenGetter(versionedInformer) + } else { + authenticatorConfig.ServiceAccountTokenGetter = serviceaccountcontroller.NewGetterFromClient( + extclient, + versionedInformer.Core().V1().Secrets().Lister(), + versionedInformer.Core().V1().ServiceAccounts().Lister(), + versionedInformer.Core().V1().Pods().Lister(), + nodeLister, + ) + } authenticatorConfig.SecretsWriter = extclient.CoreV1() if authenticatorConfig.BootstrapToken { From a72266ff9d65dd1c455a73a9475933717a7857f7 Mon Sep 17 00:00:00 2001 From: Mangirdas Judeikis Date: Tue, 2 Jul 2024 16:56:52 +0300 Subject: [PATCH 2/2] Add test for WithTokenGetter --- pkg/kubeapiserver/options/authentication.go | 2 +- .../options/authentication_test.go | 39 +++++++++++++++++++ 2 files changed, 40 insertions(+), 1 deletion(-) diff --git a/pkg/kubeapiserver/options/authentication.go b/pkg/kubeapiserver/options/authentication.go index a0e64fa3e45..c2d66d61e8e 100644 --- a/pkg/kubeapiserver/options/authentication.go +++ b/pkg/kubeapiserver/options/authentication.go @@ -691,7 +691,7 @@ func (o *BuiltInAuthenticationOptions) ApplyTo( } // If the optional token getter function is set, use it. Otherwise, use the default token getter. - if o.ServiceAccounts.OptionalTokenGetter != nil { + if o.ServiceAccounts != nil && o.ServiceAccounts.OptionalTokenGetter != nil { authenticatorConfig.ServiceAccountTokenGetter = o.ServiceAccounts.OptionalTokenGetter(versionedInformer) } else { authenticatorConfig.ServiceAccountTokenGetter = serviceaccountcontroller.NewGetterFromClient( diff --git a/pkg/kubeapiserver/options/authentication_test.go b/pkg/kubeapiserver/options/authentication_test.go index b1c599d12ec..be372006b5e 100644 --- a/pkg/kubeapiserver/options/authentication_test.go +++ b/pkg/kubeapiserver/options/authentication_test.go @@ -17,6 +17,7 @@ limitations under the License. package options import ( + "context" "os" "reflect" "strings" @@ -34,12 +35,17 @@ import ( "k8s.io/apiserver/pkg/authentication/authenticatorfactory" "k8s.io/apiserver/pkg/authentication/request/headerrequest" "k8s.io/apiserver/pkg/features" + genericapiserver "k8s.io/apiserver/pkg/server" apiserveroptions "k8s.io/apiserver/pkg/server/options" utilfeature "k8s.io/apiserver/pkg/util/feature" + "k8s.io/client-go/informers" + "k8s.io/client-go/kubernetes/fake" "k8s.io/component-base/featuregate" featuregatetesting "k8s.io/component-base/featuregate/testing" + openapicommon "k8s.io/kube-openapi/pkg/common" kubefeatures "k8s.io/kubernetes/pkg/features" kubeauthenticator "k8s.io/kubernetes/pkg/kubeapiserver/authenticator" + "k8s.io/kubernetes/pkg/serviceaccount" "k8s.io/utils/pointer" ) @@ -478,6 +484,39 @@ func TestBuiltInAuthenticationOptionsAddFlags(t *testing.T) { } } +func TestWithTokenGetterFunction(t *testing.T) { + featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, kubefeatures.ServiceAccountTokenNodeBindingValidation, false) + fakeClientset := fake.NewSimpleClientset() + versionedInformer := informers.NewSharedInformerFactory(fakeClientset, 0) + { + var called bool + f := func(factory informers.SharedInformerFactory) serviceaccount.ServiceAccountTokenGetter { + called = true + return nil + } + opts := NewBuiltInAuthenticationOptions().WithTokenGetterFunction(f) + err := opts.ApplyTo(context.Background(), &genericapiserver.AuthenticationInfo{}, nil, nil, &openapicommon.Config{}, nil, fakeClientset, versionedInformer, "") + if err != nil { + t.Fatal(err) + } + + if opts.ServiceAccounts.OptionalTokenGetter == nil { + t.Fatal("expected token getter function to be set") + } + + if !called { + t.Fatal("expected token getter function to be called") + } + } + { + opts := NewBuiltInAuthenticationOptions().WithServiceAccounts() + err := opts.ApplyTo(context.Background(), &genericapiserver.AuthenticationInfo{}, nil, nil, &openapicommon.Config{}, nil, fakeClientset, versionedInformer, "") + if err != nil { + t.Fatal(err) + } + } +} + func TestToAuthenticationConfig_Anonymous(t *testing.T) { featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.StructuredAuthenticationConfiguration, true) testCases := []struct {