Move kube-apiserver authz validation functions
This commit is contained in:
		@@ -19,10 +19,15 @@ package authorizer
 | 
				
			|||||||
import (
 | 
					import (
 | 
				
			||||||
	"errors"
 | 
						"errors"
 | 
				
			||||||
	"fmt"
 | 
						"fmt"
 | 
				
			||||||
 | 
						"strings"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						utilerrors "k8s.io/apimachinery/pkg/util/errors"
 | 
				
			||||||
	utilnet "k8s.io/apimachinery/pkg/util/net"
 | 
						utilnet "k8s.io/apimachinery/pkg/util/net"
 | 
				
			||||||
 | 
						"k8s.io/apimachinery/pkg/util/sets"
 | 
				
			||||||
	"k8s.io/apimachinery/pkg/util/wait"
 | 
						"k8s.io/apimachinery/pkg/util/wait"
 | 
				
			||||||
	authzconfig "k8s.io/apiserver/pkg/apis/apiserver"
 | 
						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/authentication/user"
 | 
				
			||||||
	"k8s.io/apiserver/pkg/authorization/authorizer"
 | 
						"k8s.io/apiserver/pkg/authorization/authorizer"
 | 
				
			||||||
	"k8s.io/apiserver/pkg/authorization/authorizerfactory"
 | 
						"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
 | 
						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"
 | 
						"strings"
 | 
				
			||||||
	"time"
 | 
						"time"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"k8s.io/apiserver/pkg/apis/apiserver/load"
 | 
					 | 
				
			||||||
	genericfeatures "k8s.io/apiserver/pkg/features"
 | 
						genericfeatures "k8s.io/apiserver/pkg/features"
 | 
				
			||||||
	utilfeature "k8s.io/apiserver/pkg/util/feature"
 | 
						utilfeature "k8s.io/apiserver/pkg/util/feature"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -31,7 +30,6 @@ import (
 | 
				
			|||||||
	"k8s.io/apimachinery/pkg/util/sets"
 | 
						"k8s.io/apimachinery/pkg/util/sets"
 | 
				
			||||||
	"k8s.io/apimachinery/pkg/util/wait"
 | 
						"k8s.io/apimachinery/pkg/util/wait"
 | 
				
			||||||
	authzconfig "k8s.io/apiserver/pkg/apis/apiserver"
 | 
						authzconfig "k8s.io/apiserver/pkg/apis/apiserver"
 | 
				
			||||||
	"k8s.io/apiserver/pkg/apis/apiserver/validation"
 | 
					 | 
				
			||||||
	genericoptions "k8s.io/apiserver/pkg/server/options"
 | 
						genericoptions "k8s.io/apiserver/pkg/server/options"
 | 
				
			||||||
	versionedinformers "k8s.io/client-go/informers"
 | 
						versionedinformers "k8s.io/client-go/informers"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -50,9 +48,6 @@ const (
 | 
				
			|||||||
	authorizationConfigFlag                 = "authorization-config"
 | 
						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
 | 
					// BuiltInAuthorizationOptions contains all build-in authorization options for API Server
 | 
				
			||||||
type BuiltInAuthorizationOptions struct {
 | 
					type BuiltInAuthorizationOptions struct {
 | 
				
			||||||
	Modes                       []string
 | 
						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))
 | 
								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
 | 
							// load/validate kube-apiserver authz config with no opinion about required modes
 | 
				
			||||||
		config, err := load.LoadFromFile(o.AuthorizationConfigurationFile)
 | 
							_, err := authorizer.LoadAndValidateFile(o.AuthorizationConfigurationFile, nil)
 | 
				
			||||||
		if err != nil {
 | 
							if err != nil {
 | 
				
			||||||
			return append(allErrors, fmt.Errorf("failed to load AuthorizationConfiguration from file: %v", err))
 | 
								return append(allErrors, 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 allErrors
 | 
							return allErrors
 | 
				
			||||||
@@ -255,24 +228,14 @@ func (o *BuiltInAuthorizationOptions) ToAuthorizationConfig(versionedInformerFac
 | 
				
			|||||||
		if !utilfeature.DefaultFeatureGate.Enabled(genericfeatures.StructuredAuthorizationConfiguration) {
 | 
							if !utilfeature.DefaultFeatureGate.Enabled(genericfeatures.StructuredAuthorizationConfiguration) {
 | 
				
			||||||
			return nil, fmt.Errorf("--%s cannot be used without enabling StructuredAuthorizationConfiguration feature flag", authorizationConfigFlag)
 | 
								return nil, fmt.Errorf("--%s cannot be used without enabling StructuredAuthorizationConfiguration feature flag", authorizationConfigFlag)
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					 | 
				
			||||||
		// error out if legacy flags are defined
 | 
							// error out if legacy flags are defined
 | 
				
			||||||
		if o.AreLegacyFlagsSet != nil && o.AreLegacyFlagsSet() {
 | 
							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)
 | 
								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
 | 
				
			||||||
		// load the file and check for errors
 | 
							authorizationConfiguration, err = authorizer.LoadAndValidateFile(o.AuthorizationConfigurationFile, nil)
 | 
				
			||||||
		authorizationConfiguration, err = load.LoadFromFile(o.AuthorizationConfigurationFile)
 | 
					 | 
				
			||||||
		if err != nil {
 | 
							if err != nil {
 | 
				
			||||||
			return nil, fmt.Errorf("failed to load AuthorizationConfiguration from file: %v", err)
 | 
								return nil, 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())
 | 
					 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	} else {
 | 
						} else {
 | 
				
			||||||
		authorizationConfiguration, err = o.buildAuthorizationConfiguration()
 | 
							authorizationConfiguration, err = o.buildAuthorizationConfiguration()
 | 
				
			||||||
@@ -321,16 +284,10 @@ func (o *BuiltInAuthorizationOptions) buildAuthorizationConfiguration() (*authzc
 | 
				
			|||||||
		default:
 | 
							default:
 | 
				
			||||||
			authorizers = append(authorizers, authzconfig.AuthorizerConfiguration{
 | 
								authorizers = append(authorizers, authzconfig.AuthorizerConfiguration{
 | 
				
			||||||
				Type: authzconfig.AuthorizerType(mode),
 | 
									Type: authzconfig.AuthorizerType(mode),
 | 
				
			||||||
				Name: getNameForAuthorizerMode(mode),
 | 
									Name: authorizer.GetNameForAuthorizerMode(mode),
 | 
				
			||||||
			})
 | 
								})
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return &authzconfig.AuthorizationConfiguration{Authorizers: authorizers}, nil
 | 
						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