diff --git a/cmd/kube-apiserver/app/server.go b/cmd/kube-apiserver/app/server.go index d7f7f2fd2eb..69588b0d158 100644 --- a/cmd/kube-apiserver/app/server.go +++ b/cmd/kube-apiserver/app/server.go @@ -96,14 +96,14 @@ func Run(s *options.ServerRunOptions) error { genericapiserver.DefaultAndValidateRunOptions(s.GenericServerRunOptions) - genericConfig, err := genericapiserver.NewConfig(). // create the new config - ApplyOptions(s.GenericServerRunOptions). // apply the options selected - ApplyInsecureServingOptions(s.InsecureServing). - ApplyAuthenticationOptions(s.Authentication). - ApplySecureServingOptions(s.SecureServing) - if err != nil { + genericConfig := genericapiserver.NewConfig(). // create the new config + ApplyOptions(s.GenericServerRunOptions). // apply the options selected + ApplyInsecureServingOptions(s.InsecureServing) + + if _, err := genericConfig.ApplySecureServingOptions(s.SecureServing); err != nil { return fmt.Errorf("failed to configure https: %s", err) } + genericConfig.ApplyAuthenticationOptions(s.Authentication) capabilities.Initialize(capabilities.Capabilities{ AllowPrivileged: s.AllowPrivileged, diff --git a/examples/apiserver/apiserver.go b/examples/apiserver/apiserver.go index 76044259fd8..6b0460020c6 100644 --- a/examples/apiserver/apiserver.go +++ b/examples/apiserver/apiserver.go @@ -99,14 +99,14 @@ func (serverOptions *ServerRunOptions) Run(stopCh <-chan struct{}) error { glog.Fatalf("Error creating self-signed certificates: %v", err) } - config, err := genericapiserver.NewConfig(). + config := genericapiserver.NewConfig(). ApplyOptions(serverOptions.GenericServerRunOptions). - ApplyInsecureServingOptions(serverOptions.InsecureServing). - ApplyAuthenticationOptions(serverOptions.Authentication). - ApplySecureServingOptions(serverOptions.SecureServing) - if err != nil { + ApplyInsecureServingOptions(serverOptions.InsecureServing) + + if _, err := config.ApplySecureServingOptions(serverOptions.SecureServing); err != nil { return fmt.Errorf("failed to configure https: %s", err) } + config.ApplyAuthenticationOptions(serverOptions.Authentication) config.Authorizer = authorizer.NewAlwaysAllowAuthorizer() s, err := config.Complete().New() diff --git a/federation/cmd/federation-apiserver/app/server.go b/federation/cmd/federation-apiserver/app/server.go index fd8c75215cd..bf444833909 100644 --- a/federation/cmd/federation-apiserver/app/server.go +++ b/federation/cmd/federation-apiserver/app/server.go @@ -78,14 +78,14 @@ func Run(s *options.ServerRunOptions) error { } genericapiserver.DefaultAndValidateRunOptions(s.GenericServerRunOptions) - genericConfig, err := genericapiserver.NewConfig(). // create the new config - ApplyOptions(s.GenericServerRunOptions). // apply the options selected - ApplyInsecureServingOptions(s.InsecureServing). - ApplyAuthenticationOptions(s.Authentication). - ApplySecureServingOptions(s.SecureServing) - if err != nil { + genericConfig := genericapiserver.NewConfig(). // create the new config + ApplyOptions(s.GenericServerRunOptions). // apply the options selected + ApplyInsecureServingOptions(s.InsecureServing) + + if _, err := genericConfig.ApplySecureServingOptions(s.SecureServing); err != nil { return fmt.Errorf("failed to configure https: %s", err) } + genericConfig.ApplyAuthenticationOptions(s.Authentication) // TODO: register cluster federation resources here. resourceConfig := genericapiserver.NewResourceConfig() diff --git a/pkg/apiserver/authenticator/delegating.go b/pkg/apiserver/authenticator/delegating.go index 185323bc869..74f7b0cdcbd 100644 --- a/pkg/apiserver/authenticator/delegating.go +++ b/pkg/apiserver/authenticator/delegating.go @@ -30,6 +30,7 @@ import ( authenticationclient "k8s.io/kubernetes/pkg/client/clientset_generated/release_1_5/typed/authentication/v1beta1" "k8s.io/kubernetes/pkg/util/cert" "k8s.io/kubernetes/plugin/pkg/auth/authenticator/request/anonymous" + "k8s.io/kubernetes/plugin/pkg/auth/authenticator/request/headerrequest" unionauth "k8s.io/kubernetes/plugin/pkg/auth/authenticator/request/union" "k8s.io/kubernetes/plugin/pkg/auth/authenticator/request/x509" webhooktoken "k8s.io/kubernetes/plugin/pkg/auth/authenticator/token/webhook" @@ -47,12 +48,30 @@ type DelegatingAuthenticatorConfig struct { // ClientCAFile is the CA bundle file used to authenticate client certificates ClientCAFile string + + RequestHeaderConfig *RequestHeaderConfig } func (c DelegatingAuthenticatorConfig) New() (authenticator.Request, *spec.SecurityDefinitions, error) { authenticators := []authenticator.Request{} securityDefinitions := spec.SecurityDefinitions{} + // front-proxy first, then remote + // Add the front proxy authenticator if requested + if c.RequestHeaderConfig != nil { + requestHeaderAuthenticator, err := headerrequest.NewSecure( + c.RequestHeaderConfig.ClientCA, + c.RequestHeaderConfig.AllowedClientNames, + c.RequestHeaderConfig.UsernameHeaders, + c.RequestHeaderConfig.GroupHeaders, + c.RequestHeaderConfig.ExtraHeaderPrefixes, + ) + if err != nil { + return nil, nil, err + } + authenticators = append(authenticators, requestHeaderAuthenticator) + } + // x509 client cert auth if len(c.ClientCAFile) > 0 { clientCAs, err := cert.NewPool(c.ClientCAFile) @@ -93,5 +112,4 @@ func (c DelegatingAuthenticatorConfig) New() (authenticator.Request, *spec.Secur authenticator = unionauth.NewFailOnError(authenticator, anonymous.NewAuthenticator()) } return authenticator, &securityDefinitions, nil - } diff --git a/pkg/genericapiserver/options/authentication.go b/pkg/genericapiserver/options/authentication.go index 3239f33b047..9d0952f4091 100644 --- a/pkg/genericapiserver/options/authentication.go +++ b/pkg/genericapiserver/options/authentication.go @@ -350,7 +350,8 @@ func (s *ClientCertAuthenticationOptions) AddFlags(fs *pflag.FlagSet) { } // DelegatingAuthenticationOptions provides an easy way for composing API servers to delegate their authentication to -// the root kube API server +// the root kube API server. The API federator will act as +// a front proxy and direction connections will be able to delegate to the core kube API server type DelegatingAuthenticationOptions struct { // RemoteKubeConfigFile is the file to use to connect to a "normal" kube API server which hosts the // TokenAccessReview.authentication.k8s.io endpoint for checking tokens. @@ -358,11 +359,21 @@ type DelegatingAuthenticationOptions struct { // CacheTTL is the length of time that a token authentication answer will be cached. CacheTTL time.Duration + + ClientCert ClientCertAuthenticationOptions + RequestHeader RequestHeaderAuthenticationOptions } func NewDelegatingAuthenticationOptions() *DelegatingAuthenticationOptions { return &DelegatingAuthenticationOptions{ - CacheTTL: 5 * time.Minute, + // very low for responsiveness, but high enough to handle storms + CacheTTL: 10 * time.Second, + ClientCert: ClientCertAuthenticationOptions{}, + RequestHeader: RequestHeaderAuthenticationOptions{ + UsernameHeaders: []string{"x-remote-user"}, + GroupHeaders: []string{"x-remote-group"}, + ExtraHeaderPrefixes: []string{"x-remote-extra-"}, + }, } } @@ -374,10 +385,16 @@ func (s *DelegatingAuthenticationOptions) Validate() []error { func (s *DelegatingAuthenticationOptions) AddFlags(fs *pflag.FlagSet) { fs.StringVar(&s.RemoteKubeConfigFile, "authentication-kubeconfig", s.RemoteKubeConfigFile, ""+ "kubeconfig file pointing at the 'core' kubernetes server with enough rights to create "+ - " tokenaccessreviews.authentication.k8s.io.") + "tokenaccessreviews.authentication.k8s.io.") + + fs.DurationVar(&s.CacheTTL, "authentication-token-webhook-cache-ttl", s.CacheTTL, + "The duration to cache responses from the webhook token authenticator.") + + s.ClientCert.AddFlags(fs) + s.RequestHeader.AddFlags(fs) } -func (s *DelegatingAuthenticationOptions) ToAuthenticationConfig(clientCAFile string) (authenticator.DelegatingAuthenticatorConfig, error) { +func (s *DelegatingAuthenticationOptions) ToAuthenticationConfig() (authenticator.DelegatingAuthenticatorConfig, error) { tokenClient, err := s.newTokenAccessReview() if err != nil { return authenticator.DelegatingAuthenticatorConfig{}, err @@ -387,7 +404,8 @@ func (s *DelegatingAuthenticationOptions) ToAuthenticationConfig(clientCAFile st Anonymous: true, TokenAccessReviewClient: tokenClient, CacheTTL: s.CacheTTL, - ClientCAFile: clientCAFile, + ClientCAFile: s.ClientCert.ClientCA, + RequestHeaderConfig: s.RequestHeader.ToAuthenticationRequestHeaderConfig(), } return ret, nil }