From ab1b77673f152bd0d1481b6342b52a2af1330027 Mon Sep 17 00:00:00 2001 From: deads2k Date: Wed, 21 Dec 2016 12:45:38 -0500 Subject: [PATCH] decouple genericapiserver from non-generic authenticator --- cmd/kube-apiserver/app/BUILD | 2 +- cmd/kube-apiserver/app/options/options.go | 4 +- cmd/kube-apiserver/app/server.go | 8 +- cmd/kubelet/app/BUILD | 2 +- cmd/kubelet/app/auth.go | 2 +- examples/apiserver/BUILD | 1 + examples/apiserver/apiserver.go | 7 +- federation/cmd/federation-apiserver/app/BUILD | 1 - .../app/options/options.go | 4 +- .../cmd/federation-apiserver/app/server.go | 5 +- pkg/apiserver/authenticator/OWNERS | 10 - pkg/genericapiserver/BUILD | 2 +- pkg/genericapiserver/authenticator/BUILD | 33 ++ .../authenticator/delegating.go | 0 .../authenticator/loopback.go | 29 ++ .../authenticator/requestheader.go | 31 ++ pkg/genericapiserver/config.go | 37 +- pkg/genericapiserver/options/BUILD | 2 +- .../options/authentication.go | 269 +-------------- .../authenticator/BUILD | 7 +- .../authenticator/config.go} | 24 +- pkg/kubeapiserver/options/BUILD | 8 +- pkg/kubeapiserver/options/authentication.go | 318 ++++++++++++++++++ test/integration/framework/BUILD | 2 +- test/integration/framework/master_utils.go | 2 +- 25 files changed, 453 insertions(+), 357 deletions(-) delete mode 100755 pkg/apiserver/authenticator/OWNERS create mode 100644 pkg/genericapiserver/authenticator/BUILD rename pkg/{apiserver => genericapiserver}/authenticator/delegating.go (100%) create mode 100644 pkg/genericapiserver/authenticator/loopback.go create mode 100644 pkg/genericapiserver/authenticator/requestheader.go rename pkg/{apiserver => kubeapiserver}/authenticator/BUILD (89%) rename pkg/{apiserver/authenticator/builtin.go => kubeapiserver/authenticator/config.go} (89%) create mode 100644 pkg/kubeapiserver/options/authentication.go diff --git a/cmd/kube-apiserver/app/BUILD b/cmd/kube-apiserver/app/BUILD index a29d567fcd1..2d9ac3ca58e 100644 --- a/cmd/kube-apiserver/app/BUILD +++ b/cmd/kube-apiserver/app/BUILD @@ -21,7 +21,6 @@ go_library( "//pkg/apis/autoscaling:go_default_library", "//pkg/apis/batch:go_default_library", "//pkg/apis/extensions:go_default_library", - "//pkg/apiserver/authenticator:go_default_library", "//pkg/capabilities:go_default_library", "//pkg/client/clientset_generated/internalclientset:go_default_library", "//pkg/cloudprovider:go_default_library", @@ -31,6 +30,7 @@ go_library( "//pkg/generated/openapi:go_default_library", "//pkg/genericapiserver:go_default_library", "//pkg/genericapiserver/filters:go_default_library", + "//pkg/kubeapiserver/authenticator:go_default_library", "//pkg/master:go_default_library", "//pkg/registry/cachesize:go_default_library", "//pkg/runtime/schema:go_default_library", diff --git a/cmd/kube-apiserver/app/options/options.go b/cmd/kube-apiserver/app/options/options.go index 6082f2be6e9..df9b18281d3 100644 --- a/cmd/kube-apiserver/app/options/options.go +++ b/cmd/kube-apiserver/app/options/options.go @@ -41,7 +41,7 @@ type ServerRunOptions struct { Etcd *genericoptions.EtcdOptions SecureServing *genericoptions.SecureServingOptions InsecureServing *genericoptions.ServingOptions - Authentication *genericoptions.BuiltInAuthenticationOptions + Authentication *kubeoptions.BuiltInAuthenticationOptions Authorization *kubeoptions.BuiltInAuthorizationOptions AllowPrivileged bool @@ -63,7 +63,7 @@ func NewServerRunOptions() *ServerRunOptions { Etcd: genericoptions.NewEtcdOptions(), SecureServing: genericoptions.NewSecureServingOptions(), InsecureServing: genericoptions.NewInsecureServingOptions(), - Authentication: genericoptions.NewBuiltInAuthenticationOptions().WithAll(), + Authentication: kubeoptions.NewBuiltInAuthenticationOptions().WithAll(), Authorization: kubeoptions.NewBuiltInAuthorizationOptions(), EventTTL: 1 * time.Hour, diff --git a/cmd/kube-apiserver/app/server.go b/cmd/kube-apiserver/app/server.go index 6c6137c4d40..f52ec29cbcd 100644 --- a/cmd/kube-apiserver/app/server.go +++ b/cmd/kube-apiserver/app/server.go @@ -41,7 +41,6 @@ import ( "k8s.io/kubernetes/pkg/apis/autoscaling" "k8s.io/kubernetes/pkg/apis/batch" "k8s.io/kubernetes/pkg/apis/extensions" - "k8s.io/kubernetes/pkg/apiserver/authenticator" "k8s.io/kubernetes/pkg/capabilities" "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset" "k8s.io/kubernetes/pkg/cloudprovider" @@ -50,6 +49,7 @@ import ( generatedopenapi "k8s.io/kubernetes/pkg/generated/openapi" "k8s.io/kubernetes/pkg/genericapiserver" "k8s.io/kubernetes/pkg/genericapiserver/filters" + kubeauthenticator "k8s.io/kubernetes/pkg/kubeapiserver/authenticator" "k8s.io/kubernetes/pkg/master" "k8s.io/kubernetes/pkg/registry/cachesize" "k8s.io/kubernetes/pkg/runtime/schema" @@ -107,7 +107,7 @@ func Run(s *options.ServerRunOptions) error { if _, err := genericConfig.ApplySecureServingOptions(s.SecureServing); err != nil { return fmt.Errorf("failed to configure https: %s", err) } - if _, err = genericConfig.ApplyAuthenticationOptions(s.Authentication); err != nil { + if err = s.Authentication.Apply(genericConfig); err != nil { return fmt.Errorf("failed to configure authentication: %s", err) } @@ -217,7 +217,7 @@ func Run(s *options.ServerRunOptions) error { // Default to the private server key for service account token signing if len(s.Authentication.ServiceAccounts.KeyFiles) == 0 && s.SecureServing.ServerCert.CertKey.KeyFile != "" { - if authenticator.IsValidServiceAccountKeyFile(s.SecureServing.ServerCert.CertKey.KeyFile) { + if kubeauthenticator.IsValidServiceAccountKeyFile(s.SecureServing.ServerCert.CertKey.KeyFile) { s.Authentication.ServiceAccounts.KeyFiles = []string{s.SecureServing.ServerCert.CertKey.KeyFile} } else { glog.Warning("No TLS key provided, service account token authentication disabled") @@ -235,7 +235,7 @@ func Run(s *options.ServerRunOptions) error { authenticatorConfig.ServiceAccountTokenGetter = serviceaccountcontroller.NewGetterFromStorageInterface(storageConfig, storageFactory.ResourcePrefix(api.Resource("serviceaccounts")), storageFactory.ResourcePrefix(api.Resource("secrets"))) } - apiAuthenticator, securityDefinitions, err := authenticator.New(authenticatorConfig) + apiAuthenticator, securityDefinitions, err := authenticatorConfig.New() if err != nil { return fmt.Errorf("invalid Authentication Config: %v", err) } diff --git a/cmd/kubelet/app/BUILD b/cmd/kubelet/app/BUILD index a8a30791216..63da956473e 100644 --- a/cmd/kubelet/app/BUILD +++ b/cmd/kubelet/app/BUILD @@ -25,7 +25,6 @@ go_library( "//pkg/apis/componentconfig:go_default_library", "//pkg/apis/componentconfig/v1alpha1:go_default_library", "//pkg/apis/meta/v1:go_default_library", - "//pkg/apiserver/authenticator:go_default_library", "//pkg/auth/authenticator:go_default_library", "//pkg/auth/authorizer:go_default_library", "//pkg/capabilities:go_default_library", @@ -46,6 +45,7 @@ go_library( "//pkg/credentialprovider/aws:go_default_library", "//pkg/credentialprovider/azure:go_default_library", "//pkg/credentialprovider/gcp:go_default_library", + "//pkg/genericapiserver/authenticator:go_default_library", "//pkg/genericapiserver/authorizer:go_default_library", "//pkg/healthz:go_default_library", "//pkg/kubelet:go_default_library", diff --git a/cmd/kubelet/app/auth.go b/cmd/kubelet/app/auth.go index 23a474ad6e9..17954df2f93 100644 --- a/cmd/kubelet/app/auth.go +++ b/cmd/kubelet/app/auth.go @@ -22,12 +22,12 @@ import ( "reflect" "k8s.io/kubernetes/pkg/apis/componentconfig" - apiserverauthenticator "k8s.io/kubernetes/pkg/apiserver/authenticator" "k8s.io/kubernetes/pkg/auth/authenticator" "k8s.io/kubernetes/pkg/auth/authorizer" clientset "k8s.io/kubernetes/pkg/client/clientset_generated/clientset" authenticationclient "k8s.io/kubernetes/pkg/client/clientset_generated/clientset/typed/authentication/v1beta1" authorizationclient "k8s.io/kubernetes/pkg/client/clientset_generated/clientset/typed/authorization/v1beta1" + apiserverauthenticator "k8s.io/kubernetes/pkg/genericapiserver/authenticator" alwaysallowauthorizer "k8s.io/kubernetes/pkg/genericapiserver/authorizer" apiserverauthorizer "k8s.io/kubernetes/pkg/genericapiserver/authorizer" "k8s.io/kubernetes/pkg/kubelet/server" diff --git a/examples/apiserver/BUILD b/examples/apiserver/BUILD index 002164598eb..6c472fc175d 100644 --- a/examples/apiserver/BUILD +++ b/examples/apiserver/BUILD @@ -21,6 +21,7 @@ go_library( "//pkg/genericapiserver:go_default_library", "//pkg/genericapiserver/authorizer:go_default_library", "//pkg/genericapiserver/options:go_default_library", + "//pkg/kubeapiserver/options:go_default_library", "//pkg/registry/generic:go_default_library", "//pkg/runtime/schema:go_default_library", "//pkg/storage/storagebackend:go_default_library", diff --git a/examples/apiserver/apiserver.go b/examples/apiserver/apiserver.go index 61abfca47e7..28aa112ed7f 100644 --- a/examples/apiserver/apiserver.go +++ b/examples/apiserver/apiserver.go @@ -27,6 +27,7 @@ import ( "k8s.io/kubernetes/pkg/genericapiserver" "k8s.io/kubernetes/pkg/genericapiserver/authorizer" genericoptions "k8s.io/kubernetes/pkg/genericapiserver/options" + kubeoptions "k8s.io/kubernetes/pkg/kubeapiserver/options" "k8s.io/kubernetes/pkg/registry/generic" "k8s.io/kubernetes/pkg/runtime/schema" "k8s.io/kubernetes/pkg/storage/storagebackend" @@ -60,7 +61,7 @@ type ServerRunOptions struct { Etcd *genericoptions.EtcdOptions SecureServing *genericoptions.SecureServingOptions InsecureServing *genericoptions.ServingOptions - Authentication *genericoptions.BuiltInAuthenticationOptions + Authentication *kubeoptions.BuiltInAuthenticationOptions } func NewServerRunOptions() *ServerRunOptions { @@ -69,7 +70,7 @@ func NewServerRunOptions() *ServerRunOptions { Etcd: genericoptions.NewEtcdOptions(), SecureServing: genericoptions.NewSecureServingOptions(), InsecureServing: genericoptions.NewInsecureServingOptions(), - Authentication: genericoptions.NewBuiltInAuthenticationOptions().WithAll(), + Authentication: kubeoptions.NewBuiltInAuthenticationOptions().WithAll(), } s.InsecureServing.BindPort = InsecurePort s.SecureServing.ServingOptions.BindPort = SecurePort @@ -107,7 +108,7 @@ func (serverOptions *ServerRunOptions) Run(stopCh <-chan struct{}) error { if _, err := config.ApplySecureServingOptions(serverOptions.SecureServing); err != nil { return fmt.Errorf("failed to configure https: %s", err) } - if _, err := config.ApplyAuthenticationOptions(serverOptions.Authentication); err != nil { + if err := serverOptions.Authentication.Apply(config); err != nil { return fmt.Errorf("failed to configure authentication: %s", err) } diff --git a/federation/cmd/federation-apiserver/app/BUILD b/federation/cmd/federation-apiserver/app/BUILD index d28d2d7c9fc..d487bbbb1b5 100644 --- a/federation/cmd/federation-apiserver/app/BUILD +++ b/federation/cmd/federation-apiserver/app/BUILD @@ -35,7 +35,6 @@ go_library( "//pkg/apis/batch/install:go_default_library", "//pkg/apis/extensions:go_default_library", "//pkg/apis/extensions/install:go_default_library", - "//pkg/apiserver/authenticator:go_default_library", "//pkg/client/clientset_generated/internalclientset:go_default_library", "//pkg/cloudprovider/providers:go_default_library", "//pkg/controller/informers:go_default_library", diff --git a/federation/cmd/federation-apiserver/app/options/options.go b/federation/cmd/federation-apiserver/app/options/options.go index f05a551c0ed..ea94c8486db 100644 --- a/federation/cmd/federation-apiserver/app/options/options.go +++ b/federation/cmd/federation-apiserver/app/options/options.go @@ -32,7 +32,7 @@ type ServerRunOptions struct { Etcd *genericoptions.EtcdOptions SecureServing *genericoptions.SecureServingOptions InsecureServing *genericoptions.ServingOptions - Authentication *genericoptions.BuiltInAuthenticationOptions + Authentication *kubeoptions.BuiltInAuthenticationOptions Authorization *kubeoptions.BuiltInAuthorizationOptions EventTTL time.Duration @@ -45,7 +45,7 @@ func NewServerRunOptions() *ServerRunOptions { Etcd: genericoptions.NewEtcdOptions(), SecureServing: genericoptions.NewSecureServingOptions(), InsecureServing: genericoptions.NewInsecureServingOptions(), - Authentication: genericoptions.NewBuiltInAuthenticationOptions().WithAll(), + Authentication: kubeoptions.NewBuiltInAuthenticationOptions().WithAll(), Authorization: kubeoptions.NewBuiltInAuthorizationOptions(), EventTTL: 1 * time.Hour, diff --git a/federation/cmd/federation-apiserver/app/server.go b/federation/cmd/federation-apiserver/app/server.go index 9c292293ffa..473dd0fea43 100644 --- a/federation/cmd/federation-apiserver/app/server.go +++ b/federation/cmd/federation-apiserver/app/server.go @@ -32,7 +32,6 @@ import ( "k8s.io/kubernetes/federation/cmd/federation-apiserver/app/options" "k8s.io/kubernetes/pkg/admission" "k8s.io/kubernetes/pkg/api" - "k8s.io/kubernetes/pkg/apiserver/authenticator" "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset" "k8s.io/kubernetes/pkg/controller/informers" "k8s.io/kubernetes/pkg/generated/openapi" @@ -91,7 +90,7 @@ func Run(s *options.ServerRunOptions) error { if _, err := genericConfig.ApplySecureServingOptions(s.SecureServing); err != nil { return fmt.Errorf("failed to configure https: %s", err) } - if _, err := genericConfig.ApplyAuthenticationOptions(s.Authentication); err != nil { + if err := s.Authentication.Apply(genericConfig); err != nil { return fmt.Errorf("failed to configure authentication: %s", err) } @@ -134,7 +133,7 @@ func Run(s *options.ServerRunOptions) error { storageFactory.SetEtcdLocation(groupResource, servers) } - apiAuthenticator, securityDefinitions, err := authenticator.New(s.Authentication.ToAuthenticationConfig()) + apiAuthenticator, securityDefinitions, err := s.Authentication.ToAuthenticationConfig().New() if err != nil { return fmt.Errorf("invalid Authentication Config: %v", err) } diff --git a/pkg/apiserver/authenticator/OWNERS b/pkg/apiserver/authenticator/OWNERS deleted file mode 100755 index 34b008b26cb..00000000000 --- a/pkg/apiserver/authenticator/OWNERS +++ /dev/null @@ -1,10 +0,0 @@ -reviewers: -- smarterclayton -- deads2k -- liggitt -- dims -- spxtr -- errordeveloper -- resouer -- cjcullen -- ericchiang diff --git a/pkg/genericapiserver/BUILD b/pkg/genericapiserver/BUILD index e5cf0acf179..cc90060c877 100644 --- a/pkg/genericapiserver/BUILD +++ b/pkg/genericapiserver/BUILD @@ -34,7 +34,6 @@ go_library( "//pkg/apimachinery/registered:go_default_library", "//pkg/apis/meta/v1:go_default_library", "//pkg/apiserver:go_default_library", - "//pkg/apiserver/authenticator:go_default_library", "//pkg/apiserver/filters:go_default_library", "//pkg/apiserver/openapi:go_default_library", "//pkg/apiserver/request:go_default_library", @@ -44,6 +43,7 @@ go_library( "//pkg/auth/handlers:go_default_library", "//pkg/auth/user:go_default_library", "//pkg/client/restclient:go_default_library", + "//pkg/genericapiserver/authenticator:go_default_library", "//pkg/genericapiserver/authorizer:go_default_library", "//pkg/genericapiserver/filters:go_default_library", "//pkg/genericapiserver/mux:go_default_library", diff --git a/pkg/genericapiserver/authenticator/BUILD b/pkg/genericapiserver/authenticator/BUILD new file mode 100644 index 00000000000..a40f825fe5c --- /dev/null +++ b/pkg/genericapiserver/authenticator/BUILD @@ -0,0 +1,33 @@ +package(default_visibility = ["//visibility:public"]) + +licenses(["notice"]) + +load( + "@io_bazel_rules_go//go:def.bzl", + "go_library", +) + +go_library( + name = "go_default_library", + srcs = [ + "delegating.go", + "loopback.go", + "requestheader.go", + ], + tags = ["automanaged"], + deps = [ + "//pkg/auth/authenticator:go_default_library", + "//pkg/auth/authenticator/bearertoken:go_default_library", + "//pkg/auth/group:go_default_library", + "//pkg/auth/user:go_default_library", + "//pkg/client/clientset_generated/clientset/typed/authentication/v1beta1:go_default_library", + "//pkg/util/cert:go_default_library", + "//plugin/pkg/auth/authenticator/request/anonymous:go_default_library", + "//plugin/pkg/auth/authenticator/request/headerrequest:go_default_library", + "//plugin/pkg/auth/authenticator/request/union:go_default_library", + "//plugin/pkg/auth/authenticator/request/x509:go_default_library", + "//plugin/pkg/auth/authenticator/token/tokenfile:go_default_library", + "//plugin/pkg/auth/authenticator/token/webhook:go_default_library", + "//vendor:github.com/go-openapi/spec", + ], +) diff --git a/pkg/apiserver/authenticator/delegating.go b/pkg/genericapiserver/authenticator/delegating.go similarity index 100% rename from pkg/apiserver/authenticator/delegating.go rename to pkg/genericapiserver/authenticator/delegating.go diff --git a/pkg/genericapiserver/authenticator/loopback.go b/pkg/genericapiserver/authenticator/loopback.go new file mode 100644 index 00000000000..8e3536a31c2 --- /dev/null +++ b/pkg/genericapiserver/authenticator/loopback.go @@ -0,0 +1,29 @@ +/* +Copyright 2016 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 authenticator + +import ( + "k8s.io/kubernetes/pkg/auth/authenticator" + "k8s.io/kubernetes/pkg/auth/authenticator/bearertoken" + "k8s.io/kubernetes/pkg/auth/user" + "k8s.io/kubernetes/plugin/pkg/auth/authenticator/token/tokenfile" +) + +// newAuthenticatorFromToken returns an authenticator.Request or an error +func NewAuthenticatorFromTokens(tokens map[string]*user.DefaultInfo) authenticator.Request { + return bearertoken.New(tokenfile.New(tokens)) +} diff --git a/pkg/genericapiserver/authenticator/requestheader.go b/pkg/genericapiserver/authenticator/requestheader.go new file mode 100644 index 00000000000..b719eccc002 --- /dev/null +++ b/pkg/genericapiserver/authenticator/requestheader.go @@ -0,0 +1,31 @@ +/* +Copyright 2014 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 authenticator + +type RequestHeaderConfig struct { + // UsernameHeaders are the headers to check (in order, case-insensitively) for an identity. The first header with a value wins. + UsernameHeaders []string + // GroupHeaders are the headers to check (case-insensitively) for a group names. All values will be used. + GroupHeaders []string + // ExtraHeaderPrefixes are the head prefixes to check (case-insentively) for filling in + // the user.Info.Extra. All values of all matching headers will be added. + ExtraHeaderPrefixes []string + // ClientCA points to CA bundle file which is used verify the identity of the front proxy + ClientCA string + // AllowedClientNames is a list of common names that may be presented by the authenticating front proxy. Empty means: accept any. + AllowedClientNames []string +} diff --git a/pkg/genericapiserver/config.go b/pkg/genericapiserver/config.go index 2d5e097645b..90b2528c22d 100644 --- a/pkg/genericapiserver/config.go +++ b/pkg/genericapiserver/config.go @@ -39,7 +39,6 @@ import ( "k8s.io/kubernetes/pkg/admission" "k8s.io/kubernetes/pkg/api" metav1 "k8s.io/kubernetes/pkg/apis/meta/v1" - apiserverauthenticator "k8s.io/kubernetes/pkg/apiserver/authenticator" apiserverfilters "k8s.io/kubernetes/pkg/apiserver/filters" apiserveropenapi "k8s.io/kubernetes/pkg/apiserver/openapi" apiserverrequest "k8s.io/kubernetes/pkg/apiserver/request" @@ -49,7 +48,8 @@ import ( authhandlers "k8s.io/kubernetes/pkg/auth/handlers" "k8s.io/kubernetes/pkg/auth/user" "k8s.io/kubernetes/pkg/client/restclient" - apiserverauthorizer "k8s.io/kubernetes/pkg/genericapiserver/authorizer" + genericauthenticator "k8s.io/kubernetes/pkg/genericapiserver/authenticator" + genericauthorizer "k8s.io/kubernetes/pkg/genericapiserver/authorizer" genericfilters "k8s.io/kubernetes/pkg/genericapiserver/filters" "k8s.io/kubernetes/pkg/genericapiserver/mux" openapicommon "k8s.io/kubernetes/pkg/genericapiserver/openapi/common" @@ -327,30 +327,7 @@ func (c *Config) ApplyInsecureServingOptions(insecureServing *options.ServingOpt return c } -func (c *Config) ApplyAuthenticationOptions(o *options.BuiltInAuthenticationOptions) (*Config, error) { - if o == nil || o.PasswordFile == nil { - return c, nil - } - - var err error - if o.ClientCert != nil { - c, err = c.applyClientCert(o.ClientCert.ClientCA) - if err != nil { - return nil, fmt.Errorf("unable to load client CA file: %v", err) - } - } - if o.RequestHeader != nil { - c, err = c.applyClientCert(o.RequestHeader.ClientCAFile) - if err != nil { - return nil, fmt.Errorf("unable to load client CA file: %v", err) - } - } - - c.SupportsBasicAuth = len(o.PasswordFile.BasicAuthFile) > 0 - return c, nil -} - -func (c *Config) applyClientCert(clientCAFile string) (*Config, error) { +func (c *Config) ApplyClientCert(clientCAFile string) (*Config, error) { if c.SecureServingInfo != nil { if len(clientCAFile) > 0 { clientCAs, err := certutil.CertsFromFile(clientCAFile) @@ -375,11 +352,11 @@ func (c *Config) ApplyDelegatingAuthenticationOptions(o *options.DelegatingAuthe } var err error - c, err = c.applyClientCert(o.ClientCert.ClientCA) + c, err = c.ApplyClientCert(o.ClientCert.ClientCA) if err != nil { return nil, fmt.Errorf("unable to load client CA file: %v", err) } - c, err = c.applyClientCert(o.RequestHeader.ClientCAFile) + c, err = c.ApplyClientCert(o.RequestHeader.ClientCAFile) if err != nil { return nil, fmt.Errorf("unable to load client CA file: %v", err) } @@ -505,10 +482,10 @@ func (c *Config) Complete() completedConfig { Groups: []string{user.SystemPrivilegedGroup}, } - tokenAuthenticator := apiserverauthenticator.NewAuthenticatorFromTokens(tokens) + tokenAuthenticator := genericauthenticator.NewAuthenticatorFromTokens(tokens) c.Authenticator = authenticatorunion.New(tokenAuthenticator, c.Authenticator) - tokenAuthorizer := apiserverauthorizer.NewPrivilegedGroups(user.SystemPrivilegedGroup) + tokenAuthorizer := genericauthorizer.NewPrivilegedGroups(user.SystemPrivilegedGroup) c.Authorizer = authorizerunion.New(tokenAuthorizer, c.Authorizer) } diff --git a/pkg/genericapiserver/options/BUILD b/pkg/genericapiserver/options/BUILD index f41f222bb86..a2744c53af9 100644 --- a/pkg/genericapiserver/options/BUILD +++ b/pkg/genericapiserver/options/BUILD @@ -23,12 +23,12 @@ go_library( "//pkg/api:go_default_library", "//pkg/api/v1:go_default_library", "//pkg/apimachinery/registered:go_default_library", - "//pkg/apiserver/authenticator:go_default_library", "//pkg/client/clientset_generated/clientset/typed/authentication/v1beta1:go_default_library", "//pkg/client/clientset_generated/clientset/typed/authorization/v1beta1:go_default_library", "//pkg/client/restclient:go_default_library", "//pkg/client/unversioned/clientcmd:go_default_library", "//pkg/cloudprovider:go_default_library", + "//pkg/genericapiserver/authenticator:go_default_library", "//pkg/genericapiserver/authorizer:go_default_library", "//pkg/runtime/schema:go_default_library", "//pkg/storage/storagebackend:go_default_library", diff --git a/pkg/genericapiserver/options/authentication.go b/pkg/genericapiserver/options/authentication.go index c453e33239c..43502d5993c 100644 --- a/pkg/genericapiserver/options/authentication.go +++ b/pkg/genericapiserver/options/authentication.go @@ -21,279 +21,12 @@ import ( "github.com/spf13/pflag" - "k8s.io/kubernetes/pkg/apiserver/authenticator" authenticationclient "k8s.io/kubernetes/pkg/client/clientset_generated/clientset/typed/authentication/v1beta1" "k8s.io/kubernetes/pkg/client/restclient" "k8s.io/kubernetes/pkg/client/unversioned/clientcmd" + "k8s.io/kubernetes/pkg/genericapiserver/authenticator" ) -type BuiltInAuthenticationOptions struct { - Anonymous *AnonymousAuthenticationOptions - AnyToken *AnyTokenAuthenticationOptions - ClientCert *ClientCertAuthenticationOptions - Keystone *KeystoneAuthenticationOptions - OIDC *OIDCAuthenticationOptions - PasswordFile *PasswordFileAuthenticationOptions - RequestHeader *RequestHeaderAuthenticationOptions - ServiceAccounts *ServiceAccountAuthenticationOptions - TokenFile *TokenFileAuthenticationOptions - WebHook *WebHookAuthenticationOptions -} - -type AnyTokenAuthenticationOptions struct { - Allow bool -} - -type AnonymousAuthenticationOptions struct { - Allow bool -} - -type KeystoneAuthenticationOptions struct { - URL string - CAFile string -} - -type OIDCAuthenticationOptions struct { - CAFile string - ClientID string - IssuerURL string - UsernameClaim string - GroupsClaim string -} - -type PasswordFileAuthenticationOptions struct { - BasicAuthFile string -} - -type ServiceAccountAuthenticationOptions struct { - KeyFiles []string - Lookup bool -} - -type TokenFileAuthenticationOptions struct { - TokenFile string -} - -type WebHookAuthenticationOptions struct { - ConfigFile string - CacheTTL time.Duration -} - -func NewBuiltInAuthenticationOptions() *BuiltInAuthenticationOptions { - return &BuiltInAuthenticationOptions{} -} - -func (s *BuiltInAuthenticationOptions) WithAll() *BuiltInAuthenticationOptions { - return s. - WithAnyonymous(). - WithAnyToken(). - WithClientCert(). - WithKeystone(). - WithOIDC(). - WithPasswordFile(). - WithRequestHeader(). - WithServiceAccounts(). - WithTokenFile(). - WithWebHook() -} - -func (s *BuiltInAuthenticationOptions) WithAnyonymous() *BuiltInAuthenticationOptions { - s.Anonymous = &AnonymousAuthenticationOptions{Allow: true} - return s -} - -func (s *BuiltInAuthenticationOptions) WithAnyToken() *BuiltInAuthenticationOptions { - s.AnyToken = &AnyTokenAuthenticationOptions{} - return s -} - -func (s *BuiltInAuthenticationOptions) WithClientCert() *BuiltInAuthenticationOptions { - s.ClientCert = &ClientCertAuthenticationOptions{} - return s -} - -func (s *BuiltInAuthenticationOptions) WithKeystone() *BuiltInAuthenticationOptions { - s.Keystone = &KeystoneAuthenticationOptions{} - return s -} - -func (s *BuiltInAuthenticationOptions) WithOIDC() *BuiltInAuthenticationOptions { - s.OIDC = &OIDCAuthenticationOptions{} - return s -} - -func (s *BuiltInAuthenticationOptions) WithPasswordFile() *BuiltInAuthenticationOptions { - s.PasswordFile = &PasswordFileAuthenticationOptions{} - return s -} - -func (s *BuiltInAuthenticationOptions) WithRequestHeader() *BuiltInAuthenticationOptions { - s.RequestHeader = &RequestHeaderAuthenticationOptions{} - return s -} - -func (s *BuiltInAuthenticationOptions) WithServiceAccounts() *BuiltInAuthenticationOptions { - s.ServiceAccounts = &ServiceAccountAuthenticationOptions{} - return s -} - -func (s *BuiltInAuthenticationOptions) WithTokenFile() *BuiltInAuthenticationOptions { - s.TokenFile = &TokenFileAuthenticationOptions{} - return s -} - -func (s *BuiltInAuthenticationOptions) WithWebHook() *BuiltInAuthenticationOptions { - s.WebHook = &WebHookAuthenticationOptions{ - CacheTTL: 2 * time.Minute, - } - return s -} - -func (s *BuiltInAuthenticationOptions) Validate() []error { - allErrors := []error{} - return allErrors -} - -func (s *BuiltInAuthenticationOptions) AddFlags(fs *pflag.FlagSet) { - if s.Anonymous != nil { - fs.BoolVar(&s.Anonymous.Allow, "anonymous-auth", s.Anonymous.Allow, ""+ - "Enables anonymous requests to the secure port of the API server. "+ - "Requests that are not rejected by another authentication method are treated as anonymous requests. "+ - "Anonymous requests have a username of system:anonymous, and a group name of system:unauthenticated.") - } - - if s.AnyToken != nil { - fs.BoolVar(&s.AnyToken.Allow, "insecure-allow-any-token", s.AnyToken.Allow, ""+ - "If set, your server will be INSECURE. Any token will be allowed and user information will be parsed "+ - "from the token as `username/group1,group2`") - - } - - if s.ClientCert != nil { - s.ClientCert.AddFlags(fs) - } - - if s.Keystone != nil { - fs.StringVar(&s.Keystone.URL, "experimental-keystone-url", s.Keystone.URL, - "If passed, activates the keystone authentication plugin.") - - fs.StringVar(&s.Keystone.CAFile, "experimental-keystone-ca-file", s.Keystone.CAFile, ""+ - "If set, the Keystone server's certificate will be verified by one of the authorities "+ - "in the experimental-keystone-ca-file, otherwise the host's root CA set will be used.") - } - - if s.OIDC != nil { - fs.StringVar(&s.OIDC.IssuerURL, "oidc-issuer-url", s.OIDC.IssuerURL, ""+ - "The URL of the OpenID issuer, only HTTPS scheme will be accepted. "+ - "If set, it will be used to verify the OIDC JSON Web Token (JWT).") - - fs.StringVar(&s.OIDC.ClientID, "oidc-client-id", s.OIDC.ClientID, - "The client ID for the OpenID Connect client, must be set if oidc-issuer-url is set.") - - fs.StringVar(&s.OIDC.CAFile, "oidc-ca-file", s.OIDC.CAFile, ""+ - "If set, the OpenID server's certificate will be verified by one of the authorities "+ - "in the oidc-ca-file, otherwise the host's root CA set will be used.") - - fs.StringVar(&s.OIDC.UsernameClaim, "oidc-username-claim", "sub", ""+ - "The OpenID claim to use as the user name. Note that claims other than the default ('sub') "+ - "is not guaranteed to be unique and immutable. This flag is experimental, please see "+ - "the authentication documentation for further details.") - - fs.StringVar(&s.OIDC.GroupsClaim, "oidc-groups-claim", "", ""+ - "If provided, the name of a custom OpenID Connect claim for specifying user groups. "+ - "The claim value is expected to be a string or array of strings. This flag is experimental, "+ - "please see the authentication documentation for further details.") - } - - if s.PasswordFile != nil { - fs.StringVar(&s.PasswordFile.BasicAuthFile, "basic-auth-file", s.PasswordFile.BasicAuthFile, ""+ - "If set, the file that will be used to admit requests to the secure port of the API server "+ - "via http basic authentication.") - } - - if s.RequestHeader != nil { - s.RequestHeader.AddFlags(fs) - } - - if s.ServiceAccounts != nil { - fs.StringArrayVar(&s.ServiceAccounts.KeyFiles, "service-account-key-file", s.ServiceAccounts.KeyFiles, ""+ - "File containing PEM-encoded x509 RSA or ECDSA private or public keys, used to verify "+ - "ServiceAccount tokens. If unspecified, --tls-private-key-file is used. "+ - "The specified file can contain multiple keys, and the flag can be specified multiple times with different files.") - - fs.BoolVar(&s.ServiceAccounts.Lookup, "service-account-lookup", s.ServiceAccounts.Lookup, - "If true, validate ServiceAccount tokens exist in etcd as part of authentication.") - } - - if s.TokenFile != nil { - fs.StringVar(&s.TokenFile.TokenFile, "token-auth-file", s.TokenFile.TokenFile, ""+ - "If set, the file that will be used to secure the secure port of the API server "+ - "via token authentication.") - } - - if s.WebHook != nil { - fs.StringVar(&s.WebHook.ConfigFile, "authentication-token-webhook-config-file", s.WebHook.ConfigFile, ""+ - "File with webhook configuration for token authentication in kubeconfig format. "+ - "The API server will query the remote service to determine authentication for bearer tokens.") - - fs.DurationVar(&s.WebHook.CacheTTL, "authentication-token-webhook-cache-ttl", s.WebHook.CacheTTL, - "The duration to cache responses from the webhook token authenticator. Default is 2m.") - } -} - -func (s *BuiltInAuthenticationOptions) ToAuthenticationConfig() authenticator.AuthenticatorConfig { - ret := authenticator.AuthenticatorConfig{} - - if s.Anonymous != nil { - ret.Anonymous = s.Anonymous.Allow - } - - if s.AnyToken != nil { - ret.AnyToken = s.AnyToken.Allow - } - - if s.ClientCert != nil { - ret.ClientCAFile = s.ClientCert.ClientCA - } - - if s.Keystone != nil { - ret.KeystoneURL = s.Keystone.URL - ret.KeystoneCAFile = s.Keystone.CAFile - } - - if s.OIDC != nil { - ret.OIDCCAFile = s.OIDC.CAFile - ret.OIDCClientID = s.OIDC.ClientID - ret.OIDCGroupsClaim = s.OIDC.GroupsClaim - ret.OIDCIssuerURL = s.OIDC.IssuerURL - ret.OIDCUsernameClaim = s.OIDC.UsernameClaim - } - - if s.PasswordFile != nil { - ret.BasicAuthFile = s.PasswordFile.BasicAuthFile - } - - if s.RequestHeader != nil { - ret.RequestHeaderConfig = s.RequestHeader.ToAuthenticationRequestHeaderConfig() - } - - if s.ServiceAccounts != nil { - ret.ServiceAccountKeyFiles = s.ServiceAccounts.KeyFiles - ret.ServiceAccountLookup = s.ServiceAccounts.Lookup - } - - if s.TokenFile != nil { - ret.TokenAuthFile = s.TokenFile.TokenFile - } - - if s.WebHook != nil { - ret.WebhookTokenAuthnConfigFile = s.WebHook.ConfigFile - ret.WebhookTokenAuthnCacheTTL = s.WebHook.CacheTTL - } - - return ret -} - type RequestHeaderAuthenticationOptions struct { UsernameHeaders []string GroupHeaders []string diff --git a/pkg/apiserver/authenticator/BUILD b/pkg/kubeapiserver/authenticator/BUILD similarity index 89% rename from pkg/apiserver/authenticator/BUILD rename to pkg/kubeapiserver/authenticator/BUILD index 04c3bdb897c..17ecac0e23c 100644 --- a/pkg/apiserver/authenticator/BUILD +++ b/pkg/kubeapiserver/authenticator/BUILD @@ -9,17 +9,14 @@ load( go_library( name = "go_default_library", - srcs = [ - "builtin.go", - "delegating.go", - ], + srcs = ["config.go"], tags = ["automanaged"], deps = [ "//pkg/auth/authenticator:go_default_library", "//pkg/auth/authenticator/bearertoken:go_default_library", "//pkg/auth/group:go_default_library", "//pkg/auth/user:go_default_library", - "//pkg/client/clientset_generated/clientset/typed/authentication/v1beta1:go_default_library", + "//pkg/genericapiserver/authenticator:go_default_library", "//pkg/serviceaccount:go_default_library", "//pkg/util/cert:go_default_library", "//plugin/pkg/auth/authenticator/password/keystone:go_default_library", diff --git a/pkg/apiserver/authenticator/builtin.go b/pkg/kubeapiserver/authenticator/config.go similarity index 89% rename from pkg/apiserver/authenticator/builtin.go rename to pkg/kubeapiserver/authenticator/config.go index f4e88101052..b85c659b0b7 100644 --- a/pkg/apiserver/authenticator/builtin.go +++ b/pkg/kubeapiserver/authenticator/config.go @@ -25,6 +25,7 @@ import ( "k8s.io/kubernetes/pkg/auth/authenticator/bearertoken" "k8s.io/kubernetes/pkg/auth/group" "k8s.io/kubernetes/pkg/auth/user" + genericauthenticator "k8s.io/kubernetes/pkg/genericapiserver/authenticator" "k8s.io/kubernetes/pkg/serviceaccount" certutil "k8s.io/kubernetes/pkg/util/cert" "k8s.io/kubernetes/plugin/pkg/auth/authenticator/password/keystone" @@ -40,20 +41,6 @@ import ( "k8s.io/kubernetes/plugin/pkg/auth/authenticator/token/webhook" ) -type RequestHeaderConfig struct { - // UsernameHeaders are the headers to check (in order, case-insensitively) for an identity. The first header with a value wins. - UsernameHeaders []string - // GroupHeaders are the headers to check (case-insensitively) for a group names. All values will be used. - GroupHeaders []string - // ExtraHeaderPrefixes are the head prefixes to check (case-insentively) for filling in - // the user.Info.Extra. All values of all matching headers will be added. - ExtraHeaderPrefixes []string - // ClientCA points to CA bundle file which is used verify the identity of the front proxy - ClientCA string - // AllowedClientNames is a list of common names that may be presented by the authenticating front proxy. Empty means: accept any. - AllowedClientNames []string -} - type AuthenticatorConfig struct { Anonymous bool AnyToken bool @@ -72,7 +59,7 @@ type AuthenticatorConfig struct { WebhookTokenAuthnConfigFile string WebhookTokenAuthnCacheTTL time.Duration - RequestHeaderConfig *RequestHeaderConfig + RequestHeaderConfig *genericauthenticator.RequestHeaderConfig // TODO, this is the only non-serializable part of the entire config. Factor it out into a clientconfig ServiceAccountTokenGetter serviceaccount.ServiceAccountTokenGetter @@ -80,7 +67,7 @@ type AuthenticatorConfig struct { // New returns an authenticator.Request or an error that supports the standard // Kubernetes authentication mechanisms. -func New(config AuthenticatorConfig) (authenticator.Request, *spec.SecurityDefinitions, error) { +func (config AuthenticatorConfig) New() (authenticator.Request, *spec.SecurityDefinitions, error) { var authenticators []authenticator.Request securityDefinitions := spec.SecurityDefinitions{} hasBasicAuth := false @@ -243,11 +230,6 @@ func newAuthenticatorFromTokenFile(tokenAuthFile string) (authenticator.Request, return bearertoken.New(tokenAuthenticator), nil } -// newAuthenticatorFromToken returns an authenticator.Request or an error -func NewAuthenticatorFromTokens(tokens map[string]*user.DefaultInfo) authenticator.Request { - return bearertoken.New(tokenfile.New(tokens)) -} - // newAuthenticatorFromOIDCIssuerURL returns an authenticator.Request or an error. func newAuthenticatorFromOIDCIssuerURL(issuerURL, clientID, caFile, usernameClaim, groupsClaim string) (authenticator.Request, error) { tokenAuthenticator, err := oidc.New(oidc.OIDCOptions{ diff --git a/pkg/kubeapiserver/options/BUILD b/pkg/kubeapiserver/options/BUILD index bafc2f7d236..ee00c92fabe 100644 --- a/pkg/kubeapiserver/options/BUILD +++ b/pkg/kubeapiserver/options/BUILD @@ -9,10 +9,16 @@ load( go_library( name = "go_default_library", - srcs = ["authorization.go"], + srcs = [ + "authentication.go", + "authorization.go", + ], tags = ["automanaged"], deps = [ "//pkg/controller/informers:go_default_library", + "//pkg/genericapiserver:go_default_library", + "//pkg/genericapiserver/options:go_default_library", + "//pkg/kubeapiserver/authenticator:go_default_library", "//pkg/kubeapiserver/authorizer:go_default_library", "//vendor:github.com/spf13/pflag", ], diff --git a/pkg/kubeapiserver/options/authentication.go b/pkg/kubeapiserver/options/authentication.go new file mode 100644 index 00000000000..d52b6773ac4 --- /dev/null +++ b/pkg/kubeapiserver/options/authentication.go @@ -0,0 +1,318 @@ +/* +Copyright 2016 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 ( + "fmt" + "time" + + "github.com/spf13/pflag" + + "k8s.io/kubernetes/pkg/genericapiserver" + genericoptions "k8s.io/kubernetes/pkg/genericapiserver/options" + "k8s.io/kubernetes/pkg/kubeapiserver/authenticator" +) + +type BuiltInAuthenticationOptions struct { + Anonymous *AnonymousAuthenticationOptions + AnyToken *AnyTokenAuthenticationOptions + ClientCert *genericoptions.ClientCertAuthenticationOptions + Keystone *KeystoneAuthenticationOptions + OIDC *OIDCAuthenticationOptions + PasswordFile *PasswordFileAuthenticationOptions + RequestHeader *genericoptions.RequestHeaderAuthenticationOptions + ServiceAccounts *ServiceAccountAuthenticationOptions + TokenFile *TokenFileAuthenticationOptions + WebHook *WebHookAuthenticationOptions +} + +type AnyTokenAuthenticationOptions struct { + Allow bool +} + +type AnonymousAuthenticationOptions struct { + Allow bool +} + +type KeystoneAuthenticationOptions struct { + URL string + CAFile string +} + +type OIDCAuthenticationOptions struct { + CAFile string + ClientID string + IssuerURL string + UsernameClaim string + GroupsClaim string +} + +type PasswordFileAuthenticationOptions struct { + BasicAuthFile string +} + +type ServiceAccountAuthenticationOptions struct { + KeyFiles []string + Lookup bool +} + +type TokenFileAuthenticationOptions struct { + TokenFile string +} + +type WebHookAuthenticationOptions struct { + ConfigFile string + CacheTTL time.Duration +} + +func NewBuiltInAuthenticationOptions() *BuiltInAuthenticationOptions { + return &BuiltInAuthenticationOptions{} +} + +func (s *BuiltInAuthenticationOptions) WithAll() *BuiltInAuthenticationOptions { + return s. + WithAnyonymous(). + WithAnyToken(). + WithClientCert(). + WithKeystone(). + WithOIDC(). + WithPasswordFile(). + WithRequestHeader(). + WithServiceAccounts(). + WithTokenFile(). + WithWebHook() +} + +func (s *BuiltInAuthenticationOptions) WithAnyonymous() *BuiltInAuthenticationOptions { + s.Anonymous = &AnonymousAuthenticationOptions{Allow: true} + return s +} + +func (s *BuiltInAuthenticationOptions) WithAnyToken() *BuiltInAuthenticationOptions { + s.AnyToken = &AnyTokenAuthenticationOptions{} + return s +} + +func (s *BuiltInAuthenticationOptions) WithClientCert() *BuiltInAuthenticationOptions { + s.ClientCert = &genericoptions.ClientCertAuthenticationOptions{} + return s +} + +func (s *BuiltInAuthenticationOptions) WithKeystone() *BuiltInAuthenticationOptions { + s.Keystone = &KeystoneAuthenticationOptions{} + return s +} + +func (s *BuiltInAuthenticationOptions) WithOIDC() *BuiltInAuthenticationOptions { + s.OIDC = &OIDCAuthenticationOptions{} + return s +} + +func (s *BuiltInAuthenticationOptions) WithPasswordFile() *BuiltInAuthenticationOptions { + s.PasswordFile = &PasswordFileAuthenticationOptions{} + return s +} + +func (s *BuiltInAuthenticationOptions) WithRequestHeader() *BuiltInAuthenticationOptions { + s.RequestHeader = &genericoptions.RequestHeaderAuthenticationOptions{} + return s +} + +func (s *BuiltInAuthenticationOptions) WithServiceAccounts() *BuiltInAuthenticationOptions { + s.ServiceAccounts = &ServiceAccountAuthenticationOptions{} + return s +} + +func (s *BuiltInAuthenticationOptions) WithTokenFile() *BuiltInAuthenticationOptions { + s.TokenFile = &TokenFileAuthenticationOptions{} + return s +} + +func (s *BuiltInAuthenticationOptions) WithWebHook() *BuiltInAuthenticationOptions { + s.WebHook = &WebHookAuthenticationOptions{ + CacheTTL: 2 * time.Minute, + } + return s +} + +func (s *BuiltInAuthenticationOptions) Validate() []error { + allErrors := []error{} + return allErrors +} + +func (s *BuiltInAuthenticationOptions) AddFlags(fs *pflag.FlagSet) { + if s.Anonymous != nil { + fs.BoolVar(&s.Anonymous.Allow, "anonymous-auth", s.Anonymous.Allow, ""+ + "Enables anonymous requests to the secure port of the API server. "+ + "Requests that are not rejected by another authentication method are treated as anonymous requests. "+ + "Anonymous requests have a username of system:anonymous, and a group name of system:unauthenticated.") + } + + if s.AnyToken != nil { + fs.BoolVar(&s.AnyToken.Allow, "insecure-allow-any-token", s.AnyToken.Allow, ""+ + "If set, your server will be INSECURE. Any token will be allowed and user information will be parsed "+ + "from the token as `username/group1,group2`") + + } + + if s.ClientCert != nil { + s.ClientCert.AddFlags(fs) + } + + if s.Keystone != nil { + fs.StringVar(&s.Keystone.URL, "experimental-keystone-url", s.Keystone.URL, + "If passed, activates the keystone authentication plugin.") + + fs.StringVar(&s.Keystone.CAFile, "experimental-keystone-ca-file", s.Keystone.CAFile, ""+ + "If set, the Keystone server's certificate will be verified by one of the authorities "+ + "in the experimental-keystone-ca-file, otherwise the host's root CA set will be used.") + } + + if s.OIDC != nil { + fs.StringVar(&s.OIDC.IssuerURL, "oidc-issuer-url", s.OIDC.IssuerURL, ""+ + "The URL of the OpenID issuer, only HTTPS scheme will be accepted. "+ + "If set, it will be used to verify the OIDC JSON Web Token (JWT).") + + fs.StringVar(&s.OIDC.ClientID, "oidc-client-id", s.OIDC.ClientID, + "The client ID for the OpenID Connect client, must be set if oidc-issuer-url is set.") + + fs.StringVar(&s.OIDC.CAFile, "oidc-ca-file", s.OIDC.CAFile, ""+ + "If set, the OpenID server's certificate will be verified by one of the authorities "+ + "in the oidc-ca-file, otherwise the host's root CA set will be used.") + + fs.StringVar(&s.OIDC.UsernameClaim, "oidc-username-claim", "sub", ""+ + "The OpenID claim to use as the user name. Note that claims other than the default ('sub') "+ + "is not guaranteed to be unique and immutable. This flag is experimental, please see "+ + "the authentication documentation for further details.") + + fs.StringVar(&s.OIDC.GroupsClaim, "oidc-groups-claim", "", ""+ + "If provided, the name of a custom OpenID Connect claim for specifying user groups. "+ + "The claim value is expected to be a string or array of strings. This flag is experimental, "+ + "please see the authentication documentation for further details.") + } + + if s.PasswordFile != nil { + fs.StringVar(&s.PasswordFile.BasicAuthFile, "basic-auth-file", s.PasswordFile.BasicAuthFile, ""+ + "If set, the file that will be used to admit requests to the secure port of the API server "+ + "via http basic authentication.") + } + + if s.RequestHeader != nil { + s.RequestHeader.AddFlags(fs) + } + + if s.ServiceAccounts != nil { + fs.StringArrayVar(&s.ServiceAccounts.KeyFiles, "service-account-key-file", s.ServiceAccounts.KeyFiles, ""+ + "File containing PEM-encoded x509 RSA or ECDSA private or public keys, used to verify "+ + "ServiceAccount tokens. If unspecified, --tls-private-key-file is used. "+ + "The specified file can contain multiple keys, and the flag can be specified multiple times with different files.") + + fs.BoolVar(&s.ServiceAccounts.Lookup, "service-account-lookup", s.ServiceAccounts.Lookup, + "If true, validate ServiceAccount tokens exist in etcd as part of authentication.") + } + + if s.TokenFile != nil { + fs.StringVar(&s.TokenFile.TokenFile, "token-auth-file", s.TokenFile.TokenFile, ""+ + "If set, the file that will be used to secure the secure port of the API server "+ + "via token authentication.") + } + + if s.WebHook != nil { + fs.StringVar(&s.WebHook.ConfigFile, "authentication-token-webhook-config-file", s.WebHook.ConfigFile, ""+ + "File with webhook configuration for token authentication in kubeconfig format. "+ + "The API server will query the remote service to determine authentication for bearer tokens.") + + fs.DurationVar(&s.WebHook.CacheTTL, "authentication-token-webhook-cache-ttl", s.WebHook.CacheTTL, + "The duration to cache responses from the webhook token authenticator. Default is 2m.") + } +} + +func (s *BuiltInAuthenticationOptions) ToAuthenticationConfig() authenticator.AuthenticatorConfig { + ret := authenticator.AuthenticatorConfig{} + + if s.Anonymous != nil { + ret.Anonymous = s.Anonymous.Allow + } + + if s.AnyToken != nil { + ret.AnyToken = s.AnyToken.Allow + } + + if s.ClientCert != nil { + ret.ClientCAFile = s.ClientCert.ClientCA + } + + if s.Keystone != nil { + ret.KeystoneURL = s.Keystone.URL + ret.KeystoneCAFile = s.Keystone.CAFile + } + + if s.OIDC != nil { + ret.OIDCCAFile = s.OIDC.CAFile + ret.OIDCClientID = s.OIDC.ClientID + ret.OIDCGroupsClaim = s.OIDC.GroupsClaim + ret.OIDCIssuerURL = s.OIDC.IssuerURL + ret.OIDCUsernameClaim = s.OIDC.UsernameClaim + } + + if s.PasswordFile != nil { + ret.BasicAuthFile = s.PasswordFile.BasicAuthFile + } + + if s.RequestHeader != nil { + ret.RequestHeaderConfig = s.RequestHeader.ToAuthenticationRequestHeaderConfig() + } + + if s.ServiceAccounts != nil { + ret.ServiceAccountKeyFiles = s.ServiceAccounts.KeyFiles + ret.ServiceAccountLookup = s.ServiceAccounts.Lookup + } + + if s.TokenFile != nil { + ret.TokenAuthFile = s.TokenFile.TokenFile + } + + if s.WebHook != nil { + ret.WebhookTokenAuthnConfigFile = s.WebHook.ConfigFile + ret.WebhookTokenAuthnCacheTTL = s.WebHook.CacheTTL + } + + return ret +} + +func (o *BuiltInAuthenticationOptions) Apply(c *genericapiserver.Config) error { + if o == nil || o.PasswordFile == nil { + return nil + } + + var err error + if o.ClientCert != nil { + c, err = c.ApplyClientCert(o.ClientCert.ClientCA) + if 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 { + return fmt.Errorf("unable to load client CA file: %v", err) + } + } + + c.SupportsBasicAuth = len(o.PasswordFile.BasicAuthFile) > 0 + return nil +} diff --git a/test/integration/framework/BUILD b/test/integration/framework/BUILD index 9293ecaa83a..2d471e025ed 100644 --- a/test/integration/framework/BUILD +++ b/test/integration/framework/BUILD @@ -30,7 +30,6 @@ go_library( "//pkg/apis/policy/v1alpha1:go_default_library", "//pkg/apis/rbac/v1alpha1:go_default_library", "//pkg/apis/storage/v1beta1:go_default_library", - "//pkg/apiserver/authenticator:go_default_library", "//pkg/auth/authenticator:go_default_library", "//pkg/auth/authorizer:go_default_library", "//pkg/auth/authorizer/union:go_default_library", @@ -44,6 +43,7 @@ go_library( "//pkg/controller/replication:go_default_library", "//pkg/generated/openapi:go_default_library", "//pkg/genericapiserver:go_default_library", + "//pkg/genericapiserver/authenticator:go_default_library", "//pkg/genericapiserver/authorizer:go_default_library", "//pkg/kubectl:go_default_library", "//pkg/kubelet/client:go_default_library", diff --git a/test/integration/framework/master_utils.go b/test/integration/framework/master_utils.go index 8513dea4d54..ab3a69456a6 100644 --- a/test/integration/framework/master_utils.go +++ b/test/integration/framework/master_utils.go @@ -40,7 +40,6 @@ import ( policy "k8s.io/kubernetes/pkg/apis/policy/v1alpha1" rbac "k8s.io/kubernetes/pkg/apis/rbac/v1alpha1" storage "k8s.io/kubernetes/pkg/apis/storage/v1beta1" - "k8s.io/kubernetes/pkg/apiserver/authenticator" authauthenticator "k8s.io/kubernetes/pkg/auth/authenticator" authauthorizer "k8s.io/kubernetes/pkg/auth/authorizer" authorizerunion "k8s.io/kubernetes/pkg/auth/authorizer/union" @@ -54,6 +53,7 @@ import ( replicationcontroller "k8s.io/kubernetes/pkg/controller/replication" "k8s.io/kubernetes/pkg/generated/openapi" "k8s.io/kubernetes/pkg/genericapiserver" + "k8s.io/kubernetes/pkg/genericapiserver/authenticator" "k8s.io/kubernetes/pkg/genericapiserver/authorizer" "k8s.io/kubernetes/pkg/kubectl" kubeletclient "k8s.io/kubernetes/pkg/kubelet/client"