Move kube-apiserver authz validation functions
This commit is contained in:
		@@ -19,10 +19,15 @@ package authorizer
 | 
			
		||||
import (
 | 
			
		||||
	"errors"
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"strings"
 | 
			
		||||
 | 
			
		||||
	utilerrors "k8s.io/apimachinery/pkg/util/errors"
 | 
			
		||||
	utilnet "k8s.io/apimachinery/pkg/util/net"
 | 
			
		||||
	"k8s.io/apimachinery/pkg/util/sets"
 | 
			
		||||
	"k8s.io/apimachinery/pkg/util/wait"
 | 
			
		||||
	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"
 | 
			
		||||
@@ -156,3 +161,56 @@ func (config Config) New() (authorizer.Authorizer, authorizer.RuleResolver, erro
 | 
			
		||||
 | 
			
		||||
	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}
 | 
			
		||||
 | 
			
		||||
// GetNameForAuthorizerMode returns the name to be set for the mode in AuthorizationConfiguration
 | 
			
		||||
// For now, lower cases the mode name
 | 
			
		||||
func GetNameForAuthorizerMode(mode string) string {
 | 
			
		||||
	return strings.ToLower(mode)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func LoadAndValidateFile(configFile string, requireNonWebhookTypes sets.Set[authzconfig.AuthorizerType]) (*authzconfig.AuthorizationConfiguration, error) {
 | 
			
		||||
	// load the file and check for errors
 | 
			
		||||
	authorizationConfiguration, err := load.LoadFromFile(configFile)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, fmt.Errorf("failed to load AuthorizationConfiguration from file: %v", err)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// validate the file and return any error
 | 
			
		||||
	if errors := validation.ValidateAuthorizationConfiguration(nil, authorizationConfiguration,
 | 
			
		||||
		sets.NewString(modes.AuthorizationModeChoices...),
 | 
			
		||||
		sets.NewString(repeatableAuthorizerTypes...),
 | 
			
		||||
	); len(errors) != 0 {
 | 
			
		||||
		return nil, fmt.Errorf(errors.ToAggregate().Error())
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// test to check if the authorizer names passed conform to the authorizers for type!=Webhook
 | 
			
		||||
	// this test is only for kube-apiserver and hence checked here
 | 
			
		||||
	// it preserves compatibility with o.buildAuthorizationConfiguration
 | 
			
		||||
	var allErrors []error
 | 
			
		||||
	seenModes := sets.New[authzconfig.AuthorizerType]()
 | 
			
		||||
	for _, authorizer := range authorizationConfiguration.Authorizers {
 | 
			
		||||
		if string(authorizer.Type) == modes.ModeWebhook {
 | 
			
		||||
			continue
 | 
			
		||||
		}
 | 
			
		||||
		seenModes.Insert(authorizer.Type)
 | 
			
		||||
 | 
			
		||||
		expectedName := GetNameForAuthorizerMode(string(authorizer.Type))
 | 
			
		||||
		if expectedName != authorizer.Name {
 | 
			
		||||
			allErrors = append(allErrors, fmt.Errorf("expected name %s for authorizer %s instead of %s", expectedName, authorizer.Type, authorizer.Name))
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if missingTypes := requireNonWebhookTypes.Difference(seenModes); missingTypes.Len() > 0 {
 | 
			
		||||
		allErrors = append(allErrors, fmt.Errorf("missing required types: %v", sets.List(missingTypes)))
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if len(allErrors) > 0 {
 | 
			
		||||
		return nil, utilerrors.NewAggregate(allErrors)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return authorizationConfiguration, nil
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -21,7 +21,6 @@ import (
 | 
			
		||||
	"strings"
 | 
			
		||||
	"time"
 | 
			
		||||
 | 
			
		||||
	"k8s.io/apiserver/pkg/apis/apiserver/load"
 | 
			
		||||
	genericfeatures "k8s.io/apiserver/pkg/features"
 | 
			
		||||
	utilfeature "k8s.io/apiserver/pkg/util/feature"
 | 
			
		||||
 | 
			
		||||
@@ -31,7 +30,6 @@ import (
 | 
			
		||||
	"k8s.io/apimachinery/pkg/util/sets"
 | 
			
		||||
	"k8s.io/apimachinery/pkg/util/wait"
 | 
			
		||||
	authzconfig "k8s.io/apiserver/pkg/apis/apiserver"
 | 
			
		||||
	"k8s.io/apiserver/pkg/apis/apiserver/validation"
 | 
			
		||||
	genericoptions "k8s.io/apiserver/pkg/server/options"
 | 
			
		||||
	versionedinformers "k8s.io/client-go/informers"
 | 
			
		||||
 | 
			
		||||
@@ -50,9 +48,6 @@ const (
 | 
			
		||||
	authorizationConfigFlag                 = "authorization-config"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// RepeatableAuthorizerTypes is the list of Authorizer that can be repeated in the Authorization Config
 | 
			
		||||
var repeatableAuthorizerTypes = []string{authzmodes.ModeWebhook}
 | 
			
		||||
 | 
			
		||||
// BuiltInAuthorizationOptions contains all build-in authorization options for API Server
 | 
			
		||||
type BuiltInAuthorizationOptions struct {
 | 
			
		||||
	Modes                       []string
 | 
			
		||||
@@ -118,32 +113,10 @@ func (o *BuiltInAuthorizationOptions) Validate() []error {
 | 
			
		||||
			return append(allErrors, fmt.Errorf("--%s can not be specified when --%s or --authorization-webhook-* flags are defined", authorizationConfigFlag, authorizationModeFlag))
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		// load the file and check for errors
 | 
			
		||||
		config, err := load.LoadFromFile(o.AuthorizationConfigurationFile)
 | 
			
		||||
		// load/validate kube-apiserver authz config with no opinion about required modes
 | 
			
		||||
		_, err := authorizer.LoadAndValidateFile(o.AuthorizationConfigurationFile, nil)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return append(allErrors, fmt.Errorf("failed to load AuthorizationConfiguration from file: %v", err))
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		// validate the file and return any error
 | 
			
		||||
		if errors := validation.ValidateAuthorizationConfiguration(nil, config,
 | 
			
		||||
			sets.NewString(authzmodes.AuthorizationModeChoices...),
 | 
			
		||||
			sets.NewString(repeatableAuthorizerTypes...),
 | 
			
		||||
		); len(errors) != 0 {
 | 
			
		||||
			allErrors = append(allErrors, errors.ToAggregate().Errors()...)
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		// test to check if the authorizer names passed conform to the authorizers for type!=Webhook
 | 
			
		||||
		// this test is only for kube-apiserver and hence checked here
 | 
			
		||||
		// it preserves compatibility with o.buildAuthorizationConfiguration
 | 
			
		||||
		for _, authorizer := range config.Authorizers {
 | 
			
		||||
			if string(authorizer.Type) == authzmodes.ModeWebhook {
 | 
			
		||||
				continue
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			expectedName := getNameForAuthorizerMode(string(authorizer.Type))
 | 
			
		||||
			if expectedName != authorizer.Name {
 | 
			
		||||
				allErrors = append(allErrors, fmt.Errorf("expected name %s for authorizer %s instead of %s", expectedName, authorizer.Type, authorizer.Name))
 | 
			
		||||
			}
 | 
			
		||||
			return append(allErrors, err)
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		return allErrors
 | 
			
		||||
@@ -255,24 +228,14 @@ func (o *BuiltInAuthorizationOptions) ToAuthorizationConfig(versionedInformerFac
 | 
			
		||||
		if !utilfeature.DefaultFeatureGate.Enabled(genericfeatures.StructuredAuthorizationConfiguration) {
 | 
			
		||||
			return nil, fmt.Errorf("--%s cannot be used without enabling StructuredAuthorizationConfiguration feature flag", authorizationConfigFlag)
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		// error out if legacy flags are defined
 | 
			
		||||
		if o.AreLegacyFlagsSet != nil && o.AreLegacyFlagsSet() {
 | 
			
		||||
			return nil, fmt.Errorf("--%s can not be specified when --%s or --authorization-webhook-* flags are defined", authorizationConfigFlag, authorizationModeFlag)
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		// load the file and check for errors
 | 
			
		||||
		authorizationConfiguration, err = load.LoadFromFile(o.AuthorizationConfigurationFile)
 | 
			
		||||
		// load/validate kube-apiserver authz config with no opinion about required modes
 | 
			
		||||
		authorizationConfiguration, err = authorizer.LoadAndValidateFile(o.AuthorizationConfigurationFile, nil)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return nil, fmt.Errorf("failed to load AuthorizationConfiguration from file: %v", err)
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		// validate the file and return any error
 | 
			
		||||
		if errors := validation.ValidateAuthorizationConfiguration(nil, authorizationConfiguration,
 | 
			
		||||
			sets.NewString(authzmodes.AuthorizationModeChoices...),
 | 
			
		||||
			sets.NewString(repeatableAuthorizerTypes...),
 | 
			
		||||
		); len(errors) != 0 {
 | 
			
		||||
			return nil, fmt.Errorf(errors.ToAggregate().Error())
 | 
			
		||||
			return nil, err
 | 
			
		||||
		}
 | 
			
		||||
	} else {
 | 
			
		||||
		authorizationConfiguration, err = o.buildAuthorizationConfiguration()
 | 
			
		||||
@@ -321,16 +284,10 @@ func (o *BuiltInAuthorizationOptions) buildAuthorizationConfiguration() (*authzc
 | 
			
		||||
		default:
 | 
			
		||||
			authorizers = append(authorizers, authzconfig.AuthorizerConfiguration{
 | 
			
		||||
				Type: authzconfig.AuthorizerType(mode),
 | 
			
		||||
				Name: getNameForAuthorizerMode(mode),
 | 
			
		||||
				Name: authorizer.GetNameForAuthorizerMode(mode),
 | 
			
		||||
			})
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return &authzconfig.AuthorizationConfiguration{Authorizers: authorizers}, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// getNameForAuthorizerMode returns the name to be set for the mode in AuthorizationConfiguration
 | 
			
		||||
// For now, lower cases the mode name
 | 
			
		||||
func getNameForAuthorizerMode(mode string) string {
 | 
			
		||||
	return strings.ToLower(mode)
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user