Merge pull request #119099 from palnabarun/authz-config
[StructuredAuthorizationConfiguration] Implement API types and wire kube-apiserver to use them
This commit is contained in:
		@@ -174,7 +174,10 @@ func BuildGenericConfig(
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
// BuildAuthorizer constructs the authorizer
 | 
					// BuildAuthorizer constructs the authorizer
 | 
				
			||||||
func BuildAuthorizer(s controlplaneapiserver.CompletedOptions, EgressSelector *egressselector.EgressSelector, versionedInformers clientgoinformers.SharedInformerFactory) (authorizer.Authorizer, authorizer.RuleResolver, error) {
 | 
					func BuildAuthorizer(s controlplaneapiserver.CompletedOptions, EgressSelector *egressselector.EgressSelector, versionedInformers clientgoinformers.SharedInformerFactory) (authorizer.Authorizer, authorizer.RuleResolver, error) {
 | 
				
			||||||
	authorizationConfig := s.Authorization.ToAuthorizationConfig(versionedInformers)
 | 
						authorizationConfig, err := s.Authorization.ToAuthorizationConfig(versionedInformers)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return nil, nil, err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if EgressSelector != nil {
 | 
						if EgressSelector != nil {
 | 
				
			||||||
		egressDialer, err := EgressSelector.Lookup(egressselector.ControlPlane.AsNetworkContext())
 | 
							egressDialer, err := EgressSelector.Lookup(egressselector.ControlPlane.AsNetworkContext())
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -19,10 +19,9 @@ package authorizer
 | 
				
			|||||||
import (
 | 
					import (
 | 
				
			||||||
	"errors"
 | 
						"errors"
 | 
				
			||||||
	"fmt"
 | 
						"fmt"
 | 
				
			||||||
	"time"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	utilnet "k8s.io/apimachinery/pkg/util/net"
 | 
						utilnet "k8s.io/apimachinery/pkg/util/net"
 | 
				
			||||||
	"k8s.io/apimachinery/pkg/util/wait"
 | 
						"k8s.io/apimachinery/pkg/util/wait"
 | 
				
			||||||
 | 
						authzconfig "k8s.io/apiserver/pkg/apis/apiserver"
 | 
				
			||||||
	"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"
 | 
				
			||||||
@@ -40,8 +39,6 @@ import (
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
// Config contains the data on how to authorize a request to the Kube API Server
 | 
					// Config contains the data on how to authorize a request to the Kube API Server
 | 
				
			||||||
type Config struct {
 | 
					type Config struct {
 | 
				
			||||||
	AuthorizationModes []string
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// Options for ModeABAC
 | 
						// Options for ModeABAC
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Path to an ABAC policy file.
 | 
						// Path to an ABAC policy file.
 | 
				
			||||||
@@ -49,14 +46,6 @@ type Config struct {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	// Options for ModeWebhook
 | 
						// Options for ModeWebhook
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Kubeconfig file for Webhook authorization plugin.
 | 
					 | 
				
			||||||
	WebhookConfigFile string
 | 
					 | 
				
			||||||
	// API version of subject access reviews to send to the webhook (e.g. "v1", "v1beta1")
 | 
					 | 
				
			||||||
	WebhookVersion string
 | 
					 | 
				
			||||||
	// TTL for caching of authorized responses from the webhook server.
 | 
					 | 
				
			||||||
	WebhookCacheAuthorizedTTL time.Duration
 | 
					 | 
				
			||||||
	// TTL for caching of unauthorized responses from the webhook server.
 | 
					 | 
				
			||||||
	WebhookCacheUnauthorizedTTL time.Duration
 | 
					 | 
				
			||||||
	// WebhookRetryBackoff specifies the backoff parameters for the authorization webhook retry logic.
 | 
						// WebhookRetryBackoff specifies the backoff parameters for the authorization webhook retry logic.
 | 
				
			||||||
	// This allows us to configure the sleep time at each iteration and the maximum number of retries allowed
 | 
						// This allows us to configure the sleep time at each iteration and the maximum number of retries allowed
 | 
				
			||||||
	// before we fail the webhook call in order to limit the fan out that ensues when the system is degraded.
 | 
						// before we fail the webhook call in order to limit the fan out that ensues when the system is degraded.
 | 
				
			||||||
@@ -66,12 +55,16 @@ type Config struct {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	// Optional field, custom dial function used to connect to webhook
 | 
						// Optional field, custom dial function used to connect to webhook
 | 
				
			||||||
	CustomDial utilnet.DialFunc
 | 
						CustomDial utilnet.DialFunc
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// AuthorizationConfiguration stores the configuration for the Authorizer chain
 | 
				
			||||||
 | 
						// It will deprecate most of the above flags when GA
 | 
				
			||||||
 | 
						AuthorizationConfiguration *authzconfig.AuthorizationConfiguration
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// New returns the right sort of union of multiple authorizer.Authorizer objects
 | 
					// New returns the right sort of union of multiple authorizer.Authorizer objects
 | 
				
			||||||
// based on the authorizationMode or an error.
 | 
					// based on the authorizationMode or an error.
 | 
				
			||||||
func (config Config) New() (authorizer.Authorizer, authorizer.RuleResolver, error) {
 | 
					func (config Config) New() (authorizer.Authorizer, authorizer.RuleResolver, error) {
 | 
				
			||||||
	if len(config.AuthorizationModes) == 0 {
 | 
						if len(config.AuthorizationConfiguration.Authorizers) == 0 {
 | 
				
			||||||
		return nil, nil, fmt.Errorf("at least one authorization mode must be passed")
 | 
							return nil, nil, fmt.Errorf("at least one authorization mode must be passed")
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -84,10 +77,10 @@ func (config Config) New() (authorizer.Authorizer, authorizer.RuleResolver, erro
 | 
				
			|||||||
	superuserAuthorizer := authorizerfactory.NewPrivilegedGroups(user.SystemPrivilegedGroup)
 | 
						superuserAuthorizer := authorizerfactory.NewPrivilegedGroups(user.SystemPrivilegedGroup)
 | 
				
			||||||
	authorizers = append(authorizers, superuserAuthorizer)
 | 
						authorizers = append(authorizers, superuserAuthorizer)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	for _, authorizationMode := range config.AuthorizationModes {
 | 
						for _, configuredAuthorizer := range config.AuthorizationConfiguration.Authorizers {
 | 
				
			||||||
		// Keep cases in sync with constant list in k8s.io/kubernetes/pkg/kubeapiserver/authorizer/modes/modes.go.
 | 
							// Keep cases in sync with constant list in k8s.io/kubernetes/pkg/kubeapiserver/authorizer/modes/modes.go.
 | 
				
			||||||
		switch authorizationMode {
 | 
							switch configuredAuthorizer.Type {
 | 
				
			||||||
		case modes.ModeNode:
 | 
							case authzconfig.AuthorizerType(modes.ModeNode):
 | 
				
			||||||
			node.RegisterMetrics()
 | 
								node.RegisterMetrics()
 | 
				
			||||||
			graph := node.NewGraph()
 | 
								graph := node.NewGraph()
 | 
				
			||||||
			node.AddGraphEventHandlers(
 | 
								node.AddGraphEventHandlers(
 | 
				
			||||||
@@ -101,33 +94,33 @@ func (config Config) New() (authorizer.Authorizer, authorizer.RuleResolver, erro
 | 
				
			|||||||
			authorizers = append(authorizers, nodeAuthorizer)
 | 
								authorizers = append(authorizers, nodeAuthorizer)
 | 
				
			||||||
			ruleResolvers = append(ruleResolvers, nodeAuthorizer)
 | 
								ruleResolvers = append(ruleResolvers, nodeAuthorizer)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		case modes.ModeAlwaysAllow:
 | 
							case authzconfig.AuthorizerType(modes.ModeAlwaysAllow):
 | 
				
			||||||
			alwaysAllowAuthorizer := authorizerfactory.NewAlwaysAllowAuthorizer()
 | 
								alwaysAllowAuthorizer := authorizerfactory.NewAlwaysAllowAuthorizer()
 | 
				
			||||||
			authorizers = append(authorizers, alwaysAllowAuthorizer)
 | 
								authorizers = append(authorizers, alwaysAllowAuthorizer)
 | 
				
			||||||
			ruleResolvers = append(ruleResolvers, alwaysAllowAuthorizer)
 | 
								ruleResolvers = append(ruleResolvers, alwaysAllowAuthorizer)
 | 
				
			||||||
		case modes.ModeAlwaysDeny:
 | 
							case authzconfig.AuthorizerType(modes.ModeAlwaysDeny):
 | 
				
			||||||
			alwaysDenyAuthorizer := authorizerfactory.NewAlwaysDenyAuthorizer()
 | 
								alwaysDenyAuthorizer := authorizerfactory.NewAlwaysDenyAuthorizer()
 | 
				
			||||||
			authorizers = append(authorizers, alwaysDenyAuthorizer)
 | 
								authorizers = append(authorizers, alwaysDenyAuthorizer)
 | 
				
			||||||
			ruleResolvers = append(ruleResolvers, alwaysDenyAuthorizer)
 | 
								ruleResolvers = append(ruleResolvers, alwaysDenyAuthorizer)
 | 
				
			||||||
		case modes.ModeABAC:
 | 
							case authzconfig.AuthorizerType(modes.ModeABAC):
 | 
				
			||||||
			abacAuthorizer, err := abac.NewFromFile(config.PolicyFile)
 | 
								abacAuthorizer, err := abac.NewFromFile(config.PolicyFile)
 | 
				
			||||||
			if err != nil {
 | 
								if err != nil {
 | 
				
			||||||
				return nil, nil, err
 | 
									return nil, nil, err
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			authorizers = append(authorizers, abacAuthorizer)
 | 
								authorizers = append(authorizers, abacAuthorizer)
 | 
				
			||||||
			ruleResolvers = append(ruleResolvers, abacAuthorizer)
 | 
								ruleResolvers = append(ruleResolvers, abacAuthorizer)
 | 
				
			||||||
		case modes.ModeWebhook:
 | 
							case authzconfig.AuthorizerType(modes.ModeWebhook):
 | 
				
			||||||
			if config.WebhookRetryBackoff == nil {
 | 
								if config.WebhookRetryBackoff == nil {
 | 
				
			||||||
				return nil, nil, errors.New("retry backoff parameters for authorization webhook has not been specified")
 | 
									return nil, nil, errors.New("retry backoff parameters for authorization webhook has not been specified")
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			clientConfig, err := webhookutil.LoadKubeconfig(config.WebhookConfigFile, config.CustomDial)
 | 
								clientConfig, err := webhookutil.LoadKubeconfig(*configuredAuthorizer.Webhook.ConnectionInfo.KubeConfigFile, config.CustomDial)
 | 
				
			||||||
			if err != nil {
 | 
								if err != nil {
 | 
				
			||||||
				return nil, nil, err
 | 
									return nil, nil, err
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			webhookAuthorizer, err := webhook.New(clientConfig,
 | 
								webhookAuthorizer, err := webhook.New(clientConfig,
 | 
				
			||||||
				config.WebhookVersion,
 | 
									configuredAuthorizer.Webhook.SubjectAccessReviewVersion,
 | 
				
			||||||
				config.WebhookCacheAuthorizedTTL,
 | 
									configuredAuthorizer.Webhook.AuthorizedTTL.Duration,
 | 
				
			||||||
				config.WebhookCacheUnauthorizedTTL,
 | 
									configuredAuthorizer.Webhook.UnauthorizedTTL.Duration,
 | 
				
			||||||
				*config.WebhookRetryBackoff,
 | 
									*config.WebhookRetryBackoff,
 | 
				
			||||||
			)
 | 
								)
 | 
				
			||||||
			if err != nil {
 | 
								if err != nil {
 | 
				
			||||||
@@ -135,7 +128,7 @@ func (config Config) New() (authorizer.Authorizer, authorizer.RuleResolver, erro
 | 
				
			|||||||
			}
 | 
								}
 | 
				
			||||||
			authorizers = append(authorizers, webhookAuthorizer)
 | 
								authorizers = append(authorizers, webhookAuthorizer)
 | 
				
			||||||
			ruleResolvers = append(ruleResolvers, webhookAuthorizer)
 | 
								ruleResolvers = append(ruleResolvers, webhookAuthorizer)
 | 
				
			||||||
		case modes.ModeRBAC:
 | 
							case authzconfig.AuthorizerType(modes.ModeRBAC):
 | 
				
			||||||
			rbacAuthorizer := rbac.New(
 | 
								rbacAuthorizer := rbac.New(
 | 
				
			||||||
				&rbac.RoleGetter{Lister: config.VersionedInformerFactory.Rbac().V1().Roles().Lister()},
 | 
									&rbac.RoleGetter{Lister: config.VersionedInformerFactory.Rbac().V1().Roles().Lister()},
 | 
				
			||||||
				&rbac.RoleBindingLister{Lister: config.VersionedInformerFactory.Rbac().V1().RoleBindings().Lister()},
 | 
									&rbac.RoleBindingLister{Lister: config.VersionedInformerFactory.Rbac().V1().RoleBindings().Lister()},
 | 
				
			||||||
@@ -145,7 +138,7 @@ func (config Config) New() (authorizer.Authorizer, authorizer.RuleResolver, erro
 | 
				
			|||||||
			authorizers = append(authorizers, rbacAuthorizer)
 | 
								authorizers = append(authorizers, rbacAuthorizer)
 | 
				
			||||||
			ruleResolvers = append(ruleResolvers, rbacAuthorizer)
 | 
								ruleResolvers = append(ruleResolvers, rbacAuthorizer)
 | 
				
			||||||
		default:
 | 
							default:
 | 
				
			||||||
			return nil, nil, fmt.Errorf("unknown authorization mode %s specified", authorizationMode)
 | 
								return nil, nil, fmt.Errorf("unknown authorization mode %s specified", configuredAuthorizer.Type)
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -23,14 +23,20 @@ import (
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	"github.com/spf13/pflag"
 | 
						"github.com/spf13/pflag"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 | 
				
			||||||
	"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"
 | 
				
			||||||
	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"
 | 
				
			||||||
	"k8s.io/kubernetes/pkg/kubeapiserver/authorizer"
 | 
						"k8s.io/kubernetes/pkg/kubeapiserver/authorizer"
 | 
				
			||||||
	authzmodes "k8s.io/kubernetes/pkg/kubeapiserver/authorizer/modes"
 | 
						authzmodes "k8s.io/kubernetes/pkg/kubeapiserver/authorizer/modes"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const (
 | 
				
			||||||
 | 
						defaultWebhookName = "default"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// 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
 | 
				
			||||||
@@ -62,7 +68,6 @@ func (o *BuiltInAuthorizationOptions) Validate() []error {
 | 
				
			|||||||
		return nil
 | 
							return nil
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	var allErrors []error
 | 
						var allErrors []error
 | 
				
			||||||
 | 
					 | 
				
			||||||
	if len(o.Modes) == 0 {
 | 
						if len(o.Modes) == 0 {
 | 
				
			||||||
		allErrors = append(allErrors, fmt.Errorf("at least one authorization-mode must be passed"))
 | 
							allErrors = append(allErrors, fmt.Errorf("at least one authorization-mode must be passed"))
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
@@ -125,15 +130,54 @@ func (o *BuiltInAuthorizationOptions) AddFlags(fs *pflag.FlagSet) {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// ToAuthorizationConfig convert BuiltInAuthorizationOptions to authorizer.Config
 | 
					// ToAuthorizationConfig convert BuiltInAuthorizationOptions to authorizer.Config
 | 
				
			||||||
func (o *BuiltInAuthorizationOptions) ToAuthorizationConfig(versionedInformerFactory versionedinformers.SharedInformerFactory) authorizer.Config {
 | 
					func (o *BuiltInAuthorizationOptions) ToAuthorizationConfig(versionedInformerFactory versionedinformers.SharedInformerFactory) (authorizer.Config, error) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						authzConfiguration, err := o.buildAuthorizationConfiguration()
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return authorizer.Config{}, fmt.Errorf("failed to build authorization config: %s", err)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return authorizer.Config{
 | 
						return authorizer.Config{
 | 
				
			||||||
		AuthorizationModes:          o.Modes,
 | 
					 | 
				
			||||||
		PolicyFile:               o.PolicyFile,
 | 
							PolicyFile:               o.PolicyFile,
 | 
				
			||||||
		WebhookConfigFile:           o.WebhookConfigFile,
 | 
					 | 
				
			||||||
		WebhookVersion:              o.WebhookVersion,
 | 
					 | 
				
			||||||
		WebhookCacheAuthorizedTTL:   o.WebhookCacheAuthorizedTTL,
 | 
					 | 
				
			||||||
		WebhookCacheUnauthorizedTTL: o.WebhookCacheUnauthorizedTTL,
 | 
					 | 
				
			||||||
		VersionedInformerFactory: versionedInformerFactory,
 | 
							VersionedInformerFactory: versionedInformerFactory,
 | 
				
			||||||
		WebhookRetryBackoff:      o.WebhookRetryBackoff,
 | 
							WebhookRetryBackoff:      o.WebhookRetryBackoff,
 | 
				
			||||||
	}
 | 
					
 | 
				
			||||||
 | 
							AuthorizationConfiguration: authzConfiguration,
 | 
				
			||||||
 | 
						}, nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// buildAuthorizationConfiguration converts existing flags to the AuthorizationConfiguration format
 | 
				
			||||||
 | 
					func (o *BuiltInAuthorizationOptions) buildAuthorizationConfiguration() (*authzconfig.AuthorizationConfiguration, error) {
 | 
				
			||||||
 | 
						var authorizers []authzconfig.AuthorizerConfiguration
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if len(o.Modes) != sets.NewString(o.Modes...).Len() {
 | 
				
			||||||
 | 
							return nil, fmt.Errorf("modes should not be repeated in --authorization-mode")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for _, mode := range o.Modes {
 | 
				
			||||||
 | 
							switch mode {
 | 
				
			||||||
 | 
							case authzmodes.ModeWebhook:
 | 
				
			||||||
 | 
								authorizers = append(authorizers, authzconfig.AuthorizerConfiguration{
 | 
				
			||||||
 | 
									Type: authzconfig.TypeWebhook,
 | 
				
			||||||
 | 
									Webhook: &authzconfig.WebhookConfiguration{
 | 
				
			||||||
 | 
										Name:            defaultWebhookName,
 | 
				
			||||||
 | 
										AuthorizedTTL:   metav1.Duration{Duration: o.WebhookCacheAuthorizedTTL},
 | 
				
			||||||
 | 
										UnauthorizedTTL: metav1.Duration{Duration: o.WebhookCacheUnauthorizedTTL},
 | 
				
			||||||
 | 
										// Timeout and FailurePolicy are required for the new configuration.
 | 
				
			||||||
 | 
										// Setting these two implicitly to preserve backward compatibility.
 | 
				
			||||||
 | 
										Timeout:                    metav1.Duration{Duration: 30 * time.Second},
 | 
				
			||||||
 | 
										FailurePolicy:              authzconfig.FailurePolicyNoOpinion,
 | 
				
			||||||
 | 
										SubjectAccessReviewVersion: o.WebhookVersion,
 | 
				
			||||||
 | 
										ConnectionInfo: authzconfig.WebhookConnectionInfo{
 | 
				
			||||||
 | 
											Type:           authzconfig.AuthorizationWebhookConnectionInfoTypeKubeConfig,
 | 
				
			||||||
 | 
											KubeConfigFile: &o.WebhookConfigFile,
 | 
				
			||||||
 | 
										},
 | 
				
			||||||
 | 
									},
 | 
				
			||||||
 | 
								})
 | 
				
			||||||
 | 
							default:
 | 
				
			||||||
 | 
								authorizers = append(authorizers, authzconfig.AuthorizerConfiguration{Type: authzconfig.AuthorizerType(mode)})
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return &authzconfig.AuthorizationConfiguration{Authorizers: authorizers}, nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -44,6 +44,7 @@ func addKnownTypes(scheme *runtime.Scheme) error {
 | 
				
			|||||||
	scheme.AddKnownTypes(SchemeGroupVersion,
 | 
						scheme.AddKnownTypes(SchemeGroupVersion,
 | 
				
			||||||
		&AdmissionConfiguration{},
 | 
							&AdmissionConfiguration{},
 | 
				
			||||||
		&AuthenticationConfiguration{},
 | 
							&AuthenticationConfiguration{},
 | 
				
			||||||
 | 
							&AuthorizationConfiguration{},
 | 
				
			||||||
		&EgressSelectorConfiguration{},
 | 
							&EgressSelectorConfiguration{},
 | 
				
			||||||
		&TracingConfiguration{},
 | 
							&TracingConfiguration{},
 | 
				
			||||||
	)
 | 
						)
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -198,3 +198,120 @@ type PrefixedClaimOrExpression struct {
 | 
				
			|||||||
	Claim  string
 | 
						Claim  string
 | 
				
			||||||
	Prefix *string
 | 
						Prefix *string
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type AuthorizationConfiguration struct {
 | 
				
			||||||
 | 
						metav1.TypeMeta
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Authorizers is an ordered list of authorizers to
 | 
				
			||||||
 | 
						// authorize requests against.
 | 
				
			||||||
 | 
						// This is similar to the --authorization-modes kube-apiserver flag
 | 
				
			||||||
 | 
						// Must be at least one.
 | 
				
			||||||
 | 
						Authorizers []AuthorizerConfiguration `json:"authorizers"`
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const (
 | 
				
			||||||
 | 
						TypeWebhook                                      AuthorizerType = "Webhook"
 | 
				
			||||||
 | 
						FailurePolicyNoOpinion                           string         = "NoOpinion"
 | 
				
			||||||
 | 
						FailurePolicyDeny                                string         = "Deny"
 | 
				
			||||||
 | 
						AuthorizationWebhookConnectionInfoTypeKubeConfig string         = "KubeConfigFile"
 | 
				
			||||||
 | 
						AuthorizationWebhookConnectionInfoTypeInCluster  string         = "InClusterConfig"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type AuthorizerType string
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type AuthorizerConfiguration struct {
 | 
				
			||||||
 | 
						// Type refers to the type of the authorizer
 | 
				
			||||||
 | 
						// "Webhook" is supported in the generic API server
 | 
				
			||||||
 | 
						// Other API servers may support additional authorizer
 | 
				
			||||||
 | 
						// types like Node, RBAC, ABAC, etc.
 | 
				
			||||||
 | 
						Type AuthorizerType
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Webhook defines the configuration for a Webhook authorizer
 | 
				
			||||||
 | 
						// Must be defined when Type=Webhook
 | 
				
			||||||
 | 
						Webhook *WebhookConfiguration
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type WebhookConfiguration struct {
 | 
				
			||||||
 | 
						// Name used to describe the webhook
 | 
				
			||||||
 | 
						// This is explicitly used in monitoring machinery for metrics
 | 
				
			||||||
 | 
						// Note: Names must be DNS1123 labels like `mywebhookname` or
 | 
				
			||||||
 | 
						//		 subdomains like `webhookname.example.domain`
 | 
				
			||||||
 | 
						// Required, with no default
 | 
				
			||||||
 | 
						Name string
 | 
				
			||||||
 | 
						// The duration to cache 'authorized' responses from the webhook
 | 
				
			||||||
 | 
						// authorizer.
 | 
				
			||||||
 | 
						// Same as setting `--authorization-webhook-cache-authorized-ttl` flag
 | 
				
			||||||
 | 
						// Default: 5m0s
 | 
				
			||||||
 | 
						AuthorizedTTL metav1.Duration
 | 
				
			||||||
 | 
						// The duration to cache 'unauthorized' responses from the webhook
 | 
				
			||||||
 | 
						// authorizer.
 | 
				
			||||||
 | 
						// Same as setting `--authorization-webhook-cache-unauthorized-ttl` flag
 | 
				
			||||||
 | 
						// Default: 30s
 | 
				
			||||||
 | 
						UnauthorizedTTL metav1.Duration
 | 
				
			||||||
 | 
						// Timeout for the webhook request
 | 
				
			||||||
 | 
						// Maximum allowed value is 30s.
 | 
				
			||||||
 | 
						// Required, no default value.
 | 
				
			||||||
 | 
						Timeout metav1.Duration
 | 
				
			||||||
 | 
						// The API version of the authorization.k8s.io SubjectAccessReview to
 | 
				
			||||||
 | 
						// send to and expect from the webhook.
 | 
				
			||||||
 | 
						// Same as setting `--authorization-webhook-version` flag
 | 
				
			||||||
 | 
						// Valid values: v1beta1, v1
 | 
				
			||||||
 | 
						// Required, no default value
 | 
				
			||||||
 | 
						SubjectAccessReviewVersion string
 | 
				
			||||||
 | 
						// MatchConditionSubjectAccessReviewVersion specifies the SubjectAccessReview
 | 
				
			||||||
 | 
						// version the CEL expressions are evaluated against
 | 
				
			||||||
 | 
						// Valid values: v1
 | 
				
			||||||
 | 
						// Required, no default value
 | 
				
			||||||
 | 
						MatchConditionSubjectAccessReviewVersion string
 | 
				
			||||||
 | 
						// Controls the authorization decision when a webhook request fails to
 | 
				
			||||||
 | 
						// complete or returns a malformed response or errors evaluating
 | 
				
			||||||
 | 
						// matchConditions.
 | 
				
			||||||
 | 
						// Valid values:
 | 
				
			||||||
 | 
						//   - NoOpinion: continue to subsequent authorizers to see if one of
 | 
				
			||||||
 | 
						//     them allows the request
 | 
				
			||||||
 | 
						//   - Deny: reject the request without consulting subsequent authorizers
 | 
				
			||||||
 | 
						// Required, with no default.
 | 
				
			||||||
 | 
						FailurePolicy string
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// ConnectionInfo defines how we talk to the webhook
 | 
				
			||||||
 | 
						ConnectionInfo WebhookConnectionInfo
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// matchConditions is a list of conditions that must be met for a request to be sent to this
 | 
				
			||||||
 | 
						// webhook. An empty list of matchConditions matches all requests.
 | 
				
			||||||
 | 
						// There are a maximum of 64 match conditions allowed.
 | 
				
			||||||
 | 
						//
 | 
				
			||||||
 | 
						// The exact matching logic is (in order):
 | 
				
			||||||
 | 
						//   1. If at least one matchCondition evaluates to FALSE, then the webhook is skipped.
 | 
				
			||||||
 | 
						//   2. If ALL matchConditions evaluate to TRUE, then the webhook is called.
 | 
				
			||||||
 | 
						//   3. If at least one matchCondition evaluates to an error (but none are FALSE):
 | 
				
			||||||
 | 
						//      - If failurePolicy=Deny, then the webhook rejects the request
 | 
				
			||||||
 | 
						//      - If failurePolicy=NoOpinion, then the error is ignored and the webhook is skipped
 | 
				
			||||||
 | 
						MatchConditions []WebhookMatchCondition
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type WebhookConnectionInfo struct {
 | 
				
			||||||
 | 
						// Controls how the webhook should communicate with the server.
 | 
				
			||||||
 | 
						// Valid values:
 | 
				
			||||||
 | 
						// - KubeConfig: use the file specified in kubeConfigFile to locate the
 | 
				
			||||||
 | 
						//   server.
 | 
				
			||||||
 | 
						// - InClusterConfig: use the in-cluster configuration to call the
 | 
				
			||||||
 | 
						//   SubjectAccessReview API hosted by kube-apiserver. This mode is not
 | 
				
			||||||
 | 
						//   allowed for kube-apiserver.
 | 
				
			||||||
 | 
						Type string
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Path to KubeConfigFile for connection info
 | 
				
			||||||
 | 
						// Required, if connectionInfo.Type is KubeConfig
 | 
				
			||||||
 | 
						KubeConfigFile *string
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type WebhookMatchCondition struct {
 | 
				
			||||||
 | 
						// expression represents the expression which will be evaluated by CEL. Must evaluate to bool.
 | 
				
			||||||
 | 
						// CEL expressions have access to the contents of the SubjectAccessReview in v1 version.
 | 
				
			||||||
 | 
						// If version specified by subjectAccessReviewVersion in the request variable is v1beta1,
 | 
				
			||||||
 | 
						// the contents would be converted to the v1 version before evaluating the CEL expression.
 | 
				
			||||||
 | 
						//
 | 
				
			||||||
 | 
						// Documentation on CEL: https://kubernetes.io/docs/reference/using-api/cel/
 | 
				
			||||||
 | 
						Expression string
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -0,0 +1,36 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					Copyright 2023 The Kubernetes Authors.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Licensed under the Apache License, Version 2.0 (the "License");
 | 
				
			||||||
 | 
					you may not use this file except in compliance with the License.
 | 
				
			||||||
 | 
					You may obtain a copy of the License at
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    http://www.apache.org/licenses/LICENSE-2.0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Unless required by applicable law or agreed to in writing, software
 | 
				
			||||||
 | 
					distributed under the License is distributed on an "AS IS" BASIS,
 | 
				
			||||||
 | 
					WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
				
			||||||
 | 
					See the License for the specific language governing permissions and
 | 
				
			||||||
 | 
					limitations under the License.
 | 
				
			||||||
 | 
					*/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					package v1alpha1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"time"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						"k8s.io/apimachinery/pkg/runtime"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func addDefaultingFuncs(scheme *runtime.Scheme) error {
 | 
				
			||||||
 | 
						return RegisterDefaults(scheme)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func SetDefaults_WebhookConfiguration(obj *WebhookConfiguration) {
 | 
				
			||||||
 | 
						if obj.AuthorizedTTL.Duration == 0 {
 | 
				
			||||||
 | 
							obj.AuthorizedTTL.Duration = 5 * time.Minute
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if obj.UnauthorizedTTL.Duration == 0 {
 | 
				
			||||||
 | 
							obj.UnauthorizedTTL.Duration = 30 * time.Second
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -43,7 +43,7 @@ func init() {
 | 
				
			|||||||
	// We only register manually written functions here. The registration of the
 | 
						// We only register manually written functions here. The registration of the
 | 
				
			||||||
	// generated functions takes place in the generated files. The separation
 | 
						// generated functions takes place in the generated files. The separation
 | 
				
			||||||
	// makes the code compile even when the generated files are missing.
 | 
						// makes the code compile even when the generated files are missing.
 | 
				
			||||||
	localSchemeBuilder.Register(addKnownTypes)
 | 
						localSchemeBuilder.Register(addKnownTypes, addDefaultingFuncs)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Adds the list of known types to the given scheme.
 | 
					// Adds the list of known types to the given scheme.
 | 
				
			||||||
@@ -54,6 +54,7 @@ func addKnownTypes(scheme *runtime.Scheme) error {
 | 
				
			|||||||
	)
 | 
						)
 | 
				
			||||||
	scheme.AddKnownTypes(ConfigSchemeGroupVersion,
 | 
						scheme.AddKnownTypes(ConfigSchemeGroupVersion,
 | 
				
			||||||
		&AuthenticationConfiguration{},
 | 
							&AuthenticationConfiguration{},
 | 
				
			||||||
 | 
							&AuthorizationConfiguration{},
 | 
				
			||||||
		&TracingConfiguration{},
 | 
							&TracingConfiguration{},
 | 
				
			||||||
	)
 | 
						)
 | 
				
			||||||
	metav1.AddToGroupVersion(scheme, SchemeGroupVersion)
 | 
						metav1.AddToGroupVersion(scheme, SchemeGroupVersion)
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -268,3 +268,121 @@ type PrefixedClaimOrExpression struct {
 | 
				
			|||||||
	// +required
 | 
						// +required
 | 
				
			||||||
	Prefix *string `json:"prefix"`
 | 
						Prefix *string `json:"prefix"`
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type AuthorizationConfiguration struct {
 | 
				
			||||||
 | 
						metav1.TypeMeta
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Authorizers is an ordered list of authorizers to
 | 
				
			||||||
 | 
						// authorize requests against.
 | 
				
			||||||
 | 
						// This is similar to the --authorization-modes kube-apiserver flag
 | 
				
			||||||
 | 
						// Must be at least one.
 | 
				
			||||||
 | 
						Authorizers []AuthorizerConfiguration `json:"authorizers"`
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const (
 | 
				
			||||||
 | 
						TypeWebhook                                      AuthorizerType = "Webhook"
 | 
				
			||||||
 | 
						FailurePolicyNoOpinion                           string         = "NoOpinion"
 | 
				
			||||||
 | 
						FailurePolicyDeny                                string         = "Deny"
 | 
				
			||||||
 | 
						AuthorizationWebhookConnectionInfoTypeKubeConfig string         = "KubeConfigFile"
 | 
				
			||||||
 | 
						AuthorizationWebhookConnectionInfoTypeInCluster  string         = "InClusterConfig"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type AuthorizerType string
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type AuthorizerConfiguration struct {
 | 
				
			||||||
 | 
						// Type refers to the type of the authorizer
 | 
				
			||||||
 | 
						// "Webhook" is supported in the generic API server
 | 
				
			||||||
 | 
						// Other API servers may support additional authorizer
 | 
				
			||||||
 | 
						// types like Node, RBAC, ABAC, etc.
 | 
				
			||||||
 | 
						Type string `json:"type"`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Webhook defines the configuration for a Webhook authorizer
 | 
				
			||||||
 | 
						// Must be defined when Type=Webhook
 | 
				
			||||||
 | 
						// Must not be defined when Type!=Webhook
 | 
				
			||||||
 | 
						Webhook *WebhookConfiguration `json:"webhook,omitempty"`
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type WebhookConfiguration struct {
 | 
				
			||||||
 | 
						// Name used to describe the webhook
 | 
				
			||||||
 | 
						// This is explicitly used in monitoring machinery for metrics
 | 
				
			||||||
 | 
						// Note: Names must be DNS1123 labels like `mywebhookname` or
 | 
				
			||||||
 | 
						//		 subdomains like `webhookname.example.domain`
 | 
				
			||||||
 | 
						// Required, with no default
 | 
				
			||||||
 | 
						Name string `json:"name"`
 | 
				
			||||||
 | 
						// The duration to cache 'authorized' responses from the webhook
 | 
				
			||||||
 | 
						// authorizer.
 | 
				
			||||||
 | 
						// Same as setting `--authorization-webhook-cache-authorized-ttl` flag
 | 
				
			||||||
 | 
						// Default: 5m0s
 | 
				
			||||||
 | 
						AuthorizedTTL metav1.Duration `json:"authorizedTTL"`
 | 
				
			||||||
 | 
						// The duration to cache 'unauthorized' responses from the webhook
 | 
				
			||||||
 | 
						// authorizer.
 | 
				
			||||||
 | 
						// Same as setting `--authorization-webhook-cache-unauthorized-ttl` flag
 | 
				
			||||||
 | 
						// Default: 30s
 | 
				
			||||||
 | 
						UnauthorizedTTL metav1.Duration `json:"unauthorizedTTL"`
 | 
				
			||||||
 | 
						// Timeout for the webhook request
 | 
				
			||||||
 | 
						// Maximum allowed value is 30s.
 | 
				
			||||||
 | 
						// Required, no default value.
 | 
				
			||||||
 | 
						Timeout metav1.Duration `json:"timeout"`
 | 
				
			||||||
 | 
						// The API version of the authorization.k8s.io SubjectAccessReview to
 | 
				
			||||||
 | 
						// send to and expect from the webhook.
 | 
				
			||||||
 | 
						// Same as setting `--authorization-webhook-version` flag
 | 
				
			||||||
 | 
						// Valid values: v1beta1, v1
 | 
				
			||||||
 | 
						// Required, no default value
 | 
				
			||||||
 | 
						SubjectAccessReviewVersion string `json:"subjectAccessReviewVersion"`
 | 
				
			||||||
 | 
						// MatchConditionSubjectAccessReviewVersion specifies the SubjectAccessReview
 | 
				
			||||||
 | 
						// version the CEL expressions are evaluated against
 | 
				
			||||||
 | 
						// Valid values: v1
 | 
				
			||||||
 | 
						// Required, no default value
 | 
				
			||||||
 | 
						MatchConditionSubjectAccessReviewVersion string `json:"matchConditionSubjectAccessReviewVersion"`
 | 
				
			||||||
 | 
						// Controls the authorization decision when a webhook request fails to
 | 
				
			||||||
 | 
						// complete or returns a malformed response or errors evaluating
 | 
				
			||||||
 | 
						// matchConditions.
 | 
				
			||||||
 | 
						// Valid values:
 | 
				
			||||||
 | 
						//   - NoOpinion: continue to subsequent authorizers to see if one of
 | 
				
			||||||
 | 
						//     them allows the request
 | 
				
			||||||
 | 
						//   - Deny: reject the request without consulting subsequent authorizers
 | 
				
			||||||
 | 
						// Required, with no default.
 | 
				
			||||||
 | 
						FailurePolicy string `json:"failurePolicy"`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// ConnectionInfo defines how we talk to the webhook
 | 
				
			||||||
 | 
						ConnectionInfo WebhookConnectionInfo `json:"connectionInfo"`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// matchConditions is a list of conditions that must be met for a request to be sent to this
 | 
				
			||||||
 | 
						// webhook. An empty list of matchConditions matches all requests.
 | 
				
			||||||
 | 
						// There are a maximum of 64 match conditions allowed.
 | 
				
			||||||
 | 
						//
 | 
				
			||||||
 | 
						// The exact matching logic is (in order):
 | 
				
			||||||
 | 
						//   1. If at least one matchCondition evaluates to FALSE, then the webhook is skipped.
 | 
				
			||||||
 | 
						//   2. If ALL matchConditions evaluate to TRUE, then the webhook is called.
 | 
				
			||||||
 | 
						//   3. If at least one matchCondition evaluates to an error (but none are FALSE):
 | 
				
			||||||
 | 
						//      - If failurePolicy=Deny, then the webhook rejects the request
 | 
				
			||||||
 | 
						//      - If failurePolicy=NoOpinion, then the error is ignored and the webhook is skipped
 | 
				
			||||||
 | 
						MatchConditions []WebhookMatchCondition `json:"matchConditions"`
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type WebhookConnectionInfo struct {
 | 
				
			||||||
 | 
						// Controls how the webhook should communicate with the server.
 | 
				
			||||||
 | 
						// Valid values:
 | 
				
			||||||
 | 
						// - KubeConfig: use the file specified in kubeConfigFile to locate the
 | 
				
			||||||
 | 
						//   server.
 | 
				
			||||||
 | 
						// - InClusterConfig: use the in-cluster configuration to call the
 | 
				
			||||||
 | 
						//   SubjectAccessReview API hosted by kube-apiserver. This mode is not
 | 
				
			||||||
 | 
						//   allowed for kube-apiserver.
 | 
				
			||||||
 | 
						Type string `json:"type"`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Path to KubeConfigFile for connection info
 | 
				
			||||||
 | 
						// Required, if connectionInfo.Type is KubeConfig
 | 
				
			||||||
 | 
						KubeConfigFile *string `json:"kubeConfigFile"`
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type WebhookMatchCondition struct {
 | 
				
			||||||
 | 
						// expression represents the expression which will be evaluated by CEL. Must evaluate to bool.
 | 
				
			||||||
 | 
						// CEL expressions have access to the contents of the SubjectAccessReview in v1 version.
 | 
				
			||||||
 | 
						// If version specified by subjectAccessReviewVersion in the request variable is v1beta1,
 | 
				
			||||||
 | 
						// the contents would be converted to the v1 version before evaluating the CEL expression.
 | 
				
			||||||
 | 
						//
 | 
				
			||||||
 | 
						// Documentation on CEL: https://kubernetes.io/docs/reference/using-api/cel/
 | 
				
			||||||
 | 
						Expression string `json:"expression"`
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -66,6 +66,26 @@ func RegisterConversions(s *runtime.Scheme) error {
 | 
				
			|||||||
	}); err != nil {
 | 
						}); err != nil {
 | 
				
			||||||
		return err
 | 
							return err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
						if err := s.AddGeneratedConversionFunc((*AuthorizationConfiguration)(nil), (*apiserver.AuthorizationConfiguration)(nil), func(a, b interface{}, scope conversion.Scope) error {
 | 
				
			||||||
 | 
							return Convert_v1alpha1_AuthorizationConfiguration_To_apiserver_AuthorizationConfiguration(a.(*AuthorizationConfiguration), b.(*apiserver.AuthorizationConfiguration), scope)
 | 
				
			||||||
 | 
						}); err != nil {
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if err := s.AddGeneratedConversionFunc((*apiserver.AuthorizationConfiguration)(nil), (*AuthorizationConfiguration)(nil), func(a, b interface{}, scope conversion.Scope) error {
 | 
				
			||||||
 | 
							return Convert_apiserver_AuthorizationConfiguration_To_v1alpha1_AuthorizationConfiguration(a.(*apiserver.AuthorizationConfiguration), b.(*AuthorizationConfiguration), scope)
 | 
				
			||||||
 | 
						}); err != nil {
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if err := s.AddGeneratedConversionFunc((*AuthorizerConfiguration)(nil), (*apiserver.AuthorizerConfiguration)(nil), func(a, b interface{}, scope conversion.Scope) error {
 | 
				
			||||||
 | 
							return Convert_v1alpha1_AuthorizerConfiguration_To_apiserver_AuthorizerConfiguration(a.(*AuthorizerConfiguration), b.(*apiserver.AuthorizerConfiguration), scope)
 | 
				
			||||||
 | 
						}); err != nil {
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if err := s.AddGeneratedConversionFunc((*apiserver.AuthorizerConfiguration)(nil), (*AuthorizerConfiguration)(nil), func(a, b interface{}, scope conversion.Scope) error {
 | 
				
			||||||
 | 
							return Convert_apiserver_AuthorizerConfiguration_To_v1alpha1_AuthorizerConfiguration(a.(*apiserver.AuthorizerConfiguration), b.(*AuthorizerConfiguration), scope)
 | 
				
			||||||
 | 
						}); err != nil {
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
	if err := s.AddGeneratedConversionFunc((*ClaimMappings)(nil), (*apiserver.ClaimMappings)(nil), func(a, b interface{}, scope conversion.Scope) error {
 | 
						if err := s.AddGeneratedConversionFunc((*ClaimMappings)(nil), (*apiserver.ClaimMappings)(nil), func(a, b interface{}, scope conversion.Scope) error {
 | 
				
			||||||
		return Convert_v1alpha1_ClaimMappings_To_apiserver_ClaimMappings(a.(*ClaimMappings), b.(*apiserver.ClaimMappings), scope)
 | 
							return Convert_v1alpha1_ClaimMappings_To_apiserver_ClaimMappings(a.(*ClaimMappings), b.(*apiserver.ClaimMappings), scope)
 | 
				
			||||||
	}); err != nil {
 | 
						}); err != nil {
 | 
				
			||||||
@@ -191,6 +211,36 @@ func RegisterConversions(s *runtime.Scheme) error {
 | 
				
			|||||||
	}); err != nil {
 | 
						}); err != nil {
 | 
				
			||||||
		return err
 | 
							return err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
						if err := s.AddGeneratedConversionFunc((*WebhookConfiguration)(nil), (*apiserver.WebhookConfiguration)(nil), func(a, b interface{}, scope conversion.Scope) error {
 | 
				
			||||||
 | 
							return Convert_v1alpha1_WebhookConfiguration_To_apiserver_WebhookConfiguration(a.(*WebhookConfiguration), b.(*apiserver.WebhookConfiguration), scope)
 | 
				
			||||||
 | 
						}); err != nil {
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if err := s.AddGeneratedConversionFunc((*apiserver.WebhookConfiguration)(nil), (*WebhookConfiguration)(nil), func(a, b interface{}, scope conversion.Scope) error {
 | 
				
			||||||
 | 
							return Convert_apiserver_WebhookConfiguration_To_v1alpha1_WebhookConfiguration(a.(*apiserver.WebhookConfiguration), b.(*WebhookConfiguration), scope)
 | 
				
			||||||
 | 
						}); err != nil {
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if err := s.AddGeneratedConversionFunc((*WebhookConnectionInfo)(nil), (*apiserver.WebhookConnectionInfo)(nil), func(a, b interface{}, scope conversion.Scope) error {
 | 
				
			||||||
 | 
							return Convert_v1alpha1_WebhookConnectionInfo_To_apiserver_WebhookConnectionInfo(a.(*WebhookConnectionInfo), b.(*apiserver.WebhookConnectionInfo), scope)
 | 
				
			||||||
 | 
						}); err != nil {
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if err := s.AddGeneratedConversionFunc((*apiserver.WebhookConnectionInfo)(nil), (*WebhookConnectionInfo)(nil), func(a, b interface{}, scope conversion.Scope) error {
 | 
				
			||||||
 | 
							return Convert_apiserver_WebhookConnectionInfo_To_v1alpha1_WebhookConnectionInfo(a.(*apiserver.WebhookConnectionInfo), b.(*WebhookConnectionInfo), scope)
 | 
				
			||||||
 | 
						}); err != nil {
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if err := s.AddGeneratedConversionFunc((*WebhookMatchCondition)(nil), (*apiserver.WebhookMatchCondition)(nil), func(a, b interface{}, scope conversion.Scope) error {
 | 
				
			||||||
 | 
							return Convert_v1alpha1_WebhookMatchCondition_To_apiserver_WebhookMatchCondition(a.(*WebhookMatchCondition), b.(*apiserver.WebhookMatchCondition), scope)
 | 
				
			||||||
 | 
						}); err != nil {
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if err := s.AddGeneratedConversionFunc((*apiserver.WebhookMatchCondition)(nil), (*WebhookMatchCondition)(nil), func(a, b interface{}, scope conversion.Scope) error {
 | 
				
			||||||
 | 
							return Convert_apiserver_WebhookMatchCondition_To_v1alpha1_WebhookMatchCondition(a.(*apiserver.WebhookMatchCondition), b.(*WebhookMatchCondition), scope)
 | 
				
			||||||
 | 
						}); err != nil {
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
	if err := s.AddConversionFunc((*EgressSelection)(nil), (*apiserver.EgressSelection)(nil), func(a, b interface{}, scope conversion.Scope) error {
 | 
						if err := s.AddConversionFunc((*EgressSelection)(nil), (*apiserver.EgressSelection)(nil), func(a, b interface{}, scope conversion.Scope) error {
 | 
				
			||||||
		return Convert_v1alpha1_EgressSelection_To_apiserver_EgressSelection(a.(*EgressSelection), b.(*apiserver.EgressSelection), scope)
 | 
							return Convert_v1alpha1_EgressSelection_To_apiserver_EgressSelection(a.(*EgressSelection), b.(*apiserver.EgressSelection), scope)
 | 
				
			||||||
	}); err != nil {
 | 
						}); err != nil {
 | 
				
			||||||
@@ -263,6 +313,48 @@ func Convert_apiserver_AuthenticationConfiguration_To_v1alpha1_AuthenticationCon
 | 
				
			|||||||
	return autoConvert_apiserver_AuthenticationConfiguration_To_v1alpha1_AuthenticationConfiguration(in, out, s)
 | 
						return autoConvert_apiserver_AuthenticationConfiguration_To_v1alpha1_AuthenticationConfiguration(in, out, s)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func autoConvert_v1alpha1_AuthorizationConfiguration_To_apiserver_AuthorizationConfiguration(in *AuthorizationConfiguration, out *apiserver.AuthorizationConfiguration, s conversion.Scope) error {
 | 
				
			||||||
 | 
						out.Authorizers = *(*[]apiserver.AuthorizerConfiguration)(unsafe.Pointer(&in.Authorizers))
 | 
				
			||||||
 | 
						return nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Convert_v1alpha1_AuthorizationConfiguration_To_apiserver_AuthorizationConfiguration is an autogenerated conversion function.
 | 
				
			||||||
 | 
					func Convert_v1alpha1_AuthorizationConfiguration_To_apiserver_AuthorizationConfiguration(in *AuthorizationConfiguration, out *apiserver.AuthorizationConfiguration, s conversion.Scope) error {
 | 
				
			||||||
 | 
						return autoConvert_v1alpha1_AuthorizationConfiguration_To_apiserver_AuthorizationConfiguration(in, out, s)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func autoConvert_apiserver_AuthorizationConfiguration_To_v1alpha1_AuthorizationConfiguration(in *apiserver.AuthorizationConfiguration, out *AuthorizationConfiguration, s conversion.Scope) error {
 | 
				
			||||||
 | 
						out.Authorizers = *(*[]AuthorizerConfiguration)(unsafe.Pointer(&in.Authorizers))
 | 
				
			||||||
 | 
						return nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Convert_apiserver_AuthorizationConfiguration_To_v1alpha1_AuthorizationConfiguration is an autogenerated conversion function.
 | 
				
			||||||
 | 
					func Convert_apiserver_AuthorizationConfiguration_To_v1alpha1_AuthorizationConfiguration(in *apiserver.AuthorizationConfiguration, out *AuthorizationConfiguration, s conversion.Scope) error {
 | 
				
			||||||
 | 
						return autoConvert_apiserver_AuthorizationConfiguration_To_v1alpha1_AuthorizationConfiguration(in, out, s)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func autoConvert_v1alpha1_AuthorizerConfiguration_To_apiserver_AuthorizerConfiguration(in *AuthorizerConfiguration, out *apiserver.AuthorizerConfiguration, s conversion.Scope) error {
 | 
				
			||||||
 | 
						out.Type = apiserver.AuthorizerType(in.Type)
 | 
				
			||||||
 | 
						out.Webhook = (*apiserver.WebhookConfiguration)(unsafe.Pointer(in.Webhook))
 | 
				
			||||||
 | 
						return nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Convert_v1alpha1_AuthorizerConfiguration_To_apiserver_AuthorizerConfiguration is an autogenerated conversion function.
 | 
				
			||||||
 | 
					func Convert_v1alpha1_AuthorizerConfiguration_To_apiserver_AuthorizerConfiguration(in *AuthorizerConfiguration, out *apiserver.AuthorizerConfiguration, s conversion.Scope) error {
 | 
				
			||||||
 | 
						return autoConvert_v1alpha1_AuthorizerConfiguration_To_apiserver_AuthorizerConfiguration(in, out, s)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func autoConvert_apiserver_AuthorizerConfiguration_To_v1alpha1_AuthorizerConfiguration(in *apiserver.AuthorizerConfiguration, out *AuthorizerConfiguration, s conversion.Scope) error {
 | 
				
			||||||
 | 
						out.Type = string(in.Type)
 | 
				
			||||||
 | 
						out.Webhook = (*WebhookConfiguration)(unsafe.Pointer(in.Webhook))
 | 
				
			||||||
 | 
						return nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Convert_apiserver_AuthorizerConfiguration_To_v1alpha1_AuthorizerConfiguration is an autogenerated conversion function.
 | 
				
			||||||
 | 
					func Convert_apiserver_AuthorizerConfiguration_To_v1alpha1_AuthorizerConfiguration(in *apiserver.AuthorizerConfiguration, out *AuthorizerConfiguration, s conversion.Scope) error {
 | 
				
			||||||
 | 
						return autoConvert_apiserver_AuthorizerConfiguration_To_v1alpha1_AuthorizerConfiguration(in, out, s)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func autoConvert_v1alpha1_ClaimMappings_To_apiserver_ClaimMappings(in *ClaimMappings, out *apiserver.ClaimMappings, s conversion.Scope) error {
 | 
					func autoConvert_v1alpha1_ClaimMappings_To_apiserver_ClaimMappings(in *ClaimMappings, out *apiserver.ClaimMappings, s conversion.Scope) error {
 | 
				
			||||||
	if err := Convert_v1alpha1_PrefixedClaimOrExpression_To_apiserver_PrefixedClaimOrExpression(&in.Username, &out.Username, s); err != nil {
 | 
						if err := Convert_v1alpha1_PrefixedClaimOrExpression_To_apiserver_PrefixedClaimOrExpression(&in.Username, &out.Username, s); err != nil {
 | 
				
			||||||
		return err
 | 
							return err
 | 
				
			||||||
@@ -583,3 +675,85 @@ func autoConvert_apiserver_UDSTransport_To_v1alpha1_UDSTransport(in *apiserver.U
 | 
				
			|||||||
func Convert_apiserver_UDSTransport_To_v1alpha1_UDSTransport(in *apiserver.UDSTransport, out *UDSTransport, s conversion.Scope) error {
 | 
					func Convert_apiserver_UDSTransport_To_v1alpha1_UDSTransport(in *apiserver.UDSTransport, out *UDSTransport, s conversion.Scope) error {
 | 
				
			||||||
	return autoConvert_apiserver_UDSTransport_To_v1alpha1_UDSTransport(in, out, s)
 | 
						return autoConvert_apiserver_UDSTransport_To_v1alpha1_UDSTransport(in, out, s)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func autoConvert_v1alpha1_WebhookConfiguration_To_apiserver_WebhookConfiguration(in *WebhookConfiguration, out *apiserver.WebhookConfiguration, s conversion.Scope) error {
 | 
				
			||||||
 | 
						out.Name = in.Name
 | 
				
			||||||
 | 
						out.AuthorizedTTL = in.AuthorizedTTL
 | 
				
			||||||
 | 
						out.UnauthorizedTTL = in.UnauthorizedTTL
 | 
				
			||||||
 | 
						out.Timeout = in.Timeout
 | 
				
			||||||
 | 
						out.SubjectAccessReviewVersion = in.SubjectAccessReviewVersion
 | 
				
			||||||
 | 
						out.MatchConditionSubjectAccessReviewVersion = in.MatchConditionSubjectAccessReviewVersion
 | 
				
			||||||
 | 
						out.FailurePolicy = in.FailurePolicy
 | 
				
			||||||
 | 
						if err := Convert_v1alpha1_WebhookConnectionInfo_To_apiserver_WebhookConnectionInfo(&in.ConnectionInfo, &out.ConnectionInfo, s); err != nil {
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						out.MatchConditions = *(*[]apiserver.WebhookMatchCondition)(unsafe.Pointer(&in.MatchConditions))
 | 
				
			||||||
 | 
						return nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Convert_v1alpha1_WebhookConfiguration_To_apiserver_WebhookConfiguration is an autogenerated conversion function.
 | 
				
			||||||
 | 
					func Convert_v1alpha1_WebhookConfiguration_To_apiserver_WebhookConfiguration(in *WebhookConfiguration, out *apiserver.WebhookConfiguration, s conversion.Scope) error {
 | 
				
			||||||
 | 
						return autoConvert_v1alpha1_WebhookConfiguration_To_apiserver_WebhookConfiguration(in, out, s)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func autoConvert_apiserver_WebhookConfiguration_To_v1alpha1_WebhookConfiguration(in *apiserver.WebhookConfiguration, out *WebhookConfiguration, s conversion.Scope) error {
 | 
				
			||||||
 | 
						out.Name = in.Name
 | 
				
			||||||
 | 
						out.AuthorizedTTL = in.AuthorizedTTL
 | 
				
			||||||
 | 
						out.UnauthorizedTTL = in.UnauthorizedTTL
 | 
				
			||||||
 | 
						out.Timeout = in.Timeout
 | 
				
			||||||
 | 
						out.SubjectAccessReviewVersion = in.SubjectAccessReviewVersion
 | 
				
			||||||
 | 
						out.MatchConditionSubjectAccessReviewVersion = in.MatchConditionSubjectAccessReviewVersion
 | 
				
			||||||
 | 
						out.FailurePolicy = in.FailurePolicy
 | 
				
			||||||
 | 
						if err := Convert_apiserver_WebhookConnectionInfo_To_v1alpha1_WebhookConnectionInfo(&in.ConnectionInfo, &out.ConnectionInfo, s); err != nil {
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						out.MatchConditions = *(*[]WebhookMatchCondition)(unsafe.Pointer(&in.MatchConditions))
 | 
				
			||||||
 | 
						return nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Convert_apiserver_WebhookConfiguration_To_v1alpha1_WebhookConfiguration is an autogenerated conversion function.
 | 
				
			||||||
 | 
					func Convert_apiserver_WebhookConfiguration_To_v1alpha1_WebhookConfiguration(in *apiserver.WebhookConfiguration, out *WebhookConfiguration, s conversion.Scope) error {
 | 
				
			||||||
 | 
						return autoConvert_apiserver_WebhookConfiguration_To_v1alpha1_WebhookConfiguration(in, out, s)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func autoConvert_v1alpha1_WebhookConnectionInfo_To_apiserver_WebhookConnectionInfo(in *WebhookConnectionInfo, out *apiserver.WebhookConnectionInfo, s conversion.Scope) error {
 | 
				
			||||||
 | 
						out.Type = in.Type
 | 
				
			||||||
 | 
						out.KubeConfigFile = (*string)(unsafe.Pointer(in.KubeConfigFile))
 | 
				
			||||||
 | 
						return nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Convert_v1alpha1_WebhookConnectionInfo_To_apiserver_WebhookConnectionInfo is an autogenerated conversion function.
 | 
				
			||||||
 | 
					func Convert_v1alpha1_WebhookConnectionInfo_To_apiserver_WebhookConnectionInfo(in *WebhookConnectionInfo, out *apiserver.WebhookConnectionInfo, s conversion.Scope) error {
 | 
				
			||||||
 | 
						return autoConvert_v1alpha1_WebhookConnectionInfo_To_apiserver_WebhookConnectionInfo(in, out, s)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func autoConvert_apiserver_WebhookConnectionInfo_To_v1alpha1_WebhookConnectionInfo(in *apiserver.WebhookConnectionInfo, out *WebhookConnectionInfo, s conversion.Scope) error {
 | 
				
			||||||
 | 
						out.Type = in.Type
 | 
				
			||||||
 | 
						out.KubeConfigFile = (*string)(unsafe.Pointer(in.KubeConfigFile))
 | 
				
			||||||
 | 
						return nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Convert_apiserver_WebhookConnectionInfo_To_v1alpha1_WebhookConnectionInfo is an autogenerated conversion function.
 | 
				
			||||||
 | 
					func Convert_apiserver_WebhookConnectionInfo_To_v1alpha1_WebhookConnectionInfo(in *apiserver.WebhookConnectionInfo, out *WebhookConnectionInfo, s conversion.Scope) error {
 | 
				
			||||||
 | 
						return autoConvert_apiserver_WebhookConnectionInfo_To_v1alpha1_WebhookConnectionInfo(in, out, s)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func autoConvert_v1alpha1_WebhookMatchCondition_To_apiserver_WebhookMatchCondition(in *WebhookMatchCondition, out *apiserver.WebhookMatchCondition, s conversion.Scope) error {
 | 
				
			||||||
 | 
						out.Expression = in.Expression
 | 
				
			||||||
 | 
						return nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Convert_v1alpha1_WebhookMatchCondition_To_apiserver_WebhookMatchCondition is an autogenerated conversion function.
 | 
				
			||||||
 | 
					func Convert_v1alpha1_WebhookMatchCondition_To_apiserver_WebhookMatchCondition(in *WebhookMatchCondition, out *apiserver.WebhookMatchCondition, s conversion.Scope) error {
 | 
				
			||||||
 | 
						return autoConvert_v1alpha1_WebhookMatchCondition_To_apiserver_WebhookMatchCondition(in, out, s)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func autoConvert_apiserver_WebhookMatchCondition_To_v1alpha1_WebhookMatchCondition(in *apiserver.WebhookMatchCondition, out *WebhookMatchCondition, s conversion.Scope) error {
 | 
				
			||||||
 | 
						out.Expression = in.Expression
 | 
				
			||||||
 | 
						return nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Convert_apiserver_WebhookMatchCondition_To_v1alpha1_WebhookMatchCondition is an autogenerated conversion function.
 | 
				
			||||||
 | 
					func Convert_apiserver_WebhookMatchCondition_To_v1alpha1_WebhookMatchCondition(in *apiserver.WebhookMatchCondition, out *WebhookMatchCondition, s conversion.Scope) error {
 | 
				
			||||||
 | 
						return autoConvert_apiserver_WebhookMatchCondition_To_v1alpha1_WebhookMatchCondition(in, out, s)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -110,6 +110,59 @@ func (in *AuthenticationConfiguration) DeepCopyObject() runtime.Object {
 | 
				
			|||||||
	return nil
 | 
						return nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
 | 
				
			||||||
 | 
					func (in *AuthorizationConfiguration) DeepCopyInto(out *AuthorizationConfiguration) {
 | 
				
			||||||
 | 
						*out = *in
 | 
				
			||||||
 | 
						out.TypeMeta = in.TypeMeta
 | 
				
			||||||
 | 
						if in.Authorizers != nil {
 | 
				
			||||||
 | 
							in, out := &in.Authorizers, &out.Authorizers
 | 
				
			||||||
 | 
							*out = make([]AuthorizerConfiguration, len(*in))
 | 
				
			||||||
 | 
							for i := range *in {
 | 
				
			||||||
 | 
								(*in)[i].DeepCopyInto(&(*out)[i])
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AuthorizationConfiguration.
 | 
				
			||||||
 | 
					func (in *AuthorizationConfiguration) DeepCopy() *AuthorizationConfiguration {
 | 
				
			||||||
 | 
						if in == nil {
 | 
				
			||||||
 | 
							return nil
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						out := new(AuthorizationConfiguration)
 | 
				
			||||||
 | 
						in.DeepCopyInto(out)
 | 
				
			||||||
 | 
						return out
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
 | 
				
			||||||
 | 
					func (in *AuthorizationConfiguration) DeepCopyObject() runtime.Object {
 | 
				
			||||||
 | 
						if c := in.DeepCopy(); c != nil {
 | 
				
			||||||
 | 
							return c
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
 | 
				
			||||||
 | 
					func (in *AuthorizerConfiguration) DeepCopyInto(out *AuthorizerConfiguration) {
 | 
				
			||||||
 | 
						*out = *in
 | 
				
			||||||
 | 
						if in.Webhook != nil {
 | 
				
			||||||
 | 
							in, out := &in.Webhook, &out.Webhook
 | 
				
			||||||
 | 
							*out = new(WebhookConfiguration)
 | 
				
			||||||
 | 
							(*in).DeepCopyInto(*out)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AuthorizerConfiguration.
 | 
				
			||||||
 | 
					func (in *AuthorizerConfiguration) DeepCopy() *AuthorizerConfiguration {
 | 
				
			||||||
 | 
						if in == nil {
 | 
				
			||||||
 | 
							return nil
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						out := new(AuthorizerConfiguration)
 | 
				
			||||||
 | 
						in.DeepCopyInto(out)
 | 
				
			||||||
 | 
						return out
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
 | 
					// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
 | 
				
			||||||
func (in *ClaimMappings) DeepCopyInto(out *ClaimMappings) {
 | 
					func (in *ClaimMappings) DeepCopyInto(out *ClaimMappings) {
 | 
				
			||||||
	*out = *in
 | 
						*out = *in
 | 
				
			||||||
@@ -383,3 +436,65 @@ func (in *UDSTransport) DeepCopy() *UDSTransport {
 | 
				
			|||||||
	in.DeepCopyInto(out)
 | 
						in.DeepCopyInto(out)
 | 
				
			||||||
	return out
 | 
						return out
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
 | 
				
			||||||
 | 
					func (in *WebhookConfiguration) DeepCopyInto(out *WebhookConfiguration) {
 | 
				
			||||||
 | 
						*out = *in
 | 
				
			||||||
 | 
						out.AuthorizedTTL = in.AuthorizedTTL
 | 
				
			||||||
 | 
						out.UnauthorizedTTL = in.UnauthorizedTTL
 | 
				
			||||||
 | 
						out.Timeout = in.Timeout
 | 
				
			||||||
 | 
						in.ConnectionInfo.DeepCopyInto(&out.ConnectionInfo)
 | 
				
			||||||
 | 
						if in.MatchConditions != nil {
 | 
				
			||||||
 | 
							in, out := &in.MatchConditions, &out.MatchConditions
 | 
				
			||||||
 | 
							*out = make([]WebhookMatchCondition, len(*in))
 | 
				
			||||||
 | 
							copy(*out, *in)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new WebhookConfiguration.
 | 
				
			||||||
 | 
					func (in *WebhookConfiguration) DeepCopy() *WebhookConfiguration {
 | 
				
			||||||
 | 
						if in == nil {
 | 
				
			||||||
 | 
							return nil
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						out := new(WebhookConfiguration)
 | 
				
			||||||
 | 
						in.DeepCopyInto(out)
 | 
				
			||||||
 | 
						return out
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
 | 
				
			||||||
 | 
					func (in *WebhookConnectionInfo) DeepCopyInto(out *WebhookConnectionInfo) {
 | 
				
			||||||
 | 
						*out = *in
 | 
				
			||||||
 | 
						if in.KubeConfigFile != nil {
 | 
				
			||||||
 | 
							in, out := &in.KubeConfigFile, &out.KubeConfigFile
 | 
				
			||||||
 | 
							*out = new(string)
 | 
				
			||||||
 | 
							**out = **in
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new WebhookConnectionInfo.
 | 
				
			||||||
 | 
					func (in *WebhookConnectionInfo) DeepCopy() *WebhookConnectionInfo {
 | 
				
			||||||
 | 
						if in == nil {
 | 
				
			||||||
 | 
							return nil
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						out := new(WebhookConnectionInfo)
 | 
				
			||||||
 | 
						in.DeepCopyInto(out)
 | 
				
			||||||
 | 
						return out
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
 | 
				
			||||||
 | 
					func (in *WebhookMatchCondition) DeepCopyInto(out *WebhookMatchCondition) {
 | 
				
			||||||
 | 
						*out = *in
 | 
				
			||||||
 | 
						return
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new WebhookMatchCondition.
 | 
				
			||||||
 | 
					func (in *WebhookMatchCondition) DeepCopy() *WebhookMatchCondition {
 | 
				
			||||||
 | 
						if in == nil {
 | 
				
			||||||
 | 
							return nil
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						out := new(WebhookMatchCondition)
 | 
				
			||||||
 | 
						in.DeepCopyInto(out)
 | 
				
			||||||
 | 
						return out
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -29,5 +29,15 @@ import (
 | 
				
			|||||||
// Public to allow building arbitrary schemes.
 | 
					// Public to allow building arbitrary schemes.
 | 
				
			||||||
// All generated defaulters are covering - they call all nested defaulters.
 | 
					// All generated defaulters are covering - they call all nested defaulters.
 | 
				
			||||||
func RegisterDefaults(scheme *runtime.Scheme) error {
 | 
					func RegisterDefaults(scheme *runtime.Scheme) error {
 | 
				
			||||||
 | 
						scheme.AddTypeDefaultingFunc(&AuthorizationConfiguration{}, func(obj interface{}) { SetObjectDefaults_AuthorizationConfiguration(obj.(*AuthorizationConfiguration)) })
 | 
				
			||||||
	return nil
 | 
						return nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func SetObjectDefaults_AuthorizationConfiguration(in *AuthorizationConfiguration) {
 | 
				
			||||||
 | 
						for i := range in.Authorizers {
 | 
				
			||||||
 | 
							a := &in.Authorizers[i]
 | 
				
			||||||
 | 
							if a.Webhook != nil {
 | 
				
			||||||
 | 
								SetDefaults_WebhookConfiguration(a.Webhook)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -19,8 +19,16 @@ package validation
 | 
				
			|||||||
import (
 | 
					import (
 | 
				
			||||||
	"fmt"
 | 
						"fmt"
 | 
				
			||||||
	"net/url"
 | 
						"net/url"
 | 
				
			||||||
 | 
						"os"
 | 
				
			||||||
 | 
						"path/filepath"
 | 
				
			||||||
 | 
						"strings"
 | 
				
			||||||
 | 
						"time"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						v1 "k8s.io/api/authorization/v1"
 | 
				
			||||||
 | 
						"k8s.io/api/authorization/v1beta1"
 | 
				
			||||||
 | 
						"k8s.io/apimachinery/pkg/runtime"
 | 
				
			||||||
	"k8s.io/apimachinery/pkg/util/sets"
 | 
						"k8s.io/apimachinery/pkg/util/sets"
 | 
				
			||||||
 | 
						utilvalidation "k8s.io/apimachinery/pkg/util/validation"
 | 
				
			||||||
	"k8s.io/apimachinery/pkg/util/validation/field"
 | 
						"k8s.io/apimachinery/pkg/util/validation/field"
 | 
				
			||||||
	api "k8s.io/apiserver/pkg/apis/apiserver"
 | 
						api "k8s.io/apiserver/pkg/apis/apiserver"
 | 
				
			||||||
	"k8s.io/client-go/util/cert"
 | 
						"k8s.io/client-go/util/cert"
 | 
				
			||||||
@@ -202,3 +210,147 @@ func validateClaimMappings(m api.ClaimMappings, fldPath *field.Path) field.Error
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	return allErrs
 | 
						return allErrs
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// ValidateAuthorizationConfiguration validates a given AuthorizationConfiguration.
 | 
				
			||||||
 | 
					func ValidateAuthorizationConfiguration(fldPath *field.Path, c *api.AuthorizationConfiguration, knownTypes sets.String, repeatableTypes sets.String) field.ErrorList {
 | 
				
			||||||
 | 
						allErrs := field.ErrorList{}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if len(c.Authorizers) == 0 {
 | 
				
			||||||
 | 
							allErrs = append(allErrs, field.Required(fldPath.Child("authorizers"), "at least one authorization mode must be defined"))
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						seenAuthorizerTypes := sets.NewString()
 | 
				
			||||||
 | 
						seenWebhookNames := sets.NewString()
 | 
				
			||||||
 | 
						for i, a := range c.Authorizers {
 | 
				
			||||||
 | 
							fldPath := fldPath.Child("authorizers").Index(i)
 | 
				
			||||||
 | 
							aType := string(a.Type)
 | 
				
			||||||
 | 
							if aType == "" {
 | 
				
			||||||
 | 
								allErrs = append(allErrs, field.Required(fldPath.Child("type"), ""))
 | 
				
			||||||
 | 
								continue
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							if !knownTypes.Has(aType) {
 | 
				
			||||||
 | 
								allErrs = append(allErrs, field.NotSupported(fldPath.Child("type"), aType, knownTypes.List()))
 | 
				
			||||||
 | 
								continue
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							if seenAuthorizerTypes.Has(aType) && !repeatableTypes.Has(aType) {
 | 
				
			||||||
 | 
								allErrs = append(allErrs, field.Duplicate(fldPath.Child("type"), aType))
 | 
				
			||||||
 | 
								continue
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							seenAuthorizerTypes.Insert(aType)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							switch a.Type {
 | 
				
			||||||
 | 
							case api.TypeWebhook:
 | 
				
			||||||
 | 
								if a.Webhook == nil {
 | 
				
			||||||
 | 
									allErrs = append(allErrs, field.Required(fldPath.Child("webhook"), "required when type=Webhook"))
 | 
				
			||||||
 | 
									continue
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								allErrs = append(allErrs, ValidateWebhookConfiguration(fldPath, a.Webhook, seenWebhookNames)...)
 | 
				
			||||||
 | 
							default:
 | 
				
			||||||
 | 
								if a.Webhook != nil {
 | 
				
			||||||
 | 
									allErrs = append(allErrs, field.Invalid(fldPath.Child("webhook"), "non-null", "may only be specified when type=Webhook"))
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return allErrs
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func ValidateWebhookConfiguration(fldPath *field.Path, c *api.WebhookConfiguration, seenNames sets.String) field.ErrorList {
 | 
				
			||||||
 | 
						allErrs := field.ErrorList{}
 | 
				
			||||||
 | 
						if len(c.Name) == 0 {
 | 
				
			||||||
 | 
							allErrs = append(allErrs, field.Required(fldPath.Child("name"), ""))
 | 
				
			||||||
 | 
						} else if seenNames.Has(c.Name) {
 | 
				
			||||||
 | 
							allErrs = append(allErrs, field.Duplicate(fldPath.Child("name"), c.Name))
 | 
				
			||||||
 | 
						} else if errs := utilvalidation.IsDNS1123Subdomain(c.Name); len(errs) != 0 {
 | 
				
			||||||
 | 
							allErrs = append(allErrs, field.Invalid(fldPath.Child("name"), c.Name, fmt.Sprintf("webhook name is invalid: %s", strings.Join(errs, ", "))))
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						seenNames.Insert(c.Name)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if c.Timeout.Duration == 0 {
 | 
				
			||||||
 | 
							allErrs = append(allErrs, field.Required(fldPath.Child("timeout"), ""))
 | 
				
			||||||
 | 
						} else if c.Timeout.Duration > 30*time.Second || c.Timeout.Duration < 0 {
 | 
				
			||||||
 | 
							allErrs = append(allErrs, field.Invalid(fldPath.Child("timeout"), c.Timeout.Duration.String(), "must be > 0s and <= 30s"))
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if c.AuthorizedTTL.Duration == 0 {
 | 
				
			||||||
 | 
							allErrs = append(allErrs, field.Required(fldPath.Child("authorizedTTL"), ""))
 | 
				
			||||||
 | 
						} else if c.AuthorizedTTL.Duration < 0 {
 | 
				
			||||||
 | 
							allErrs = append(allErrs, field.Invalid(fldPath.Child("authorizedTTL"), c.AuthorizedTTL.Duration.String(), "must be > 0s"))
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if c.UnauthorizedTTL.Duration == 0 {
 | 
				
			||||||
 | 
							allErrs = append(allErrs, field.Required(fldPath.Child("unauthorizedTTL"), ""))
 | 
				
			||||||
 | 
						} else if c.UnauthorizedTTL.Duration < 0 {
 | 
				
			||||||
 | 
							allErrs = append(allErrs, field.Invalid(fldPath.Child("unauthorizedTTL"), c.UnauthorizedTTL.Duration.String(), "must be > 0s"))
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						switch c.SubjectAccessReviewVersion {
 | 
				
			||||||
 | 
						case "":
 | 
				
			||||||
 | 
							allErrs = append(allErrs, field.Required(fldPath.Child("subjectAccessReviewVersion"), ""))
 | 
				
			||||||
 | 
						case "v1":
 | 
				
			||||||
 | 
							_ = &v1.SubjectAccessReview{}
 | 
				
			||||||
 | 
						case "v1beta1":
 | 
				
			||||||
 | 
							_ = &v1beta1.SubjectAccessReview{}
 | 
				
			||||||
 | 
						default:
 | 
				
			||||||
 | 
							allErrs = append(allErrs, field.NotSupported(fldPath.Child("subjectAccessReviewVersion"), c.SubjectAccessReviewVersion, []string{"v1", "v1beta1"}))
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						switch c.MatchConditionSubjectAccessReviewVersion {
 | 
				
			||||||
 | 
						case "":
 | 
				
			||||||
 | 
							allErrs = append(allErrs, field.Required(fldPath.Child("matchConditionSubjectAccessReviewVersion"), ""))
 | 
				
			||||||
 | 
						case "v1":
 | 
				
			||||||
 | 
							_ = &v1.SubjectAccessReview{}
 | 
				
			||||||
 | 
						default:
 | 
				
			||||||
 | 
							allErrs = append(allErrs, field.NotSupported(fldPath.Child("matchConditionSubjectAccessReviewVersion"), c.MatchConditionSubjectAccessReviewVersion, []string{"v1"}))
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						switch c.FailurePolicy {
 | 
				
			||||||
 | 
						case "":
 | 
				
			||||||
 | 
							allErrs = append(allErrs, field.Required(fldPath.Child("failurePolicy"), ""))
 | 
				
			||||||
 | 
						case api.FailurePolicyNoOpinion, api.FailurePolicyDeny:
 | 
				
			||||||
 | 
						default:
 | 
				
			||||||
 | 
							allErrs = append(allErrs, field.NotSupported(fldPath.Child("failurePolicy"), c.FailurePolicy, []string{"NoOpinion", "Deny"}))
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						switch c.ConnectionInfo.Type {
 | 
				
			||||||
 | 
						case "":
 | 
				
			||||||
 | 
							allErrs = append(allErrs, field.Required(fldPath.Child("connectionInfo", "type"), ""))
 | 
				
			||||||
 | 
						case api.AuthorizationWebhookConnectionInfoTypeInCluster:
 | 
				
			||||||
 | 
							if c.ConnectionInfo.KubeConfigFile != nil {
 | 
				
			||||||
 | 
								allErrs = append(allErrs, field.Invalid(fldPath.Child("connectionInfo", "kubeConfigFile"), *c.ConnectionInfo.KubeConfigFile, "can only be set when type=KubeConfigFile"))
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						case api.AuthorizationWebhookConnectionInfoTypeKubeConfig:
 | 
				
			||||||
 | 
							if c.ConnectionInfo.KubeConfigFile == nil || *c.ConnectionInfo.KubeConfigFile == "" {
 | 
				
			||||||
 | 
								allErrs = append(allErrs, field.Required(fldPath.Child("connectionInfo", "kubeConfigFile"), ""))
 | 
				
			||||||
 | 
							} else if !filepath.IsAbs(*c.ConnectionInfo.KubeConfigFile) {
 | 
				
			||||||
 | 
								allErrs = append(allErrs, field.Invalid(fldPath.Child("connectionInfo", "kubeConfigFile"), *c.ConnectionInfo.KubeConfigFile, "must be an absolute path"))
 | 
				
			||||||
 | 
							} else if info, err := os.Stat(*c.ConnectionInfo.KubeConfigFile); err != nil {
 | 
				
			||||||
 | 
								allErrs = append(allErrs, field.Invalid(fldPath.Child("connectionInfo", "kubeConfigFile"), *c.ConnectionInfo.KubeConfigFile, fmt.Sprintf("error loading file: %v", err)))
 | 
				
			||||||
 | 
							} else if !info.Mode().IsRegular() {
 | 
				
			||||||
 | 
								allErrs = append(allErrs, field.Invalid(fldPath.Child("connectionInfo", "kubeConfigFile"), *c.ConnectionInfo.KubeConfigFile, "must be a regular file"))
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						default:
 | 
				
			||||||
 | 
							allErrs = append(allErrs, field.NotSupported(fldPath.Child("connectionInfo", "type"), c.ConnectionInfo, []string{"InClusterConfig", "KubeConfigFile"}))
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// TODO: Remove this check and ensure that correct validations below for MatchConditions are added
 | 
				
			||||||
 | 
						// for i, condition := range c.MatchConditions {
 | 
				
			||||||
 | 
						//	 fldPath := fldPath.Child("matchConditions").Index(i).Child("expression")
 | 
				
			||||||
 | 
						//	 if len(strings.TrimSpace(condition.Expression)) == 0 {
 | 
				
			||||||
 | 
						//	     allErrs = append(allErrs, field.Required(fldPath, ""))
 | 
				
			||||||
 | 
						//	 } else {
 | 
				
			||||||
 | 
						//		 allErrs = append(allErrs, ValidateWebhookMatchCondition(fldPath, sampleSAR, condition.Expression)...)
 | 
				
			||||||
 | 
						//	 }
 | 
				
			||||||
 | 
						// }
 | 
				
			||||||
 | 
						if len(c.MatchConditions) != 0 {
 | 
				
			||||||
 | 
							allErrs = append(allErrs, field.NotSupported(fldPath.Child("matchConditions"), c.MatchConditions, []string{}))
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return allErrs
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func ValidateWebhookMatchCondition(fldPath *field.Path, sampleSAR runtime.Object, expression string) field.ErrorList {
 | 
				
			||||||
 | 
						allErrs := field.ErrorList{}
 | 
				
			||||||
 | 
						// TODO: typecheck CEL expression
 | 
				
			||||||
 | 
						return allErrs
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -21,11 +21,15 @@ import (
 | 
				
			|||||||
	"crypto/elliptic"
 | 
						"crypto/elliptic"
 | 
				
			||||||
	"crypto/rand"
 | 
						"crypto/rand"
 | 
				
			||||||
	"encoding/pem"
 | 
						"encoding/pem"
 | 
				
			||||||
 | 
						"os"
 | 
				
			||||||
	"testing"
 | 
						"testing"
 | 
				
			||||||
 | 
						"time"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"github.com/google/go-cmp/cmp"
 | 
						"github.com/google/go-cmp/cmp"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 | 
				
			||||||
	"k8s.io/apimachinery/pkg/util/errors"
 | 
						"k8s.io/apimachinery/pkg/util/errors"
 | 
				
			||||||
 | 
						"k8s.io/apimachinery/pkg/util/sets"
 | 
				
			||||||
	"k8s.io/apimachinery/pkg/util/validation/field"
 | 
						"k8s.io/apimachinery/pkg/util/validation/field"
 | 
				
			||||||
	api "k8s.io/apiserver/pkg/apis/apiserver"
 | 
						api "k8s.io/apiserver/pkg/apis/apiserver"
 | 
				
			||||||
	certutil "k8s.io/client-go/util/cert"
 | 
						certutil "k8s.io/client-go/util/cert"
 | 
				
			||||||
@@ -412,3 +416,832 @@ func errString(errs errors.Aggregate) string {
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
	return ""
 | 
						return ""
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type (
 | 
				
			||||||
 | 
						test struct {
 | 
				
			||||||
 | 
							name            string
 | 
				
			||||||
 | 
							configuration   api.AuthorizationConfiguration
 | 
				
			||||||
 | 
							expectedErrList field.ErrorList
 | 
				
			||||||
 | 
							knownTypes      sets.String
 | 
				
			||||||
 | 
							repeatableTypes sets.String
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func TestValidateAuthorizationConfiguration(t *testing.T) {
 | 
				
			||||||
 | 
						badKubeConfigFile := "../some/relative/path/kubeconfig"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						tempKubeConfigFile, err := os.CreateTemp("/tmp", "kubeconfig")
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							t.Fatalf("failed to set up temp file: %v", err)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						tempKubeConfigFilePath := tempKubeConfigFile.Name()
 | 
				
			||||||
 | 
						defer os.Remove(tempKubeConfigFilePath)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						tests := []test{
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								name: "atleast one authorizer should be defined",
 | 
				
			||||||
 | 
								configuration: api.AuthorizationConfiguration{
 | 
				
			||||||
 | 
									Authorizers: []api.AuthorizerConfiguration{},
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
								expectedErrList: field.ErrorList{field.Required(field.NewPath("authorizers"), "at least one authorization mode must be defined")},
 | 
				
			||||||
 | 
								knownTypes:      sets.NewString(),
 | 
				
			||||||
 | 
								repeatableTypes: sets.NewString(),
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								name: "type is required if an authorizer is defined",
 | 
				
			||||||
 | 
								configuration: api.AuthorizationConfiguration{
 | 
				
			||||||
 | 
									Authorizers: []api.AuthorizerConfiguration{
 | 
				
			||||||
 | 
										{},
 | 
				
			||||||
 | 
									},
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
								expectedErrList: field.ErrorList{field.Required(field.NewPath("type"), "")},
 | 
				
			||||||
 | 
								knownTypes:      sets.NewString(string("Webhook")),
 | 
				
			||||||
 | 
								repeatableTypes: sets.NewString(string("Webhook")),
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								name: "bare minimum configuration with Webhook",
 | 
				
			||||||
 | 
								configuration: api.AuthorizationConfiguration{
 | 
				
			||||||
 | 
									Authorizers: []api.AuthorizerConfiguration{
 | 
				
			||||||
 | 
										{
 | 
				
			||||||
 | 
											Type: "Webhook",
 | 
				
			||||||
 | 
											Webhook: &api.WebhookConfiguration{
 | 
				
			||||||
 | 
												Name:                                     "default",
 | 
				
			||||||
 | 
												Timeout:                                  metav1.Duration{Duration: 5 * time.Second},
 | 
				
			||||||
 | 
												AuthorizedTTL:                            metav1.Duration{Duration: 5 * time.Minute},
 | 
				
			||||||
 | 
												UnauthorizedTTL:                          metav1.Duration{Duration: 30 * time.Second},
 | 
				
			||||||
 | 
												FailurePolicy:                            "NoOpinion",
 | 
				
			||||||
 | 
												SubjectAccessReviewVersion:               "v1",
 | 
				
			||||||
 | 
												MatchConditionSubjectAccessReviewVersion: "v1",
 | 
				
			||||||
 | 
												ConnectionInfo: api.WebhookConnectionInfo{
 | 
				
			||||||
 | 
													Type: "InClusterConfig",
 | 
				
			||||||
 | 
												},
 | 
				
			||||||
 | 
											},
 | 
				
			||||||
 | 
										},
 | 
				
			||||||
 | 
									},
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
								expectedErrList: field.ErrorList{},
 | 
				
			||||||
 | 
								knownTypes:      sets.NewString(string("Webhook")),
 | 
				
			||||||
 | 
								repeatableTypes: sets.NewString(string("Webhook")),
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								name: "bare minimum configuration with multiple webhooks",
 | 
				
			||||||
 | 
								configuration: api.AuthorizationConfiguration{
 | 
				
			||||||
 | 
									Authorizers: []api.AuthorizerConfiguration{
 | 
				
			||||||
 | 
										{
 | 
				
			||||||
 | 
											Type: "Webhook",
 | 
				
			||||||
 | 
											Webhook: &api.WebhookConfiguration{
 | 
				
			||||||
 | 
												Name:                                     "default",
 | 
				
			||||||
 | 
												Timeout:                                  metav1.Duration{Duration: 5 * time.Second},
 | 
				
			||||||
 | 
												AuthorizedTTL:                            metav1.Duration{Duration: 5 * time.Minute},
 | 
				
			||||||
 | 
												UnauthorizedTTL:                          metav1.Duration{Duration: 30 * time.Second},
 | 
				
			||||||
 | 
												FailurePolicy:                            "NoOpinion",
 | 
				
			||||||
 | 
												SubjectAccessReviewVersion:               "v1",
 | 
				
			||||||
 | 
												MatchConditionSubjectAccessReviewVersion: "v1",
 | 
				
			||||||
 | 
												ConnectionInfo: api.WebhookConnectionInfo{
 | 
				
			||||||
 | 
													Type: "InClusterConfig",
 | 
				
			||||||
 | 
												},
 | 
				
			||||||
 | 
											},
 | 
				
			||||||
 | 
										},
 | 
				
			||||||
 | 
										{
 | 
				
			||||||
 | 
											Type: "Webhook",
 | 
				
			||||||
 | 
											Webhook: &api.WebhookConfiguration{
 | 
				
			||||||
 | 
												Name:                                     "second-webhook",
 | 
				
			||||||
 | 
												Timeout:                                  metav1.Duration{Duration: 5 * time.Second},
 | 
				
			||||||
 | 
												AuthorizedTTL:                            metav1.Duration{Duration: 5 * time.Minute},
 | 
				
			||||||
 | 
												UnauthorizedTTL:                          metav1.Duration{Duration: 30 * time.Second},
 | 
				
			||||||
 | 
												FailurePolicy:                            "NoOpinion",
 | 
				
			||||||
 | 
												SubjectAccessReviewVersion:               "v1",
 | 
				
			||||||
 | 
												MatchConditionSubjectAccessReviewVersion: "v1",
 | 
				
			||||||
 | 
												ConnectionInfo: api.WebhookConnectionInfo{
 | 
				
			||||||
 | 
													Type: "InClusterConfig",
 | 
				
			||||||
 | 
												},
 | 
				
			||||||
 | 
											},
 | 
				
			||||||
 | 
										},
 | 
				
			||||||
 | 
									},
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
								expectedErrList: field.ErrorList{},
 | 
				
			||||||
 | 
								knownTypes:      sets.NewString(string("Webhook")),
 | 
				
			||||||
 | 
								repeatableTypes: sets.NewString(string("Webhook")),
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								name: "configuration with unknown types",
 | 
				
			||||||
 | 
								configuration: api.AuthorizationConfiguration{
 | 
				
			||||||
 | 
									Authorizers: []api.AuthorizerConfiguration{
 | 
				
			||||||
 | 
										{
 | 
				
			||||||
 | 
											Type: "Foo",
 | 
				
			||||||
 | 
										},
 | 
				
			||||||
 | 
									},
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
								expectedErrList: field.ErrorList{field.NotSupported(field.NewPath("type"), "Foo", []string{"..."})},
 | 
				
			||||||
 | 
								knownTypes:      sets.NewString(string("Webhook")),
 | 
				
			||||||
 | 
								repeatableTypes: sets.NewString(string("Webhook")),
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								name: "configuration with not repeatable types",
 | 
				
			||||||
 | 
								configuration: api.AuthorizationConfiguration{
 | 
				
			||||||
 | 
									Authorizers: []api.AuthorizerConfiguration{
 | 
				
			||||||
 | 
										{
 | 
				
			||||||
 | 
											Type: "Foo",
 | 
				
			||||||
 | 
										},
 | 
				
			||||||
 | 
										{
 | 
				
			||||||
 | 
											Type: "Foo",
 | 
				
			||||||
 | 
										},
 | 
				
			||||||
 | 
									},
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
								expectedErrList: field.ErrorList{field.Duplicate(field.NewPath("type"), "Foo")},
 | 
				
			||||||
 | 
								knownTypes:      sets.NewString([]string{string("Foo"), string("Webhook")}...),
 | 
				
			||||||
 | 
								repeatableTypes: sets.NewString(string("Webhook")),
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								name: "when type=Webhook, webhook needs to be defined",
 | 
				
			||||||
 | 
								configuration: api.AuthorizationConfiguration{
 | 
				
			||||||
 | 
									Authorizers: []api.AuthorizerConfiguration{
 | 
				
			||||||
 | 
										{
 | 
				
			||||||
 | 
											Type: "Webhook",
 | 
				
			||||||
 | 
										},
 | 
				
			||||||
 | 
									},
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
								expectedErrList: field.ErrorList{field.Required(field.NewPath("webhook"), "required when type=Webhook")},
 | 
				
			||||||
 | 
								knownTypes:      sets.NewString(string("Webhook")),
 | 
				
			||||||
 | 
								repeatableTypes: sets.NewString(string("Webhook")),
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								name: "when type!=Webhook, webhooks needs to be nil",
 | 
				
			||||||
 | 
								configuration: api.AuthorizationConfiguration{
 | 
				
			||||||
 | 
									Authorizers: []api.AuthorizerConfiguration{
 | 
				
			||||||
 | 
										{
 | 
				
			||||||
 | 
											Type:    "Foo",
 | 
				
			||||||
 | 
											Webhook: &api.WebhookConfiguration{},
 | 
				
			||||||
 | 
										},
 | 
				
			||||||
 | 
									},
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
								expectedErrList: field.ErrorList{field.Invalid(field.NewPath("webhook"), "non-null", "may only be specified when type=Webhook")},
 | 
				
			||||||
 | 
								knownTypes:      sets.NewString(string("Foo")),
 | 
				
			||||||
 | 
								repeatableTypes: sets.NewString(string("Webhook")),
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								name: "webhook name should be of non-zero length",
 | 
				
			||||||
 | 
								configuration: api.AuthorizationConfiguration{
 | 
				
			||||||
 | 
									Authorizers: []api.AuthorizerConfiguration{
 | 
				
			||||||
 | 
										{
 | 
				
			||||||
 | 
											Type: "Webhook",
 | 
				
			||||||
 | 
											Webhook: &api.WebhookConfiguration{
 | 
				
			||||||
 | 
												Name:                                     "",
 | 
				
			||||||
 | 
												Timeout:                                  metav1.Duration{Duration: 5 * time.Second},
 | 
				
			||||||
 | 
												AuthorizedTTL:                            metav1.Duration{Duration: 5 * time.Minute},
 | 
				
			||||||
 | 
												UnauthorizedTTL:                          metav1.Duration{Duration: 30 * time.Second},
 | 
				
			||||||
 | 
												FailurePolicy:                            "NoOpinion",
 | 
				
			||||||
 | 
												SubjectAccessReviewVersion:               "v1",
 | 
				
			||||||
 | 
												MatchConditionSubjectAccessReviewVersion: "v1",
 | 
				
			||||||
 | 
												ConnectionInfo: api.WebhookConnectionInfo{
 | 
				
			||||||
 | 
													Type: "InClusterConfig",
 | 
				
			||||||
 | 
												},
 | 
				
			||||||
 | 
											},
 | 
				
			||||||
 | 
										},
 | 
				
			||||||
 | 
									},
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
								expectedErrList: field.ErrorList{field.Required(field.NewPath("name"), "")},
 | 
				
			||||||
 | 
								knownTypes:      sets.NewString(string("Webhook")),
 | 
				
			||||||
 | 
								repeatableTypes: sets.NewString(string("Webhook")),
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								name: "webhook names should be unique",
 | 
				
			||||||
 | 
								configuration: api.AuthorizationConfiguration{
 | 
				
			||||||
 | 
									Authorizers: []api.AuthorizerConfiguration{
 | 
				
			||||||
 | 
										{
 | 
				
			||||||
 | 
											Type: "Webhook",
 | 
				
			||||||
 | 
											Webhook: &api.WebhookConfiguration{
 | 
				
			||||||
 | 
												Name:                                     "name-1",
 | 
				
			||||||
 | 
												Timeout:                                  metav1.Duration{Duration: 5 * time.Second},
 | 
				
			||||||
 | 
												AuthorizedTTL:                            metav1.Duration{Duration: 5 * time.Minute},
 | 
				
			||||||
 | 
												UnauthorizedTTL:                          metav1.Duration{Duration: 30 * time.Second},
 | 
				
			||||||
 | 
												FailurePolicy:                            "NoOpinion",
 | 
				
			||||||
 | 
												SubjectAccessReviewVersion:               "v1",
 | 
				
			||||||
 | 
												MatchConditionSubjectAccessReviewVersion: "v1",
 | 
				
			||||||
 | 
												ConnectionInfo: api.WebhookConnectionInfo{
 | 
				
			||||||
 | 
													Type: "InClusterConfig",
 | 
				
			||||||
 | 
												},
 | 
				
			||||||
 | 
											},
 | 
				
			||||||
 | 
										},
 | 
				
			||||||
 | 
										{
 | 
				
			||||||
 | 
											Type: "Webhook",
 | 
				
			||||||
 | 
											Webhook: &api.WebhookConfiguration{
 | 
				
			||||||
 | 
												Name:                                     "name-1",
 | 
				
			||||||
 | 
												Timeout:                                  metav1.Duration{Duration: 5 * time.Second},
 | 
				
			||||||
 | 
												AuthorizedTTL:                            metav1.Duration{Duration: 5 * time.Minute},
 | 
				
			||||||
 | 
												UnauthorizedTTL:                          metav1.Duration{Duration: 30 * time.Second},
 | 
				
			||||||
 | 
												FailurePolicy:                            "NoOpinion",
 | 
				
			||||||
 | 
												SubjectAccessReviewVersion:               "v1",
 | 
				
			||||||
 | 
												MatchConditionSubjectAccessReviewVersion: "v1",
 | 
				
			||||||
 | 
												ConnectionInfo: api.WebhookConnectionInfo{
 | 
				
			||||||
 | 
													Type: "InClusterConfig",
 | 
				
			||||||
 | 
												},
 | 
				
			||||||
 | 
											},
 | 
				
			||||||
 | 
										},
 | 
				
			||||||
 | 
									},
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
								expectedErrList: field.ErrorList{field.Duplicate(field.NewPath("name"), "name-1")},
 | 
				
			||||||
 | 
								knownTypes:      sets.NewString(string("Webhook")),
 | 
				
			||||||
 | 
								repeatableTypes: sets.NewString(string("Webhook")),
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								name: "webhook names should be DNS1123 labels",
 | 
				
			||||||
 | 
								configuration: api.AuthorizationConfiguration{
 | 
				
			||||||
 | 
									Authorizers: []api.AuthorizerConfiguration{
 | 
				
			||||||
 | 
										{
 | 
				
			||||||
 | 
											Type: "Webhook",
 | 
				
			||||||
 | 
											Webhook: &api.WebhookConfiguration{
 | 
				
			||||||
 | 
												Name:                                     "mywebhookname",
 | 
				
			||||||
 | 
												Timeout:                                  metav1.Duration{Duration: 5 * time.Second},
 | 
				
			||||||
 | 
												AuthorizedTTL:                            metav1.Duration{Duration: 5 * time.Minute},
 | 
				
			||||||
 | 
												UnauthorizedTTL:                          metav1.Duration{Duration: 30 * time.Second},
 | 
				
			||||||
 | 
												FailurePolicy:                            "NoOpinion",
 | 
				
			||||||
 | 
												SubjectAccessReviewVersion:               "v1",
 | 
				
			||||||
 | 
												MatchConditionSubjectAccessReviewVersion: "v1",
 | 
				
			||||||
 | 
												ConnectionInfo: api.WebhookConnectionInfo{
 | 
				
			||||||
 | 
													Type: "InClusterConfig",
 | 
				
			||||||
 | 
												},
 | 
				
			||||||
 | 
											},
 | 
				
			||||||
 | 
										},
 | 
				
			||||||
 | 
									},
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
								expectedErrList: field.ErrorList{},
 | 
				
			||||||
 | 
								knownTypes:      sets.NewString(string("Webhook")),
 | 
				
			||||||
 | 
								repeatableTypes: sets.NewString(string("Webhook")),
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								name: "webhook names should be DNS1123 subdomains",
 | 
				
			||||||
 | 
								configuration: api.AuthorizationConfiguration{
 | 
				
			||||||
 | 
									Authorizers: []api.AuthorizerConfiguration{
 | 
				
			||||||
 | 
										{
 | 
				
			||||||
 | 
											Type: "Webhook",
 | 
				
			||||||
 | 
											Webhook: &api.WebhookConfiguration{
 | 
				
			||||||
 | 
												Name:                                     "webhookname.example.domain",
 | 
				
			||||||
 | 
												Timeout:                                  metav1.Duration{Duration: 5 * time.Second},
 | 
				
			||||||
 | 
												AuthorizedTTL:                            metav1.Duration{Duration: 5 * time.Minute},
 | 
				
			||||||
 | 
												UnauthorizedTTL:                          metav1.Duration{Duration: 30 * time.Second},
 | 
				
			||||||
 | 
												FailurePolicy:                            "NoOpinion",
 | 
				
			||||||
 | 
												SubjectAccessReviewVersion:               "v1",
 | 
				
			||||||
 | 
												MatchConditionSubjectAccessReviewVersion: "v1",
 | 
				
			||||||
 | 
												ConnectionInfo: api.WebhookConnectionInfo{
 | 
				
			||||||
 | 
													Type: "InClusterConfig",
 | 
				
			||||||
 | 
												},
 | 
				
			||||||
 | 
											},
 | 
				
			||||||
 | 
										},
 | 
				
			||||||
 | 
									},
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
								expectedErrList: field.ErrorList{},
 | 
				
			||||||
 | 
								knownTypes:      sets.NewString(string("Webhook")),
 | 
				
			||||||
 | 
								repeatableTypes: sets.NewString(string("Webhook")),
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								name: "webhook names should not be invalid DNS1123 labels or subdomains",
 | 
				
			||||||
 | 
								configuration: api.AuthorizationConfiguration{
 | 
				
			||||||
 | 
									Authorizers: []api.AuthorizerConfiguration{
 | 
				
			||||||
 | 
										{
 | 
				
			||||||
 | 
											Type: "Webhook",
 | 
				
			||||||
 | 
											Webhook: &api.WebhookConfiguration{
 | 
				
			||||||
 | 
												Name:                                     "WEBHOOKNAME.example.domain",
 | 
				
			||||||
 | 
												Timeout:                                  metav1.Duration{Duration: 5 * time.Second},
 | 
				
			||||||
 | 
												AuthorizedTTL:                            metav1.Duration{Duration: 5 * time.Minute},
 | 
				
			||||||
 | 
												UnauthorizedTTL:                          metav1.Duration{Duration: 30 * time.Second},
 | 
				
			||||||
 | 
												FailurePolicy:                            "NoOpinion",
 | 
				
			||||||
 | 
												SubjectAccessReviewVersion:               "v1",
 | 
				
			||||||
 | 
												MatchConditionSubjectAccessReviewVersion: "v1",
 | 
				
			||||||
 | 
												ConnectionInfo: api.WebhookConnectionInfo{
 | 
				
			||||||
 | 
													Type: "InClusterConfig",
 | 
				
			||||||
 | 
												},
 | 
				
			||||||
 | 
											},
 | 
				
			||||||
 | 
										},
 | 
				
			||||||
 | 
									},
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
								expectedErrList: field.ErrorList{field.Invalid(field.NewPath("name"), "WEBHOOKNAME.example.domain", "")},
 | 
				
			||||||
 | 
								knownTypes:      sets.NewString(string("Webhook")),
 | 
				
			||||||
 | 
								repeatableTypes: sets.NewString(string("Webhook")),
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								name: "timeout should be specified",
 | 
				
			||||||
 | 
								configuration: api.AuthorizationConfiguration{
 | 
				
			||||||
 | 
									Authorizers: []api.AuthorizerConfiguration{
 | 
				
			||||||
 | 
										{
 | 
				
			||||||
 | 
											Type: "Webhook",
 | 
				
			||||||
 | 
											Webhook: &api.WebhookConfiguration{
 | 
				
			||||||
 | 
												Name:                                     "default",
 | 
				
			||||||
 | 
												FailurePolicy:                            "NoOpinion",
 | 
				
			||||||
 | 
												AuthorizedTTL:                            metav1.Duration{Duration: 5 * time.Minute},
 | 
				
			||||||
 | 
												UnauthorizedTTL:                          metav1.Duration{Duration: 30 * time.Second},
 | 
				
			||||||
 | 
												SubjectAccessReviewVersion:               "v1",
 | 
				
			||||||
 | 
												MatchConditionSubjectAccessReviewVersion: "v1",
 | 
				
			||||||
 | 
												ConnectionInfo: api.WebhookConnectionInfo{
 | 
				
			||||||
 | 
													Type: "InClusterConfig",
 | 
				
			||||||
 | 
												},
 | 
				
			||||||
 | 
											},
 | 
				
			||||||
 | 
										},
 | 
				
			||||||
 | 
									},
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
								expectedErrList: field.ErrorList{field.Required(field.NewPath("timeout"), "")},
 | 
				
			||||||
 | 
								knownTypes:      sets.NewString(string("Webhook")),
 | 
				
			||||||
 | 
								repeatableTypes: sets.NewString(string("Webhook")),
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							//
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								name: "timeout shouldn't be zero",
 | 
				
			||||||
 | 
								configuration: api.AuthorizationConfiguration{
 | 
				
			||||||
 | 
									Authorizers: []api.AuthorizerConfiguration{
 | 
				
			||||||
 | 
										{
 | 
				
			||||||
 | 
											Type: "Webhook",
 | 
				
			||||||
 | 
											Webhook: &api.WebhookConfiguration{
 | 
				
			||||||
 | 
												Name:                                     "default",
 | 
				
			||||||
 | 
												FailurePolicy:                            "NoOpinion",
 | 
				
			||||||
 | 
												Timeout:                                  metav1.Duration{Duration: 0 * time.Second},
 | 
				
			||||||
 | 
												AuthorizedTTL:                            metav1.Duration{Duration: 5 * time.Minute},
 | 
				
			||||||
 | 
												UnauthorizedTTL:                          metav1.Duration{Duration: 30 * time.Second},
 | 
				
			||||||
 | 
												SubjectAccessReviewVersion:               "v1",
 | 
				
			||||||
 | 
												MatchConditionSubjectAccessReviewVersion: "v1",
 | 
				
			||||||
 | 
												ConnectionInfo: api.WebhookConnectionInfo{
 | 
				
			||||||
 | 
													Type: "InClusterConfig",
 | 
				
			||||||
 | 
												},
 | 
				
			||||||
 | 
											},
 | 
				
			||||||
 | 
										},
 | 
				
			||||||
 | 
									},
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
								expectedErrList: field.ErrorList{field.Required(field.NewPath("timeout"), "")},
 | 
				
			||||||
 | 
								knownTypes:      sets.NewString(string("Webhook")),
 | 
				
			||||||
 | 
								repeatableTypes: sets.NewString(string("Webhook")),
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								name: "timeout shouldn't be negative",
 | 
				
			||||||
 | 
								configuration: api.AuthorizationConfiguration{
 | 
				
			||||||
 | 
									Authorizers: []api.AuthorizerConfiguration{
 | 
				
			||||||
 | 
										{
 | 
				
			||||||
 | 
											Type: "Webhook",
 | 
				
			||||||
 | 
											Webhook: &api.WebhookConfiguration{
 | 
				
			||||||
 | 
												Name:                                     "default",
 | 
				
			||||||
 | 
												FailurePolicy:                            "NoOpinion",
 | 
				
			||||||
 | 
												Timeout:                                  metav1.Duration{Duration: -30 * time.Second},
 | 
				
			||||||
 | 
												AuthorizedTTL:                            metav1.Duration{Duration: 5 * time.Minute},
 | 
				
			||||||
 | 
												UnauthorizedTTL:                          metav1.Duration{Duration: 30 * time.Second},
 | 
				
			||||||
 | 
												SubjectAccessReviewVersion:               "v1",
 | 
				
			||||||
 | 
												MatchConditionSubjectAccessReviewVersion: "v1",
 | 
				
			||||||
 | 
												ConnectionInfo: api.WebhookConnectionInfo{
 | 
				
			||||||
 | 
													Type: "InClusterConfig",
 | 
				
			||||||
 | 
												},
 | 
				
			||||||
 | 
											},
 | 
				
			||||||
 | 
										},
 | 
				
			||||||
 | 
									},
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
								expectedErrList: field.ErrorList{field.Invalid(field.NewPath("timeout"), time.Duration(-30*time.Second).String(), "must be > 0s and <= 30s")},
 | 
				
			||||||
 | 
								knownTypes:      sets.NewString(string("Webhook")),
 | 
				
			||||||
 | 
								repeatableTypes: sets.NewString(string("Webhook")),
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								name: "timeout shouldn't be greater than 30seconds",
 | 
				
			||||||
 | 
								configuration: api.AuthorizationConfiguration{
 | 
				
			||||||
 | 
									Authorizers: []api.AuthorizerConfiguration{
 | 
				
			||||||
 | 
										{
 | 
				
			||||||
 | 
											Type: "Webhook",
 | 
				
			||||||
 | 
											Webhook: &api.WebhookConfiguration{
 | 
				
			||||||
 | 
												Name:                                     "default",
 | 
				
			||||||
 | 
												FailurePolicy:                            "NoOpinion",
 | 
				
			||||||
 | 
												Timeout:                                  metav1.Duration{Duration: 60 * time.Second},
 | 
				
			||||||
 | 
												AuthorizedTTL:                            metav1.Duration{Duration: 5 * time.Minute},
 | 
				
			||||||
 | 
												UnauthorizedTTL:                          metav1.Duration{Duration: 30 * time.Second},
 | 
				
			||||||
 | 
												SubjectAccessReviewVersion:               "v1",
 | 
				
			||||||
 | 
												MatchConditionSubjectAccessReviewVersion: "v1",
 | 
				
			||||||
 | 
												ConnectionInfo: api.WebhookConnectionInfo{
 | 
				
			||||||
 | 
													Type: "InClusterConfig",
 | 
				
			||||||
 | 
												},
 | 
				
			||||||
 | 
											},
 | 
				
			||||||
 | 
										},
 | 
				
			||||||
 | 
									},
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
								expectedErrList: field.ErrorList{field.Invalid(field.NewPath("timeout"), time.Duration(60*time.Second).String(), "must be > 0s and <= 30s")},
 | 
				
			||||||
 | 
								knownTypes:      sets.NewString(string("Webhook")),
 | 
				
			||||||
 | 
								repeatableTypes: sets.NewString(string("Webhook")),
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								name: "authorizedTTL should be defined ",
 | 
				
			||||||
 | 
								configuration: api.AuthorizationConfiguration{
 | 
				
			||||||
 | 
									Authorizers: []api.AuthorizerConfiguration{
 | 
				
			||||||
 | 
										{
 | 
				
			||||||
 | 
											Type: "Webhook",
 | 
				
			||||||
 | 
											Webhook: &api.WebhookConfiguration{
 | 
				
			||||||
 | 
												Name:                                     "default",
 | 
				
			||||||
 | 
												FailurePolicy:                            "NoOpinion",
 | 
				
			||||||
 | 
												Timeout:                                  metav1.Duration{Duration: 5 * time.Second},
 | 
				
			||||||
 | 
												UnauthorizedTTL:                          metav1.Duration{Duration: 30 * time.Second},
 | 
				
			||||||
 | 
												SubjectAccessReviewVersion:               "v1",
 | 
				
			||||||
 | 
												MatchConditionSubjectAccessReviewVersion: "v1",
 | 
				
			||||||
 | 
												ConnectionInfo: api.WebhookConnectionInfo{
 | 
				
			||||||
 | 
													Type: "InClusterConfig",
 | 
				
			||||||
 | 
												},
 | 
				
			||||||
 | 
											},
 | 
				
			||||||
 | 
										},
 | 
				
			||||||
 | 
									},
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
								expectedErrList: field.ErrorList{field.Required(field.NewPath("authorizedTTL"), "")},
 | 
				
			||||||
 | 
								knownTypes:      sets.NewString(string("Webhook")),
 | 
				
			||||||
 | 
								repeatableTypes: sets.NewString(string("Webhook")),
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								name: "authorizedTTL shouldn't be negative",
 | 
				
			||||||
 | 
								configuration: api.AuthorizationConfiguration{
 | 
				
			||||||
 | 
									Authorizers: []api.AuthorizerConfiguration{
 | 
				
			||||||
 | 
										{
 | 
				
			||||||
 | 
											Type: "Webhook",
 | 
				
			||||||
 | 
											Webhook: &api.WebhookConfiguration{
 | 
				
			||||||
 | 
												Name:                                     "default",
 | 
				
			||||||
 | 
												FailurePolicy:                            "NoOpinion",
 | 
				
			||||||
 | 
												Timeout:                                  metav1.Duration{Duration: 5 * time.Second},
 | 
				
			||||||
 | 
												AuthorizedTTL:                            metav1.Duration{Duration: -30 * time.Second},
 | 
				
			||||||
 | 
												UnauthorizedTTL:                          metav1.Duration{Duration: 30 * time.Second},
 | 
				
			||||||
 | 
												SubjectAccessReviewVersion:               "v1",
 | 
				
			||||||
 | 
												MatchConditionSubjectAccessReviewVersion: "v1",
 | 
				
			||||||
 | 
												ConnectionInfo: api.WebhookConnectionInfo{
 | 
				
			||||||
 | 
													Type: "InClusterConfig",
 | 
				
			||||||
 | 
												},
 | 
				
			||||||
 | 
											},
 | 
				
			||||||
 | 
										},
 | 
				
			||||||
 | 
									},
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
								expectedErrList: field.ErrorList{field.Invalid(field.NewPath("authorizedTTL"), time.Duration(-30*time.Second).String(), "must be > 0s")},
 | 
				
			||||||
 | 
								knownTypes:      sets.NewString(string("Webhook")),
 | 
				
			||||||
 | 
								repeatableTypes: sets.NewString(string("Webhook")),
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								name: "unauthorizedTTL should be defined ",
 | 
				
			||||||
 | 
								configuration: api.AuthorizationConfiguration{
 | 
				
			||||||
 | 
									Authorizers: []api.AuthorizerConfiguration{
 | 
				
			||||||
 | 
										{
 | 
				
			||||||
 | 
											Type: "Webhook",
 | 
				
			||||||
 | 
											Webhook: &api.WebhookConfiguration{
 | 
				
			||||||
 | 
												Name:                                     "default",
 | 
				
			||||||
 | 
												FailurePolicy:                            "NoOpinion",
 | 
				
			||||||
 | 
												Timeout:                                  metav1.Duration{Duration: 5 * time.Second},
 | 
				
			||||||
 | 
												AuthorizedTTL:                            metav1.Duration{Duration: 5 * time.Minute},
 | 
				
			||||||
 | 
												SubjectAccessReviewVersion:               "v1",
 | 
				
			||||||
 | 
												MatchConditionSubjectAccessReviewVersion: "v1",
 | 
				
			||||||
 | 
												ConnectionInfo: api.WebhookConnectionInfo{
 | 
				
			||||||
 | 
													Type: "InClusterConfig",
 | 
				
			||||||
 | 
												},
 | 
				
			||||||
 | 
											},
 | 
				
			||||||
 | 
										},
 | 
				
			||||||
 | 
									},
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
								expectedErrList: field.ErrorList{field.Required(field.NewPath("unauthorizedTTL"), "")},
 | 
				
			||||||
 | 
								knownTypes:      sets.NewString(string("Webhook")),
 | 
				
			||||||
 | 
								repeatableTypes: sets.NewString(string("Webhook")),
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								name: "unauthorizedTTL shouldn't be negative",
 | 
				
			||||||
 | 
								configuration: api.AuthorizationConfiguration{
 | 
				
			||||||
 | 
									Authorizers: []api.AuthorizerConfiguration{
 | 
				
			||||||
 | 
										{
 | 
				
			||||||
 | 
											Type: "Webhook",
 | 
				
			||||||
 | 
											Webhook: &api.WebhookConfiguration{
 | 
				
			||||||
 | 
												Name:                                     "default",
 | 
				
			||||||
 | 
												FailurePolicy:                            "NoOpinion",
 | 
				
			||||||
 | 
												Timeout:                                  metav1.Duration{Duration: 5 * time.Second},
 | 
				
			||||||
 | 
												AuthorizedTTL:                            metav1.Duration{Duration: 5 * time.Minute},
 | 
				
			||||||
 | 
												UnauthorizedTTL:                          metav1.Duration{Duration: -30 * time.Second},
 | 
				
			||||||
 | 
												SubjectAccessReviewVersion:               "v1",
 | 
				
			||||||
 | 
												MatchConditionSubjectAccessReviewVersion: "v1",
 | 
				
			||||||
 | 
												ConnectionInfo: api.WebhookConnectionInfo{
 | 
				
			||||||
 | 
													Type: "InClusterConfig",
 | 
				
			||||||
 | 
												},
 | 
				
			||||||
 | 
											},
 | 
				
			||||||
 | 
										},
 | 
				
			||||||
 | 
									},
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
								expectedErrList: field.ErrorList{field.Invalid(field.NewPath("unauthorizedTTL"), time.Duration(-30*time.Second).String(), "must be > 0s")},
 | 
				
			||||||
 | 
								knownTypes:      sets.NewString(string("Webhook")),
 | 
				
			||||||
 | 
								repeatableTypes: sets.NewString(string("Webhook")),
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								name: "SAR should be defined",
 | 
				
			||||||
 | 
								configuration: api.AuthorizationConfiguration{
 | 
				
			||||||
 | 
									Authorizers: []api.AuthorizerConfiguration{
 | 
				
			||||||
 | 
										{
 | 
				
			||||||
 | 
											Type: "Webhook",
 | 
				
			||||||
 | 
											Webhook: &api.WebhookConfiguration{
 | 
				
			||||||
 | 
												Name:                                     "default",
 | 
				
			||||||
 | 
												Timeout:                                  metav1.Duration{Duration: 5 * time.Second},
 | 
				
			||||||
 | 
												AuthorizedTTL:                            metav1.Duration{Duration: 5 * time.Minute},
 | 
				
			||||||
 | 
												UnauthorizedTTL:                          metav1.Duration{Duration: 30 * time.Second},
 | 
				
			||||||
 | 
												MatchConditionSubjectAccessReviewVersion: "v1",
 | 
				
			||||||
 | 
												FailurePolicy:                            "NoOpinion",
 | 
				
			||||||
 | 
												ConnectionInfo: api.WebhookConnectionInfo{
 | 
				
			||||||
 | 
													Type: "InClusterConfig",
 | 
				
			||||||
 | 
												},
 | 
				
			||||||
 | 
											},
 | 
				
			||||||
 | 
										},
 | 
				
			||||||
 | 
									},
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
								expectedErrList: field.ErrorList{field.Required(field.NewPath("subjectAccessReviewVersion"), "")},
 | 
				
			||||||
 | 
								knownTypes:      sets.NewString(string("Webhook")),
 | 
				
			||||||
 | 
								repeatableTypes: sets.NewString(string("Webhook")),
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								name: "SAR should be one of v1 and v1beta1",
 | 
				
			||||||
 | 
								configuration: api.AuthorizationConfiguration{
 | 
				
			||||||
 | 
									Authorizers: []api.AuthorizerConfiguration{
 | 
				
			||||||
 | 
										{
 | 
				
			||||||
 | 
											Type: "Webhook",
 | 
				
			||||||
 | 
											Webhook: &api.WebhookConfiguration{
 | 
				
			||||||
 | 
												Name:                                     "default",
 | 
				
			||||||
 | 
												Timeout:                                  metav1.Duration{Duration: 5 * time.Second},
 | 
				
			||||||
 | 
												AuthorizedTTL:                            metav1.Duration{Duration: 5 * time.Minute},
 | 
				
			||||||
 | 
												UnauthorizedTTL:                          metav1.Duration{Duration: 30 * time.Second},
 | 
				
			||||||
 | 
												FailurePolicy:                            "NoOpinion",
 | 
				
			||||||
 | 
												SubjectAccessReviewVersion:               "v2beta1",
 | 
				
			||||||
 | 
												MatchConditionSubjectAccessReviewVersion: "v1",
 | 
				
			||||||
 | 
												ConnectionInfo: api.WebhookConnectionInfo{
 | 
				
			||||||
 | 
													Type: "InClusterConfig",
 | 
				
			||||||
 | 
												},
 | 
				
			||||||
 | 
											},
 | 
				
			||||||
 | 
										},
 | 
				
			||||||
 | 
									},
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
								expectedErrList: field.ErrorList{field.NotSupported(field.NewPath("subjectAccessReviewVersion"), "v2beta1", []string{"v1", "v1beta1"})},
 | 
				
			||||||
 | 
								knownTypes:      sets.NewString(string("Webhook")),
 | 
				
			||||||
 | 
								repeatableTypes: sets.NewString(string("Webhook")),
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								name: "MatchConditionSAR should be defined",
 | 
				
			||||||
 | 
								configuration: api.AuthorizationConfiguration{
 | 
				
			||||||
 | 
									Authorizers: []api.AuthorizerConfiguration{
 | 
				
			||||||
 | 
										{
 | 
				
			||||||
 | 
											Type: "Webhook",
 | 
				
			||||||
 | 
											Webhook: &api.WebhookConfiguration{
 | 
				
			||||||
 | 
												Name:                       "default",
 | 
				
			||||||
 | 
												Timeout:                    metav1.Duration{Duration: 5 * time.Second},
 | 
				
			||||||
 | 
												AuthorizedTTL:              metav1.Duration{Duration: 5 * time.Minute},
 | 
				
			||||||
 | 
												UnauthorizedTTL:            metav1.Duration{Duration: 30 * time.Second},
 | 
				
			||||||
 | 
												FailurePolicy:              "NoOpinion",
 | 
				
			||||||
 | 
												SubjectAccessReviewVersion: "v1",
 | 
				
			||||||
 | 
												ConnectionInfo: api.WebhookConnectionInfo{
 | 
				
			||||||
 | 
													Type: "InClusterConfig",
 | 
				
			||||||
 | 
												},
 | 
				
			||||||
 | 
											},
 | 
				
			||||||
 | 
										},
 | 
				
			||||||
 | 
									},
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
								expectedErrList: field.ErrorList{field.Required(field.NewPath("matchConditionSubjectAccessReviewVersion"), "")},
 | 
				
			||||||
 | 
								knownTypes:      sets.NewString(string("Webhook")),
 | 
				
			||||||
 | 
								repeatableTypes: sets.NewString(string("Webhook")),
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								name: "MatchConditionSAR must not be anything other than v1",
 | 
				
			||||||
 | 
								configuration: api.AuthorizationConfiguration{
 | 
				
			||||||
 | 
									Authorizers: []api.AuthorizerConfiguration{
 | 
				
			||||||
 | 
										{
 | 
				
			||||||
 | 
											Type: "Webhook",
 | 
				
			||||||
 | 
											Webhook: &api.WebhookConfiguration{
 | 
				
			||||||
 | 
												Name:                                     "default",
 | 
				
			||||||
 | 
												Timeout:                                  metav1.Duration{Duration: 5 * time.Second},
 | 
				
			||||||
 | 
												AuthorizedTTL:                            metav1.Duration{Duration: 5 * time.Minute},
 | 
				
			||||||
 | 
												UnauthorizedTTL:                          metav1.Duration{Duration: 30 * time.Second},
 | 
				
			||||||
 | 
												FailurePolicy:                            "NoOpinion",
 | 
				
			||||||
 | 
												SubjectAccessReviewVersion:               "v1",
 | 
				
			||||||
 | 
												MatchConditionSubjectAccessReviewVersion: "v1beta1",
 | 
				
			||||||
 | 
												ConnectionInfo: api.WebhookConnectionInfo{
 | 
				
			||||||
 | 
													Type: "InClusterConfig",
 | 
				
			||||||
 | 
												},
 | 
				
			||||||
 | 
											},
 | 
				
			||||||
 | 
										},
 | 
				
			||||||
 | 
									},
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
								expectedErrList: field.ErrorList{field.NotSupported(field.NewPath("matchConditionSubjectAccessReviewVersion"), "v1beta1", []string{"v1"})},
 | 
				
			||||||
 | 
								knownTypes:      sets.NewString(string("Webhook")),
 | 
				
			||||||
 | 
								repeatableTypes: sets.NewString(string("Webhook")),
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								name: "failurePolicy should be defined",
 | 
				
			||||||
 | 
								configuration: api.AuthorizationConfiguration{
 | 
				
			||||||
 | 
									Authorizers: []api.AuthorizerConfiguration{
 | 
				
			||||||
 | 
										{
 | 
				
			||||||
 | 
											Type: "Webhook",
 | 
				
			||||||
 | 
											Webhook: &api.WebhookConfiguration{
 | 
				
			||||||
 | 
												Name:                                     "default",
 | 
				
			||||||
 | 
												Timeout:                                  metav1.Duration{Duration: 5 * time.Second},
 | 
				
			||||||
 | 
												AuthorizedTTL:                            metav1.Duration{Duration: 5 * time.Minute},
 | 
				
			||||||
 | 
												UnauthorizedTTL:                          metav1.Duration{Duration: 30 * time.Second},
 | 
				
			||||||
 | 
												SubjectAccessReviewVersion:               "v1",
 | 
				
			||||||
 | 
												MatchConditionSubjectAccessReviewVersion: "v1",
 | 
				
			||||||
 | 
												ConnectionInfo: api.WebhookConnectionInfo{
 | 
				
			||||||
 | 
													Type: "InClusterConfig",
 | 
				
			||||||
 | 
												},
 | 
				
			||||||
 | 
											},
 | 
				
			||||||
 | 
										},
 | 
				
			||||||
 | 
									},
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
								expectedErrList: field.ErrorList{field.Required(field.NewPath("failurePolicy"), "")},
 | 
				
			||||||
 | 
								knownTypes:      sets.NewString(string("Webhook")),
 | 
				
			||||||
 | 
								repeatableTypes: sets.NewString(string("Webhook")),
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								name: "failurePolicy should be one of \"NoOpinion\" or \"Deny\"",
 | 
				
			||||||
 | 
								configuration: api.AuthorizationConfiguration{
 | 
				
			||||||
 | 
									Authorizers: []api.AuthorizerConfiguration{
 | 
				
			||||||
 | 
										{
 | 
				
			||||||
 | 
											Type: "Webhook",
 | 
				
			||||||
 | 
											Webhook: &api.WebhookConfiguration{
 | 
				
			||||||
 | 
												Name:                                     "default",
 | 
				
			||||||
 | 
												Timeout:                                  metav1.Duration{Duration: 5 * time.Second},
 | 
				
			||||||
 | 
												AuthorizedTTL:                            metav1.Duration{Duration: 5 * time.Minute},
 | 
				
			||||||
 | 
												UnauthorizedTTL:                          metav1.Duration{Duration: 30 * time.Second},
 | 
				
			||||||
 | 
												FailurePolicy:                            "AlwaysAllow",
 | 
				
			||||||
 | 
												SubjectAccessReviewVersion:               "v1",
 | 
				
			||||||
 | 
												MatchConditionSubjectAccessReviewVersion: "v1",
 | 
				
			||||||
 | 
												ConnectionInfo: api.WebhookConnectionInfo{
 | 
				
			||||||
 | 
													Type: "InClusterConfig",
 | 
				
			||||||
 | 
												},
 | 
				
			||||||
 | 
											},
 | 
				
			||||||
 | 
										},
 | 
				
			||||||
 | 
									},
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
								expectedErrList: field.ErrorList{field.NotSupported(field.NewPath("failurePolicy"), "AlwaysAllow", []string{"NoOpinion", "Deny"})},
 | 
				
			||||||
 | 
								knownTypes:      sets.NewString(string("Webhook")),
 | 
				
			||||||
 | 
								repeatableTypes: sets.NewString(string("Webhook")),
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								name: "connectionInfo should be defined",
 | 
				
			||||||
 | 
								configuration: api.AuthorizationConfiguration{
 | 
				
			||||||
 | 
									Authorizers: []api.AuthorizerConfiguration{
 | 
				
			||||||
 | 
										{
 | 
				
			||||||
 | 
											Type: "Webhook",
 | 
				
			||||||
 | 
											Webhook: &api.WebhookConfiguration{
 | 
				
			||||||
 | 
												Name:                                     "default",
 | 
				
			||||||
 | 
												Timeout:                                  metav1.Duration{Duration: 5 * time.Second},
 | 
				
			||||||
 | 
												AuthorizedTTL:                            metav1.Duration{Duration: 5 * time.Minute},
 | 
				
			||||||
 | 
												UnauthorizedTTL:                          metav1.Duration{Duration: 30 * time.Second},
 | 
				
			||||||
 | 
												FailurePolicy:                            "NoOpinion",
 | 
				
			||||||
 | 
												SubjectAccessReviewVersion:               "v1",
 | 
				
			||||||
 | 
												MatchConditionSubjectAccessReviewVersion: "v1",
 | 
				
			||||||
 | 
											},
 | 
				
			||||||
 | 
										},
 | 
				
			||||||
 | 
									},
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
								expectedErrList: field.ErrorList{field.Required(field.NewPath("connectionInfo"), "")},
 | 
				
			||||||
 | 
								knownTypes:      sets.NewString(string("Webhook")),
 | 
				
			||||||
 | 
								repeatableTypes: sets.NewString(string("Webhook")),
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								name: "connectionInfo should be one of InClusterConfig or KubeConfigFile",
 | 
				
			||||||
 | 
								configuration: api.AuthorizationConfiguration{
 | 
				
			||||||
 | 
									Authorizers: []api.AuthorizerConfiguration{
 | 
				
			||||||
 | 
										{
 | 
				
			||||||
 | 
											Type: "Webhook",
 | 
				
			||||||
 | 
											Webhook: &api.WebhookConfiguration{
 | 
				
			||||||
 | 
												Name:                                     "default",
 | 
				
			||||||
 | 
												Timeout:                                  metav1.Duration{Duration: 5 * time.Second},
 | 
				
			||||||
 | 
												AuthorizedTTL:                            metav1.Duration{Duration: 5 * time.Minute},
 | 
				
			||||||
 | 
												UnauthorizedTTL:                          metav1.Duration{Duration: 30 * time.Second},
 | 
				
			||||||
 | 
												FailurePolicy:                            "NoOpinion",
 | 
				
			||||||
 | 
												SubjectAccessReviewVersion:               "v1",
 | 
				
			||||||
 | 
												MatchConditionSubjectAccessReviewVersion: "v1",
 | 
				
			||||||
 | 
												ConnectionInfo: api.WebhookConnectionInfo{
 | 
				
			||||||
 | 
													Type: "ExternalClusterConfig",
 | 
				
			||||||
 | 
												},
 | 
				
			||||||
 | 
											},
 | 
				
			||||||
 | 
										},
 | 
				
			||||||
 | 
									},
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
								expectedErrList: field.ErrorList{
 | 
				
			||||||
 | 
									field.NotSupported(field.NewPath("connectionInfo"), api.WebhookConnectionInfo{Type: "ExternalClusterConfig"}, []string{"InClusterConfig", "KubeConfigFile"}),
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
								knownTypes:      sets.NewString(string("Webhook")),
 | 
				
			||||||
 | 
								repeatableTypes: sets.NewString(string("Webhook")),
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								name: "if connectionInfo=InClusterConfig, then kubeConfigFile should be nil",
 | 
				
			||||||
 | 
								configuration: api.AuthorizationConfiguration{
 | 
				
			||||||
 | 
									Authorizers: []api.AuthorizerConfiguration{
 | 
				
			||||||
 | 
										{
 | 
				
			||||||
 | 
											Type: "Webhook",
 | 
				
			||||||
 | 
											Webhook: &api.WebhookConfiguration{
 | 
				
			||||||
 | 
												Name:                                     "default",
 | 
				
			||||||
 | 
												Timeout:                                  metav1.Duration{Duration: 5 * time.Second},
 | 
				
			||||||
 | 
												AuthorizedTTL:                            metav1.Duration{Duration: 5 * time.Minute},
 | 
				
			||||||
 | 
												UnauthorizedTTL:                          metav1.Duration{Duration: 30 * time.Second},
 | 
				
			||||||
 | 
												FailurePolicy:                            "NoOpinion",
 | 
				
			||||||
 | 
												SubjectAccessReviewVersion:               "v1",
 | 
				
			||||||
 | 
												MatchConditionSubjectAccessReviewVersion: "v1",
 | 
				
			||||||
 | 
												ConnectionInfo: api.WebhookConnectionInfo{
 | 
				
			||||||
 | 
													Type:           "InClusterConfig",
 | 
				
			||||||
 | 
													KubeConfigFile: new(string),
 | 
				
			||||||
 | 
												},
 | 
				
			||||||
 | 
											},
 | 
				
			||||||
 | 
										},
 | 
				
			||||||
 | 
									},
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
								expectedErrList: field.ErrorList{
 | 
				
			||||||
 | 
									field.Invalid(field.NewPath("connectionInfo", "kubeConfigFile"), "", "can only be set when type=KubeConfigFile"),
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
								knownTypes:      sets.NewString(string("Webhook")),
 | 
				
			||||||
 | 
								repeatableTypes: sets.NewString(string("Webhook")),
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								name: "if connectionInfo=KubeConfigFile, then KubeConfigFile should be defined",
 | 
				
			||||||
 | 
								configuration: api.AuthorizationConfiguration{
 | 
				
			||||||
 | 
									Authorizers: []api.AuthorizerConfiguration{
 | 
				
			||||||
 | 
										{
 | 
				
			||||||
 | 
											Type: "Webhook",
 | 
				
			||||||
 | 
											Webhook: &api.WebhookConfiguration{
 | 
				
			||||||
 | 
												Name:                                     "default",
 | 
				
			||||||
 | 
												Timeout:                                  metav1.Duration{Duration: 5 * time.Second},
 | 
				
			||||||
 | 
												AuthorizedTTL:                            metav1.Duration{Duration: 5 * time.Minute},
 | 
				
			||||||
 | 
												UnauthorizedTTL:                          metav1.Duration{Duration: 30 * time.Second},
 | 
				
			||||||
 | 
												FailurePolicy:                            "NoOpinion",
 | 
				
			||||||
 | 
												SubjectAccessReviewVersion:               "v1",
 | 
				
			||||||
 | 
												MatchConditionSubjectAccessReviewVersion: "v1",
 | 
				
			||||||
 | 
												ConnectionInfo: api.WebhookConnectionInfo{
 | 
				
			||||||
 | 
													Type: "KubeConfigFile",
 | 
				
			||||||
 | 
												},
 | 
				
			||||||
 | 
											},
 | 
				
			||||||
 | 
										},
 | 
				
			||||||
 | 
									},
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
								expectedErrList: field.ErrorList{field.Required(field.NewPath("kubeConfigFile"), "")},
 | 
				
			||||||
 | 
								knownTypes:      sets.NewString(string("Webhook")),
 | 
				
			||||||
 | 
								repeatableTypes: sets.NewString(string("Webhook")),
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								name: "if connectionInfo=KubeConfigFile, then KubeConfigFile should be defined, must be an absolute path, should exist, shouldn't be a symlink",
 | 
				
			||||||
 | 
								configuration: api.AuthorizationConfiguration{
 | 
				
			||||||
 | 
									Authorizers: []api.AuthorizerConfiguration{
 | 
				
			||||||
 | 
										{
 | 
				
			||||||
 | 
											Type: "Webhook",
 | 
				
			||||||
 | 
											Webhook: &api.WebhookConfiguration{
 | 
				
			||||||
 | 
												Name:                                     "default",
 | 
				
			||||||
 | 
												Timeout:                                  metav1.Duration{Duration: 5 * time.Second},
 | 
				
			||||||
 | 
												AuthorizedTTL:                            metav1.Duration{Duration: 5 * time.Minute},
 | 
				
			||||||
 | 
												UnauthorizedTTL:                          metav1.Duration{Duration: 30 * time.Second},
 | 
				
			||||||
 | 
												FailurePolicy:                            "NoOpinion",
 | 
				
			||||||
 | 
												SubjectAccessReviewVersion:               "v1",
 | 
				
			||||||
 | 
												MatchConditionSubjectAccessReviewVersion: "v1",
 | 
				
			||||||
 | 
												ConnectionInfo: api.WebhookConnectionInfo{
 | 
				
			||||||
 | 
													Type:           "KubeConfigFile",
 | 
				
			||||||
 | 
													KubeConfigFile: &badKubeConfigFile,
 | 
				
			||||||
 | 
												},
 | 
				
			||||||
 | 
											},
 | 
				
			||||||
 | 
										},
 | 
				
			||||||
 | 
									},
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
								expectedErrList: field.ErrorList{field.Invalid(field.NewPath("kubeConfigFile"), badKubeConfigFile, "must be an absolute path")},
 | 
				
			||||||
 | 
								knownTypes:      sets.NewString(string("Webhook")),
 | 
				
			||||||
 | 
								repeatableTypes: sets.NewString(string("Webhook")),
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								name: "if connectionInfo=KubeConfigFile, an existent file needs to be passed",
 | 
				
			||||||
 | 
								configuration: api.AuthorizationConfiguration{
 | 
				
			||||||
 | 
									Authorizers: []api.AuthorizerConfiguration{
 | 
				
			||||||
 | 
										{
 | 
				
			||||||
 | 
											Type: "Webhook",
 | 
				
			||||||
 | 
											Webhook: &api.WebhookConfiguration{
 | 
				
			||||||
 | 
												Name:                                     "default",
 | 
				
			||||||
 | 
												Timeout:                                  metav1.Duration{Duration: 5 * time.Second},
 | 
				
			||||||
 | 
												AuthorizedTTL:                            metav1.Duration{Duration: 5 * time.Minute},
 | 
				
			||||||
 | 
												UnauthorizedTTL:                          metav1.Duration{Duration: 30 * time.Second},
 | 
				
			||||||
 | 
												FailurePolicy:                            "NoOpinion",
 | 
				
			||||||
 | 
												SubjectAccessReviewVersion:               "v1",
 | 
				
			||||||
 | 
												MatchConditionSubjectAccessReviewVersion: "v1",
 | 
				
			||||||
 | 
												ConnectionInfo: api.WebhookConnectionInfo{
 | 
				
			||||||
 | 
													Type:           "KubeConfigFile",
 | 
				
			||||||
 | 
													KubeConfigFile: &tempKubeConfigFilePath,
 | 
				
			||||||
 | 
												},
 | 
				
			||||||
 | 
											},
 | 
				
			||||||
 | 
										},
 | 
				
			||||||
 | 
									},
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
								expectedErrList: field.ErrorList{},
 | 
				
			||||||
 | 
								knownTypes:      sets.NewString(string("Webhook")),
 | 
				
			||||||
 | 
								repeatableTypes: sets.NewString(string("Webhook")),
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							// TODO: When the CEL expression validator is implemented, add a few test cases to typecheck the expression
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for _, test := range tests {
 | 
				
			||||||
 | 
							t.Run(test.name, func(t *testing.T) {
 | 
				
			||||||
 | 
								errList := ValidateAuthorizationConfiguration(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)
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								for i, expected := range test.expectedErrList {
 | 
				
			||||||
 | 
									if expected.Type.String() != errList[i].Type.String() {
 | 
				
			||||||
 | 
										t.Errorf("expected err type %s, got %s",
 | 
				
			||||||
 | 
											expected.Type.String(),
 | 
				
			||||||
 | 
											errList[i].Type.String())
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
									if expected.BadValue != errList[i].BadValue {
 | 
				
			||||||
 | 
										t.Errorf("expected bad value '%s', got '%s'",
 | 
				
			||||||
 | 
											expected.BadValue,
 | 
				
			||||||
 | 
											errList[i].BadValue)
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -110,6 +110,59 @@ func (in *AuthenticationConfiguration) DeepCopyObject() runtime.Object {
 | 
				
			|||||||
	return nil
 | 
						return nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
 | 
				
			||||||
 | 
					func (in *AuthorizationConfiguration) DeepCopyInto(out *AuthorizationConfiguration) {
 | 
				
			||||||
 | 
						*out = *in
 | 
				
			||||||
 | 
						out.TypeMeta = in.TypeMeta
 | 
				
			||||||
 | 
						if in.Authorizers != nil {
 | 
				
			||||||
 | 
							in, out := &in.Authorizers, &out.Authorizers
 | 
				
			||||||
 | 
							*out = make([]AuthorizerConfiguration, len(*in))
 | 
				
			||||||
 | 
							for i := range *in {
 | 
				
			||||||
 | 
								(*in)[i].DeepCopyInto(&(*out)[i])
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AuthorizationConfiguration.
 | 
				
			||||||
 | 
					func (in *AuthorizationConfiguration) DeepCopy() *AuthorizationConfiguration {
 | 
				
			||||||
 | 
						if in == nil {
 | 
				
			||||||
 | 
							return nil
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						out := new(AuthorizationConfiguration)
 | 
				
			||||||
 | 
						in.DeepCopyInto(out)
 | 
				
			||||||
 | 
						return out
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
 | 
				
			||||||
 | 
					func (in *AuthorizationConfiguration) DeepCopyObject() runtime.Object {
 | 
				
			||||||
 | 
						if c := in.DeepCopy(); c != nil {
 | 
				
			||||||
 | 
							return c
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
 | 
				
			||||||
 | 
					func (in *AuthorizerConfiguration) DeepCopyInto(out *AuthorizerConfiguration) {
 | 
				
			||||||
 | 
						*out = *in
 | 
				
			||||||
 | 
						if in.Webhook != nil {
 | 
				
			||||||
 | 
							in, out := &in.Webhook, &out.Webhook
 | 
				
			||||||
 | 
							*out = new(WebhookConfiguration)
 | 
				
			||||||
 | 
							(*in).DeepCopyInto(*out)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AuthorizerConfiguration.
 | 
				
			||||||
 | 
					func (in *AuthorizerConfiguration) DeepCopy() *AuthorizerConfiguration {
 | 
				
			||||||
 | 
						if in == nil {
 | 
				
			||||||
 | 
							return nil
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						out := new(AuthorizerConfiguration)
 | 
				
			||||||
 | 
						in.DeepCopyInto(out)
 | 
				
			||||||
 | 
						return out
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
 | 
					// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
 | 
				
			||||||
func (in *ClaimMappings) DeepCopyInto(out *ClaimMappings) {
 | 
					func (in *ClaimMappings) DeepCopyInto(out *ClaimMappings) {
 | 
				
			||||||
	*out = *in
 | 
						*out = *in
 | 
				
			||||||
@@ -383,3 +436,65 @@ func (in *UDSTransport) DeepCopy() *UDSTransport {
 | 
				
			|||||||
	in.DeepCopyInto(out)
 | 
						in.DeepCopyInto(out)
 | 
				
			||||||
	return out
 | 
						return out
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
 | 
				
			||||||
 | 
					func (in *WebhookConfiguration) DeepCopyInto(out *WebhookConfiguration) {
 | 
				
			||||||
 | 
						*out = *in
 | 
				
			||||||
 | 
						out.AuthorizedTTL = in.AuthorizedTTL
 | 
				
			||||||
 | 
						out.UnauthorizedTTL = in.UnauthorizedTTL
 | 
				
			||||||
 | 
						out.Timeout = in.Timeout
 | 
				
			||||||
 | 
						in.ConnectionInfo.DeepCopyInto(&out.ConnectionInfo)
 | 
				
			||||||
 | 
						if in.MatchConditions != nil {
 | 
				
			||||||
 | 
							in, out := &in.MatchConditions, &out.MatchConditions
 | 
				
			||||||
 | 
							*out = make([]WebhookMatchCondition, len(*in))
 | 
				
			||||||
 | 
							copy(*out, *in)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new WebhookConfiguration.
 | 
				
			||||||
 | 
					func (in *WebhookConfiguration) DeepCopy() *WebhookConfiguration {
 | 
				
			||||||
 | 
						if in == nil {
 | 
				
			||||||
 | 
							return nil
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						out := new(WebhookConfiguration)
 | 
				
			||||||
 | 
						in.DeepCopyInto(out)
 | 
				
			||||||
 | 
						return out
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
 | 
				
			||||||
 | 
					func (in *WebhookConnectionInfo) DeepCopyInto(out *WebhookConnectionInfo) {
 | 
				
			||||||
 | 
						*out = *in
 | 
				
			||||||
 | 
						if in.KubeConfigFile != nil {
 | 
				
			||||||
 | 
							in, out := &in.KubeConfigFile, &out.KubeConfigFile
 | 
				
			||||||
 | 
							*out = new(string)
 | 
				
			||||||
 | 
							**out = **in
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new WebhookConnectionInfo.
 | 
				
			||||||
 | 
					func (in *WebhookConnectionInfo) DeepCopy() *WebhookConnectionInfo {
 | 
				
			||||||
 | 
						if in == nil {
 | 
				
			||||||
 | 
							return nil
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						out := new(WebhookConnectionInfo)
 | 
				
			||||||
 | 
						in.DeepCopyInto(out)
 | 
				
			||||||
 | 
						return out
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
 | 
				
			||||||
 | 
					func (in *WebhookMatchCondition) DeepCopyInto(out *WebhookMatchCondition) {
 | 
				
			||||||
 | 
						*out = *in
 | 
				
			||||||
 | 
						return
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new WebhookMatchCondition.
 | 
				
			||||||
 | 
					func (in *WebhookMatchCondition) DeepCopy() *WebhookMatchCondition {
 | 
				
			||||||
 | 
						if in == nil {
 | 
				
			||||||
 | 
							return nil
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						out := new(WebhookMatchCondition)
 | 
				
			||||||
 | 
						in.DeepCopyInto(out)
 | 
				
			||||||
 | 
						return out
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user