Move authz construction to reloader

This commit is contained in:
Jordan Liggitt 2023-11-07 15:28:42 -06:00
parent 2b00035b5f
commit 3a98e60a71
No known key found for this signature in database
2 changed files with 90 additions and 88 deletions

View File

@ -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}

View File

@ -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
}