From 3a98e60a719d5fab726976f1cdb7fe73a3575105 Mon Sep 17 00:00:00 2001 From: Jordan Liggitt Date: Tue, 7 Nov 2023 15:28:42 -0600 Subject: [PATCH] Move authz construction to reloader --- pkg/kubeapiserver/authorizer/config.go | 88 ------------------------- pkg/kubeapiserver/authorizer/reload.go | 90 ++++++++++++++++++++++++++ 2 files changed, 90 insertions(+), 88 deletions(-) diff --git a/pkg/kubeapiserver/authorizer/config.go b/pkg/kubeapiserver/authorizer/config.go index 825e36a17a6..7c4b0e6f221 100644 --- a/pkg/kubeapiserver/authorizer/config.go +++ b/pkg/kubeapiserver/authorizer/config.go @@ -17,7 +17,6 @@ limitations under the License. package authorizer import ( - "errors" "fmt" "strings" @@ -28,12 +27,7 @@ import ( authzconfig "k8s.io/apiserver/pkg/apis/apiserver" "k8s.io/apiserver/pkg/apis/apiserver/load" "k8s.io/apiserver/pkg/apis/apiserver/validation" - "k8s.io/apiserver/pkg/authentication/user" "k8s.io/apiserver/pkg/authorization/authorizer" - "k8s.io/apiserver/pkg/authorization/authorizerfactory" - "k8s.io/apiserver/pkg/authorization/union" - webhookutil "k8s.io/apiserver/pkg/util/webhook" - "k8s.io/apiserver/plugin/pkg/authorizer/webhook" versionedinformers "k8s.io/client-go/informers" "k8s.io/kubernetes/pkg/auth/authorizer/abac" "k8s.io/kubernetes/pkg/auth/nodeidentifier" @@ -123,88 +117,6 @@ func (config Config) New() (authorizer.Authorizer, authorizer.RuleResolver, erro return r, r, nil } -// newForConfig constructs -func (r *reloadableAuthorizerResolver) newForConfig(authzConfig *authzconfig.AuthorizationConfiguration) (authorizer.Authorizer, authorizer.RuleResolver, error) { - if len(authzConfig.Authorizers) == 0 { - return nil, nil, fmt.Errorf("at least one authorization mode must be passed") - } - - var ( - authorizers []authorizer.Authorizer - ruleResolvers []authorizer.RuleResolver - ) - - // Add SystemPrivilegedGroup as an authorizing group - superuserAuthorizer := authorizerfactory.NewPrivilegedGroups(user.SystemPrivilegedGroup) - authorizers = append(authorizers, superuserAuthorizer) - - for _, configuredAuthorizer := range authzConfig.Authorizers { - // Keep cases in sync with constant list in k8s.io/kubernetes/pkg/kubeapiserver/authorizer/modes/modes.go. - switch configuredAuthorizer.Type { - case authzconfig.AuthorizerType(modes.ModeNode): - if r.nodeAuthorizer == nil { - return nil, nil, fmt.Errorf("nil nodeAuthorizer") - } - authorizers = append(authorizers, r.nodeAuthorizer) - ruleResolvers = append(ruleResolvers, r.nodeAuthorizer) - case authzconfig.AuthorizerType(modes.ModeAlwaysAllow): - alwaysAllowAuthorizer := authorizerfactory.NewAlwaysAllowAuthorizer() - authorizers = append(authorizers, alwaysAllowAuthorizer) - ruleResolvers = append(ruleResolvers, alwaysAllowAuthorizer) - case authzconfig.AuthorizerType(modes.ModeAlwaysDeny): - alwaysDenyAuthorizer := authorizerfactory.NewAlwaysDenyAuthorizer() - authorizers = append(authorizers, alwaysDenyAuthorizer) - ruleResolvers = append(ruleResolvers, alwaysDenyAuthorizer) - case authzconfig.AuthorizerType(modes.ModeABAC): - if r.abacAuthorizer == nil { - return nil, nil, fmt.Errorf("nil abacAuthorizer") - } - authorizers = append(authorizers, r.abacAuthorizer) - ruleResolvers = append(ruleResolvers, r.abacAuthorizer) - case authzconfig.AuthorizerType(modes.ModeWebhook): - if r.initialConfig.WebhookRetryBackoff == nil { - return nil, nil, errors.New("retry backoff parameters for authorization webhook has not been specified") - } - clientConfig, err := webhookutil.LoadKubeconfig(*configuredAuthorizer.Webhook.ConnectionInfo.KubeConfigFile, r.initialConfig.CustomDial) - if err != nil { - return nil, nil, err - } - var decisionOnError authorizer.Decision - switch configuredAuthorizer.Webhook.FailurePolicy { - case authzconfig.FailurePolicyNoOpinion: - decisionOnError = authorizer.DecisionNoOpinion - case authzconfig.FailurePolicyDeny: - decisionOnError = authorizer.DecisionDeny - default: - return nil, nil, fmt.Errorf("unknown failurePolicy %q", configuredAuthorizer.Webhook.FailurePolicy) - } - webhookAuthorizer, err := webhook.New(clientConfig, - configuredAuthorizer.Webhook.SubjectAccessReviewVersion, - configuredAuthorizer.Webhook.AuthorizedTTL.Duration, - configuredAuthorizer.Webhook.UnauthorizedTTL.Duration, - *r.initialConfig.WebhookRetryBackoff, - decisionOnError, - configuredAuthorizer.Webhook.MatchConditions, - ) - if err != nil { - return nil, nil, err - } - authorizers = append(authorizers, webhookAuthorizer) - ruleResolvers = append(ruleResolvers, webhookAuthorizer) - case authzconfig.AuthorizerType(modes.ModeRBAC): - if r.rbacAuthorizer == nil { - return nil, nil, fmt.Errorf("nil rbacAuthorizer") - } - authorizers = append(authorizers, r.rbacAuthorizer) - ruleResolvers = append(ruleResolvers, r.rbacAuthorizer) - default: - return nil, nil, fmt.Errorf("unknown authorization mode %s specified", configuredAuthorizer.Type) - } - } - - return union.New(authorizers...), union.NewRuleResolvers(ruleResolvers...), nil -} - // RepeatableAuthorizerTypes is the list of Authorizer that can be repeated in the Authorization Config var repeatableAuthorizerTypes = []string{modes.ModeWebhook} diff --git a/pkg/kubeapiserver/authorizer/reload.go b/pkg/kubeapiserver/authorizer/reload.go index 3b0faf90882..f18bffb10a4 100644 --- a/pkg/kubeapiserver/authorizer/reload.go +++ b/pkg/kubeapiserver/authorizer/reload.go @@ -18,11 +18,19 @@ package authorizer import ( "context" + "errors" + "fmt" "sync/atomic" + authzconfig "k8s.io/apiserver/pkg/apis/apiserver" "k8s.io/apiserver/pkg/authentication/user" "k8s.io/apiserver/pkg/authorization/authorizer" + "k8s.io/apiserver/pkg/authorization/authorizerfactory" + "k8s.io/apiserver/pkg/authorization/union" + webhookutil "k8s.io/apiserver/pkg/util/webhook" + "k8s.io/apiserver/plugin/pkg/authorizer/webhook" "k8s.io/kubernetes/pkg/auth/authorizer/abac" + "k8s.io/kubernetes/pkg/kubeapiserver/authorizer/modes" "k8s.io/kubernetes/plugin/pkg/auth/authorizer/node" "k8s.io/kubernetes/plugin/pkg/auth/authorizer/rbac" ) @@ -52,3 +60,85 @@ func (r *reloadableAuthorizerResolver) Authorize(ctx context.Context, a authoriz func (r *reloadableAuthorizerResolver) RulesFor(user user.Info, namespace string) ([]authorizer.ResourceRuleInfo, []authorizer.NonResourceRuleInfo, bool, error) { return r.current.Load().ruleResolver.RulesFor(user, namespace) } + +// newForConfig constructs +func (r *reloadableAuthorizerResolver) newForConfig(authzConfig *authzconfig.AuthorizationConfiguration) (authorizer.Authorizer, authorizer.RuleResolver, error) { + if len(authzConfig.Authorizers) == 0 { + return nil, nil, fmt.Errorf("at least one authorization mode must be passed") + } + + var ( + authorizers []authorizer.Authorizer + ruleResolvers []authorizer.RuleResolver + ) + + // Add SystemPrivilegedGroup as an authorizing group + superuserAuthorizer := authorizerfactory.NewPrivilegedGroups(user.SystemPrivilegedGroup) + authorizers = append(authorizers, superuserAuthorizer) + + for _, configuredAuthorizer := range authzConfig.Authorizers { + // Keep cases in sync with constant list in k8s.io/kubernetes/pkg/kubeapiserver/authorizer/modes/modes.go. + switch configuredAuthorizer.Type { + case authzconfig.AuthorizerType(modes.ModeNode): + if r.nodeAuthorizer == nil { + return nil, nil, fmt.Errorf("authorizer type Node is not allowed if it was not enabled at initial server startup") + } + authorizers = append(authorizers, r.nodeAuthorizer) + ruleResolvers = append(ruleResolvers, r.nodeAuthorizer) + case authzconfig.AuthorizerType(modes.ModeAlwaysAllow): + alwaysAllowAuthorizer := authorizerfactory.NewAlwaysAllowAuthorizer() + authorizers = append(authorizers, alwaysAllowAuthorizer) + ruleResolvers = append(ruleResolvers, alwaysAllowAuthorizer) + case authzconfig.AuthorizerType(modes.ModeAlwaysDeny): + alwaysDenyAuthorizer := authorizerfactory.NewAlwaysDenyAuthorizer() + authorizers = append(authorizers, alwaysDenyAuthorizer) + ruleResolvers = append(ruleResolvers, alwaysDenyAuthorizer) + case authzconfig.AuthorizerType(modes.ModeABAC): + if r.abacAuthorizer == nil { + return nil, nil, fmt.Errorf("authorizer type ABAC is not allowed if it was not enabled at initial server startup") + } + authorizers = append(authorizers, r.abacAuthorizer) + ruleResolvers = append(ruleResolvers, r.abacAuthorizer) + case authzconfig.AuthorizerType(modes.ModeWebhook): + if r.initialConfig.WebhookRetryBackoff == nil { + return nil, nil, errors.New("retry backoff parameters for authorization webhook has not been specified") + } + clientConfig, err := webhookutil.LoadKubeconfig(*configuredAuthorizer.Webhook.ConnectionInfo.KubeConfigFile, r.initialConfig.CustomDial) + if err != nil { + return nil, nil, err + } + var decisionOnError authorizer.Decision + switch configuredAuthorizer.Webhook.FailurePolicy { + case authzconfig.FailurePolicyNoOpinion: + decisionOnError = authorizer.DecisionNoOpinion + case authzconfig.FailurePolicyDeny: + decisionOnError = authorizer.DecisionDeny + default: + return nil, nil, fmt.Errorf("unknown failurePolicy %q", configuredAuthorizer.Webhook.FailurePolicy) + } + webhookAuthorizer, err := webhook.New(clientConfig, + configuredAuthorizer.Webhook.SubjectAccessReviewVersion, + configuredAuthorizer.Webhook.AuthorizedTTL.Duration, + configuredAuthorizer.Webhook.UnauthorizedTTL.Duration, + *r.initialConfig.WebhookRetryBackoff, + decisionOnError, + configuredAuthorizer.Webhook.MatchConditions, + ) + if err != nil { + return nil, nil, err + } + authorizers = append(authorizers, webhookAuthorizer) + ruleResolvers = append(ruleResolvers, webhookAuthorizer) + case authzconfig.AuthorizerType(modes.ModeRBAC): + if r.rbacAuthorizer == nil { + return nil, nil, fmt.Errorf("authorizer type RBAC is not allowed if it was not enabled at initial server startup") + } + authorizers = append(authorizers, r.rbacAuthorizer) + ruleResolvers = append(ruleResolvers, r.rbacAuthorizer) + default: + return nil, nil, fmt.Errorf("unknown authorization mode %s specified", configuredAuthorizer.Type) + } + } + + return union.New(authorizers...), union.NewRuleResolvers(ruleResolvers...), nil +}