From 4e0114b0dd3701b68c02d038edcf4fbe84515a68 Mon Sep 17 00:00:00 2001 From: "Dr. Stefan Schimanski" Date: Wed, 31 Jan 2018 16:17:48 +0100 Subject: [PATCH] apiserver: make SecureServingOptions and authz/n options re-usable --- cmd/kube-apiserver/app/options/options.go | 2 +- .../app/options/options_test.go | 5 +- cmd/kube-apiserver/app/server.go | 6 +- pkg/kubeapiserver/options/authentication.go | 8 +- pkg/kubeapiserver/options/serving.go | 6 +- pkg/master/master.go | 6 +- .../src/k8s.io/apiserver/pkg/server/config.go | 64 +++++++++------ .../apiserver/pkg/server/genericapiserver.go | 2 +- .../pkg/server/genericapiserver_test.go | 2 +- .../k8s.io/apiserver/pkg/server/options/BUILD | 1 + .../apiserver/pkg/server/options/admission.go | 2 +- .../pkg/server/options/authentication.go | 13 ++- .../pkg/server/options/authorization.go | 2 +- .../pkg/server/options/recommended.go | 8 +- .../apiserver/pkg/server/options/serving.go | 56 +++---------- .../pkg/server/options/serving_test.go | 6 +- .../server/options/serving_with_loopback.go | 79 +++++++++++++++++++ .../src/k8s.io/apiserver/pkg/server/serve.go | 32 ++++---- test/integration/auth/accessreview_test.go | 12 +-- test/integration/auth/auth_test.go | 38 ++++----- test/integration/auth/bootstraptoken_test.go | 2 +- test/integration/auth/node_test.go | 4 +- test/integration/auth/rbac_test.go | 8 +- test/integration/framework/master_utils.go | 14 ++-- .../master/synthetic_master_test.go | 6 +- .../serviceaccount/service_account_test.go | 4 +- 26 files changed, 222 insertions(+), 166 deletions(-) create mode 100644 staging/src/k8s.io/apiserver/pkg/server/options/serving_with_loopback.go diff --git a/cmd/kube-apiserver/app/options/options.go b/cmd/kube-apiserver/app/options/options.go index 4dbd1370474..1f57add7c3e 100644 --- a/cmd/kube-apiserver/app/options/options.go +++ b/cmd/kube-apiserver/app/options/options.go @@ -42,7 +42,7 @@ import ( type ServerRunOptions struct { GenericServerRunOptions *genericoptions.ServerRunOptions Etcd *genericoptions.EtcdOptions - SecureServing *genericoptions.SecureServingOptions + SecureServing *genericoptions.SecureServingOptionsWithLoopback InsecureServing *kubeoptions.InsecureServingOptions Audit *genericoptions.AuditOptions Features *genericoptions.FeatureOptions diff --git a/cmd/kube-apiserver/app/options/options_test.go b/cmd/kube-apiserver/app/options/options_test.go index 38d95b4c04b..9f97b175608 100644 --- a/cmd/kube-apiserver/app/options/options_test.go +++ b/cmd/kube-apiserver/app/options/options_test.go @@ -26,6 +26,7 @@ import ( "k8s.io/apimachinery/pkg/util/diff" apiserveroptions "k8s.io/apiserver/pkg/server/options" + genericoptions "k8s.io/apiserver/pkg/server/options" "k8s.io/apiserver/pkg/storage/storagebackend" utilflag "k8s.io/apiserver/pkg/util/flag" auditwebhook "k8s.io/apiserver/plugin/pkg/audit/webhook" @@ -137,14 +138,14 @@ func TestAddFlags(t *testing.T) { EnableWatchCache: true, DefaultWatchCacheSize: 100, }, - SecureServing: &apiserveroptions.SecureServingOptions{ + SecureServing: genericoptions.WithLoopback(&apiserveroptions.SecureServingOptions{ BindAddress: net.ParseIP("192.168.10.20"), BindPort: 6443, ServerCert: apiserveroptions.GeneratableKeyCert{ CertDirectory: "/var/run/kubernetes", PairName: "apiserver", }, - }, + }), InsecureServing: &kubeoptions.InsecureServingOptions{ BindAddress: net.ParseIP("127.0.0.1"), BindPort: 8080, diff --git a/cmd/kube-apiserver/app/server.go b/cmd/kube-apiserver/app/server.go index 5a3a46afd54..092a77cd7f2 100644 --- a/cmd/kube-apiserver/app/server.go +++ b/cmd/kube-apiserver/app/server.go @@ -450,12 +450,12 @@ func BuildGenericConfig(s *options.ServerRunOptions, proxyTransport *http.Transp ) } - genericConfig.Authenticator, genericConfig.OpenAPIConfig.SecurityDefinitions, err = BuildAuthenticator(s, storageFactory, client, sharedInformers) + genericConfig.Authentication.Authenticator, genericConfig.OpenAPIConfig.SecurityDefinitions, err = BuildAuthenticator(s, storageFactory, client, sharedInformers) if err != nil { return nil, nil, nil, nil, nil, fmt.Errorf("invalid authentication config: %v", err) } - genericConfig.Authorizer, genericConfig.RuleResolver, err = BuildAuthorizer(s, sharedInformers, versionedInformers) + genericConfig.Authorization.Authorizer, genericConfig.RuleResolver, err = BuildAuthorizer(s, sharedInformers, versionedInformers) if err != nil { return nil, nil, nil, nil, nil, fmt.Errorf("invalid authorization config: %v", err) } @@ -634,7 +634,7 @@ func BuildStorageFactory(s *options.ServerRunOptions, apiResourceConfig *servers func defaultOptions(s *options.ServerRunOptions) error { // set defaults - if err := s.GenericServerRunOptions.DefaultAdvertiseAddress(s.SecureServing); err != nil { + if err := s.GenericServerRunOptions.DefaultAdvertiseAddress(s.SecureServing.SecureServingOptions); err != nil { return err } if err := kubeoptions.DefaultAdvertiseAddress(s.GenericServerRunOptions, s.InsecureServing); err != nil { diff --git a/pkg/kubeapiserver/options/authentication.go b/pkg/kubeapiserver/options/authentication.go index 6a6b579f215..5896871a673 100644 --- a/pkg/kubeapiserver/options/authentication.go +++ b/pkg/kubeapiserver/options/authentication.go @@ -341,19 +341,17 @@ func (o *BuiltInAuthenticationOptions) ApplyTo(c *genericapiserver.Config) error var err error if o.ClientCert != nil { - c, err = c.ApplyClientCert(o.ClientCert.ClientCA) - if err != nil { + if err = c.Authentication.ApplyClientCert(o.ClientCert.ClientCA, c.SecureServing); err != nil { return fmt.Errorf("unable to load client CA file: %v", err) } } if o.RequestHeader != nil { - c, err = c.ApplyClientCert(o.RequestHeader.ClientCAFile) - if err != nil { + if err = c.Authentication.ApplyClientCert(o.RequestHeader.ClientCAFile, c.SecureServing); err != nil { return fmt.Errorf("unable to load client CA file: %v", err) } } - c.SupportsBasicAuth = o.PasswordFile != nil && len(o.PasswordFile.BasicAuthFile) > 0 + c.Authentication.SupportsBasicAuth = o.PasswordFile != nil && len(o.PasswordFile.BasicAuthFile) > 0 return nil } diff --git a/pkg/kubeapiserver/options/serving.go b/pkg/kubeapiserver/options/serving.go index 2b1ca82d91e..74dd56f41c9 100644 --- a/pkg/kubeapiserver/options/serving.go +++ b/pkg/kubeapiserver/options/serving.go @@ -33,15 +33,15 @@ import ( // NewSecureServingOptions gives default values for the kube-apiserver which are not the options wanted by // "normal" API servers running on the platform -func NewSecureServingOptions() *genericoptions.SecureServingOptions { - return &genericoptions.SecureServingOptions{ +func NewSecureServingOptions() *genericoptions.SecureServingOptionsWithLoopback { + return genericoptions.WithLoopback(&genericoptions.SecureServingOptions{ BindAddress: net.ParseIP("0.0.0.0"), BindPort: 6443, ServerCert: genericoptions.GeneratableKeyCert{ PairName: "apiserver", CertDirectory: "/var/run/kubernetes", }, - } + }) } // DefaultAdvertiseAddress sets the field AdvertiseAddress if diff --git a/pkg/master/master.go b/pkg/master/master.go index eb8569d072d..a8b8a47a219 100644 --- a/pkg/master/master.go +++ b/pkg/master/master.go @@ -337,15 +337,15 @@ func (c completedConfig) New(delegationTarget genericapiserver.DelegationTarget) // TODO: describe the priority all the way down in the RESTStorageProviders and plumb it back through the various discovery // handlers that we have. restStorageProviders := []RESTStorageProvider{ - authenticationrest.RESTStorageProvider{Authenticator: c.GenericConfig.Authenticator}, - authorizationrest.RESTStorageProvider{Authorizer: c.GenericConfig.Authorizer, RuleResolver: c.GenericConfig.RuleResolver}, + authenticationrest.RESTStorageProvider{Authenticator: c.GenericConfig.Authentication.Authenticator}, + authorizationrest.RESTStorageProvider{Authorizer: c.GenericConfig.Authorization.Authorizer, RuleResolver: c.GenericConfig.RuleResolver}, autoscalingrest.RESTStorageProvider{}, batchrest.RESTStorageProvider{}, certificatesrest.RESTStorageProvider{}, extensionsrest.RESTStorageProvider{}, networkingrest.RESTStorageProvider{}, policyrest.RESTStorageProvider{}, - rbacrest.RESTStorageProvider{Authorizer: c.GenericConfig.Authorizer}, + rbacrest.RESTStorageProvider{Authorizer: c.GenericConfig.Authorization.Authorizer}, schedulingrest.RESTStorageProvider{}, settingsrest.RESTStorageProvider{}, storagerest.RESTStorageProvider{}, diff --git a/staging/src/k8s.io/apiserver/pkg/server/config.go b/staging/src/k8s.io/apiserver/pkg/server/config.go index 5ddd2e91122..4d5a5ed422c 100644 --- a/staging/src/k8s.io/apiserver/pkg/server/config.go +++ b/staging/src/k8s.io/apiserver/pkg/server/config.go @@ -79,14 +79,19 @@ const ( // Config is a structure used to configure a GenericAPIServer. // Its members are sorted roughly in order of importance for composers. type Config struct { - // SecureServingInfo is required to serve https - SecureServingInfo *SecureServingInfo + // SecureServing is required to serve https + SecureServing *SecureServingInfo + + // Authentication is the configuration for authentication + Authentication AuthenticationInfo + + // Authentication is the configuration for authentication + Authorization AuthorizationInfo // LoopbackClientConfig is a config for a privileged loopback connection to the API server // This is required for proper functioning of the PostStartHooks on a GenericAPIServer + // TODO: move into SecureServing(WithLoopback) as soon as insecure serving is gone LoopbackClientConfig *restclient.Config - // Authenticator determines which subject is making the request - Authenticator authenticator.Request // Authorizer determines whether the subject is allowed to make the request based only // on the RequestURI Authorizer authorizer.Authorizer @@ -116,10 +121,6 @@ type Config struct { AuditBackend audit.Backend // AuditPolicyChecker makes the decision of whether and how to audit log a request. AuditPolicyChecker auditpolicy.Checker - // SupportsBasicAuth indicates that's at least one Authenticator supports basic auth - // If this is true, a basic auth challenge is returned on authentication failure - // TODO(roberthbailey): Remove once the server no longer supports http basic auth. - SupportsBasicAuth bool // ExternalAddress is the host name to use for external (public internet) facing URLs (e.g. Swagger) // Will default to a value based on secure serving info and available ipv4 IPs. ExternalAddress string @@ -231,6 +232,21 @@ type SecureServingInfo struct { CipherSuites []uint16 } +type AuthenticationInfo struct { + // Authenticator determines which subject is making the request + Authenticator authenticator.Request + // SupportsBasicAuth indicates that's at least one Authenticator supports basic auth + // If this is true, a basic auth challenge is returned on authentication failure + // TODO(roberthbailey): Remove once the server no longer supports http basic auth. + SupportsBasicAuth bool +} + +type AuthorizationInfo struct { + // Authorizer determines whether the subject is allowed to make the request based only + // on the RequestURI + Authorizer authorizer.Authorizer +} + // NewConfig returns a Config struct with the default values func NewConfig(codecs serializer.CodecFactory) *Config { return &Config{ @@ -302,23 +318,23 @@ func DefaultSwaggerConfig() *swagger.Config { } } -func (c *Config) ApplyClientCert(clientCAFile string) (*Config, error) { - if c.SecureServingInfo != nil { +func (c *AuthenticationInfo) ApplyClientCert(clientCAFile string, servingInfo *SecureServingInfo) error { + if servingInfo != nil { if len(clientCAFile) > 0 { clientCAs, err := certutil.CertsFromFile(clientCAFile) if err != nil { - return nil, fmt.Errorf("unable to load client CA file: %v", err) + return fmt.Errorf("unable to load client CA file: %v", err) } - if c.SecureServingInfo.ClientCA == nil { - c.SecureServingInfo.ClientCA = x509.NewCertPool() + if servingInfo.ClientCA == nil { + servingInfo.ClientCA = x509.NewCertPool() } for _, cert := range clientCAs { - c.SecureServingInfo.ClientCA.AddCert(cert) + servingInfo.ClientCA.AddCert(cert) } } } - return c, nil + return nil } type completedConfig struct { @@ -385,7 +401,7 @@ func (c *Config) Complete(informers informers.SharedInformerFactory) CompletedCo } } if c.SwaggerConfig != nil && len(c.SwaggerConfig.WebServicesUrl) == 0 { - if c.SecureServingInfo != nil { + if c.SecureServing != nil { c.SwaggerConfig.WebServicesUrl = "https://" + c.ExternalAddress } else { c.SwaggerConfig.WebServicesUrl = "http://" + c.ExternalAddress @@ -397,7 +413,7 @@ func (c *Config) Complete(informers informers.SharedInformerFactory) CompletedCo // If the loopbackclientconfig is specified AND it has a token for use against the API server // wrap the authenticator and authorizer in loopback authentication logic - if c.Authenticator != nil && c.Authorizer != nil && c.LoopbackClientConfig != nil && len(c.LoopbackClientConfig.BearerToken) > 0 { + if c.Authentication.Authenticator != nil && c.Authorization.Authorizer != nil && c.LoopbackClientConfig != nil && len(c.LoopbackClientConfig.BearerToken) > 0 { privilegedLoopbackToken := c.LoopbackClientConfig.BearerToken var uid = uuid.NewRandom().String() tokens := make(map[string]*user.DefaultInfo) @@ -408,10 +424,10 @@ func (c *Config) Complete(informers informers.SharedInformerFactory) CompletedCo } tokenAuthenticator := authenticatorfactory.NewFromTokens(tokens) - c.Authenticator = authenticatorunion.New(tokenAuthenticator, c.Authenticator) + c.Authentication.Authenticator = authenticatorunion.New(tokenAuthenticator, c.Authentication.Authenticator) tokenAuthorizer := authorizerfactory.NewPrivilegedGroups(user.SystemPrivilegedGroup) - c.Authorizer = authorizerunion.New(tokenAuthorizer, c.Authorizer) + c.Authorization.Authorizer = authorizerunion.New(tokenAuthorizer, c.Authorization.Authorizer) } if c.RequestInfoResolver == nil { @@ -458,7 +474,7 @@ func (c completedConfig) New(name string, delegationTarget DelegationTarget) (*G minRequestTimeout: time.Duration(c.MinRequestTimeout) * time.Second, ShutdownTimeout: c.RequestTimeout, - SecureServingInfo: c.SecureServingInfo, + SecureServingInfo: c.SecureServing, ExternalAddress: c.ExternalAddress, Handler: apiServerHandler, @@ -530,19 +546,19 @@ func (c completedConfig) New(name string, delegationTarget DelegationTarget) (*G } func DefaultBuildHandlerChain(apiHandler http.Handler, c *Config) http.Handler { - handler := genericapifilters.WithAuthorization(apiHandler, c.RequestContextMapper, c.Authorizer, c.Serializer) + handler := genericapifilters.WithAuthorization(apiHandler, c.RequestContextMapper, c.Authorization.Authorizer, c.Serializer) handler = genericfilters.WithMaxInFlightLimit(handler, c.MaxRequestsInFlight, c.MaxMutatingRequestsInFlight, c.RequestContextMapper, c.LongRunningFunc) - handler = genericapifilters.WithImpersonation(handler, c.RequestContextMapper, c.Authorizer, c.Serializer) + handler = genericapifilters.WithImpersonation(handler, c.RequestContextMapper, c.Authorization.Authorizer, c.Serializer) if utilfeature.DefaultFeatureGate.Enabled(features.AdvancedAuditing) { handler = genericapifilters.WithAudit(handler, c.RequestContextMapper, c.AuditBackend, c.AuditPolicyChecker, c.LongRunningFunc) } else { handler = genericapifilters.WithLegacyAudit(handler, c.RequestContextMapper, c.LegacyAuditWriter) } - failedHandler := genericapifilters.Unauthorized(c.RequestContextMapper, c.Serializer, c.SupportsBasicAuth) + failedHandler := genericapifilters.Unauthorized(c.RequestContextMapper, c.Serializer, c.Authentication.SupportsBasicAuth) if utilfeature.DefaultFeatureGate.Enabled(features.AdvancedAuditing) { failedHandler = genericapifilters.WithFailedAuthenticationAudit(failedHandler, c.RequestContextMapper, c.AuditBackend, c.AuditPolicyChecker) } - handler = genericapifilters.WithAuthentication(handler, c.RequestContextMapper, c.Authenticator, failedHandler) + handler = genericapifilters.WithAuthentication(handler, c.RequestContextMapper, c.Authentication.Authenticator, failedHandler) handler = genericfilters.WithCORS(handler, c.CorsAllowedOriginList, nil, nil, nil, "true") handler = genericfilters.WithTimeoutForNonLongRunningRequests(handler, c.RequestContextMapper, c.LongRunningFunc, c.RequestTimeout) handler = genericfilters.WithWaitGroup(handler, c.RequestContextMapper, c.LongRunningFunc, c.HandlerChainWaitGroup) diff --git a/staging/src/k8s.io/apiserver/pkg/server/genericapiserver.go b/staging/src/k8s.io/apiserver/pkg/server/genericapiserver.go index 8235b26540f..38cd2e98179 100644 --- a/staging/src/k8s.io/apiserver/pkg/server/genericapiserver.go +++ b/staging/src/k8s.io/apiserver/pkg/server/genericapiserver.go @@ -310,7 +310,7 @@ func (s preparedGenericAPIServer) NonBlockingRun(stopCh <-chan struct{}) error { internalStopCh := make(chan struct{}) if s.SecureServingInfo != nil && s.Handler != nil { - if err := s.serveSecurely(internalStopCh); err != nil { + if err := s.SecureServingInfo.Serve(s.Handler, s.ShutdownTimeout, internalStopCh); err != nil { close(internalStopCh) return err } diff --git a/staging/src/k8s.io/apiserver/pkg/server/genericapiserver_test.go b/staging/src/k8s.io/apiserver/pkg/server/genericapiserver_test.go index 0ce483219d8..18761881b37 100644 --- a/staging/src/k8s.io/apiserver/pkg/server/genericapiserver_test.go +++ b/staging/src/k8s.io/apiserver/pkg/server/genericapiserver_test.go @@ -387,7 +387,7 @@ func TestNotRestRoutesHaveAuth(t *testing.T) { authz := mockAuthorizer{} config.LegacyAPIGroupPrefixes = sets.NewString("/apiPrefix") - config.Authorizer = &authz + config.Authorization.Authorizer = &authz config.EnableSwaggerUI = true config.EnableIndex = true diff --git a/staging/src/k8s.io/apiserver/pkg/server/options/BUILD b/staging/src/k8s.io/apiserver/pkg/server/options/BUILD index f026cd2d760..ea27ab891fa 100644 --- a/staging/src/k8s.io/apiserver/pkg/server/options/BUILD +++ b/staging/src/k8s.io/apiserver/pkg/server/options/BUILD @@ -15,6 +15,7 @@ go_library( "recommended.go", "server_run_options.go", "serving.go", + "serving_with_loopback.go", ], importpath = "k8s.io/apiserver/pkg/server/options", visibility = ["//visibility:public"], diff --git a/staging/src/k8s.io/apiserver/pkg/server/options/admission.go b/staging/src/k8s.io/apiserver/pkg/server/options/admission.go index ce5b01e4819..180ba4ffdc3 100644 --- a/staging/src/k8s.io/apiserver/pkg/server/options/admission.go +++ b/staging/src/k8s.io/apiserver/pkg/server/options/admission.go @@ -136,7 +136,7 @@ func (a *AdmissionOptions) ApplyTo( if err != nil { return err } - genericInitializer := initializer.New(clientset, informers, c.Authorizer, scheme) + genericInitializer := initializer.New(clientset, informers, c.Authorization.Authorizer, scheme) initializersChain := admission.PluginInitializers{} pluginInitializers = append(pluginInitializers, genericInitializer) initializersChain = append(initializersChain, pluginInitializers...) diff --git a/staging/src/k8s.io/apiserver/pkg/server/options/authentication.go b/staging/src/k8s.io/apiserver/pkg/server/options/authentication.go index 28c933bea54..c516a6bba42 100644 --- a/staging/src/k8s.io/apiserver/pkg/server/options/authentication.go +++ b/staging/src/k8s.io/apiserver/pkg/server/options/authentication.go @@ -32,6 +32,7 @@ import ( coreclient "k8s.io/client-go/kubernetes/typed/core/v1" "k8s.io/client-go/rest" "k8s.io/client-go/tools/clientcmd" + openapicommon "k8s.io/kube-openapi/pkg/common" ) type RequestHeaderAuthenticationOptions struct { @@ -146,7 +147,7 @@ func (s *DelegatingAuthenticationOptions) AddFlags(fs *pflag.FlagSet) { } -func (s *DelegatingAuthenticationOptions) ApplyTo(c *server.Config) error { +func (s *DelegatingAuthenticationOptions) ApplyTo(c *server.AuthenticationInfo, servingInfo *server.SecureServingInfo, openAPIConfig *openapicommon.Config) error { if s == nil { c.Authenticator = nil return nil @@ -156,8 +157,7 @@ func (s *DelegatingAuthenticationOptions) ApplyTo(c *server.Config) error { if err != nil { return err } - c, err = c.ApplyClientCert(clientCA.ClientCA) - if err != nil { + if err = c.ApplyClientCert(clientCA.ClientCA, servingInfo); err != nil { return fmt.Errorf("unable to load client CA file: %v", err) } @@ -165,8 +165,7 @@ func (s *DelegatingAuthenticationOptions) ApplyTo(c *server.Config) error { if err != nil { return err } - c, err = c.ApplyClientCert(requestHeader.ClientCAFile) - if err != nil { + if err = c.ApplyClientCert(requestHeader.ClientCAFile, servingInfo); err != nil { return fmt.Errorf("unable to load client CA file: %v", err) } @@ -180,8 +179,8 @@ func (s *DelegatingAuthenticationOptions) ApplyTo(c *server.Config) error { } c.Authenticator = authenticator - if c.OpenAPIConfig != nil { - c.OpenAPIConfig.SecurityDefinitions = securityDefinitions + if openAPIConfig != nil { + openAPIConfig.SecurityDefinitions = securityDefinitions } c.SupportsBasicAuth = false diff --git a/staging/src/k8s.io/apiserver/pkg/server/options/authorization.go b/staging/src/k8s.io/apiserver/pkg/server/options/authorization.go index 9a452d11e6b..fb8899bff9b 100644 --- a/staging/src/k8s.io/apiserver/pkg/server/options/authorization.go +++ b/staging/src/k8s.io/apiserver/pkg/server/options/authorization.go @@ -74,7 +74,7 @@ func (s *DelegatingAuthorizationOptions) AddFlags(fs *pflag.FlagSet) { "The duration to cache 'unauthorized' responses from the webhook authorizer.") } -func (s *DelegatingAuthorizationOptions) ApplyTo(c *server.Config) error { +func (s *DelegatingAuthorizationOptions) ApplyTo(c *server.AuthorizationInfo) error { if s == nil { c.Authorizer = authorizerfactory.NewAlwaysAllowAuthorizer() return nil diff --git a/staging/src/k8s.io/apiserver/pkg/server/options/recommended.go b/staging/src/k8s.io/apiserver/pkg/server/options/recommended.go index 148bfbdce5a..c2aa6d576a5 100644 --- a/staging/src/k8s.io/apiserver/pkg/server/options/recommended.go +++ b/staging/src/k8s.io/apiserver/pkg/server/options/recommended.go @@ -30,7 +30,7 @@ import ( // Each of them can be nil to leave the feature unconfigured on ApplyTo. type RecommendedOptions struct { Etcd *EtcdOptions - SecureServing *SecureServingOptions + SecureServing *SecureServingOptionsWithLoopback Authentication *DelegatingAuthenticationOptions Authorization *DelegatingAuthorizationOptions Audit *AuditOptions @@ -46,7 +46,7 @@ type RecommendedOptions struct { func NewRecommendedOptions(prefix string, codec runtime.Codec) *RecommendedOptions { return &RecommendedOptions{ Etcd: NewEtcdOptions(storagebackend.NewDefaultConfig(prefix, codec)), - SecureServing: NewSecureServingOptions(), + SecureServing: WithLoopback(NewSecureServingOptions()), Authentication: NewDelegatingAuthenticationOptions(), Authorization: NewDelegatingAuthorizationOptions(), Audit: NewAuditOptions(), @@ -78,10 +78,10 @@ func (o *RecommendedOptions) ApplyTo(config *server.RecommendedConfig, scheme *r if err := o.SecureServing.ApplyTo(&config.Config); err != nil { return err } - if err := o.Authentication.ApplyTo(&config.Config); err != nil { + if err := o.Authentication.ApplyTo(&config.Config.Authentication, config.SecureServing, config.OpenAPIConfig); err != nil { return err } - if err := o.Authorization.ApplyTo(&config.Config); err != nil { + if err := o.Authorization.ApplyTo(&config.Config.Authorization); err != nil { return err } if err := o.Audit.ApplyTo(&config.Config); err != nil { diff --git a/staging/src/k8s.io/apiserver/pkg/server/options/serving.go b/staging/src/k8s.io/apiserver/pkg/server/options/serving.go index edf2b02f5cf..a1addcbe75f 100644 --- a/staging/src/k8s.io/apiserver/pkg/server/options/serving.go +++ b/staging/src/k8s.io/apiserver/pkg/server/options/serving.go @@ -24,7 +24,6 @@ import ( "strconv" "github.com/golang/glog" - "github.com/pborman/uuid" "github.com/spf13/pflag" utilnet "k8s.io/apimachinery/pkg/util/net" @@ -110,9 +109,7 @@ func (s *SecureServingOptions) AddFlags(fs *pflag.FlagSet) { } fs.IPVar(&s.BindAddress, "bind-address", s.BindAddress, ""+ - "The IP address on which to listen for the --secure-port port. The "+ - "associated interface(s) must be reachable by the rest of the cluster, and by CLI/web "+ - "clients. If blank, all interfaces will be used (0.0.0.0).") + "The IP address on which to listen for the --secure-port port. If blank, all interfaces will be used (0.0.0.0).") fs.IntVar(&s.BindPort, "secure-port", s.BindPort, ""+ "The port on which to serve HTTPS with authentication and authorization. If 0, "+ @@ -156,7 +153,7 @@ func (s *SecureServingOptions) AddFlags(fs *pflag.FlagSet) { } // ApplyTo fills up serving information in the server configuration. -func (s *SecureServingOptions) ApplyTo(c *server.Config) error { +func (s *SecureServingOptions) ApplyTo(config **server.SecureServingInfo) error { if s == nil { return nil } @@ -173,42 +170,10 @@ func (s *SecureServingOptions) ApplyTo(c *server.Config) error { } } - if err := s.applyServingInfoTo(c); err != nil { - return err + *config = &server.SecureServingInfo{ + Listener: s.Listener, } - - c.SecureServingInfo.Listener = s.Listener - - // create self-signed cert+key with the fake server.LoopbackClientServerNameOverride and - // let the server return it when the loopback client connects. - certPem, keyPem, err := certutil.GenerateSelfSignedCertKey(server.LoopbackClientServerNameOverride, nil, nil) - if err != nil { - return fmt.Errorf("failed to generate self-signed certificate for loopback connection: %v", err) - } - tlsCert, err := tls.X509KeyPair(certPem, keyPem) - if err != nil { - return fmt.Errorf("failed to generate self-signed certificate for loopback connection: %v", err) - } - - secureLoopbackClientConfig, err := c.SecureServingInfo.NewLoopbackClientConfig(uuid.NewRandom().String(), certPem) - switch { - // if we failed and there's no fallback loopback client config, we need to fail - case err != nil && c.LoopbackClientConfig == nil: - return err - - // if we failed, but we already have a fallback loopback client config (usually insecure), allow it - case err != nil && c.LoopbackClientConfig != nil: - - default: - c.LoopbackClientConfig = secureLoopbackClientConfig - c.SecureServingInfo.SNICerts[server.LoopbackClientServerNameOverride] = &tlsCert - } - - return nil -} - -func (s *SecureServingOptions) applyServingInfoTo(c *server.Config) error { - secureServingInfo := &server.SecureServingInfo{} + c := *config serverCertFile, serverKeyFile := s.ServerCert.CertKey.CertFile, s.ServerCert.CertKey.KeyFile // load main cert @@ -217,7 +182,7 @@ func (s *SecureServingOptions) applyServingInfoTo(c *server.Config) error { if err != nil { return fmt.Errorf("unable to load server certificate: %v", err) } - secureServingInfo.Cert = &tlsCert + c.Cert = &tlsCert } if len(s.CipherSuites) != 0 { @@ -225,11 +190,11 @@ func (s *SecureServingOptions) applyServingInfoTo(c *server.Config) error { if err != nil { return err } - secureServingInfo.CipherSuites = cipherSuites + c.CipherSuites = cipherSuites } var err error - secureServingInfo.MinTLSVersion, err = utilflag.TLSVersion(s.MinTLSVersion) + c.MinTLSVersion, err = utilflag.TLSVersion(s.MinTLSVersion) if err != nil { return err } @@ -246,14 +211,11 @@ func (s *SecureServingOptions) applyServingInfoTo(c *server.Config) error { return fmt.Errorf("failed to load SNI cert and key: %v", err) } } - secureServingInfo.SNICerts, err = server.GetNamedCertificateMap(namedTLSCerts) + c.SNICerts, err = server.GetNamedCertificateMap(namedTLSCerts) if err != nil { return err } - c.SecureServingInfo = secureServingInfo - c.ReadWritePort = s.BindPort - return nil } diff --git a/staging/src/k8s.io/apiserver/pkg/server/options/serving_test.go b/staging/src/k8s.io/apiserver/pkg/server/options/serving_test.go index 86d38474547..01a443a33de 100644 --- a/staging/src/k8s.io/apiserver/pkg/server/options/serving_test.go +++ b/staging/src/k8s.io/apiserver/pkg/server/options/serving_test.go @@ -32,6 +32,7 @@ import ( "os" "path/filepath" "reflect" + "strconv" "strings" "testing" "time" @@ -47,7 +48,6 @@ import ( utilflag "k8s.io/apiserver/pkg/util/flag" "k8s.io/client-go/discovery" restclient "k8s.io/client-go/rest" - "strconv" ) func setUp(t *testing.T) Config { @@ -471,7 +471,7 @@ NextTest: config.Version = &v config.EnableIndex = true - secureOptions := &SecureServingOptions{ + secureOptions := WithLoopback(&SecureServingOptions{ BindAddress: net.ParseIP("127.0.0.1"), BindPort: 6443, ServerCert: GeneratableKeyCert{ @@ -481,7 +481,7 @@ NextTest: }, }, SNICertKeys: namedCertKeys, - } + }) // use a random free port ln, err := net.Listen("tcp", "127.0.0.1:0") if err != nil { diff --git a/staging/src/k8s.io/apiserver/pkg/server/options/serving_with_loopback.go b/staging/src/k8s.io/apiserver/pkg/server/options/serving_with_loopback.go new file mode 100644 index 00000000000..8d249cb54b4 --- /dev/null +++ b/staging/src/k8s.io/apiserver/pkg/server/options/serving_with_loopback.go @@ -0,0 +1,79 @@ +/* +Copyright 2018 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 options + +import ( + "crypto/tls" + "fmt" + + "github.com/pborman/uuid" + + "k8s.io/apiserver/pkg/server" + certutil "k8s.io/client-go/util/cert" +) + +type SecureServingOptionsWithLoopback struct { + *SecureServingOptions +} + +func WithLoopback(o *SecureServingOptions) *SecureServingOptionsWithLoopback { + return &SecureServingOptionsWithLoopback{o} +} + +// ApplyTo fills up serving information in the server configuration. +func (s *SecureServingOptionsWithLoopback) ApplyTo(c *server.Config) error { + if s == nil || s.SecureServingOptions == nil { + return nil + } + + if err := s.SecureServingOptions.ApplyTo(&c.SecureServing); err != nil { + return err + } + + if c.SecureServing == nil { + return nil + } + + c.ReadWritePort = s.BindPort + + // create self-signed cert+key with the fake server.LoopbackClientServerNameOverride and + // let the server return it when the loopback client connects. + certPem, keyPem, err := certutil.GenerateSelfSignedCertKey(server.LoopbackClientServerNameOverride, nil, nil) + if err != nil { + return fmt.Errorf("failed to generate self-signed certificate for loopback connection: %v", err) + } + tlsCert, err := tls.X509KeyPair(certPem, keyPem) + if err != nil { + return fmt.Errorf("failed to generate self-signed certificate for loopback connection: %v", err) + } + + secureLoopbackClientConfig, err := c.SecureServing.NewLoopbackClientConfig(uuid.NewRandom().String(), certPem) + switch { + // if we failed and there's no fallback loopback client config, we need to fail + case err != nil && c.LoopbackClientConfig == nil: + return err + + // if we failed, but we already have a fallback loopback client config (usually insecure), allow it + case err != nil && c.LoopbackClientConfig != nil: + + default: + c.LoopbackClientConfig = secureLoopbackClientConfig + c.SecureServing.SNICerts[server.LoopbackClientServerNameOverride] = &tlsCert + } + + return nil +} diff --git a/staging/src/k8s.io/apiserver/pkg/server/serve.go b/staging/src/k8s.io/apiserver/pkg/server/serve.go index dcb4de1e592..71a3a34793b 100644 --- a/staging/src/k8s.io/apiserver/pkg/server/serve.go +++ b/staging/src/k8s.io/apiserver/pkg/server/serve.go @@ -39,17 +39,17 @@ const ( // serveSecurely runs the secure http server. It fails only if certificates cannot // be loaded or the initial listen call fails. The actual server loop (stoppable by closing // stopCh) runs in a go routine, i.e. serveSecurely does not block. -func (s *GenericAPIServer) serveSecurely(stopCh <-chan struct{}) error { - if s.SecureServingInfo.Listener == nil { +func (s *SecureServingInfo) Serve(handler http.Handler, shutdownTimeout time.Duration, stopCh <-chan struct{}) error { + if s.Listener == nil { return fmt.Errorf("listener must not be nil") } secureServer := &http.Server{ - Addr: s.SecureServingInfo.Listener.Addr().String(), - Handler: s.Handler, + Addr: s.Listener.Addr().String(), + Handler: handler, MaxHeaderBytes: 1 << 20, TLSConfig: &tls.Config{ - NameToCertificate: s.SecureServingInfo.SNICerts, + NameToCertificate: s.SNICerts, // Can't use SSLv3 because of POODLE and BEAST // Can't use TLSv1.0 because of POODLE and BEAST using CBC cipher // Can't use TLSv1.1 because of RC4 cipher usage @@ -59,41 +59,41 @@ func (s *GenericAPIServer) serveSecurely(stopCh <-chan struct{}) error { }, } - if s.SecureServingInfo.MinTLSVersion > 0 { - secureServer.TLSConfig.MinVersion = s.SecureServingInfo.MinTLSVersion + if s.MinTLSVersion > 0 { + secureServer.TLSConfig.MinVersion = s.MinTLSVersion } - if len(s.SecureServingInfo.CipherSuites) > 0 { - secureServer.TLSConfig.CipherSuites = s.SecureServingInfo.CipherSuites + if len(s.CipherSuites) > 0 { + secureServer.TLSConfig.CipherSuites = s.CipherSuites } - if s.SecureServingInfo.Cert != nil { - secureServer.TLSConfig.Certificates = []tls.Certificate{*s.SecureServingInfo.Cert} + if s.Cert != nil { + secureServer.TLSConfig.Certificates = []tls.Certificate{*s.Cert} } // append all named certs. Otherwise, the go tls stack will think no SNI processing // is necessary because there is only one cert anyway. // Moreover, if ServerCert.CertFile/ServerCert.KeyFile are not set, the first SNI // cert will become the default cert. That's what we expect anyway. - for _, c := range s.SecureServingInfo.SNICerts { + for _, c := range s.SNICerts { secureServer.TLSConfig.Certificates = append(secureServer.TLSConfig.Certificates, *c) } - if s.SecureServingInfo.ClientCA != nil { + if s.ClientCA != nil { // Populate PeerCertificates in requests, but don't reject connections without certificates // This allows certificates to be validated by authenticators, while still allowing other auth types secureServer.TLSConfig.ClientAuth = tls.RequestClientCert // Specify allowed CAs for client certificates - secureServer.TLSConfig.ClientCAs = s.SecureServingInfo.ClientCA + secureServer.TLSConfig.ClientCAs = s.ClientCA } glog.Infof("Serving securely on %s", secureServer.Addr) - err := RunServer(secureServer, s.SecureServingInfo.Listener, s.ShutdownTimeout, stopCh) - return err + return RunServer(secureServer, s.Listener, shutdownTimeout, stopCh) } // RunServer listens on the given port if listener is not given, // then spawns a go-routine continuously serving // until the stopCh is closed. This function does not block. +// TODO: make private when insecure serving is gone from the kube-apiserver func RunServer( server *http.Server, ln net.Listener, diff --git a/test/integration/auth/accessreview_test.go b/test/integration/auth/accessreview_test.go index c5e1fbe32d1..f5835aaec3f 100644 --- a/test/integration/auth/accessreview_test.go +++ b/test/integration/auth/accessreview_test.go @@ -55,8 +55,8 @@ func alwaysAlice(req *http.Request) (user.Info, bool, error) { func TestSubjectAccessReview(t *testing.T) { masterConfig := framework.NewIntegrationTestMasterConfig() - masterConfig.GenericConfig.Authenticator = authenticator.RequestFunc(alwaysAlice) - masterConfig.GenericConfig.Authorizer = sarAuthorizer{} + masterConfig.GenericConfig.Authentication.Authenticator = authenticator.RequestFunc(alwaysAlice) + masterConfig.GenericConfig.Authorization.Authorizer = sarAuthorizer{} masterConfig.GenericConfig.AdmissionControl = admit.NewAlwaysAdmit() _, s, closeFn := framework.RunAMaster(masterConfig) defer closeFn() @@ -147,10 +147,10 @@ func TestSubjectAccessReview(t *testing.T) { func TestSelfSubjectAccessReview(t *testing.T) { username := "alice" masterConfig := framework.NewIntegrationTestMasterConfig() - masterConfig.GenericConfig.Authenticator = authenticator.RequestFunc(func(req *http.Request) (user.Info, bool, error) { + masterConfig.GenericConfig.Authentication.Authenticator = authenticator.RequestFunc(func(req *http.Request) (user.Info, bool, error) { return &user.DefaultInfo{Name: username}, true, nil }) - masterConfig.GenericConfig.Authorizer = sarAuthorizer{} + masterConfig.GenericConfig.Authorization.Authorizer = sarAuthorizer{} masterConfig.GenericConfig.AdmissionControl = admit.NewAlwaysAdmit() _, s, closeFn := framework.RunAMaster(masterConfig) defer closeFn() @@ -229,8 +229,8 @@ func TestSelfSubjectAccessReview(t *testing.T) { func TestLocalSubjectAccessReview(t *testing.T) { masterConfig := framework.NewIntegrationTestMasterConfig() - masterConfig.GenericConfig.Authenticator = authenticator.RequestFunc(alwaysAlice) - masterConfig.GenericConfig.Authorizer = sarAuthorizer{} + masterConfig.GenericConfig.Authentication.Authenticator = authenticator.RequestFunc(alwaysAlice) + masterConfig.GenericConfig.Authorization.Authorizer = sarAuthorizer{} masterConfig.GenericConfig.AdmissionControl = admit.NewAlwaysAdmit() _, s, closeFn := framework.RunAMaster(masterConfig) defer closeFn() diff --git a/test/integration/auth/auth_test.go b/test/integration/auth/auth_test.go index 41c53e3bf2b..3d2141ce5aa 100644 --- a/test/integration/auth/auth_test.go +++ b/test/integration/auth/auth_test.go @@ -500,7 +500,7 @@ func getPreviousResourceVersionKey(url, id string) string { func TestAuthModeAlwaysDeny(t *testing.T) { // Set up a master masterConfig := framework.NewIntegrationTestMasterConfig() - masterConfig.GenericConfig.Authorizer = authorizerfactory.NewAlwaysDenyAuthorizer() + masterConfig.GenericConfig.Authorization.Authorizer = authorizerfactory.NewAlwaysDenyAuthorizer() _, s, closeFn := framework.RunAMaster(masterConfig) defer closeFn() @@ -549,8 +549,8 @@ func TestAliceNotForbiddenOrUnauthorized(t *testing.T) { // Set up a master masterConfig := framework.NewIntegrationTestMasterConfig() - masterConfig.GenericConfig.Authenticator = getTestTokenAuth() - masterConfig.GenericConfig.Authorizer = allowAliceAuthorizer{} + masterConfig.GenericConfig.Authentication.Authenticator = getTestTokenAuth() + masterConfig.GenericConfig.Authorization.Authorizer = allowAliceAuthorizer{} masterConfig.GenericConfig.AdmissionControl = admit.NewAlwaysAdmit() _, s, closeFn := framework.RunAMaster(masterConfig) defer closeFn() @@ -619,8 +619,8 @@ func TestAliceNotForbiddenOrUnauthorized(t *testing.T) { func TestBobIsForbidden(t *testing.T) { // This file has alice and bob in it. masterConfig := framework.NewIntegrationTestMasterConfig() - masterConfig.GenericConfig.Authenticator = getTestTokenAuth() - masterConfig.GenericConfig.Authorizer = allowAliceAuthorizer{} + masterConfig.GenericConfig.Authentication.Authenticator = getTestTokenAuth() + masterConfig.GenericConfig.Authorization.Authorizer = allowAliceAuthorizer{} _, s, closeFn := framework.RunAMaster(masterConfig) defer closeFn() @@ -663,8 +663,8 @@ func TestUnknownUserIsUnauthorized(t *testing.T) { // Set up a master masterConfig := framework.NewIntegrationTestMasterConfig() - masterConfig.GenericConfig.Authenticator = getTestTokenAuth() - masterConfig.GenericConfig.Authorizer = allowAliceAuthorizer{} + masterConfig.GenericConfig.Authentication.Authenticator = getTestTokenAuth() + masterConfig.GenericConfig.Authorization.Authorizer = allowAliceAuthorizer{} _, s, closeFn := framework.RunAMaster(masterConfig) defer closeFn() @@ -725,8 +725,8 @@ func (impersonateAuthorizer) Authorize(a authorizer.Attributes) (authorizer.Deci func TestImpersonateIsForbidden(t *testing.T) { // Set up a master masterConfig := framework.NewIntegrationTestMasterConfig() - masterConfig.GenericConfig.Authenticator = getTestTokenAuth() - masterConfig.GenericConfig.Authorizer = impersonateAuthorizer{} + masterConfig.GenericConfig.Authentication.Authenticator = getTestTokenAuth() + masterConfig.GenericConfig.Authorization.Authorizer = impersonateAuthorizer{} _, s, closeFn := framework.RunAMaster(masterConfig) defer closeFn() @@ -872,8 +872,8 @@ func TestAuthorizationAttributeDetermination(t *testing.T) { // Set up a master masterConfig := framework.NewIntegrationTestMasterConfig() - masterConfig.GenericConfig.Authenticator = getTestTokenAuth() - masterConfig.GenericConfig.Authorizer = trackingAuthorizer + masterConfig.GenericConfig.Authentication.Authenticator = getTestTokenAuth() + masterConfig.GenericConfig.Authorization.Authorizer = trackingAuthorizer _, s, closeFn := framework.RunAMaster(masterConfig) defer closeFn() @@ -938,8 +938,8 @@ func TestNamespaceAuthorization(t *testing.T) { // Set up a master masterConfig := framework.NewIntegrationTestMasterConfig() - masterConfig.GenericConfig.Authenticator = getTestTokenAuth() - masterConfig.GenericConfig.Authorizer = a + masterConfig.GenericConfig.Authentication.Authenticator = getTestTokenAuth() + masterConfig.GenericConfig.Authorization.Authorizer = a _, s, closeFn := framework.RunAMaster(masterConfig) defer closeFn() @@ -1036,8 +1036,8 @@ func TestKindAuthorization(t *testing.T) { // Set up a master masterConfig := framework.NewIntegrationTestMasterConfig() - masterConfig.GenericConfig.Authenticator = getTestTokenAuth() - masterConfig.GenericConfig.Authorizer = a + masterConfig.GenericConfig.Authentication.Authenticator = getTestTokenAuth() + masterConfig.GenericConfig.Authorization.Authorizer = a _, s, closeFn := framework.RunAMaster(masterConfig) defer closeFn() @@ -1120,8 +1120,8 @@ func TestReadOnlyAuthorization(t *testing.T) { // Set up a master masterConfig := framework.NewIntegrationTestMasterConfig() - masterConfig.GenericConfig.Authenticator = getTestTokenAuth() - masterConfig.GenericConfig.Authorizer = a + masterConfig.GenericConfig.Authentication.Authenticator = getTestTokenAuth() + masterConfig.GenericConfig.Authorization.Authorizer = a _, s, closeFn := framework.RunAMaster(masterConfig) defer closeFn() @@ -1179,8 +1179,8 @@ func TestWebhookTokenAuthenticator(t *testing.T) { // Set up a master masterConfig := framework.NewIntegrationTestMasterConfig() - masterConfig.GenericConfig.Authenticator = authenticator - masterConfig.GenericConfig.Authorizer = allowAliceAuthorizer{} + masterConfig.GenericConfig.Authentication.Authenticator = authenticator + masterConfig.GenericConfig.Authorization.Authorizer = allowAliceAuthorizer{} _, s, closeFn := framework.RunAMaster(masterConfig) defer closeFn() diff --git a/test/integration/auth/bootstraptoken_test.go b/test/integration/auth/bootstraptoken_test.go index 43b17c71128..38139adc71e 100644 --- a/test/integration/auth/bootstraptoken_test.go +++ b/test/integration/auth/bootstraptoken_test.go @@ -125,7 +125,7 @@ func TestBootstrapTokenAuth(t *testing.T) { authenticator := bearertoken.New(bootstrap.NewTokenAuthenticator(bootstrapSecrets{test.secret})) // Set up a master masterConfig := framework.NewIntegrationTestMasterConfig() - masterConfig.GenericConfig.Authenticator = authenticator + masterConfig.GenericConfig.Authentication.Authenticator = authenticator masterConfig.GenericConfig.AdmissionControl = admit.NewAlwaysAdmit() _, s, closeFn := framework.RunAMaster(masterConfig) defer closeFn() diff --git a/test/integration/auth/node_test.go b/test/integration/auth/node_test.go index 7698ff1be4f..a17e9605072 100644 --- a/test/integration/auth/node_test.go +++ b/test/integration/auth/node_test.go @@ -101,8 +101,8 @@ func TestNodeAuthorizer(t *testing.T) { // Start the server masterConfig := framework.NewIntegrationTestMasterConfig() - masterConfig.GenericConfig.Authenticator = authenticator - masterConfig.GenericConfig.Authorizer = nodeRBACAuthorizer + masterConfig.GenericConfig.Authentication.Authenticator = authenticator + masterConfig.GenericConfig.Authorization.Authorizer = nodeRBACAuthorizer masterConfig.GenericConfig.AdmissionControl = nodeRestrictionAdmission _, _, closeFn := framework.RunAMasterUsingServer(masterConfig, apiServer, h) diff --git a/test/integration/auth/rbac_test.go b/test/integration/auth/rbac_test.go index ea5f9594016..448b51c93a8 100644 --- a/test/integration/auth/rbac_test.go +++ b/test/integration/auth/rbac_test.go @@ -414,8 +414,8 @@ func TestRBAC(t *testing.T) { for i, tc := range tests { // Create an API Server. masterConfig := framework.NewIntegrationTestMasterConfig() - masterConfig.GenericConfig.Authorizer = newRBACAuthorizer(masterConfig) - masterConfig.GenericConfig.Authenticator = bearertoken.New(tokenfile.New(map[string]*user.DefaultInfo{ + masterConfig.GenericConfig.Authorization.Authorizer = newRBACAuthorizer(masterConfig) + masterConfig.GenericConfig.Authentication.Authenticator = bearertoken.New(tokenfile.New(map[string]*user.DefaultInfo{ superUser: {Name: "admin", Groups: []string{"system:masters"}}, "any-rolebinding-writer": {Name: "any-rolebinding-writer"}, "any-rolebinding-writer-namespace": {Name: "any-rolebinding-writer-namespace"}, @@ -517,8 +517,8 @@ func TestBootstrapping(t *testing.T) { superUser := "admin/system:masters" masterConfig := framework.NewIntegrationTestMasterConfig() - masterConfig.GenericConfig.Authorizer = newRBACAuthorizer(masterConfig) - masterConfig.GenericConfig.Authenticator = bearertoken.New(tokenfile.New(map[string]*user.DefaultInfo{ + masterConfig.GenericConfig.Authorization.Authorizer = newRBACAuthorizer(masterConfig) + masterConfig.GenericConfig.Authentication.Authenticator = bearertoken.New(tokenfile.New(map[string]*user.DefaultInfo{ superUser: {Name: "admin", Groups: []string{"system:masters"}}, })) _, s, closeFn := framework.RunAMaster(masterConfig) diff --git a/test/integration/framework/master_utils.go b/test/integration/framework/master_utils.go index 807c902c9e9..77f2ff68291 100644 --- a/test/integration/framework/master_utils.go +++ b/test/integration/framework/master_utils.go @@ -160,17 +160,17 @@ func startMasterOrDie(masterConfig *master.Config, incomingServer *httptest.Serv } tokenAuthenticator := authenticatorfactory.NewFromTokens(tokens) - if masterConfig.GenericConfig.Authenticator == nil { - masterConfig.GenericConfig.Authenticator = authenticatorunion.New(tokenAuthenticator, authauthenticator.RequestFunc(alwaysEmpty)) + if masterConfig.GenericConfig.Authentication.Authenticator == nil { + masterConfig.GenericConfig.Authentication.Authenticator = authenticatorunion.New(tokenAuthenticator, authauthenticator.RequestFunc(alwaysEmpty)) } else { - masterConfig.GenericConfig.Authenticator = authenticatorunion.New(tokenAuthenticator, masterConfig.GenericConfig.Authenticator) + masterConfig.GenericConfig.Authentication.Authenticator = authenticatorunion.New(tokenAuthenticator, masterConfig.GenericConfig.Authentication.Authenticator) } - if masterConfig.GenericConfig.Authorizer != nil { + if masterConfig.GenericConfig.Authorization.Authorizer != nil { tokenAuthorizer := authorizerfactory.NewPrivilegedGroups(user.SystemPrivilegedGroup) - masterConfig.GenericConfig.Authorizer = authorizerunion.New(tokenAuthorizer, masterConfig.GenericConfig.Authorizer) + masterConfig.GenericConfig.Authorization.Authorizer = authorizerunion.New(tokenAuthorizer, masterConfig.GenericConfig.Authorization.Authorizer) } else { - masterConfig.GenericConfig.Authorizer = alwaysAllow{} + masterConfig.GenericConfig.Authorization.Authorizer = alwaysAllow{} } masterConfig.GenericConfig.LoopbackClientConfig.BearerToken = privilegedLoopbackToken @@ -281,7 +281,7 @@ func NewMasterConfig() *master.Config { genericConfig := genericapiserver.NewConfig(legacyscheme.Codecs) kubeVersion := version.Get() genericConfig.Version = &kubeVersion - genericConfig.Authorizer = authorizerfactory.NewAlwaysAllowAuthorizer() + genericConfig.Authorization.Authorizer = authorizerfactory.NewAlwaysAllowAuthorizer() genericConfig.AdmissionControl = admit.NewAlwaysAdmit() genericConfig.EnableMetrics = true diff --git a/test/integration/master/synthetic_master_test.go b/test/integration/master/synthetic_master_test.go index aa063be5d2e..90d5350d6f3 100644 --- a/test/integration/master/synthetic_master_test.go +++ b/test/integration/master/synthetic_master_test.go @@ -134,7 +134,7 @@ func TestEmptyList(t *testing.T) { func initStatusForbiddenMasterCongfig() *master.Config { masterConfig := framework.NewIntegrationTestMasterConfig() - masterConfig.GenericConfig.Authorizer = authorizerfactory.NewAlwaysDenyAuthorizer() + masterConfig.GenericConfig.Authorization.Authorizer = authorizerfactory.NewAlwaysDenyAuthorizer() return masterConfig } @@ -143,8 +143,8 @@ func initUnauthorizedMasterCongfig() *master.Config { tokenAuthenticator := tokentest.New() tokenAuthenticator.Tokens[AliceToken] = &user.DefaultInfo{Name: "alice", UID: "1"} tokenAuthenticator.Tokens[BobToken] = &user.DefaultInfo{Name: "bob", UID: "2"} - masterConfig.GenericConfig.Authenticator = group.NewGroupAdder(bearertoken.New(tokenAuthenticator), []string{user.AllAuthenticated}) - masterConfig.GenericConfig.Authorizer = allowAliceAuthorizer{} + masterConfig.GenericConfig.Authentication.Authenticator = group.NewGroupAdder(bearertoken.New(tokenAuthenticator), []string{user.AllAuthenticated}) + masterConfig.GenericConfig.Authorization.Authorizer = allowAliceAuthorizer{} return masterConfig } diff --git a/test/integration/serviceaccount/service_account_test.go b/test/integration/serviceaccount/service_account_test.go index 68655d2c1ec..7bd3bacb236 100644 --- a/test/integration/serviceaccount/service_account_test.go +++ b/test/integration/serviceaccount/service_account_test.go @@ -425,8 +425,8 @@ func startServiceAccountTestServer(t *testing.T) (*clientset.Clientset, restclie masterConfig := framework.NewMasterConfig() masterConfig.GenericConfig.EnableIndex = true - masterConfig.GenericConfig.Authenticator = authenticator - masterConfig.GenericConfig.Authorizer = authorizer + masterConfig.GenericConfig.Authentication.Authenticator = authenticator + masterConfig.GenericConfig.Authorization.Authorizer = authorizer masterConfig.GenericConfig.AdmissionControl = serviceAccountAdmission framework.RunAMasterUsingServer(masterConfig, apiServer, h)