From 4c8959df59225b70263275f938572e1f1da95345 Mon Sep 17 00:00:00 2001 From: deads2k Date: Thu, 29 Sep 2016 15:10:04 -0400 Subject: [PATCH 1/2] pass loopback config to posthooks --- cmd/kube-apiserver/app/server.go | 5 ++ .../cmd/federation-apiserver/app/server.go | 5 ++ pkg/genericapiserver/config.go | 5 ++ pkg/genericapiserver/genericapiserver.go | 6 +- pkg/genericapiserver/hooks.go | 9 ++- .../options/server_run_options.go | 11 +++- .../rbac/clusterrole/policybased/storage.go | 8 +++ .../clusterrolebinding/policybased/storage.go | 8 +++ pkg/registry/rbac/rest/storage_rbac.go | 57 +++++++++---------- pkg/registry/rbac/role/policybased/storage.go | 8 +++ .../rbac/rolebinding/policybased/storage.go | 8 +++ test/integration/framework/master_utils.go | 34 ++++++++++- 12 files changed, 128 insertions(+), 36 deletions(-) diff --git a/cmd/kube-apiserver/app/server.go b/cmd/kube-apiserver/app/server.go index c9036cda1b7..ea982428e8d 100644 --- a/cmd/kube-apiserver/app/server.go +++ b/cmd/kube-apiserver/app/server.go @@ -265,6 +265,10 @@ func Run(s *options.APIServer) error { admissionControlPluginNames := strings.Split(s.AdmissionControl, ",") privilegedLoopbackToken := uuid.NewRandom().String() + selfClientConfig, err := s.NewSelfClientConfig(privilegedLoopbackToken) + if err != nil { + glog.Fatalf("Failed to create clientset: %v", err) + } client, err := s.NewSelfClient(privilegedLoopbackToken) if err != nil { glog.Errorf("Failed to create clientset: %v", err) @@ -297,6 +301,7 @@ func Run(s *options.APIServer) error { genericConfig := genericapiserver.NewConfig(s.ServerRunOptions) // TODO: Move the following to generic api server as well. + genericConfig.LoopbackClientConfig = selfClientConfig genericConfig.Authenticator = apiAuthenticator genericConfig.SupportsBasicAuth = len(s.BasicAuthFile) > 0 genericConfig.Authorizer = apiAuthorizer diff --git a/federation/cmd/federation-apiserver/app/server.go b/federation/cmd/federation-apiserver/app/server.go index 36d9163d03a..3b01269bd46 100644 --- a/federation/cmd/federation-apiserver/app/server.go +++ b/federation/cmd/federation-apiserver/app/server.go @@ -173,6 +173,10 @@ func Run(s *options.ServerRunOptions) error { admissionControlPluginNames := strings.Split(s.AdmissionControl, ",") privilegedLoopbackToken := uuid.NewRandom().String() + selfClientConfig, err := s.NewSelfClientConfig(privilegedLoopbackToken) + if err != nil { + glog.Fatalf("Failed to create clientset: %v", err) + } client, err := s.NewSelfClient(privilegedLoopbackToken) if err != nil { glog.Errorf("Failed to create clientset: %v", err) @@ -204,6 +208,7 @@ func Run(s *options.ServerRunOptions) error { } genericConfig := genericapiserver.NewConfig(s.ServerRunOptions) // TODO: Move the following to generic api server as well. + genericConfig.LoopbackClientConfig = selfClientConfig genericConfig.Authenticator = apiAuthenticator genericConfig.SupportsBasicAuth = len(s.BasicAuthFile) > 0 genericConfig.Authorizer = apiAuthorizer diff --git a/pkg/genericapiserver/config.go b/pkg/genericapiserver/config.go index e236f4573f7..ae7c9fad4ae 100644 --- a/pkg/genericapiserver/config.go +++ b/pkg/genericapiserver/config.go @@ -42,6 +42,7 @@ import ( "k8s.io/kubernetes/pkg/auth/authenticator" "k8s.io/kubernetes/pkg/auth/authorizer" authhandlers "k8s.io/kubernetes/pkg/auth/handlers" + "k8s.io/kubernetes/pkg/client/restclient" "k8s.io/kubernetes/pkg/cloudprovider" genericfilters "k8s.io/kubernetes/pkg/genericapiserver/filters" "k8s.io/kubernetes/pkg/genericapiserver/openapi/common" @@ -83,6 +84,9 @@ type Config struct { // TODO(ericchiang): Determine if policy escalation checks should be an admission controller. AuthorizerRBACSuperUser string + // LoopbackClientConfig is a config for a privileged loopback connection to the API server + LoopbackClientConfig *restclient.Config + // Map requests to contexts. Exported so downstream consumers can provider their own mappers RequestContextMapper api.RequestContextMapper @@ -309,6 +313,7 @@ func (c completedConfig) New() (*GenericAPIServer, error) { s := &GenericAPIServer{ ServiceClusterIPRange: c.ServiceClusterIPRange, ServiceNodePortRange: c.ServiceNodePortRange, + LoopbackClientConfig: c.LoopbackClientConfig, legacyAPIPrefix: c.APIPrefix, apiPrefix: c.APIGroupPrefix, admissionControl: c.AdmissionControl, diff --git a/pkg/genericapiserver/genericapiserver.go b/pkg/genericapiserver/genericapiserver.go index 4b4e797be37..8f6a9a7beae 100644 --- a/pkg/genericapiserver/genericapiserver.go +++ b/pkg/genericapiserver/genericapiserver.go @@ -42,6 +42,7 @@ import ( "k8s.io/kubernetes/pkg/apimachinery" "k8s.io/kubernetes/pkg/apimachinery/registered" "k8s.io/kubernetes/pkg/apiserver" + "k8s.io/kubernetes/pkg/client/restclient" "k8s.io/kubernetes/pkg/genericapiserver/openapi" "k8s.io/kubernetes/pkg/genericapiserver/openapi/common" "k8s.io/kubernetes/pkg/genericapiserver/options" @@ -94,6 +95,9 @@ type GenericAPIServer struct { // TODO refactor this closer to the point of use. ServiceNodePortRange utilnet.PortRange + // LoopbackClientConfig is a config for a privileged loopback connection to the API server + LoopbackClientConfig *restclient.Config + // minRequestTimeout is how short the request timeout can be. This is used to build the RESTHandler minRequestTimeout time.Duration @@ -315,7 +319,7 @@ func (s *GenericAPIServer) Run(options *options.ServerRunOptions) { <-secureStartedCh <-insecureStartedCh - s.RunPostStartHooks(PostStartHookContext{}) + s.RunPostStartHooks() // err == systemd.SdNotifyNoSocket when not running on a systemd system if err := systemd.SdNotify("READY=1\n"); err != nil && err != systemd.SdNotifyNoSocket { diff --git a/pkg/genericapiserver/hooks.go b/pkg/genericapiserver/hooks.go index 71cf885e272..93fba6bb1a5 100644 --- a/pkg/genericapiserver/hooks.go +++ b/pkg/genericapiserver/hooks.go @@ -21,6 +21,7 @@ import ( "github.com/golang/glog" + "k8s.io/kubernetes/pkg/client/restclient" utilruntime "k8s.io/kubernetes/pkg/util/runtime" ) @@ -37,8 +38,8 @@ type PostStartHookFunc func(context PostStartHookContext) error // PostStartHookContext provides information about this API server to a PostStartHookFunc type PostStartHookContext struct { - // TODO this should probably contain a cluster-admin powered client config which can be used to loopback - // to this API server. That client config doesn't exist yet. + // LoopbackClientConfig is a config for a privileged loopback connection to the API server + LoopbackClientConfig *restclient.Config } // PostStartHookProvider is an interface in addition to provide a post start hook for the api server @@ -74,11 +75,13 @@ func (s *GenericAPIServer) AddPostStartHook(name string, hook PostStartHookFunc) } // RunPostStartHooks runs the PostStartHooks for the server -func (s *GenericAPIServer) RunPostStartHooks(context PostStartHookContext) { +func (s *GenericAPIServer) RunPostStartHooks() { s.postStartHookLock.Lock() defer s.postStartHookLock.Unlock() s.postStartHooksCalled = true + context := PostStartHookContext{LoopbackClientConfig: s.LoopbackClientConfig} + for hookName, hook := range s.postStartHooks { go runPostStartHook(hookName, hook, context) } diff --git a/pkg/genericapiserver/options/server_run_options.go b/pkg/genericapiserver/options/server_run_options.go index f84af14b1eb..40289b11fd6 100644 --- a/pkg/genericapiserver/options/server_run_options.go +++ b/pkg/genericapiserver/options/server_run_options.go @@ -211,6 +211,15 @@ func mergeGroupVersionIntoMap(gvList string, dest map[string]unversioned.GroupVe // Returns a clientset which can be used to talk to this apiserver. func (s *ServerRunOptions) NewSelfClient(token string) (clientset.Interface, error) { + clientConfig, err := s.NewSelfClientConfig(token) + if err != nil { + return nil, err + } + return clientset.NewForConfig(clientConfig) +} + +// Returns a clientconfig which can be used to talk to this apiserver. +func (s *ServerRunOptions) NewSelfClientConfig(token string) (*restclient.Config, error) { clientConfig := &restclient.Config{ // Increase QPS limits. The client is currently passed to all admission plugins, // and those can be throttled in case of higher load on apiserver - see #22340 and #22422 @@ -228,7 +237,7 @@ func (s *ServerRunOptions) NewSelfClient(token string) (clientset.Interface, err return nil, errors.New("Unable to set url for apiserver local client") } - return clientset.NewForConfig(clientConfig) + return clientConfig, nil } // AddFlags adds flags for a specific APIServer to the specified FlagSet diff --git a/pkg/registry/rbac/clusterrole/policybased/storage.go b/pkg/registry/rbac/clusterrole/policybased/storage.go index 3c6a4a63e00..403b7a5e260 100644 --- a/pkg/registry/rbac/clusterrole/policybased/storage.go +++ b/pkg/registry/rbac/clusterrole/policybased/storage.go @@ -46,6 +46,14 @@ func (s *Storage) Create(ctx api.Context, obj runtime.Object) (runtime.Object, e if s.superUser != "" && user.GetName() == s.superUser { return s.StandardStorage.Create(ctx, obj) } + + // system:masters is special because the API server uses it for privileged loopback connections + // therefore we know that a member of system:masters can always do anything + for _, group := range user.GetGroups() { + if group == "system:masters" { + return s.StandardStorage.Create(ctx, obj) + } + } } clusterRole := obj.(*rbac.ClusterRole) diff --git a/pkg/registry/rbac/clusterrolebinding/policybased/storage.go b/pkg/registry/rbac/clusterrolebinding/policybased/storage.go index bc6da0569df..06e326374b2 100644 --- a/pkg/registry/rbac/clusterrolebinding/policybased/storage.go +++ b/pkg/registry/rbac/clusterrolebinding/policybased/storage.go @@ -46,6 +46,14 @@ func (s *Storage) Create(ctx api.Context, obj runtime.Object) (runtime.Object, e if s.superUser != "" && user.GetName() == s.superUser { return s.StandardStorage.Create(ctx, obj) } + + // system:masters is special because the API server uses it for privileged loopback connections + // therefore we know that a member of system:masters can always do anything + for _, group := range user.GetGroups() { + if group == "system:masters" { + return s.StandardStorage.Create(ctx, obj) + } + } } clusterRoleBinding := obj.(*rbac.ClusterRoleBinding) diff --git a/pkg/registry/rbac/rest/storage_rbac.go b/pkg/registry/rbac/rest/storage_rbac.go index 5f9190c74c1..f77d7bc2b37 100644 --- a/pkg/registry/rbac/rest/storage_rbac.go +++ b/pkg/registry/rbac/rest/storage_rbac.go @@ -27,6 +27,7 @@ import ( "k8s.io/kubernetes/pkg/apis/rbac" rbacapiv1alpha1 "k8s.io/kubernetes/pkg/apis/rbac/v1alpha1" rbacvalidation "k8s.io/kubernetes/pkg/apis/rbac/validation" + rbacclient "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/rbac/unversioned" "k8s.io/kubernetes/pkg/genericapiserver" "k8s.io/kubernetes/pkg/registry/rbac/clusterrole" clusterroleetcd "k8s.io/kubernetes/pkg/registry/rbac/clusterrole/etcd" @@ -46,8 +47,6 @@ import ( type RESTStorageProvider struct { AuthorizerRBACSuperUser string - - postStartHook genericapiserver.PostStartHookFunc } var _ genericapiserver.RESTStorageProvider = &RESTStorageProvider{} @@ -93,8 +92,6 @@ func (p *RESTStorageProvider) v1alpha1Storage(apiResourceConfigSource genericapi if apiResourceConfigSource.ResourceEnabled(version.WithResource("clusterroles")) { clusterRolesStorage := clusterroleetcd.NewREST(restOptionsGetter(rbac.Resource("clusterroles"))) storage["clusterroles"] = clusterrolepolicybased.NewStorage(clusterRolesStorage, newRuleValidator(), p.AuthorizerRBACSuperUser) - - p.postStartHook = newPostStartHook(clusterRolesStorage) } if apiResourceConfigSource.ResourceEnabled(version.WithResource("clusterrolebindings")) { clusterRoleBindingsStorage := clusterrolebindingetcd.NewREST(restOptionsGetter(rbac.Resource("clusterrolebindings"))) @@ -104,33 +101,35 @@ func (p *RESTStorageProvider) v1alpha1Storage(apiResourceConfigSource genericapi } func (p *RESTStorageProvider) PostStartHook() (string, genericapiserver.PostStartHookFunc, error) { - return "rbac/bootstrap-roles", p.postStartHook, nil + return "rbac/bootstrap-roles", PostStartHook, nil } -func newPostStartHook(directClusterRoleAccess *clusterroleetcd.REST) genericapiserver.PostStartHookFunc { - return func(genericapiserver.PostStartHookContext) error { - ctx := api.NewContext() - - existingClusterRoles, err := directClusterRoleAccess.List(ctx, &api.ListOptions{}) - if err != nil { - utilruntime.HandleError(fmt.Errorf("unable to initialize clusterroles: %v", err)) - return nil - } - // if clusterroles already exist, then assume we don't have work to do because we've already - // initialized or another API server has started this task - if len(existingClusterRoles.(*rbac.ClusterRoleList).Items) > 0 { - return nil - } - - for _, clusterRole := range append(bootstrappolicy.ClusterRoles(), bootstrappolicy.ControllerRoles()...) { - if _, err := directClusterRoleAccess.Create(ctx, &clusterRole); err != nil { - // don't fail on failures, try to create as many as you can - utilruntime.HandleError(fmt.Errorf("unable to initialize clusterroles: %v", err)) - continue - } - glog.Infof("Created clusterrole.%s/%s", rbac.GroupName, clusterRole.Name) - } - +func PostStartHook(hookContext genericapiserver.PostStartHookContext) error { + clientset, err := rbacclient.NewForConfig(hookContext.LoopbackClientConfig) + if err != nil { + utilruntime.HandleError(fmt.Errorf("unable to initialize clusterroles: %v", err)) return nil } + + existingClusterRoles, err := clientset.ClusterRoles().List(api.ListOptions{}) + if err != nil { + utilruntime.HandleError(fmt.Errorf("unable to initialize clusterroles: %v", err)) + return nil + } + // if clusterroles already exist, then assume we don't have work to do because we've already + // initialized or another API server has started this task + if len(existingClusterRoles.Items) > 0 { + return nil + } + + for _, clusterRole := range append(bootstrappolicy.ClusterRoles(), bootstrappolicy.ControllerRoles()...) { + if _, err := clientset.ClusterRoles().Create(&clusterRole); err != nil { + // don't fail on failures, try to create as many as you can + utilruntime.HandleError(fmt.Errorf("unable to initialize clusterroles: %v", err)) + continue + } + glog.Infof("Created clusterrole.%s/%s", rbac.GroupName, clusterRole.Name) + } + + return nil } diff --git a/pkg/registry/rbac/role/policybased/storage.go b/pkg/registry/rbac/role/policybased/storage.go index f9e07435e13..97833ad436a 100644 --- a/pkg/registry/rbac/role/policybased/storage.go +++ b/pkg/registry/rbac/role/policybased/storage.go @@ -46,6 +46,14 @@ func (s *Storage) Create(ctx api.Context, obj runtime.Object) (runtime.Object, e if s.superUser != "" && user.GetName() == s.superUser { return s.StandardStorage.Create(ctx, obj) } + + // system:masters is special because the API server uses it for privileged loopback connections + // therefore we know that a member of system:masters can always do anything + for _, group := range user.GetGroups() { + if group == "system:masters" { + return s.StandardStorage.Create(ctx, obj) + } + } } role := obj.(*rbac.Role) diff --git a/pkg/registry/rbac/rolebinding/policybased/storage.go b/pkg/registry/rbac/rolebinding/policybased/storage.go index c0d3ce1259a..ae48020e4d2 100644 --- a/pkg/registry/rbac/rolebinding/policybased/storage.go +++ b/pkg/registry/rbac/rolebinding/policybased/storage.go @@ -46,6 +46,14 @@ func (s *Storage) Create(ctx api.Context, obj runtime.Object) (runtime.Object, e if s.superUser != "" && user.GetName() == s.superUser { return s.StandardStorage.Create(ctx, obj) } + + // system:masters is special because the API server uses it for privileged loopback connections + // therefore we know that a member of system:masters can always do anything + for _, group := range user.GetGroups() { + if group == "system:masters" { + return s.StandardStorage.Create(ctx, obj) + } + } } roleBinding := obj.(*rbac.RoleBinding) diff --git a/test/integration/framework/master_utils.go b/test/integration/framework/master_utils.go index ca7fea5f944..fd14523e004 100644 --- a/test/integration/framework/master_utils.go +++ b/test/integration/framework/master_utils.go @@ -38,12 +38,16 @@ import ( "k8s.io/kubernetes/pkg/apis/policy" "k8s.io/kubernetes/pkg/apis/rbac" "k8s.io/kubernetes/pkg/apis/storage" + "k8s.io/kubernetes/pkg/apiserver/authenticator" + authorizerunion "k8s.io/kubernetes/pkg/auth/authorizer/union" + "k8s.io/kubernetes/pkg/auth/user" clientset "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset" "k8s.io/kubernetes/pkg/client/record" "k8s.io/kubernetes/pkg/client/restclient" client "k8s.io/kubernetes/pkg/client/unversioned" "k8s.io/kubernetes/pkg/controller" replicationcontroller "k8s.io/kubernetes/pkg/controller/replication" + "k8s.io/kubernetes/pkg/generated/openapi" "k8s.io/kubernetes/pkg/genericapiserver" "k8s.io/kubernetes/pkg/genericapiserver/authorizer" "k8s.io/kubernetes/pkg/kubectl" @@ -53,10 +57,10 @@ import ( "k8s.io/kubernetes/pkg/storage/storagebackend" utilnet "k8s.io/kubernetes/pkg/util/net" "k8s.io/kubernetes/plugin/pkg/admission/admit" + authenticatorunion "k8s.io/kubernetes/plugin/pkg/auth/authenticator/request/union" "github.com/go-openapi/spec" "github.com/pborman/uuid" - "k8s.io/kubernetes/pkg/generated/openapi" ) const ( @@ -149,6 +153,32 @@ func startMasterOrDie(masterConfig *master.Config) (*master.Master, *httptest.Se }, } } + + // set the loopback client config + if masterConfig.GenericConfig.LoopbackClientConfig == nil { + masterConfig.GenericConfig.LoopbackClientConfig = &restclient.Config{QPS: 50, Burst: 100} + } + masterConfig.GenericConfig.LoopbackClientConfig.Host = s.URL + + privilegedLoopbackToken := uuid.NewRandom().String() + // wrap any available authorizer + if masterConfig.GenericConfig.Authenticator != nil { + tokens := make(map[string]*user.DefaultInfo) + tokens[privilegedLoopbackToken] = &user.DefaultInfo{ + Name: "system:apiserver", + UID: uuid.NewRandom().String(), + Groups: []string{"system:masters"}, + } + + tokenAuthenticator := authenticator.NewAuthenticatorFromTokens(tokens) + masterConfig.GenericConfig.Authenticator = authenticatorunion.New(tokenAuthenticator, masterConfig.GenericConfig.Authenticator) + + tokenAuthorizer := authorizer.NewPrivilegedGroups("system:masters") + masterConfig.GenericConfig.Authorizer = authorizerunion.New(tokenAuthorizer, masterConfig.GenericConfig.Authorizer) + + masterConfig.GenericConfig.LoopbackClientConfig.BearerToken = privilegedLoopbackToken + } + m, err := masterConfig.Complete().New() if err != nil { glog.Fatalf("error in bringing up the master: %v", err) @@ -157,7 +187,7 @@ func startMasterOrDie(masterConfig *master.Config) (*master.Master, *httptest.Se // TODO have this start method actually use the normal start sequence for the API server // this method never actually calls the `Run` method for the API server // fire the post hooks ourselves - m.GenericAPIServer.RunPostStartHooks(genericapiserver.PostStartHookContext{}) + m.GenericAPIServer.RunPostStartHooks() return m, s } From 57039cfdfadf26575469f425b029e99309b2d079 Mon Sep 17 00:00:00 2001 From: deads2k Date: Thu, 29 Sep 2016 16:27:14 -0400 Subject: [PATCH 2/2] make well-known users and groups into constants --- cmd/kube-apiserver/app/server.go | 6 +++--- federation/cmd/federation-apiserver/app/server.go | 6 +++--- pkg/apiserver/authenticator/authn.go | 2 +- pkg/auth/user/user.go | 10 ++++++++++ pkg/registry/rbac/clusterrole/policybased/storage.go | 9 +++++---- .../rbac/clusterrolebinding/policybased/storage.go | 9 +++++---- pkg/registry/rbac/role/policybased/storage.go | 9 +++++---- pkg/registry/rbac/rolebinding/policybased/storage.go | 9 +++++---- .../auth/authenticator/request/anonymous/anonymous.go | 4 ++-- .../authenticator/request/anonymous/anonymous_test.go | 9 +++++---- test/integration/framework/master_utils.go | 6 +++--- 11 files changed, 47 insertions(+), 32 deletions(-) diff --git a/cmd/kube-apiserver/app/server.go b/cmd/kube-apiserver/app/server.go index ea982428e8d..ac38728ef5a 100644 --- a/cmd/kube-apiserver/app/server.go +++ b/cmd/kube-apiserver/app/server.go @@ -279,15 +279,15 @@ func Run(s *options.APIServer) error { var uid = uuid.NewRandom().String() tokens := make(map[string]*user.DefaultInfo) tokens[privilegedLoopbackToken] = &user.DefaultInfo{ - Name: "system:apiserver", + Name: user.APIServerUser, UID: uid, - Groups: []string{"system:masters"}, + Groups: []string{user.SystemPrivilegedGroup}, } tokenAuthenticator := authenticator.NewAuthenticatorFromTokens(tokens) apiAuthenticator = authenticatorunion.New(tokenAuthenticator, apiAuthenticator) - tokenAuthorizer := authorizer.NewPrivilegedGroups("system:masters") + tokenAuthorizer := authorizer.NewPrivilegedGroups(user.SystemPrivilegedGroup) apiAuthorizer = authorizerunion.New(tokenAuthorizer, apiAuthorizer) } diff --git a/federation/cmd/federation-apiserver/app/server.go b/federation/cmd/federation-apiserver/app/server.go index 3b01269bd46..b7e99fe0eca 100644 --- a/federation/cmd/federation-apiserver/app/server.go +++ b/federation/cmd/federation-apiserver/app/server.go @@ -187,15 +187,15 @@ func Run(s *options.ServerRunOptions) error { var uid = uuid.NewRandom().String() tokens := make(map[string]*user.DefaultInfo) tokens[privilegedLoopbackToken] = &user.DefaultInfo{ - Name: "system:apiserver", + Name: user.APIServerUser, UID: uid, - Groups: []string{"system:masters"}, + Groups: []string{user.SystemPrivilegedGroup}, } tokenAuthenticator := authenticator.NewAuthenticatorFromTokens(tokens) apiAuthenticator = authenticatorunion.New(tokenAuthenticator, apiAuthenticator) - tokenAuthorizer := authorizer.NewPrivilegedGroups("system:masters") + tokenAuthorizer := authorizer.NewPrivilegedGroups(user.SystemPrivilegedGroup) apiAuthorizer = authorizerunion.New(tokenAuthorizer, apiAuthorizer) } diff --git a/pkg/apiserver/authenticator/authn.go b/pkg/apiserver/authenticator/authn.go index e415be65aaa..2f306dc02c8 100644 --- a/pkg/apiserver/authenticator/authn.go +++ b/pkg/apiserver/authenticator/authn.go @@ -141,7 +141,7 @@ func New(config AuthenticatorConfig) (authenticator.Request, error) { authenticator := union.New(authenticators...) - authenticator = group.NewGroupAdder(authenticator, []string{"system:authenticated"}) + authenticator = group.NewGroupAdder(authenticator, []string{user.AllAuthenticated}) if config.Anonymous { // If the authenticator chain returns an error, return an error (don't consider a bad bearer token anonymous). diff --git a/pkg/auth/user/user.go b/pkg/auth/user/user.go index 7e7cc16f68b..c48695b6d54 100644 --- a/pkg/auth/user/user.go +++ b/pkg/auth/user/user.go @@ -65,3 +65,13 @@ func (i *DefaultInfo) GetGroups() []string { func (i *DefaultInfo) GetExtra() map[string][]string { return i.Extra } + +// well-known user and group names +const ( + SystemPrivilegedGroup = "system:masters" + AllUnauthenticated = "system:unauthenticated" + AllAuthenticated = "system:authenticated" + + Anonymous = "system:anonymous" + APIServerUser = "system:apiserver" +) diff --git a/pkg/registry/rbac/clusterrole/policybased/storage.go b/pkg/registry/rbac/clusterrole/policybased/storage.go index 403b7a5e260..a605ce74517 100644 --- a/pkg/registry/rbac/clusterrole/policybased/storage.go +++ b/pkg/registry/rbac/clusterrole/policybased/storage.go @@ -23,6 +23,7 @@ import ( "k8s.io/kubernetes/pkg/api/rest" "k8s.io/kubernetes/pkg/apis/rbac" "k8s.io/kubernetes/pkg/apis/rbac/validation" + "k8s.io/kubernetes/pkg/auth/user" "k8s.io/kubernetes/pkg/runtime" ) @@ -42,15 +43,15 @@ func NewStorage(s rest.StandardStorage, ruleResolver validation.AuthorizationRul } func (s *Storage) Create(ctx api.Context, obj runtime.Object) (runtime.Object, error) { - if user, ok := api.UserFrom(ctx); ok { - if s.superUser != "" && user.GetName() == s.superUser { + if u, ok := api.UserFrom(ctx); ok { + if s.superUser != "" && u.GetName() == s.superUser { return s.StandardStorage.Create(ctx, obj) } // system:masters is special because the API server uses it for privileged loopback connections // therefore we know that a member of system:masters can always do anything - for _, group := range user.GetGroups() { - if group == "system:masters" { + for _, group := range u.GetGroups() { + if group == user.SystemPrivilegedGroup { return s.StandardStorage.Create(ctx, obj) } } diff --git a/pkg/registry/rbac/clusterrolebinding/policybased/storage.go b/pkg/registry/rbac/clusterrolebinding/policybased/storage.go index 06e326374b2..539e97d1250 100644 --- a/pkg/registry/rbac/clusterrolebinding/policybased/storage.go +++ b/pkg/registry/rbac/clusterrolebinding/policybased/storage.go @@ -23,6 +23,7 @@ import ( "k8s.io/kubernetes/pkg/api/rest" "k8s.io/kubernetes/pkg/apis/rbac" "k8s.io/kubernetes/pkg/apis/rbac/validation" + "k8s.io/kubernetes/pkg/auth/user" "k8s.io/kubernetes/pkg/runtime" ) @@ -42,15 +43,15 @@ func NewStorage(s rest.StandardStorage, ruleResolver validation.AuthorizationRul } func (s *Storage) Create(ctx api.Context, obj runtime.Object) (runtime.Object, error) { - if user, ok := api.UserFrom(ctx); ok { - if s.superUser != "" && user.GetName() == s.superUser { + if u, ok := api.UserFrom(ctx); ok { + if s.superUser != "" && u.GetName() == s.superUser { return s.StandardStorage.Create(ctx, obj) } // system:masters is special because the API server uses it for privileged loopback connections // therefore we know that a member of system:masters can always do anything - for _, group := range user.GetGroups() { - if group == "system:masters" { + for _, group := range u.GetGroups() { + if group == user.SystemPrivilegedGroup { return s.StandardStorage.Create(ctx, obj) } } diff --git a/pkg/registry/rbac/role/policybased/storage.go b/pkg/registry/rbac/role/policybased/storage.go index 97833ad436a..38ad81decfd 100644 --- a/pkg/registry/rbac/role/policybased/storage.go +++ b/pkg/registry/rbac/role/policybased/storage.go @@ -23,6 +23,7 @@ import ( "k8s.io/kubernetes/pkg/api/rest" "k8s.io/kubernetes/pkg/apis/rbac" "k8s.io/kubernetes/pkg/apis/rbac/validation" + "k8s.io/kubernetes/pkg/auth/user" "k8s.io/kubernetes/pkg/runtime" ) @@ -42,15 +43,15 @@ func NewStorage(s rest.StandardStorage, ruleResolver validation.AuthorizationRul } func (s *Storage) Create(ctx api.Context, obj runtime.Object) (runtime.Object, error) { - if user, ok := api.UserFrom(ctx); ok { - if s.superUser != "" && user.GetName() == s.superUser { + if u, ok := api.UserFrom(ctx); ok { + if s.superUser != "" && u.GetName() == s.superUser { return s.StandardStorage.Create(ctx, obj) } // system:masters is special because the API server uses it for privileged loopback connections // therefore we know that a member of system:masters can always do anything - for _, group := range user.GetGroups() { - if group == "system:masters" { + for _, group := range u.GetGroups() { + if group == user.SystemPrivilegedGroup { return s.StandardStorage.Create(ctx, obj) } } diff --git a/pkg/registry/rbac/rolebinding/policybased/storage.go b/pkg/registry/rbac/rolebinding/policybased/storage.go index ae48020e4d2..49750d457dc 100644 --- a/pkg/registry/rbac/rolebinding/policybased/storage.go +++ b/pkg/registry/rbac/rolebinding/policybased/storage.go @@ -23,6 +23,7 @@ import ( "k8s.io/kubernetes/pkg/api/rest" "k8s.io/kubernetes/pkg/apis/rbac" "k8s.io/kubernetes/pkg/apis/rbac/validation" + "k8s.io/kubernetes/pkg/auth/user" "k8s.io/kubernetes/pkg/runtime" ) @@ -42,15 +43,15 @@ func NewStorage(s rest.StandardStorage, ruleResolver validation.AuthorizationRul } func (s *Storage) Create(ctx api.Context, obj runtime.Object) (runtime.Object, error) { - if user, ok := api.UserFrom(ctx); ok { - if s.superUser != "" && user.GetName() == s.superUser { + if u, ok := api.UserFrom(ctx); ok { + if s.superUser != "" && u.GetName() == s.superUser { return s.StandardStorage.Create(ctx, obj) } // system:masters is special because the API server uses it for privileged loopback connections // therefore we know that a member of system:masters can always do anything - for _, group := range user.GetGroups() { - if group == "system:masters" { + for _, group := range u.GetGroups() { + if group == user.SystemPrivilegedGroup { return s.StandardStorage.Create(ctx, obj) } } diff --git a/plugin/pkg/auth/authenticator/request/anonymous/anonymous.go b/plugin/pkg/auth/authenticator/request/anonymous/anonymous.go index 9864722ec7c..4a7a7a0a845 100644 --- a/plugin/pkg/auth/authenticator/request/anonymous/anonymous.go +++ b/plugin/pkg/auth/authenticator/request/anonymous/anonymous.go @@ -24,9 +24,9 @@ import ( ) const ( - anonymousUser = "system:anonymous" + anonymousUser = user.Anonymous - unauthenticatedGroup = "system:unauthenticated" + unauthenticatedGroup = user.AllUnauthenticated ) func NewAuthenticator() authenticator.Request { diff --git a/plugin/pkg/auth/authenticator/request/anonymous/anonymous_test.go b/plugin/pkg/auth/authenticator/request/anonymous/anonymous_test.go index ca22fb7bfc0..0d095cfc4aa 100644 --- a/plugin/pkg/auth/authenticator/request/anonymous/anonymous_test.go +++ b/plugin/pkg/auth/authenticator/request/anonymous/anonymous_test.go @@ -20,6 +20,7 @@ import ( "testing" "k8s.io/kubernetes/pkg/auth/authenticator" + "k8s.io/kubernetes/pkg/auth/user" "k8s.io/kubernetes/pkg/util/sets" ) @@ -32,10 +33,10 @@ func TestAnonymous(t *testing.T) { if !ok { t.Fatalf("Unexpectedly unauthenticated") } - if u.GetName() != "system:anonymous" { - t.Fatalf("Expected username %s, got %s", "system:anonymous", u.GetName()) + if u.GetName() != user.Anonymous { + t.Fatalf("Expected username %s, got %s", user.Anonymous, u.GetName()) } - if !sets.NewString(u.GetGroups()...).Equal(sets.NewString("system:unauthenticated")) { - t.Fatalf("Expected group %s, got %v", "system:unauthenticated", u.GetGroups()) + if !sets.NewString(u.GetGroups()...).Equal(sets.NewString(user.AllUnauthenticated)) { + t.Fatalf("Expected group %s, got %v", user.AllUnauthenticated, u.GetGroups()) } } diff --git a/test/integration/framework/master_utils.go b/test/integration/framework/master_utils.go index fd14523e004..a037c7339b9 100644 --- a/test/integration/framework/master_utils.go +++ b/test/integration/framework/master_utils.go @@ -165,15 +165,15 @@ func startMasterOrDie(masterConfig *master.Config) (*master.Master, *httptest.Se if masterConfig.GenericConfig.Authenticator != nil { tokens := make(map[string]*user.DefaultInfo) tokens[privilegedLoopbackToken] = &user.DefaultInfo{ - Name: "system:apiserver", + Name: user.APIServerUser, UID: uuid.NewRandom().String(), - Groups: []string{"system:masters"}, + Groups: []string{user.SystemPrivilegedGroup}, } tokenAuthenticator := authenticator.NewAuthenticatorFromTokens(tokens) masterConfig.GenericConfig.Authenticator = authenticatorunion.New(tokenAuthenticator, masterConfig.GenericConfig.Authenticator) - tokenAuthorizer := authorizer.NewPrivilegedGroups("system:masters") + tokenAuthorizer := authorizer.NewPrivilegedGroups(user.SystemPrivilegedGroup) masterConfig.GenericConfig.Authorizer = authorizerunion.New(tokenAuthorizer, masterConfig.GenericConfig.Authorizer) masterConfig.GenericConfig.LoopbackClientConfig.BearerToken = privilegedLoopbackToken