diff --git a/pkg/kubeapiserver/authorizer/config.go b/pkg/kubeapiserver/authorizer/config.go index eec90bb451e..32ef8267af2 100644 --- a/pkg/kubeapiserver/authorizer/config.go +++ b/pkg/kubeapiserver/authorizer/config.go @@ -31,6 +31,7 @@ import ( "k8s.io/apiserver/pkg/apis/apiserver/load" "k8s.io/apiserver/pkg/apis/apiserver/validation" "k8s.io/apiserver/pkg/authorization/authorizer" + authorizationcel "k8s.io/apiserver/pkg/authorization/cel" utilfeature "k8s.io/apiserver/pkg/util/feature" versionedinformers "k8s.io/client-go/informers" resourceinformers "k8s.io/client-go/informers/resource/v1alpha3" @@ -72,6 +73,8 @@ type Config struct { // New returns the right sort of union of multiple authorizer.Authorizer objects // based on the authorizationMode or an error. // stopCh is used to shut down config reload goroutines when the server is shutting down. +// +// Note: the cel compiler construction depends on feature gates and the compatibility version to be initialized. func (config Config) New(ctx context.Context, serverID string) (authorizer.Authorizer, authorizer.RuleResolver, error) { if len(config.AuthorizationConfiguration.Authorizers) == 0 { return nil, nil, fmt.Errorf("at least one authorization mode must be passed") @@ -82,6 +85,7 @@ func (config Config) New(ctx context.Context, serverID string) (authorizer.Autho apiServerID: serverID, lastLoadedConfig: config.AuthorizationConfiguration, reloadInterval: time.Minute, + compiler: authorizationcel.NewDefaultCompiler(), } seenTypes := sets.New[authzconfig.AuthorizerType]() @@ -156,15 +160,15 @@ func GetNameForAuthorizerMode(mode string) string { return strings.ToLower(mode) } -func LoadAndValidateFile(configFile string, requireNonWebhookTypes sets.Set[authzconfig.AuthorizerType]) (*authzconfig.AuthorizationConfiguration, error) { +func LoadAndValidateFile(configFile string, compiler authorizationcel.Compiler, requireNonWebhookTypes sets.Set[authzconfig.AuthorizerType]) (*authzconfig.AuthorizationConfiguration, error) { data, err := os.ReadFile(configFile) if err != nil { return nil, err } - return LoadAndValidateData(data, requireNonWebhookTypes) + return LoadAndValidateData(data, compiler, requireNonWebhookTypes) } -func LoadAndValidateData(data []byte, requireNonWebhookTypes sets.Set[authzconfig.AuthorizerType]) (*authzconfig.AuthorizationConfiguration, error) { +func LoadAndValidateData(data []byte, compiler authorizationcel.Compiler, requireNonWebhookTypes sets.Set[authzconfig.AuthorizerType]) (*authzconfig.AuthorizationConfiguration, error) { // load the file and check for errors authorizationConfiguration, err := load.LoadFromData(data) if err != nil { @@ -172,7 +176,7 @@ func LoadAndValidateData(data []byte, requireNonWebhookTypes sets.Set[authzconfi } // validate the file and return any error - if errors := validation.ValidateAuthorizationConfiguration(nil, authorizationConfiguration, + if errors := validation.ValidateAuthorizationConfiguration(compiler, nil, authorizationConfiguration, sets.NewString(modes.AuthorizationModeChoices...), sets.NewString(repeatableAuthorizerTypes...), ); len(errors) != 0 { diff --git a/pkg/kubeapiserver/authorizer/reload.go b/pkg/kubeapiserver/authorizer/reload.go index c5b53dfb06d..2e3525686bd 100644 --- a/pkg/kubeapiserver/authorizer/reload.go +++ b/pkg/kubeapiserver/authorizer/reload.go @@ -32,7 +32,7 @@ import ( "k8s.io/apiserver/pkg/authentication/user" "k8s.io/apiserver/pkg/authorization/authorizer" "k8s.io/apiserver/pkg/authorization/authorizerfactory" - "k8s.io/apiserver/pkg/authorization/cel" + authorizationcel "k8s.io/apiserver/pkg/authorization/cel" authorizationmetrics "k8s.io/apiserver/pkg/authorization/metrics" "k8s.io/apiserver/pkg/authorization/union" "k8s.io/apiserver/pkg/server/options/authorizationconfig/metrics" @@ -61,6 +61,7 @@ type reloadableAuthorizerResolver struct { nodeAuthorizer *node.NodeAuthorizer rbacAuthorizer *rbac.RBACAuthorizer abacAuthorizer abac.PolicyList + compiler authorizationcel.Compiler // non-nil and shared across reloads. lastLoadedLock sync.Mutex lastLoadedConfig *authzconfig.AuthorizationConfiguration @@ -148,7 +149,8 @@ func (r *reloadableAuthorizerResolver) newForConfig(authzConfig *authzconfig.Aut decisionOnError, configuredAuthorizer.Webhook.MatchConditions, configuredAuthorizer.Name, - kubeapiserverWebhookMetrics{WebhookMetrics: webhookmetrics.NewWebhookMetrics(), MatcherMetrics: cel.NewMatcherMetrics()}, + kubeapiserverWebhookMetrics{WebhookMetrics: webhookmetrics.NewWebhookMetrics(), MatcherMetrics: authorizationcel.NewMatcherMetrics()}, + r.compiler, ) if err != nil { return nil, nil, err @@ -175,7 +177,7 @@ type kubeapiserverWebhookMetrics struct { // kube-apiserver does report webhook metrics webhookmetrics.WebhookMetrics // kube-apiserver does report matchCondition metrics - cel.MatcherMetrics + authorizationcel.MatcherMetrics } // runReload starts checking the config file for changes and reloads the authorizer when it changes. @@ -214,7 +216,7 @@ func (r *reloadableAuthorizerResolver) checkFile(ctx context.Context) { klog.InfoS("found new authorization config data") r.lastReadData = data - config, err := LoadAndValidateData(data, r.requireNonWebhookTypes) + config, err := LoadAndValidateData(data, r.compiler, r.requireNonWebhookTypes) if err != nil { klog.ErrorS(err, "reloading authorization config") metrics.RecordAuthorizationConfigAutomaticReloadFailure(r.apiServerID) diff --git a/pkg/kubeapiserver/options/authentication.go b/pkg/kubeapiserver/options/authentication.go index 18502f6ff5c..8df383adeb4 100644 --- a/pkg/kubeapiserver/options/authentication.go +++ b/pkg/kubeapiserver/options/authentication.go @@ -39,6 +39,7 @@ import ( "k8s.io/apiserver/pkg/apis/apiserver/install" apiservervalidation "k8s.io/apiserver/pkg/apis/apiserver/validation" "k8s.io/apiserver/pkg/authentication/authenticator" + authenticationcel "k8s.io/apiserver/pkg/authentication/cel" genericfeatures "k8s.io/apiserver/pkg/features" genericapiserver "k8s.io/apiserver/pkg/server" "k8s.io/apiserver/pkg/server/egressselector" @@ -574,7 +575,7 @@ func (o *BuiltInAuthenticationOptions) ToAuthenticationConfig() (kubeauthenticat } } - if err := apiservervalidation.ValidateAuthenticationConfiguration(ret.AuthenticationConfig, ret.ServiceAccountIssuers).ToAggregate(); err != nil { + if err := apiservervalidation.ValidateAuthenticationConfiguration(authenticationcel.NewDefaultCompiler(), ret.AuthenticationConfig, ret.ServiceAccountIssuers).ToAggregate(); err != nil { return kubeauthenticator.Config{}, err } @@ -756,7 +757,7 @@ func (o *BuiltInAuthenticationOptions) ApplyTo( return } - validationErrs := apiservervalidation.ValidateAuthenticationConfiguration(authConfig, authenticatorConfig.ServiceAccountIssuers) + validationErrs := apiservervalidation.ValidateAuthenticationConfiguration(authenticationcel.NewDefaultCompiler(), authConfig, authenticatorConfig.ServiceAccountIssuers) if !reflect.DeepEqual(originalFileAnonymousConfig, authConfig.Anonymous) { validationErrs = append(validationErrs, field.Forbidden(field.NewPath("anonymous"), "changed from initial configuration file")) } diff --git a/pkg/kubeapiserver/options/authorization.go b/pkg/kubeapiserver/options/authorization.go index 9f4c0724c59..1c5240f3cdd 100644 --- a/pkg/kubeapiserver/options/authorization.go +++ b/pkg/kubeapiserver/options/authorization.go @@ -21,6 +21,7 @@ import ( "strings" "time" + authorizationcel "k8s.io/apiserver/pkg/authorization/cel" genericfeatures "k8s.io/apiserver/pkg/features" utilfeature "k8s.io/apiserver/pkg/util/feature" @@ -118,7 +119,7 @@ func (o *BuiltInAuthorizationOptions) Validate() []error { } // load/validate kube-apiserver authz config with no opinion about required modes - _, err := authorizer.LoadAndValidateFile(o.AuthorizationConfigurationFile, nil) + _, err := authorizer.LoadAndValidateFile(o.AuthorizationConfigurationFile, authorizationcel.NewDefaultCompiler(), nil) if err != nil { return append(allErrors, err) } @@ -236,7 +237,7 @@ func (o *BuiltInAuthorizationOptions) ToAuthorizationConfig(versionedInformerFac return nil, fmt.Errorf("--%s can not be specified when --%s or --authorization-webhook-* flags are defined", authorizationConfigFlag, authorizationModeFlag) } // load/validate kube-apiserver authz config with no opinion about required modes - authorizationConfiguration, err = authorizer.LoadAndValidateFile(o.AuthorizationConfigurationFile, nil) + authorizationConfiguration, err = authorizer.LoadAndValidateFile(o.AuthorizationConfigurationFile, authorizationcel.NewDefaultCompiler(), nil) if err != nil { return nil, err } diff --git a/staging/src/k8s.io/apiserver/pkg/apis/apiserver/validation/validation.go b/staging/src/k8s.io/apiserver/pkg/apis/apiserver/validation/validation.go index bed40faac29..7f1b8e834af 100644 --- a/staging/src/k8s.io/apiserver/pkg/apis/apiserver/validation/validation.go +++ b/staging/src/k8s.io/apiserver/pkg/apis/apiserver/validation/validation.go @@ -38,14 +38,13 @@ import ( authenticationcel "k8s.io/apiserver/pkg/authentication/cel" authorizationcel "k8s.io/apiserver/pkg/authorization/cel" "k8s.io/apiserver/pkg/cel" - "k8s.io/apiserver/pkg/cel/environment" "k8s.io/apiserver/pkg/features" utilfeature "k8s.io/apiserver/pkg/util/feature" "k8s.io/client-go/util/cert" ) // ValidateAuthenticationConfiguration validates a given AuthenticationConfiguration. -func ValidateAuthenticationConfiguration(c *api.AuthenticationConfiguration, disallowedIssuers []string) field.ErrorList { +func ValidateAuthenticationConfiguration(compiler authenticationcel.Compiler, c *api.AuthenticationConfiguration, disallowedIssuers []string) field.ErrorList { root := field.NewPath("jwt") var allErrs field.ErrorList @@ -62,7 +61,7 @@ func ValidateAuthenticationConfiguration(c *api.AuthenticationConfiguration, dis seenDiscoveryURLs := sets.New[string]() for i, a := range c.JWT { fldPath := root.Index(i) - _, errs := validateJWTAuthenticator(a, fldPath, sets.New(disallowedIssuers...), utilfeature.DefaultFeatureGate.Enabled(features.StructuredAuthenticationConfiguration)) + _, errs := validateJWTAuthenticator(compiler, a, fldPath, sets.New(disallowedIssuers...), utilfeature.DefaultFeatureGate.Enabled(features.StructuredAuthenticationConfiguration)) allErrs = append(allErrs, errs...) if seenIssuers.Has(a.Issuer.URL) { @@ -93,15 +92,13 @@ func ValidateAuthenticationConfiguration(c *api.AuthenticationConfiguration, dis // CompileAndValidateJWTAuthenticator validates a given JWTAuthenticator and returns a CELMapper with the compiled // CEL expressions for claim mappings and validation rules. // This is exported for use in oidc package. -func CompileAndValidateJWTAuthenticator(authenticator api.JWTAuthenticator, disallowedIssuers []string) (authenticationcel.CELMapper, field.ErrorList) { - return validateJWTAuthenticator(authenticator, nil, sets.New(disallowedIssuers...), utilfeature.DefaultFeatureGate.Enabled(features.StructuredAuthenticationConfiguration)) +func CompileAndValidateJWTAuthenticator(compiler authenticationcel.Compiler, authenticator api.JWTAuthenticator, disallowedIssuers []string) (authenticationcel.CELMapper, field.ErrorList) { + return validateJWTAuthenticator(compiler, authenticator, nil, sets.New(disallowedIssuers...), utilfeature.DefaultFeatureGate.Enabled(features.StructuredAuthenticationConfiguration)) } -func validateJWTAuthenticator(authenticator api.JWTAuthenticator, fldPath *field.Path, disallowedIssuers sets.Set[string], structuredAuthnFeatureEnabled bool) (authenticationcel.CELMapper, field.ErrorList) { +func validateJWTAuthenticator(compiler authenticationcel.Compiler, authenticator api.JWTAuthenticator, fldPath *field.Path, disallowedIssuers sets.Set[string], structuredAuthnFeatureEnabled bool) (authenticationcel.CELMapper, field.ErrorList) { var allErrs field.ErrorList - // strictCost is set to true which enables the strict cost for CEL validation. - compiler := authenticationcel.NewCompiler(environment.MustBaseEnvSet(environment.DefaultCompatibilityVersion(), true)) state := &validationState{} allErrs = append(allErrs, validateIssuer(authenticator.Issuer, disallowedIssuers, fldPath.Child("issuer"), structuredAuthnFeatureEnabled)...) @@ -616,7 +613,7 @@ func compileUserCELExpression(compiler authenticationcel.Compiler, expression au } // ValidateAuthorizationConfiguration validates a given AuthorizationConfiguration. -func ValidateAuthorizationConfiguration(fldPath *field.Path, c *api.AuthorizationConfiguration, knownTypes sets.String, repeatableTypes sets.String) field.ErrorList { +func ValidateAuthorizationConfiguration(compiler authorizationcel.Compiler, fldPath *field.Path, c *api.AuthorizationConfiguration, knownTypes sets.String, repeatableTypes sets.String) field.ErrorList { allErrs := field.ErrorList{} if len(c.Authorizers) == 0 { @@ -657,7 +654,7 @@ func ValidateAuthorizationConfiguration(fldPath *field.Path, c *api.Authorizatio allErrs = append(allErrs, field.Required(fldPath.Child("webhook"), "required when type=Webhook")) continue } - allErrs = append(allErrs, ValidateWebhookConfiguration(fldPath, a.Webhook)...) + allErrs = append(allErrs, ValidateWebhookConfiguration(compiler, fldPath, a.Webhook)...) default: if a.Webhook != nil { allErrs = append(allErrs, field.Invalid(fldPath.Child("webhook"), "non-null", "may only be specified when type=Webhook")) @@ -668,7 +665,7 @@ func ValidateAuthorizationConfiguration(fldPath *field.Path, c *api.Authorizatio return allErrs } -func ValidateWebhookConfiguration(fldPath *field.Path, c *api.WebhookConfiguration) field.ErrorList { +func ValidateWebhookConfiguration(compiler authorizationcel.Compiler, fldPath *field.Path, c *api.WebhookConfiguration) field.ErrorList { allErrs := field.ErrorList{} if c.Timeout.Duration == 0 { @@ -740,7 +737,7 @@ func ValidateWebhookConfiguration(fldPath *field.Path, c *api.WebhookConfigurati allErrs = append(allErrs, field.NotSupported(fldPath.Child("connectionInfo", "type"), c.ConnectionInfo, []string{api.AuthorizationWebhookConnectionInfoTypeInCluster, api.AuthorizationWebhookConnectionInfoTypeKubeConfigFile})) } - _, errs := compileMatchConditions(c.MatchConditions, fldPath, utilfeature.DefaultFeatureGate.Enabled(features.StructuredAuthorizationConfiguration)) + _, errs := compileMatchConditions(compiler, c.MatchConditions, fldPath, utilfeature.DefaultFeatureGate.Enabled(features.StructuredAuthorizationConfiguration)) allErrs = append(allErrs, errs...) return allErrs @@ -748,11 +745,11 @@ func ValidateWebhookConfiguration(fldPath *field.Path, c *api.WebhookConfigurati // ValidateAndCompileMatchConditions validates a given webhook's matchConditions. // This is exported for use in authz package. -func ValidateAndCompileMatchConditions(matchConditions []api.WebhookMatchCondition) (*authorizationcel.CELMatcher, field.ErrorList) { - return compileMatchConditions(matchConditions, nil, utilfeature.DefaultFeatureGate.Enabled(features.StructuredAuthorizationConfiguration)) +func ValidateAndCompileMatchConditions(compiler authorizationcel.Compiler, matchConditions []api.WebhookMatchCondition) (*authorizationcel.CELMatcher, field.ErrorList) { + return compileMatchConditions(compiler, matchConditions, nil, utilfeature.DefaultFeatureGate.Enabled(features.StructuredAuthorizationConfiguration)) } -func compileMatchConditions(matchConditions []api.WebhookMatchCondition, fldPath *field.Path, structuredAuthzFeatureEnabled bool) (*authorizationcel.CELMatcher, field.ErrorList) { +func compileMatchConditions(compiler authorizationcel.Compiler, matchConditions []api.WebhookMatchCondition, fldPath *field.Path, structuredAuthzFeatureEnabled bool) (*authorizationcel.CELMatcher, field.ErrorList) { var allErrs field.ErrorList // should fail when match conditions are used without feature enabled if len(matchConditions) > 0 && !structuredAuthzFeatureEnabled { @@ -763,8 +760,6 @@ func compileMatchConditions(matchConditions []api.WebhookMatchCondition, fldPath return nil, allErrs } - // strictCost is set to true which enables the strict cost for CEL validation. - compiler := authorizationcel.NewCompiler(environment.MustBaseEnvSet(environment.DefaultCompatibilityVersion(), true)) seenExpressions := sets.NewString() var compilationResults []authorizationcel.CompilationResult var usesFieldSelector, usesLabelSelector bool diff --git a/staging/src/k8s.io/apiserver/pkg/apis/apiserver/validation/validation_test.go b/staging/src/k8s.io/apiserver/pkg/apis/apiserver/validation/validation_test.go index deba4617c1e..9496c75fe15 100644 --- a/staging/src/k8s.io/apiserver/pkg/apis/apiserver/validation/validation_test.go +++ b/staging/src/k8s.io/apiserver/pkg/apis/apiserver/validation/validation_test.go @@ -34,7 +34,7 @@ import ( "k8s.io/apimachinery/pkg/util/validation/field" api "k8s.io/apiserver/pkg/apis/apiserver" authenticationcel "k8s.io/apiserver/pkg/authentication/cel" - "k8s.io/apiserver/pkg/cel/environment" + authorizationcel "k8s.io/apiserver/pkg/authorization/cel" "k8s.io/apiserver/pkg/features" utilfeature "k8s.io/apiserver/pkg/util/feature" certutil "k8s.io/client-go/util/cert" @@ -42,10 +42,6 @@ import ( "k8s.io/utils/pointer" ) -var ( - compiler = authenticationcel.NewCompiler(environment.MustBaseEnvSet(environment.DefaultCompatibilityVersion(), true)) -) - func TestValidateAuthenticationConfiguration(t *testing.T) { featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.StructuredAuthenticationConfiguration, true) @@ -619,7 +615,7 @@ func TestValidateAuthenticationConfiguration(t *testing.T) { for _, tt := range testCases { t.Run(tt.name, func(t *testing.T) { - got := ValidateAuthenticationConfiguration(tt.in, tt.disallowedIssuers).ToAggregate() + got := ValidateAuthenticationConfiguration(authenticationcel.NewDefaultCompiler(), tt.in, tt.disallowedIssuers).ToAggregate() if d := cmp.Diff(tt.want, errString(got)); d != "" { t.Fatalf("AuthenticationConfiguration validation mismatch (-want +got):\n%s", d) } @@ -1044,7 +1040,7 @@ func TestValidateClaimValidationRules(t *testing.T) { for _, tt := range testCases { t.Run(tt.name, func(t *testing.T) { state := &validationState{} - got := validateClaimValidationRules(compiler, state, tt.in, fldPath, tt.structuredAuthnFeatureEnabled).ToAggregate() + got := validateClaimValidationRules(authenticationcel.NewDefaultCompiler(), state, tt.in, fldPath, tt.structuredAuthnFeatureEnabled).ToAggregate() if d := cmp.Diff(tt.want, errString(got)); d != "" { t.Fatalf("ClaimValidationRules validation mismatch (-want +got):\n%s", d) } @@ -1572,7 +1568,7 @@ func TestValidateClaimMappings(t *testing.T) { for _, tt := range testCases { t.Run(tt.name, func(t *testing.T) { state := &validationState{usesEmailVerifiedClaim: tt.usesEmailVerifiedClaim} - got := validateClaimMappings(compiler, state, tt.in, fldPath, tt.structuredAuthnFeatureEnabled).ToAggregate() + got := validateClaimMappings(authenticationcel.NewDefaultCompiler(), state, tt.in, fldPath, tt.structuredAuthnFeatureEnabled).ToAggregate() if d := cmp.Diff(tt.want, errString(got)); d != "" { fmt.Println(errString(got)) t.Fatalf("ClaimMappings validation mismatch (-want +got):\n%s", d) @@ -1661,7 +1657,7 @@ func TestValidateUserValidationRules(t *testing.T) { for _, tt := range testCases { t.Run(tt.name, func(t *testing.T) { state := &validationState{} - got := validateUserValidationRules(compiler, state, tt.in, fldPath, tt.structuredAuthnFeatureEnabled).ToAggregate() + got := validateUserValidationRules(authenticationcel.NewDefaultCompiler(), state, tt.in, fldPath, tt.structuredAuthnFeatureEnabled).ToAggregate() if d := cmp.Diff(tt.want, errString(got)); d != "" { t.Fatalf("UserValidationRules validation mismatch (-want +got):\n%s", d) } @@ -2458,7 +2454,7 @@ func TestValidateAuthorizationConfiguration(t *testing.T) { for _, test := range tests { t.Run(test.name, func(t *testing.T) { - errList := ValidateAuthorizationConfiguration(nil, &test.configuration, test.knownTypes, test.repeatableTypes) + errList := ValidateAuthorizationConfiguration(authorizationcel.NewDefaultCompiler(), nil, &test.configuration, test.knownTypes, test.repeatableTypes) if len(errList) != len(test.expectedErrList) { t.Errorf("expected %d errs, got %d, errors %v", len(test.expectedErrList), len(errList), errList) } @@ -2568,7 +2564,7 @@ func TestValidateAndCompileMatchConditions(t *testing.T) { for _, tt := range testCases { t.Run(tt.name, func(t *testing.T) { featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.StructuredAuthorizationConfiguration, tt.featureEnabled) - celMatcher, errList := ValidateAndCompileMatchConditions(tt.matchConditions) + celMatcher, errList := ValidateAndCompileMatchConditions(authorizationcel.NewDefaultCompiler(), tt.matchConditions) if len(tt.expectedErr) == 0 && len(tt.matchConditions) > 0 && len(errList) == 0 && celMatcher == nil { t.Errorf("celMatcher should not be nil when there are matchCondition and no error returned") } diff --git a/staging/src/k8s.io/apiserver/pkg/authentication/cel/compile.go b/staging/src/k8s.io/apiserver/pkg/authentication/cel/compile.go index 5550955af92..8c74e7ad4de 100644 --- a/staging/src/k8s.io/apiserver/pkg/authentication/cel/compile.go +++ b/staging/src/k8s.io/apiserver/pkg/authentication/cel/compile.go @@ -39,6 +39,12 @@ type compiler struct { varEnvs map[string]*environment.EnvSet } +// NewDefaultCompiler returns a new Compiler following the default compatibility version. +// Note: the compiler construction depends on feature gates and the compatibility version to be initialized. +func NewDefaultCompiler() Compiler { + return NewCompiler(environment.MustBaseEnvSet(environment.DefaultCompatibilityVersion(), true)) +} + // NewCompiler returns a new Compiler. func NewCompiler(env *environment.EnvSet) Compiler { return &compiler{ diff --git a/staging/src/k8s.io/apiserver/pkg/authentication/cel/compile_test.go b/staging/src/k8s.io/apiserver/pkg/authentication/cel/compile_test.go index 5615f4766cc..2f6f9ef349e 100644 --- a/staging/src/k8s.io/apiserver/pkg/authentication/cel/compile_test.go +++ b/staging/src/k8s.io/apiserver/pkg/authentication/cel/compile_test.go @@ -23,7 +23,6 @@ import ( authenticationv1 "k8s.io/api/authentication/v1" apiservercel "k8s.io/apiserver/pkg/cel" - "k8s.io/apiserver/pkg/cel/environment" ) func TestCompileClaimsExpression(t *testing.T) { @@ -57,12 +56,10 @@ func TestCompileClaimsExpression(t *testing.T) { }, } - compiler := NewCompiler(environment.MustBaseEnvSet(environment.DefaultCompatibilityVersion(), true)) - for _, tc := range testCases { t.Run(tc.name, func(t *testing.T) { for _, expressionAccessor := range tc.expressionAccessors { - _, err := compiler.CompileClaimsExpression(expressionAccessor) + _, err := NewDefaultCompiler().CompileClaimsExpression(expressionAccessor) if err != nil { t.Errorf("unexpected error: %v", err) } @@ -86,12 +83,10 @@ func TestCompileUserExpression(t *testing.T) { }, } - compiler := NewCompiler(environment.MustBaseEnvSet(environment.DefaultCompatibilityVersion(), true)) - for _, tc := range testCases { t.Run(tc.name, func(t *testing.T) { for _, expressionAccessor := range tc.expressionAccessors { - _, err := compiler.CompileUserExpression(expressionAccessor) + _, err := NewDefaultCompiler().CompileUserExpression(expressionAccessor) if err != nil { t.Errorf("unexpected error: %v", err) } @@ -135,12 +130,10 @@ func TestCompileClaimsExpressionError(t *testing.T) { }, } - compiler := NewCompiler(environment.MustBaseEnvSet(environment.DefaultCompatibilityVersion(), true)) - for _, tc := range testCases { t.Run(tc.name, func(t *testing.T) { for _, expressionAccessor := range tc.expressionAccessors { - _, err := compiler.CompileClaimsExpression(expressionAccessor) + _, err := NewDefaultCompiler().CompileClaimsExpression(expressionAccessor) if err == nil { t.Errorf("expected error but got nil") } @@ -205,12 +198,10 @@ func TestCompileUserExpressionError(t *testing.T) { }, } - compiler := NewCompiler(environment.MustBaseEnvSet(environment.DefaultCompatibilityVersion(), true)) - for _, tc := range testCases { t.Run(tc.name, func(t *testing.T) { for _, expressionAccessor := range tc.expressionAccessors { - _, err := compiler.CompileUserExpression(expressionAccessor) + _, err := NewDefaultCompiler().CompileUserExpression(expressionAccessor) if err == nil { t.Errorf("expected error but got nil") } diff --git a/staging/src/k8s.io/apiserver/pkg/authorization/authorizerfactory/delegating.go b/staging/src/k8s.io/apiserver/pkg/authorization/authorizerfactory/delegating.go index 070189145af..483aedd4238 100644 --- a/staging/src/k8s.io/apiserver/pkg/authorization/authorizerfactory/delegating.go +++ b/staging/src/k8s.io/apiserver/pkg/authorization/authorizerfactory/delegating.go @@ -22,6 +22,7 @@ import ( "k8s.io/apimachinery/pkg/util/wait" "k8s.io/apiserver/pkg/authorization/authorizer" + authorizationcel "k8s.io/apiserver/pkg/authorization/cel" "k8s.io/apiserver/plugin/pkg/authorizer/webhook" authorizationclient "k8s.io/client-go/kubernetes/typed/authorization/v1" ) @@ -31,6 +32,9 @@ import ( type DelegatingAuthorizerConfig struct { SubjectAccessReviewClient authorizationclient.AuthorizationV1Interface + // Compiler is the CEL compiler to use for evaluating policies. If nil, a default compiler will be used. + Compiler authorizationcel.Compiler + // AllowCacheTTL is the length of time that a successful authorization response will be cached AllowCacheTTL time.Duration @@ -48,6 +52,10 @@ func (c DelegatingAuthorizerConfig) New() (authorizer.Authorizer, error) { if c.WebhookRetryBackoff == nil { return nil, errors.New("retry backoff parameters for delegating authorization webhook has not been specified") } + compiler := c.Compiler + if compiler == nil { + compiler = authorizationcel.NewDefaultCompiler() + } return webhook.NewFromInterface( c.SubjectAccessReviewClient, @@ -56,5 +64,6 @@ func (c DelegatingAuthorizerConfig) New() (authorizer.Authorizer, error) { *c.WebhookRetryBackoff, authorizer.DecisionNoOpinion, NewDelegatingAuthorizerMetrics(), + compiler, ) } diff --git a/staging/src/k8s.io/apiserver/pkg/authorization/cel/compile.go b/staging/src/k8s.io/apiserver/pkg/authorization/cel/compile.go index 829ff91d395..765864846c1 100644 --- a/staging/src/k8s.io/apiserver/pkg/authorization/cel/compile.go +++ b/staging/src/k8s.io/apiserver/pkg/authorization/cel/compile.go @@ -65,6 +65,12 @@ type compiler struct { envSet *environment.EnvSet } +// NewDefaultCompiler returns a new Compiler following the default compatibility version. +// Note: the compiler construction depends on feature gates and the compatibility version to be initialized. +func NewDefaultCompiler() Compiler { + return NewCompiler(environment.MustBaseEnvSet(environment.DefaultCompatibilityVersion(), true)) +} + // NewCompiler returns a new Compiler. func NewCompiler(env *environment.EnvSet) Compiler { return &compiler{ diff --git a/staging/src/k8s.io/apiserver/pkg/authorization/cel/compile_test.go b/staging/src/k8s.io/apiserver/pkg/authorization/cel/compile_test.go index 0ed3a9d1077..f1ee258e7a8 100644 --- a/staging/src/k8s.io/apiserver/pkg/authorization/cel/compile_test.go +++ b/staging/src/k8s.io/apiserver/pkg/authorization/cel/compile_test.go @@ -25,7 +25,6 @@ import ( v1 "k8s.io/api/authorization/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" apiservercel "k8s.io/apiserver/pkg/cel" - "k8s.io/apiserver/pkg/cel/environment" genericfeatures "k8s.io/apiserver/pkg/features" utilfeature "k8s.io/apiserver/pkg/util/feature" featuregatetesting "k8s.io/component-base/featuregate/testing" @@ -100,7 +99,10 @@ func TestCompileCELExpression(t *testing.T) { for _, tc := range cases { t.Run(tc.name, func(t *testing.T) { featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, genericfeatures.AuthorizeWithSelectors, tc.authorizeWithSelectorsEnabled) - compiler := NewCompiler(environment.MustBaseEnvSet(environment.DefaultCompatibilityVersion(), true)) + + // create new compiler because it depends on the feature gate + compiler := NewDefaultCompiler() + _, err := compiler.CompileCELExpression(&SubjectAccessReviewMatchCondition{ Expression: tc.expression, }) diff --git a/staging/src/k8s.io/apiserver/plugin/pkg/authenticator/token/oidc/oidc.go b/staging/src/k8s.io/apiserver/plugin/pkg/authenticator/token/oidc/oidc.go index 226ea22dec5..d5fd28f0ebe 100644 --- a/staging/src/k8s.io/apiserver/plugin/pkg/authenticator/token/oidc/oidc.go +++ b/staging/src/k8s.io/apiserver/plugin/pkg/authenticator/token/oidc/oidc.go @@ -86,6 +86,12 @@ type Options struct { // Optional http.Client used to make all requests to the remote issuer. Mutually exclusive with CAContentProvider. Client *http.Client + // Optional CEL compiler used to compile the CEL expressions. This is useful to use a shared instance + // of the compiler as these compilers holding a CEL environment are expensive to create. If not provided, + // a default compiler will be created. + // Note: the compiler construction depends on feature gates and the compatibility version to be initialized. + Compiler authenticationcel.Compiler + // SupportedSigningAlgs sets the accepted set of JOSE signing algorithms that // can be used by the provider to sign tokens. // @@ -245,7 +251,11 @@ type AuthenticatorTokenWithHealthCheck interface { // Thus, once the lifecycleCtx is canceled, the authenticator must not be used. // A caller may check if the authenticator is healthy by calling the HealthCheck method. func New(lifecycleCtx context.Context, opts Options) (AuthenticatorTokenWithHealthCheck, error) { - celMapper, fieldErr := apiservervalidation.CompileAndValidateJWTAuthenticator(opts.JWTAuthenticator, opts.DisallowedIssuers) + compiler := opts.Compiler + if compiler == nil { + compiler = authenticationcel.NewDefaultCompiler() + } + celMapper, fieldErr := apiservervalidation.CompileAndValidateJWTAuthenticator(compiler, opts.JWTAuthenticator, opts.DisallowedIssuers) if err := fieldErr.ToAggregate(); err != nil { return nil, err } diff --git a/staging/src/k8s.io/apiserver/plugin/pkg/authorizer/webhook/metrics_test.go b/staging/src/k8s.io/apiserver/plugin/pkg/authorizer/webhook/metrics_test.go index 422358f1483..9fa48014dc2 100644 --- a/staging/src/k8s.io/apiserver/plugin/pkg/authorizer/webhook/metrics_test.go +++ b/staging/src/k8s.io/apiserver/plugin/pkg/authorizer/webhook/metrics_test.go @@ -122,7 +122,7 @@ func TestAuthorizerMetrics(t *testing.T) { defer server.Close() fakeAuthzMetrics := &fakeAuthorizerMetrics{} - wh, err := newV1Authorizer(server.URL, scenario.clientCert, scenario.clientKey, scenario.clientCA, 0, fakeAuthzMetrics, []apiserver.WebhookMatchCondition{}, "") + wh, err := newV1Authorizer(server.URL, scenario.clientCert, scenario.clientKey, scenario.clientCA, 0, fakeAuthzMetrics, cel.NewDefaultCompiler(), []apiserver.WebhookMatchCondition{}, "") if err != nil { t.Error("failed to create client") return diff --git a/staging/src/k8s.io/apiserver/plugin/pkg/authorizer/webhook/webhook.go b/staging/src/k8s.io/apiserver/plugin/pkg/authorizer/webhook/webhook.go index f70cce6e15c..3df8e580e44 100644 --- a/staging/src/k8s.io/apiserver/plugin/pkg/authorizer/webhook/webhook.go +++ b/staging/src/k8s.io/apiserver/plugin/pkg/authorizer/webhook/webhook.go @@ -82,8 +82,8 @@ type WebhookAuthorizer struct { } // NewFromInterface creates a WebhookAuthorizer using the given subjectAccessReview client -func NewFromInterface(subjectAccessReview authorizationv1client.AuthorizationV1Interface, authorizedTTL, unauthorizedTTL time.Duration, retryBackoff wait.Backoff, decisionOnError authorizer.Decision, metrics metrics.AuthorizerMetrics) (*WebhookAuthorizer, error) { - return newWithBackoff(&subjectAccessReviewV1Client{subjectAccessReview.RESTClient()}, authorizedTTL, unauthorizedTTL, retryBackoff, decisionOnError, nil, metrics, "") +func NewFromInterface(subjectAccessReview authorizationv1client.AuthorizationV1Interface, authorizedTTL, unauthorizedTTL time.Duration, retryBackoff wait.Backoff, decisionOnError authorizer.Decision, metrics metrics.AuthorizerMetrics, compiler authorizationcel.Compiler) (*WebhookAuthorizer, error) { + return newWithBackoff(&subjectAccessReviewV1Client{subjectAccessReview.RESTClient()}, authorizedTTL, unauthorizedTTL, retryBackoff, decisionOnError, nil, metrics, compiler, "") } // New creates a new WebhookAuthorizer from the provided kubeconfig file. @@ -105,18 +105,18 @@ func NewFromInterface(subjectAccessReview authorizationv1client.AuthorizationV1I // // For additional HTTP configuration, refer to the kubeconfig documentation // https://kubernetes.io/docs/user-guide/kubeconfig-file/. -func New(config *rest.Config, version string, authorizedTTL, unauthorizedTTL time.Duration, retryBackoff wait.Backoff, decisionOnError authorizer.Decision, matchConditions []apiserver.WebhookMatchCondition, name string, metrics metrics.AuthorizerMetrics) (*WebhookAuthorizer, error) { +func New(config *rest.Config, version string, authorizedTTL, unauthorizedTTL time.Duration, retryBackoff wait.Backoff, decisionOnError authorizer.Decision, matchConditions []apiserver.WebhookMatchCondition, name string, metrics metrics.AuthorizerMetrics, compiler authorizationcel.Compiler) (*WebhookAuthorizer, error) { subjectAccessReview, err := subjectAccessReviewInterfaceFromConfig(config, version, retryBackoff) if err != nil { return nil, err } - return newWithBackoff(subjectAccessReview, authorizedTTL, unauthorizedTTL, retryBackoff, decisionOnError, matchConditions, metrics, name) + return newWithBackoff(subjectAccessReview, authorizedTTL, unauthorizedTTL, retryBackoff, decisionOnError, matchConditions, metrics, compiler, name) } // newWithBackoff allows tests to skip the sleep. -func newWithBackoff(subjectAccessReview subjectAccessReviewer, authorizedTTL, unauthorizedTTL time.Duration, retryBackoff wait.Backoff, decisionOnError authorizer.Decision, matchConditions []apiserver.WebhookMatchCondition, am metrics.AuthorizerMetrics, name string) (*WebhookAuthorizer, error) { +func newWithBackoff(subjectAccessReview subjectAccessReviewer, authorizedTTL, unauthorizedTTL time.Duration, retryBackoff wait.Backoff, decisionOnError authorizer.Decision, matchConditions []apiserver.WebhookMatchCondition, am metrics.AuthorizerMetrics, compiler authorizationcel.Compiler, name string) (*WebhookAuthorizer, error) { // compile all expressions once in validation and save the results to be used for eval later - cm, fieldErr := apiservervalidation.ValidateAndCompileMatchConditions(matchConditions) + cm, fieldErr := apiservervalidation.ValidateAndCompileMatchConditions(compiler, matchConditions) if err := fieldErr.ToAggregate(); err != nil { return nil, err } diff --git a/staging/src/k8s.io/apiserver/plugin/pkg/authorizer/webhook/webhook_v1_test.go b/staging/src/k8s.io/apiserver/plugin/pkg/authorizer/webhook/webhook_v1_test.go index f04a8b267cc..ea058c9d5e7 100644 --- a/staging/src/k8s.io/apiserver/plugin/pkg/authorizer/webhook/webhook_v1_test.go +++ b/staging/src/k8s.io/apiserver/plugin/pkg/authorizer/webhook/webhook_v1_test.go @@ -34,8 +34,6 @@ import ( "text/template" "time" - utiltesting "k8s.io/client-go/util/testing" - "github.com/google/go-cmp/cmp" authorizationv1 "k8s.io/api/authorization/v1" @@ -47,12 +45,13 @@ import ( "k8s.io/apiserver/pkg/apis/apiserver" "k8s.io/apiserver/pkg/authentication/user" "k8s.io/apiserver/pkg/authorization/authorizer" - celmetrics "k8s.io/apiserver/pkg/authorization/cel" + authorizationcel "k8s.io/apiserver/pkg/authorization/cel" "k8s.io/apiserver/pkg/features" utilfeature "k8s.io/apiserver/pkg/util/feature" webhookutil "k8s.io/apiserver/pkg/util/webhook" "k8s.io/apiserver/plugin/pkg/authorizer/webhook/metrics" v1 "k8s.io/client-go/tools/clientcmd/api/v1" + utiltesting "k8s.io/client-go/util/testing" featuregatetesting "k8s.io/component-base/featuregate/testing" "k8s.io/component-base/metrics/legacyregistry" "k8s.io/component-base/metrics/testutil" @@ -217,7 +216,7 @@ current-context: default if err != nil { return fmt.Errorf("error building sar client: %v", err) } - _, err = newWithBackoff(sarClient, 0, 0, testRetryBackoff, authorizer.DecisionNoOpinion, []apiserver.WebhookMatchCondition{}, noopAuthorizerMetrics(), "") + _, err = newWithBackoff(sarClient, 0, 0, testRetryBackoff, authorizer.DecisionNoOpinion, []apiserver.WebhookMatchCondition{}, noopAuthorizerMetrics(), authorizationcel.NewDefaultCompiler(), "") return err }() if err != nil && !tt.wantErr { @@ -337,7 +336,7 @@ func (m *mockV1Service) HTTPStatusCode() int { return m.statusCode } // newV1Authorizer creates a temporary kubeconfig file from the provided arguments and attempts to load // a new WebhookAuthorizer from it. -func newV1Authorizer(callbackURL string, clientCert, clientKey, ca []byte, cacheTime time.Duration, metrics metrics.AuthorizerMetrics, expressions []apiserver.WebhookMatchCondition, authzName string) (*WebhookAuthorizer, error) { +func newV1Authorizer(callbackURL string, clientCert, clientKey, ca []byte, cacheTime time.Duration, metrics metrics.AuthorizerMetrics, compiler authorizationcel.Compiler, expressions []apiserver.WebhookMatchCondition, authzName string) (*WebhookAuthorizer, error) { tempfile, err := ioutil.TempFile("", "") if err != nil { return nil, err @@ -367,7 +366,7 @@ func newV1Authorizer(callbackURL string, clientCert, clientKey, ca []byte, cache if err != nil { return nil, fmt.Errorf("error building sar client: %v", err) } - return newWithBackoff(sarClient, cacheTime, cacheTime, testRetryBackoff, authorizer.DecisionNoOpinion, expressions, metrics, authzName) + return newWithBackoff(sarClient, cacheTime, cacheTime, testRetryBackoff, authorizer.DecisionNoOpinion, expressions, metrics, compiler, authzName) } func TestV1TLSConfig(t *testing.T) { @@ -426,7 +425,7 @@ func TestV1TLSConfig(t *testing.T) { } defer server.Close() - wh, err := newV1Authorizer(server.URL, tt.clientCert, tt.clientKey, tt.clientCA, 0, noopAuthorizerMetrics(), []apiserver.WebhookMatchCondition{}, "") + wh, err := newV1Authorizer(server.URL, tt.clientCert, tt.clientKey, tt.clientCA, 0, noopAuthorizerMetrics(), authorizationcel.NewDefaultCompiler(), []apiserver.WebhookMatchCondition{}, "") if err != nil { t.Errorf("%s: failed to create client: %v", tt.test, err) return @@ -491,7 +490,7 @@ func TestV1Webhook(t *testing.T) { } defer s.Close() - wh, err := newV1Authorizer(s.URL, clientCert, clientKey, caCert, 0, noopAuthorizerMetrics(), []apiserver.WebhookMatchCondition{}, "") + wh, err := newV1Authorizer(s.URL, clientCert, clientKey, caCert, 0, noopAuthorizerMetrics(), authorizationcel.NewDefaultCompiler(), []apiserver.WebhookMatchCondition{}, "") if err != nil { t.Fatal(err) } @@ -598,7 +597,7 @@ func TestV1WebhookCache(t *testing.T) { }, } // Create an authorizer that caches successful responses "forever" (100 days). - wh, err := newV1Authorizer(s.URL, clientCert, clientKey, caCert, 2400*time.Hour, noopAuthorizerMetrics(), expressions, "") + wh, err := newV1Authorizer(s.URL, clientCert, clientKey, caCert, 2400*time.Hour, noopAuthorizerMetrics(), authorizationcel.NewDefaultCompiler(), expressions, "") if err != nil { t.Fatal(err) } @@ -693,7 +692,6 @@ func TestV1WebhookCache(t *testing.T) { // TestStructuredAuthzConfigFeatureEnablement verifies cel expressions can only be used when feature is enabled func TestStructuredAuthzConfigFeatureEnablement(t *testing.T) { - service := new(mockV1Service) service.statusCode = 200 service.Allow() @@ -804,7 +802,11 @@ func TestStructuredAuthzConfigFeatureEnablement(t *testing.T) { t.Run(test.name, func(t *testing.T) { featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.StructuredAuthorizationConfiguration, test.featureEnabled) featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.AuthorizeWithSelectors, test.selectorEnabled) - wh, err := newV1Authorizer(s.URL, clientCert, clientKey, caCert, 0, noopAuthorizerMetrics(), test.expressions, "") + + // create new compiler because it depends on the feature gate + compiler := authorizationcel.NewDefaultCompiler() + + wh, err := newV1Authorizer(s.URL, clientCert, clientKey, caCert, 0, noopAuthorizerMetrics(), compiler, test.expressions, "") if test.expectedCompileErr && err == nil { t.Fatalf("%d: Expected compile error", i) } else if !test.expectedCompileErr && err != nil { @@ -910,13 +912,13 @@ func TestWebhookMetrics(t *testing.T) { for _, tt := range testCases { t.Run(tt.name, func(t *testing.T) { - celmetrics.ResetMetricsForTest() - defer celmetrics.ResetMetricsForTest() - wh1, err := newV1Authorizer(s.URL, clientCert, clientKey, caCert, 0, celAuthorizerMetrics(), tt.expressions1, "wh1.example.com") + authorizationcel.ResetMetricsForTest() + defer authorizationcel.ResetMetricsForTest() + wh1, err := newV1Authorizer(s.URL, clientCert, clientKey, caCert, 0, celAuthorizerMetrics(), authorizationcel.NewDefaultCompiler(), tt.expressions1, "wh1.example.com") if err != nil { t.Fatal(err) } - wh2, err := newV1Authorizer(s.URL, clientCert, clientKey, caCert, 0, celAuthorizerMetrics(), tt.expressions2, "wh2.example.com") + wh2, err := newV1Authorizer(s.URL, clientCert, clientKey, caCert, 0, celAuthorizerMetrics(), authorizationcel.NewDefaultCompiler(), tt.expressions2, "wh2.example.com") if err != nil { t.Fatal(err) } @@ -1092,7 +1094,7 @@ func benchmarkNewWebhookAuthorizer(b *testing.B, expressions []apiserver.Webhook b.ResetTimer() for i := 0; i < b.N; i++ { // Create an authorizer with or without expressions to compile - _, err := newV1Authorizer(s.URL, clientCert, clientKey, caCert, 0, noopAuthorizerMetrics(), expressions, "") + _, err := newV1Authorizer(s.URL, clientCert, clientKey, caCert, 0, noopAuthorizerMetrics(), authorizationcel.NewDefaultCompiler(), expressions, "") if err != nil { b.Fatal(err) } @@ -1122,7 +1124,7 @@ func benchmarkWebhookAuthorize(b *testing.B, expressions []apiserver.WebhookMatc defer s.Close() featuregatetesting.SetFeatureGateDuringTest(b, utilfeature.DefaultFeatureGate, features.StructuredAuthorizationConfiguration, featureEnabled) // Create an authorizer with or without expressions to compile - wh, err := newV1Authorizer(s.URL, clientCert, clientKey, caCert, 0, noopAuthorizerMetrics(), expressions, "") + wh, err := newV1Authorizer(s.URL, clientCert, clientKey, caCert, 0, noopAuthorizerMetrics(), authorizationcel.NewDefaultCompiler(), expressions, "") if err != nil { b.Fatal(err) } @@ -1409,7 +1411,7 @@ func TestV1WebhookMatchConditions(t *testing.T) { for i, test := range tests { t.Run(test.name, func(t *testing.T) { - wh, err := newV1Authorizer(s.URL, clientCert, clientKey, caCert, 0, noopAuthorizerMetrics(), test.expressions, "") + wh, err := newV1Authorizer(s.URL, clientCert, clientKey, caCert, 0, noopAuthorizerMetrics(), authorizationcel.NewDefaultCompiler(), test.expressions, "") if len(test.expectedCompileErr) > 0 && err == nil { t.Fatalf("%d: Expected compile error", i) } else if len(test.expectedCompileErr) == 0 && err != nil { @@ -1448,12 +1450,12 @@ func noopAuthorizerMetrics() metrics.AuthorizerMetrics { func celAuthorizerMetrics() metrics.AuthorizerMetrics { return celAuthorizerMetricsType{ - MatcherMetrics: celmetrics.NewMatcherMetrics(), + MatcherMetrics: authorizationcel.NewMatcherMetrics(), } } type celAuthorizerMetricsType struct { metrics.NoopRequestMetrics metrics.NoopWebhookMetrics - celmetrics.MatcherMetrics + authorizationcel.MatcherMetrics } diff --git a/staging/src/k8s.io/apiserver/plugin/pkg/authorizer/webhook/webhook_v1beta1_test.go b/staging/src/k8s.io/apiserver/plugin/pkg/authorizer/webhook/webhook_v1beta1_test.go index 3e7c9538e93..e69a9f15d4f 100644 --- a/staging/src/k8s.io/apiserver/plugin/pkg/authorizer/webhook/webhook_v1beta1_test.go +++ b/staging/src/k8s.io/apiserver/plugin/pkg/authorizer/webhook/webhook_v1beta1_test.go @@ -41,6 +41,7 @@ import ( authzconfig "k8s.io/apiserver/pkg/apis/apiserver" "k8s.io/apiserver/pkg/authentication/user" "k8s.io/apiserver/pkg/authorization/authorizer" + authorizationcel "k8s.io/apiserver/pkg/authorization/cel" webhookutil "k8s.io/apiserver/pkg/util/webhook" v1 "k8s.io/client-go/tools/clientcmd/api/v1" ) @@ -197,7 +198,7 @@ current-context: default if err != nil { return fmt.Errorf("error building sar client: %v", err) } - _, err = newWithBackoff(sarClient, 0, 0, testRetryBackoff, authorizer.DecisionNoOpinion, []authzconfig.WebhookMatchCondition{}, noopAuthorizerMetrics(), "") + _, err = newWithBackoff(sarClient, 0, 0, testRetryBackoff, authorizer.DecisionNoOpinion, []authzconfig.WebhookMatchCondition{}, noopAuthorizerMetrics(), authorizationcel.NewDefaultCompiler(), "") return err }() if err != nil && !tt.wantErr { @@ -340,7 +341,7 @@ func newV1beta1Authorizer(callbackURL string, clientCert, clientKey, ca []byte, if err != nil { return nil, fmt.Errorf("error building sar client: %v", err) } - return newWithBackoff(sarClient, cacheTime, cacheTime, testRetryBackoff, authorizer.DecisionNoOpinion, []authzconfig.WebhookMatchCondition{}, noopAuthorizerMetrics(), "") + return newWithBackoff(sarClient, cacheTime, cacheTime, testRetryBackoff, authorizer.DecisionNoOpinion, []authzconfig.WebhookMatchCondition{}, noopAuthorizerMetrics(), authorizationcel.NewDefaultCompiler(), "") } func TestV1beta1TLSConfig(t *testing.T) {