diff --git a/cmd/kube-apiserver/app/server.go b/cmd/kube-apiserver/app/server.go index a180deb5901..87a93280abc 100644 --- a/cmd/kube-apiserver/app/server.go +++ b/cmd/kube-apiserver/app/server.go @@ -39,7 +39,6 @@ import ( "k8s.io/kubernetes/pkg/apis/autoscaling" "k8s.io/kubernetes/pkg/apis/batch" "k8s.io/kubernetes/pkg/apis/extensions" - "k8s.io/kubernetes/pkg/apis/rbac" "k8s.io/kubernetes/pkg/apiserver" "k8s.io/kubernetes/pkg/apiserver/authenticator" "k8s.io/kubernetes/pkg/apiserver/openapi" @@ -52,20 +51,10 @@ import ( generatedopenapi "k8s.io/kubernetes/pkg/generated/openapi" "k8s.io/kubernetes/pkg/genericapiserver" "k8s.io/kubernetes/pkg/genericapiserver/authorizer" - genericoptions "k8s.io/kubernetes/pkg/genericapiserver/options" genericvalidation "k8s.io/kubernetes/pkg/genericapiserver/validation" kubeletclient "k8s.io/kubernetes/pkg/kubelet/client" "k8s.io/kubernetes/pkg/master" "k8s.io/kubernetes/pkg/registry/cachesize" - "k8s.io/kubernetes/pkg/registry/generic" - "k8s.io/kubernetes/pkg/registry/rbac/clusterrole" - clusterroleetcd "k8s.io/kubernetes/pkg/registry/rbac/clusterrole/etcd" - "k8s.io/kubernetes/pkg/registry/rbac/clusterrolebinding" - clusterrolebindingetcd "k8s.io/kubernetes/pkg/registry/rbac/clusterrolebinding/etcd" - "k8s.io/kubernetes/pkg/registry/rbac/role" - roleetcd "k8s.io/kubernetes/pkg/registry/rbac/role/etcd" - "k8s.io/kubernetes/pkg/registry/rbac/rolebinding" - rolebindingetcd "k8s.io/kubernetes/pkg/registry/rbac/rolebinding/etcd" "k8s.io/kubernetes/pkg/serviceaccount" "k8s.io/kubernetes/pkg/util/wait" authenticatorunion "k8s.io/kubernetes/plugin/pkg/auth/authenticator/request/union" @@ -253,48 +242,7 @@ func Run(s *options.APIServer) error { glog.Fatalf("Invalid Authentication Config: %v", err) } - authorizationModeNames := strings.Split(s.AuthorizationMode, ",") - - modeEnabled := func(mode string) bool { - for _, m := range authorizationModeNames { - if m == mode { - return true - } - } - return false - } - - authorizationConfig := authorizer.AuthorizationConfig{ - PolicyFile: s.AuthorizationPolicyFile, - WebhookConfigFile: s.AuthorizationWebhookConfigFile, - WebhookCacheAuthorizedTTL: s.AuthorizationWebhookCacheAuthorizedTTL, - WebhookCacheUnauthorizedTTL: s.AuthorizationWebhookCacheUnauthorizedTTL, - RBACSuperUser: s.AuthorizationRBACSuperUser, - } - if modeEnabled(genericoptions.ModeRBAC) { - mustGetRESTOptions := func(resource string) generic.RESTOptions { - config, err := storageFactory.NewConfig(rbac.Resource(resource)) - if err != nil { - glog.Fatalf("Unable to get %s storage: %v", resource, err) - } - return generic.RESTOptions{StorageConfig: config, Decorator: generic.UndecoratedStorage, ResourcePrefix: storageFactory.ResourcePrefix(rbac.Resource(resource))} - } - - // For initial bootstrapping go directly to etcd to avoid privillege escalation check. - authorizationConfig.RBACRoleRegistry = role.NewRegistry(roleetcd.NewREST(mustGetRESTOptions("roles"))) - authorizationConfig.RBACRoleBindingRegistry = rolebinding.NewRegistry(rolebindingetcd.NewREST(mustGetRESTOptions("rolebindings"))) - authorizationConfig.RBACClusterRoleRegistry = clusterrole.NewRegistry(clusterroleetcd.NewREST(mustGetRESTOptions("clusterroles"))) - authorizationConfig.RBACClusterRoleBindingRegistry = clusterrolebinding.NewRegistry(clusterrolebindingetcd.NewREST(mustGetRESTOptions("clusterrolebindings"))) - } - - apiAuthorizer, err := authorizer.NewAuthorizerFromAuthorizationConfig(authorizationModeNames, authorizationConfig) - if err != nil { - glog.Fatalf("Invalid Authorization Config: %v", err) - } - - 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) @@ -303,6 +251,23 @@ func Run(s *options.APIServer) error { if err != nil { glog.Errorf("Failed to create clientset: %v", err) } + sharedInformers := informers.NewSharedInformerFactory(client, 10*time.Minute) + + authorizationConfig := authorizer.AuthorizationConfig{ + PolicyFile: s.AuthorizationPolicyFile, + WebhookConfigFile: s.AuthorizationWebhookConfigFile, + WebhookCacheAuthorizedTTL: s.AuthorizationWebhookCacheAuthorizedTTL, + WebhookCacheUnauthorizedTTL: s.AuthorizationWebhookCacheUnauthorizedTTL, + RBACSuperUser: s.AuthorizationRBACSuperUser, + InformerFactory: sharedInformers, + } + authorizationModeNames := strings.Split(s.AuthorizationMode, ",") + apiAuthorizer, err := authorizer.NewAuthorizerFromAuthorizationConfig(authorizationModeNames, authorizationConfig) + if err != nil { + glog.Fatalf("Invalid Authorization Config: %v", err) + } + + admissionControlPluginNames := strings.Split(s.AdmissionControl, ",") // TODO(dims): We probably need to add an option "EnableLoopbackToken" if apiAuthenticator != nil { @@ -321,7 +286,6 @@ func Run(s *options.APIServer) error { apiAuthorizer = authorizerunion.New(tokenAuthorizer, apiAuthorizer) } - sharedInformers := informers.NewSharedInformerFactory(client, 10*time.Minute) pluginInitializer := admission.NewPluginInitializer(sharedInformers, apiAuthorizer) admissionController, err := admission.NewFromPlugins(client, admissionControlPluginNames, s.AdmissionControlConfigFile, pluginInitializer) diff --git a/federation/cmd/federation-apiserver/app/server.go b/federation/cmd/federation-apiserver/app/server.go index 013bbf940a6..b43f3caa91e 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/pkg/admission" "k8s.io/kubernetes/pkg/api" "k8s.io/kubernetes/pkg/api/unversioned" - "k8s.io/kubernetes/pkg/apis/rbac" "k8s.io/kubernetes/pkg/apiserver/authenticator" apiserveropenapi "k8s.io/kubernetes/pkg/apiserver/openapi" authorizerunion "k8s.io/kubernetes/pkg/auth/authorizer/union" @@ -41,19 +40,10 @@ import ( "k8s.io/kubernetes/pkg/generated/openapi" "k8s.io/kubernetes/pkg/genericapiserver" "k8s.io/kubernetes/pkg/genericapiserver/authorizer" - genericoptions "k8s.io/kubernetes/pkg/genericapiserver/options" genericvalidation "k8s.io/kubernetes/pkg/genericapiserver/validation" "k8s.io/kubernetes/pkg/registry/cachesize" "k8s.io/kubernetes/pkg/registry/generic" "k8s.io/kubernetes/pkg/registry/generic/registry" - "k8s.io/kubernetes/pkg/registry/rbac/clusterrole" - clusterroleetcd "k8s.io/kubernetes/pkg/registry/rbac/clusterrole/etcd" - "k8s.io/kubernetes/pkg/registry/rbac/clusterrolebinding" - clusterrolebindingetcd "k8s.io/kubernetes/pkg/registry/rbac/clusterrolebinding/etcd" - "k8s.io/kubernetes/pkg/registry/rbac/role" - roleetcd "k8s.io/kubernetes/pkg/registry/rbac/role/etcd" - "k8s.io/kubernetes/pkg/registry/rbac/rolebinding" - rolebindingetcd "k8s.io/kubernetes/pkg/registry/rbac/rolebinding/etcd" "k8s.io/kubernetes/pkg/routes" "k8s.io/kubernetes/pkg/util/wait" authenticatorunion "k8s.io/kubernetes/plugin/pkg/auth/authenticator/request/union" @@ -143,48 +133,7 @@ func Run(s *options.ServerRunOptions) error { glog.Fatalf("Invalid Authentication Config: %v", err) } - authorizationModeNames := strings.Split(s.AuthorizationMode, ",") - - modeEnabled := func(mode string) bool { - for _, m := range authorizationModeNames { - if m == mode { - return true - } - } - return false - } - - authorizationConfig := authorizer.AuthorizationConfig{ - PolicyFile: s.AuthorizationPolicyFile, - WebhookConfigFile: s.AuthorizationWebhookConfigFile, - WebhookCacheAuthorizedTTL: s.AuthorizationWebhookCacheAuthorizedTTL, - WebhookCacheUnauthorizedTTL: s.AuthorizationWebhookCacheUnauthorizedTTL, - RBACSuperUser: s.AuthorizationRBACSuperUser, - } - if modeEnabled(genericoptions.ModeRBAC) { - mustGetRESTOptions := func(resource string) generic.RESTOptions { - config, err := storageFactory.NewConfig(rbac.Resource(resource)) - if err != nil { - glog.Fatalf("Unable to get %s storage: %v", resource, err) - } - return generic.RESTOptions{StorageConfig: config, Decorator: generic.UndecoratedStorage, ResourcePrefix: storageFactory.ResourcePrefix(rbac.Resource(resource))} - } - - // For initial bootstrapping go directly to etcd to avoid privillege escalation check. - authorizationConfig.RBACRoleRegistry = role.NewRegistry(roleetcd.NewREST(mustGetRESTOptions("roles"))) - authorizationConfig.RBACRoleBindingRegistry = rolebinding.NewRegistry(rolebindingetcd.NewREST(mustGetRESTOptions("rolebindings"))) - authorizationConfig.RBACClusterRoleRegistry = clusterrole.NewRegistry(clusterroleetcd.NewREST(mustGetRESTOptions("clusterroles"))) - authorizationConfig.RBACClusterRoleBindingRegistry = clusterrolebinding.NewRegistry(clusterrolebindingetcd.NewREST(mustGetRESTOptions("clusterrolebindings"))) - } - - apiAuthorizer, err := authorizer.NewAuthorizerFromAuthorizationConfig(authorizationModeNames, authorizationConfig) - if err != nil { - glog.Fatalf("Invalid Authorization Config: %v", err) - } - - 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) @@ -193,6 +142,23 @@ func Run(s *options.ServerRunOptions) error { if err != nil { glog.Errorf("Failed to create clientset: %v", err) } + sharedInformers := informers.NewSharedInformerFactory(client, 10*time.Minute) + + authorizationConfig := authorizer.AuthorizationConfig{ + PolicyFile: s.AuthorizationPolicyFile, + WebhookConfigFile: s.AuthorizationWebhookConfigFile, + WebhookCacheAuthorizedTTL: s.AuthorizationWebhookCacheAuthorizedTTL, + WebhookCacheUnauthorizedTTL: s.AuthorizationWebhookCacheUnauthorizedTTL, + RBACSuperUser: s.AuthorizationRBACSuperUser, + InformerFactory: sharedInformers, + } + authorizationModeNames := strings.Split(s.AuthorizationMode, ",") + apiAuthorizer, err := authorizer.NewAuthorizerFromAuthorizationConfig(authorizationModeNames, authorizationConfig) + if err != nil { + glog.Fatalf("Invalid Authorization Config: %v", err) + } + + admissionControlPluginNames := strings.Split(s.AdmissionControl, ",") // TODO(dims): We probably need to add an option "EnableLoopbackToken" if apiAuthenticator != nil { @@ -211,7 +177,6 @@ func Run(s *options.ServerRunOptions) error { apiAuthorizer = authorizerunion.New(tokenAuthorizer, apiAuthorizer) } - sharedInformers := informers.NewSharedInformerFactory(client, 10*time.Minute) pluginInitializer := admission.NewPluginInitializer(sharedInformers, apiAuthorizer) admissionController, err := admission.NewFromPlugins(client, admissionControlPluginNames, s.AdmissionControlConfigFile, pluginInitializer) diff --git a/pkg/apis/rbac/validation/rulevalidation.go b/pkg/apis/rbac/validation/rulevalidation.go index fbb910a6f44..4ed3a910322 100644 --- a/pkg/apis/rbac/validation/rulevalidation.go +++ b/pkg/apis/rbac/validation/rulevalidation.go @@ -32,7 +32,7 @@ import ( type AuthorizationRuleResolver interface { // GetRoleReferenceRules attempts to resolve the role reference of a RoleBinding or ClusterRoleBinding. The passed namespace should be the namepsace // of the role binding, the empty string if a cluster role binding. - GetRoleReferenceRules(ctx api.Context, roleRef rbac.RoleRef, namespace string) ([]rbac.PolicyRule, error) + GetRoleReferenceRules(roleRef rbac.RoleRef, namespace string) ([]rbac.PolicyRule, error) // RulesFor returns the list of rules that apply to a given user in a given namespace and error. If an error is returned, the slice of // PolicyRules may not be complete, but it contains all retrievable rules. This is done because policy rules are purely additive and policy determinations @@ -77,35 +77,34 @@ func NewDefaultRuleResolver(roleGetter RoleGetter, roleBindingLister RoleBinding } type RoleGetter interface { - GetRole(ctx api.Context, id string) (*rbac.Role, error) + GetRole(namespace, name string) (*rbac.Role, error) } type RoleBindingLister interface { - ListRoleBindings(ctx api.Context, options *api.ListOptions) (*rbac.RoleBindingList, error) + ListRoleBindings(namespace string) ([]*rbac.RoleBinding, error) } type ClusterRoleGetter interface { - GetClusterRole(ctx api.Context, id string) (*rbac.ClusterRole, error) + GetClusterRole(name string) (*rbac.ClusterRole, error) } type ClusterRoleBindingLister interface { - ListClusterRoleBindings(ctx api.Context, options *api.ListOptions) (*rbac.ClusterRoleBindingList, error) + ListClusterRoleBindings() ([]*rbac.ClusterRoleBinding, error) } func (r *DefaultRuleResolver) RulesFor(user user.Info, namespace string) ([]rbac.PolicyRule, error) { policyRules := []rbac.PolicyRule{} errorlist := []error{} - ctx := api.NewContext() - if clusterRoleBindings, err := r.clusterRoleBindingLister.ListClusterRoleBindings(ctx, &api.ListOptions{}); err != nil { + if clusterRoleBindings, err := r.clusterRoleBindingLister.ListClusterRoleBindings(); err != nil { errorlist = append(errorlist, err) } else { - for _, clusterRoleBinding := range clusterRoleBindings.Items { + for _, clusterRoleBinding := range clusterRoleBindings { if !appliesTo(user, clusterRoleBinding.Subjects, "") { continue } - rules, err := r.GetRoleReferenceRules(ctx, clusterRoleBinding.RoleRef, "") + rules, err := r.GetRoleReferenceRules(clusterRoleBinding.RoleRef, "") if err != nil { errorlist = append(errorlist, err) continue @@ -115,17 +114,15 @@ func (r *DefaultRuleResolver) RulesFor(user user.Info, namespace string) ([]rbac } if len(namespace) > 0 { - ctx := api.WithNamespace(api.NewContext(), namespace) - - if roleBindings, err := r.roleBindingLister.ListRoleBindings(ctx, &api.ListOptions{}); err != nil { + if roleBindings, err := r.roleBindingLister.ListRoleBindings(namespace); err != nil { errorlist = append(errorlist, err) } else { - for _, roleBinding := range roleBindings.Items { + for _, roleBinding := range roleBindings { if !appliesTo(user, roleBinding.Subjects, namespace) { continue } - rules, err := r.GetRoleReferenceRules(ctx, roleBinding.RoleRef, namespace) + rules, err := r.GetRoleReferenceRules(roleBinding.RoleRef, namespace) if err != nil { errorlist = append(errorlist, err) continue @@ -139,17 +136,17 @@ func (r *DefaultRuleResolver) RulesFor(user user.Info, namespace string) ([]rbac } // GetRoleReferenceRules attempts to resolve the RoleBinding or ClusterRoleBinding. -func (r *DefaultRuleResolver) GetRoleReferenceRules(ctx api.Context, roleRef rbac.RoleRef, bindingNamespace string) ([]rbac.PolicyRule, error) { +func (r *DefaultRuleResolver) GetRoleReferenceRules(roleRef rbac.RoleRef, bindingNamespace string) ([]rbac.PolicyRule, error) { switch kind := rbac.RoleRefGroupKind(roleRef); kind { case rbac.Kind("Role"): - role, err := r.roleGetter.GetRole(api.WithNamespace(ctx, bindingNamespace), roleRef.Name) + role, err := r.roleGetter.GetRole(bindingNamespace, roleRef.Name) if err != nil { return nil, err } return role.Rules, nil case rbac.Kind("ClusterRole"): - clusterRole, err := r.clusterRoleGetter.GetClusterRole(api.WithNamespace(ctx, ""), roleRef.Name) + clusterRole, err := r.clusterRoleGetter.GetClusterRole(roleRef.Name) if err != nil { return nil, err } @@ -193,7 +190,7 @@ func appliesToUser(user user.Info, subject rbac.Subject, namespace string) bool } // NewTestRuleResolver returns a rule resolver from lists of role objects. -func NewTestRuleResolver(roles []rbac.Role, roleBindings []rbac.RoleBinding, clusterRoles []rbac.ClusterRole, clusterRoleBindings []rbac.ClusterRoleBinding) AuthorizationRuleResolver { +func NewTestRuleResolver(roles []*rbac.Role, roleBindings []*rbac.RoleBinding, clusterRoles []*rbac.ClusterRole, clusterRoleBindings []*rbac.ClusterRoleBinding) AuthorizationRuleResolver { r := staticRoles{ roles: roles, roleBindings: roleBindings, @@ -208,62 +205,49 @@ func newMockRuleResolver(r *staticRoles) AuthorizationRuleResolver { } type staticRoles struct { - roles []rbac.Role - roleBindings []rbac.RoleBinding - clusterRoles []rbac.ClusterRole - clusterRoleBindings []rbac.ClusterRoleBinding + roles []*rbac.Role + roleBindings []*rbac.RoleBinding + clusterRoles []*rbac.ClusterRole + clusterRoleBindings []*rbac.ClusterRoleBinding } -func (r *staticRoles) GetRole(ctx api.Context, id string) (*rbac.Role, error) { - namespace, ok := api.NamespaceFrom(ctx) - if !ok || namespace == "" { +func (r *staticRoles) GetRole(namespace, name string) (*rbac.Role, error) { + if len(namespace) == 0 { return nil, errors.New("must provide namespace when getting role") } for _, role := range r.roles { - if role.Namespace == namespace && role.Name == id { - return &role, nil + if role.Namespace == namespace && role.Name == name { + return role, nil } } return nil, errors.New("role not found") } -func (r *staticRoles) GetClusterRole(ctx api.Context, id string) (*rbac.ClusterRole, error) { - namespace, ok := api.NamespaceFrom(ctx) - if ok && namespace != "" { - return nil, errors.New("cannot provide namespace when getting cluster role") - } +func (r *staticRoles) GetClusterRole(name string) (*rbac.ClusterRole, error) { for _, clusterRole := range r.clusterRoles { - if clusterRole.Namespace == namespace && clusterRole.Name == id { - return &clusterRole, nil + if clusterRole.Name == name { + return clusterRole, nil } } return nil, errors.New("role not found") } -func (r *staticRoles) ListRoleBindings(ctx api.Context, options *api.ListOptions) (*rbac.RoleBindingList, error) { - namespace, ok := api.NamespaceFrom(ctx) - if !ok || namespace == "" { +func (r *staticRoles) ListRoleBindings(namespace string) ([]*rbac.RoleBinding, error) { + if len(namespace) == 0 { return nil, errors.New("must provide namespace when listing role bindings") } - roleBindingList := new(rbac.RoleBindingList) + roleBindingList := []*rbac.RoleBinding{} for _, roleBinding := range r.roleBindings { if roleBinding.Namespace != namespace { continue } // TODO(ericchiang): need to implement label selectors? - roleBindingList.Items = append(roleBindingList.Items, roleBinding) + roleBindingList = append(roleBindingList, roleBinding) } return roleBindingList, nil } -func (r *staticRoles) ListClusterRoleBindings(ctx api.Context, options *api.ListOptions) (*rbac.ClusterRoleBindingList, error) { - namespace, ok := api.NamespaceFrom(ctx) - if ok && namespace != "" { - return nil, errors.New("cannot list cluster role bindings from within a namespace") - } - clusterRoleBindings := new(rbac.ClusterRoleBindingList) - clusterRoleBindings.Items = make([]rbac.ClusterRoleBinding, len(r.clusterRoleBindings)) - copy(clusterRoleBindings.Items, r.clusterRoleBindings) - return clusterRoleBindings, nil +func (r *staticRoles) ListClusterRoleBindings() ([]*rbac.ClusterRoleBinding, error) { + return r.clusterRoleBindings, nil } diff --git a/pkg/apis/rbac/validation/rulevalidation_test.go b/pkg/apis/rbac/validation/rulevalidation_test.go index a972171edff..96b9725b8d4 100644 --- a/pkg/apis/rbac/validation/rulevalidation_test.go +++ b/pkg/apis/rbac/validation/rulevalidation_test.go @@ -73,13 +73,13 @@ func TestDefaultRuleResolver(t *testing.T) { } staticRoles1 := staticRoles{ - roles: []rbac.Role{ + roles: []*rbac.Role{ { ObjectMeta: api.ObjectMeta{Namespace: "namespace1", Name: "readthings"}, Rules: []rbac.PolicyRule{ruleReadPods, ruleReadServices}, }, }, - clusterRoles: []rbac.ClusterRole{ + clusterRoles: []*rbac.ClusterRole{ { ObjectMeta: api.ObjectMeta{Name: "cluster-admin"}, Rules: []rbac.PolicyRule{ruleAdmin}, @@ -89,7 +89,7 @@ func TestDefaultRuleResolver(t *testing.T) { Rules: []rbac.PolicyRule{ruleWriteNodes}, }, }, - roleBindings: []rbac.RoleBinding{ + roleBindings: []*rbac.RoleBinding{ { ObjectMeta: api.ObjectMeta{Namespace: "namespace1"}, Subjects: []rbac.Subject{ @@ -99,7 +99,7 @@ func TestDefaultRuleResolver(t *testing.T) { RoleRef: rbac.RoleRef{APIGroup: rbac.GroupName, Kind: "Role", Name: "readthings"}, }, }, - clusterRoleBindings: []rbac.ClusterRoleBinding{ + clusterRoleBindings: []*rbac.ClusterRoleBinding{ { Subjects: []rbac.Subject{ {Kind: rbac.UserKind, Name: "admin"}, diff --git a/pkg/client/cache/listers_rbac.go b/pkg/client/cache/listers_rbac.go new file mode 100644 index 00000000000..2b1cf8bb2a8 --- /dev/null +++ b/pkg/client/cache/listers_rbac.go @@ -0,0 +1,234 @@ +/* +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 cache + +import ( + "k8s.io/kubernetes/pkg/api/errors" + "k8s.io/kubernetes/pkg/apis/rbac" + "k8s.io/kubernetes/pkg/labels" +) + +// TODO: generate these classes and methods for all resources of interest using +// a script. Can use "go generate" once 1.4 is supported by all users. + +// Lister makes an Index have the List method. The Stores must contain only the expected type +// Example: +// s := cache.NewStore() +// lw := cache.ListWatch{Client: c, FieldSelector: sel, Resource: "pods"} +// r := cache.NewReflector(lw, &rbac.ClusterRole{}, s).Run() +// l := clusterRoleLister{s} +// l.List() + +func NewClusterRoleLister(indexer Indexer) ClusterRoleLister { + return &clusterRoleLister{indexer: indexer} +} +func NewClusterRoleBindingLister(indexer Indexer) ClusterRoleBindingLister { + return &clusterRoleBindingLister{indexer: indexer} +} +func NewRoleLister(indexer Indexer) RoleLister { + return &roleLister{indexer: indexer} +} +func NewRoleBindingLister(indexer Indexer) RoleBindingLister { + return &roleBindingLister{indexer: indexer} +} + +// these interfaces are used by the rbac authorizer +type authorizerClusterRoleGetter interface { + GetClusterRole(name string) (*rbac.ClusterRole, error) +} + +type authorizerClusterRoleBindingLister interface { + ListClusterRoleBindings() ([]*rbac.ClusterRoleBinding, error) +} + +type authorizerRoleGetter interface { + GetRole(namespace, name string) (*rbac.Role, error) +} + +type authorizerRoleBindingLister interface { + ListRoleBindings(namespace string) ([]*rbac.RoleBinding, error) +} + +type ClusterRoleLister interface { + authorizerClusterRoleGetter + List(selector labels.Selector) (ret []*rbac.ClusterRole, err error) + Get(name string) (*rbac.ClusterRole, error) +} + +type clusterRoleLister struct { + indexer Indexer +} + +func (s *clusterRoleLister) List(selector labels.Selector) (ret []*rbac.ClusterRole, err error) { + err = ListAll(s.indexer, selector, func(m interface{}) { + ret = append(ret, m.(*rbac.ClusterRole)) + }) + return ret, err +} + +func (s clusterRoleLister) Get(name string) (*rbac.ClusterRole, error) { + obj, exists, err := s.indexer.GetByKey(name) + if err != nil { + return nil, err + } + if !exists { + return nil, errors.NewNotFound(rbac.Resource("clusterrole"), name) + } + return obj.(*rbac.ClusterRole), nil +} + +func (s clusterRoleLister) GetClusterRole(name string) (*rbac.ClusterRole, error) { + return s.Get(name) +} + +type ClusterRoleBindingLister interface { + authorizerClusterRoleBindingLister + List(selector labels.Selector) (ret []*rbac.ClusterRoleBinding, err error) + Get(name string) (*rbac.ClusterRoleBinding, error) +} + +type clusterRoleBindingLister struct { + indexer Indexer +} + +func (s *clusterRoleBindingLister) List(selector labels.Selector) (ret []*rbac.ClusterRoleBinding, err error) { + err = ListAll(s.indexer, selector, func(m interface{}) { + ret = append(ret, m.(*rbac.ClusterRoleBinding)) + }) + return ret, err +} + +func (s clusterRoleBindingLister) Get(name string) (*rbac.ClusterRoleBinding, error) { + obj, exists, err := s.indexer.GetByKey(name) + if err != nil { + return nil, err + } + if !exists { + return nil, errors.NewNotFound(rbac.Resource("clusterrolebinding"), name) + } + return obj.(*rbac.ClusterRoleBinding), nil +} + +func (s clusterRoleBindingLister) ListClusterRoleBindings() ([]*rbac.ClusterRoleBinding, error) { + return s.List(labels.Everything()) +} + +type RoleLister interface { + authorizerRoleGetter + List(selector labels.Selector) (ret []*rbac.Role, err error) + Roles(namespace string) RoleNamespaceLister +} + +type RoleNamespaceLister interface { + List(selector labels.Selector) (ret []*rbac.Role, err error) + Get(name string) (*rbac.Role, error) +} + +type roleLister struct { + indexer Indexer +} + +func (s *roleLister) List(selector labels.Selector) (ret []*rbac.Role, err error) { + err = ListAll(s.indexer, selector, func(m interface{}) { + ret = append(ret, m.(*rbac.Role)) + }) + return ret, err +} + +func (s *roleLister) Roles(namespace string) RoleNamespaceLister { + return roleNamespaceLister{indexer: s.indexer, namespace: namespace} +} + +func (s roleLister) GetRole(namespace, name string) (*rbac.Role, error) { + return s.Roles(namespace).Get(name) +} + +type roleNamespaceLister struct { + indexer Indexer + namespace string +} + +func (s roleNamespaceLister) List(selector labels.Selector) (ret []*rbac.Role, err error) { + err = ListAllByNamespace(s.indexer, s.namespace, selector, func(m interface{}) { + ret = append(ret, m.(*rbac.Role)) + }) + return ret, err +} + +func (s roleNamespaceLister) Get(name string) (*rbac.Role, error) { + obj, exists, err := s.indexer.GetByKey(s.namespace + "/" + name) + if err != nil { + return nil, err + } + if !exists { + return nil, errors.NewNotFound(rbac.Resource("role"), name) + } + return obj.(*rbac.Role), nil +} + +type RoleBindingLister interface { + authorizerRoleBindingLister + List(selector labels.Selector) (ret []*rbac.RoleBinding, err error) + RoleBindings(namespace string) RoleBindingNamespaceLister +} + +type RoleBindingNamespaceLister interface { + List(selector labels.Selector) (ret []*rbac.RoleBinding, err error) + Get(name string) (*rbac.RoleBinding, error) +} + +type roleBindingLister struct { + indexer Indexer +} + +func (s *roleBindingLister) List(selector labels.Selector) (ret []*rbac.RoleBinding, err error) { + err = ListAll(s.indexer, selector, func(m interface{}) { + ret = append(ret, m.(*rbac.RoleBinding)) + }) + return ret, err +} + +func (s *roleBindingLister) RoleBindings(namespace string) RoleBindingNamespaceLister { + return roleBindingNamespaceLister{indexer: s.indexer, namespace: namespace} +} + +func (s roleBindingLister) ListRoleBindings(namespace string) ([]*rbac.RoleBinding, error) { + return s.RoleBindings(namespace).List(labels.Everything()) +} + +type roleBindingNamespaceLister struct { + indexer Indexer + namespace string +} + +func (s roleBindingNamespaceLister) List(selector labels.Selector) (ret []*rbac.RoleBinding, err error) { + err = ListAllByNamespace(s.indexer, s.namespace, selector, func(m interface{}) { + ret = append(ret, m.(*rbac.RoleBinding)) + }) + return ret, err +} + +func (s roleBindingNamespaceLister) Get(name string) (*rbac.RoleBinding, error) { + obj, exists, err := s.indexer.GetByKey(s.namespace + "/" + name) + if err != nil { + return nil, err + } + if !exists { + return nil, errors.NewNotFound(rbac.Resource("rolebinding"), name) + } + return obj.(*rbac.RoleBinding), nil +} diff --git a/pkg/controller/informers/factory.go b/pkg/controller/informers/factory.go index 6218df59167..a9f50aa4522 100644 --- a/pkg/controller/informers/factory.go +++ b/pkg/controller/informers/factory.go @@ -40,6 +40,11 @@ type SharedInformerFactory interface { DaemonSets() DaemonSetInformer Deployments() DeploymentInformer ReplicaSets() ReplicaSetInformer + + ClusterRoles() ClusterRoleInformer + ClusterRoleBindings() ClusterRoleBindingInformer + Roles() RoleInformer + RoleBindings() RoleBindingInformer } type sharedInformerFactory struct { @@ -112,3 +117,19 @@ func (f *sharedInformerFactory) Deployments() DeploymentInformer { func (f *sharedInformerFactory) ReplicaSets() ReplicaSetInformer { return &replicaSetInformer{sharedInformerFactory: f} } + +func (f *sharedInformerFactory) ClusterRoles() ClusterRoleInformer { + return &clusterRoleInformer{sharedInformerFactory: f} +} + +func (f *sharedInformerFactory) ClusterRoleBindings() ClusterRoleBindingInformer { + return &clusterRoleBindingInformer{sharedInformerFactory: f} +} + +func (f *sharedInformerFactory) Roles() RoleInformer { + return &roleInformer{sharedInformerFactory: f} +} + +func (f *sharedInformerFactory) RoleBindings() RoleBindingInformer { + return &roleBindingInformer{sharedInformerFactory: f} +} diff --git a/pkg/controller/informers/rbac.go b/pkg/controller/informers/rbac.go new file mode 100644 index 00000000000..aa5681f3db4 --- /dev/null +++ b/pkg/controller/informers/rbac.go @@ -0,0 +1,187 @@ +/* +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 informers + +import ( + "reflect" + + "k8s.io/kubernetes/pkg/api" + "k8s.io/kubernetes/pkg/apis/rbac" + "k8s.io/kubernetes/pkg/client/cache" + "k8s.io/kubernetes/pkg/runtime" + "k8s.io/kubernetes/pkg/watch" +) + +type ClusterRoleInformer interface { + Informer() cache.SharedIndexInformer + Lister() cache.ClusterRoleLister +} + +type clusterRoleInformer struct { + *sharedInformerFactory +} + +func (f *clusterRoleInformer) Informer() cache.SharedIndexInformer { + f.lock.Lock() + defer f.lock.Unlock() + + informerType := reflect.TypeOf(&rbac.ClusterRole{}) + informer, exists := f.informers[informerType] + if exists { + return informer + } + informer = cache.NewSharedIndexInformer( + &cache.ListWatch{ + ListFunc: func(options api.ListOptions) (runtime.Object, error) { + return f.client.Rbac().ClusterRoles().List(options) + }, + WatchFunc: func(options api.ListOptions) (watch.Interface, error) { + return f.client.Rbac().ClusterRoles().Watch(options) + }, + }, + &rbac.ClusterRole{}, + f.defaultResync, + cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}, + ) + f.informers[informerType] = informer + + return informer +} + +func (f *clusterRoleInformer) Lister() cache.ClusterRoleLister { + return cache.NewClusterRoleLister(f.Informer().GetIndexer()) +} + +type ClusterRoleBindingInformer interface { + Informer() cache.SharedIndexInformer + Lister() cache.ClusterRoleBindingLister +} + +type clusterRoleBindingInformer struct { + *sharedInformerFactory +} + +func (f *clusterRoleBindingInformer) Informer() cache.SharedIndexInformer { + f.lock.Lock() + defer f.lock.Unlock() + + informerType := reflect.TypeOf(&rbac.ClusterRoleBinding{}) + informer, exists := f.informers[informerType] + if exists { + return informer + } + informer = cache.NewSharedIndexInformer( + &cache.ListWatch{ + ListFunc: func(options api.ListOptions) (runtime.Object, error) { + return f.client.Rbac().ClusterRoleBindings().List(options) + }, + WatchFunc: func(options api.ListOptions) (watch.Interface, error) { + return f.client.Rbac().ClusterRoleBindings().Watch(options) + }, + }, + &rbac.ClusterRoleBinding{}, + f.defaultResync, + cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}, + ) + f.informers[informerType] = informer + + return informer +} + +func (f *clusterRoleBindingInformer) Lister() cache.ClusterRoleBindingLister { + return cache.NewClusterRoleBindingLister(f.Informer().GetIndexer()) +} + +type RoleInformer interface { + Informer() cache.SharedIndexInformer + Lister() cache.RoleLister +} + +type roleInformer struct { + *sharedInformerFactory +} + +func (f *roleInformer) Informer() cache.SharedIndexInformer { + f.lock.Lock() + defer f.lock.Unlock() + + informerType := reflect.TypeOf(&rbac.Role{}) + informer, exists := f.informers[informerType] + if exists { + return informer + } + informer = cache.NewSharedIndexInformer( + &cache.ListWatch{ + ListFunc: func(options api.ListOptions) (runtime.Object, error) { + return f.client.Rbac().Roles(api.NamespaceAll).List(options) + }, + WatchFunc: func(options api.ListOptions) (watch.Interface, error) { + return f.client.Rbac().Roles(api.NamespaceAll).Watch(options) + }, + }, + &rbac.Role{}, + f.defaultResync, + cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}, + ) + f.informers[informerType] = informer + + return informer +} + +func (f *roleInformer) Lister() cache.RoleLister { + return cache.NewRoleLister(f.Informer().GetIndexer()) +} + +type RoleBindingInformer interface { + Informer() cache.SharedIndexInformer + Lister() cache.RoleBindingLister +} + +type roleBindingInformer struct { + *sharedInformerFactory +} + +func (f *roleBindingInformer) Informer() cache.SharedIndexInformer { + f.lock.Lock() + defer f.lock.Unlock() + + informerType := reflect.TypeOf(&rbac.RoleBinding{}) + informer, exists := f.informers[informerType] + if exists { + return informer + } + informer = cache.NewSharedIndexInformer( + &cache.ListWatch{ + ListFunc: func(options api.ListOptions) (runtime.Object, error) { + return f.client.Rbac().RoleBindings(api.NamespaceAll).List(options) + }, + WatchFunc: func(options api.ListOptions) (watch.Interface, error) { + return f.client.Rbac().RoleBindings(api.NamespaceAll).Watch(options) + }, + }, + &rbac.RoleBinding{}, + f.defaultResync, + cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}, + ) + f.informers[informerType] = informer + + return informer +} + +func (f *roleBindingInformer) Lister() cache.RoleBindingLister { + return cache.NewRoleBindingLister(f.Informer().GetIndexer()) +} diff --git a/pkg/genericapiserver/authorizer/authz.go b/pkg/genericapiserver/authorizer/authz.go index eb76f20fbe6..fb41ba75d52 100644 --- a/pkg/genericapiserver/authorizer/authz.go +++ b/pkg/genericapiserver/authorizer/authz.go @@ -24,11 +24,8 @@ import ( "k8s.io/kubernetes/pkg/auth/authorizer" "k8s.io/kubernetes/pkg/auth/authorizer/abac" "k8s.io/kubernetes/pkg/auth/authorizer/union" + "k8s.io/kubernetes/pkg/controller/informers" "k8s.io/kubernetes/pkg/genericapiserver/options" - "k8s.io/kubernetes/pkg/registry/rbac/clusterrole" - "k8s.io/kubernetes/pkg/registry/rbac/clusterrolebinding" - "k8s.io/kubernetes/pkg/registry/rbac/role" - "k8s.io/kubernetes/pkg/registry/rbac/rolebinding" "k8s.io/kubernetes/plugin/pkg/auth/authorizer/rbac" "k8s.io/kubernetes/plugin/pkg/auth/authorizer/webhook" ) @@ -117,10 +114,7 @@ type AuthorizationConfig struct { // User which can bootstrap role policies RBACSuperUser string - RBACClusterRoleRegistry clusterrole.Registry - RBACClusterRoleBindingRegistry clusterrolebinding.Registry - RBACRoleRegistry role.Registry - RBACRoleBindingRegistry rolebinding.Registry + InformerFactory informers.SharedInformerFactory } // NewAuthorizerFromAuthorizationConfig returns the right sort of union of multiple authorizer.Authorizer objects @@ -167,10 +161,10 @@ func NewAuthorizerFromAuthorizationConfig(authorizationModes []string, config Au authorizers = append(authorizers, webhookAuthorizer) case options.ModeRBAC: rbacAuthorizer := rbac.New( - config.RBACRoleRegistry, - config.RBACRoleBindingRegistry, - config.RBACClusterRoleRegistry, - config.RBACClusterRoleBindingRegistry, + config.InformerFactory.Roles().Lister(), + config.InformerFactory.RoleBindings().Lister(), + config.InformerFactory.ClusterRoles().Lister(), + config.InformerFactory.ClusterRoleBindings().Lister(), config.RBACSuperUser, ) authorizers = append(authorizers, rbacAuthorizer) diff --git a/pkg/registry/rbac/clusterrole/registry.go b/pkg/registry/rbac/clusterrole/registry.go index 4312307c671..25d823b0db3 100644 --- a/pkg/registry/rbac/clusterrole/registry.go +++ b/pkg/registry/rbac/clusterrole/registry.go @@ -79,3 +79,12 @@ func (s *storage) DeleteClusterRole(ctx api.Context, name string) error { _, err := s.Delete(ctx, name, nil) return err } + +// AuthorizerAdapter adapts the registry to the authorizer interface +type AuthorizerAdapter struct { + Registry Registry +} + +func (a AuthorizerAdapter) GetClusterRole(name string) (*rbac.ClusterRole, error) { + return a.Registry.GetClusterRole(api.NewContext(), name) +} diff --git a/pkg/registry/rbac/clusterrolebinding/policybased/storage.go b/pkg/registry/rbac/clusterrolebinding/policybased/storage.go index 39fdc7d8267..80b9374ec38 100644 --- a/pkg/registry/rbac/clusterrolebinding/policybased/storage.go +++ b/pkg/registry/rbac/clusterrolebinding/policybased/storage.go @@ -48,7 +48,7 @@ func (s *Storage) Create(ctx api.Context, obj runtime.Object) (runtime.Object, e } clusterRoleBinding := obj.(*rbac.ClusterRoleBinding) - rules, err := s.ruleResolver.GetRoleReferenceRules(ctx, clusterRoleBinding.RoleRef, clusterRoleBinding.Namespace) + rules, err := s.ruleResolver.GetRoleReferenceRules(clusterRoleBinding.RoleRef, clusterRoleBinding.Namespace) if err != nil { return nil, err } @@ -66,7 +66,7 @@ func (s *Storage) Update(ctx api.Context, name string, obj rest.UpdatedObjectInf nonEscalatingInfo := wrapUpdatedObjectInfo(obj, func(ctx api.Context, obj runtime.Object, oldObj runtime.Object) (runtime.Object, error) { clusterRoleBinding := obj.(*rbac.ClusterRoleBinding) - rules, err := s.ruleResolver.GetRoleReferenceRules(ctx, clusterRoleBinding.RoleRef, clusterRoleBinding.Namespace) + rules, err := s.ruleResolver.GetRoleReferenceRules(clusterRoleBinding.RoleRef, clusterRoleBinding.Namespace) if err != nil { return nil, err } diff --git a/pkg/registry/rbac/clusterrolebinding/registry.go b/pkg/registry/rbac/clusterrolebinding/registry.go index c7738640aea..a79ff5dfc73 100644 --- a/pkg/registry/rbac/clusterrolebinding/registry.go +++ b/pkg/registry/rbac/clusterrolebinding/registry.go @@ -79,3 +79,21 @@ func (s *storage) DeleteClusterRoleBinding(ctx api.Context, name string) error { _, err := s.Delete(ctx, name, nil) return err } + +// AuthorizerAdapter adapts the registry to the authorizer interface +type AuthorizerAdapter struct { + Registry Registry +} + +func (a AuthorizerAdapter) ListClusterRoleBindings() ([]*rbac.ClusterRoleBinding, error) { + list, err := a.Registry.ListClusterRoleBindings(api.NewContext(), &api.ListOptions{}) + if err != nil { + return nil, err + } + + ret := []*rbac.ClusterRoleBinding{} + for i := range list.Items { + ret = append(ret, &list.Items[i]) + } + return ret, nil +} diff --git a/pkg/registry/rbac/rest/storage_rbac.go b/pkg/registry/rbac/rest/storage_rbac.go index 0f34400c645..32427553a82 100644 --- a/pkg/registry/rbac/rest/storage_rbac.go +++ b/pkg/registry/rbac/rest/storage_rbac.go @@ -71,10 +71,10 @@ func (p *RESTStorageProvider) v1alpha1Storage(apiResourceConfigSource genericapi newRuleValidator := func() rbacvalidation.AuthorizationRuleResolver { once.Do(func() { authorizationRuleResolver = rbacvalidation.NewDefaultRuleResolver( - role.NewRegistry(roleetcd.NewREST(restOptionsGetter(rbac.Resource("roles")))), - rolebinding.NewRegistry(rolebindingetcd.NewREST(restOptionsGetter(rbac.Resource("rolebindings")))), - clusterrole.NewRegistry(clusterroleetcd.NewREST(restOptionsGetter(rbac.Resource("clusterroles")))), - clusterrolebinding.NewRegistry(clusterrolebindingetcd.NewREST(restOptionsGetter(rbac.Resource("clusterrolebindings")))), + role.AuthorizerAdapter{Registry: role.NewRegistry(roleetcd.NewREST(restOptionsGetter(rbac.Resource("roles"))))}, + rolebinding.AuthorizerAdapter{Registry: rolebinding.NewRegistry(rolebindingetcd.NewREST(restOptionsGetter(rbac.Resource("rolebindings"))))}, + clusterrole.AuthorizerAdapter{Registry: clusterrole.NewRegistry(clusterroleetcd.NewREST(restOptionsGetter(rbac.Resource("clusterroles"))))}, + clusterrolebinding.AuthorizerAdapter{Registry: clusterrolebinding.NewRegistry(clusterrolebindingetcd.NewREST(restOptionsGetter(rbac.Resource("clusterrolebindings"))))}, ) }) return authorizationRuleResolver diff --git a/pkg/registry/rbac/role/registry.go b/pkg/registry/rbac/role/registry.go index 706988dfe1d..f2816a3f5d6 100644 --- a/pkg/registry/rbac/role/registry.go +++ b/pkg/registry/rbac/role/registry.go @@ -79,3 +79,12 @@ func (s *storage) DeleteRole(ctx api.Context, name string) error { _, err := s.Delete(ctx, name, nil) return err } + +// AuthorizerAdapter adapts the registry to the authorizer interface +type AuthorizerAdapter struct { + Registry Registry +} + +func (a AuthorizerAdapter) GetRole(namespace, name string) (*rbac.Role, error) { + return a.Registry.GetRole(api.WithNamespace(api.NewContext(), namespace), name) +} diff --git a/pkg/registry/rbac/rolebinding/policybased/storage.go b/pkg/registry/rbac/rolebinding/policybased/storage.go index 8fb2c435020..9622b6451f4 100644 --- a/pkg/registry/rbac/rolebinding/policybased/storage.go +++ b/pkg/registry/rbac/rolebinding/policybased/storage.go @@ -48,7 +48,7 @@ func (s *Storage) Create(ctx api.Context, obj runtime.Object) (runtime.Object, e } roleBinding := obj.(*rbac.RoleBinding) - rules, err := s.ruleResolver.GetRoleReferenceRules(ctx, roleBinding.RoleRef, roleBinding.Namespace) + rules, err := s.ruleResolver.GetRoleReferenceRules(roleBinding.RoleRef, roleBinding.Namespace) if err != nil { return nil, err } @@ -66,7 +66,7 @@ func (s *Storage) Update(ctx api.Context, name string, obj rest.UpdatedObjectInf nonEscalatingInfo := wrapUpdatedObjectInfo(obj, func(ctx api.Context, obj runtime.Object, oldObj runtime.Object) (runtime.Object, error) { roleBinding := obj.(*rbac.RoleBinding) - rules, err := s.ruleResolver.GetRoleReferenceRules(ctx, roleBinding.RoleRef, roleBinding.Namespace) + rules, err := s.ruleResolver.GetRoleReferenceRules(roleBinding.RoleRef, roleBinding.Namespace) if err != nil { return nil, err } diff --git a/pkg/registry/rbac/rolebinding/registry.go b/pkg/registry/rbac/rolebinding/registry.go index fa7a2694181..8a56981625b 100644 --- a/pkg/registry/rbac/rolebinding/registry.go +++ b/pkg/registry/rbac/rolebinding/registry.go @@ -80,3 +80,21 @@ func (s *storage) DeleteRoleBinding(ctx api.Context, name string) error { _, err := s.Delete(ctx, name, nil) return err } + +// AuthorizerAdapter adapts the registry to the authorizer interface +type AuthorizerAdapter struct { + Registry Registry +} + +func (a AuthorizerAdapter) ListRoleBindings(namespace string) ([]*rbac.RoleBinding, error) { + list, err := a.Registry.ListRoleBindings(api.WithNamespace(api.NewContext(), namespace), &api.ListOptions{}) + if err != nil { + return nil, err + } + + ret := []*rbac.RoleBinding{} + for i := range list.Items { + ret = append(ret, &list.Items[i]) + } + return ret, nil +} diff --git a/plugin/pkg/auth/authorizer/rbac/rbac.go b/plugin/pkg/auth/authorizer/rbac/rbac.go index 739cd61e577..04fdf457525 100644 --- a/plugin/pkg/auth/authorizer/rbac/rbac.go +++ b/plugin/pkg/auth/authorizer/rbac/rbac.go @@ -22,10 +22,6 @@ import ( "k8s.io/kubernetes/pkg/apis/rbac/validation" "k8s.io/kubernetes/pkg/auth/authorizer" "k8s.io/kubernetes/pkg/auth/user" - "k8s.io/kubernetes/pkg/registry/rbac/clusterrole" - "k8s.io/kubernetes/pkg/registry/rbac/clusterrolebinding" - "k8s.io/kubernetes/pkg/registry/rbac/role" - "k8s.io/kubernetes/pkg/registry/rbac/rolebinding" ) type RequestToRuleMapper interface { @@ -55,14 +51,11 @@ func (r *RBACAuthorizer) Authorize(requestAttributes authorizer.Attributes) (boo return false, "", ruleResolutionError } -func New(roleRegistry role.Registry, roleBindingRegistry rolebinding.Registry, clusterRoleRegistry clusterrole.Registry, clusterRoleBindingRegistry clusterrolebinding.Registry, superUser string) *RBACAuthorizer { +func New(roles validation.RoleGetter, roleBindings validation.RoleBindingLister, clusterRoles validation.ClusterRoleGetter, clusterRoleBindings validation.ClusterRoleBindingLister, superUser string) *RBACAuthorizer { authorizer := &RBACAuthorizer{ superUser: superUser, authorizationRuleResolver: validation.NewDefaultRuleResolver( - roleRegistry, - roleBindingRegistry, - clusterRoleRegistry, - clusterRoleBindingRegistry, + roles, roleBindings, clusterRoles, clusterRoleBindings, ), } return authorizer diff --git a/plugin/pkg/auth/authorizer/rbac/rbac_test.go b/plugin/pkg/auth/authorizer/rbac/rbac_test.go index 63f8a4d3f2e..76e179742cd 100644 --- a/plugin/pkg/auth/authorizer/rbac/rbac_test.go +++ b/plugin/pkg/auth/authorizer/rbac/rbac_test.go @@ -37,12 +37,12 @@ func newRule(verbs, apiGroups, resources, nonResourceURLs string) rbac.PolicyRul } } -func newRole(name, namespace string, rules ...rbac.PolicyRule) rbac.Role { - return rbac.Role{ObjectMeta: api.ObjectMeta{Namespace: namespace, Name: name}, Rules: rules} +func newRole(name, namespace string, rules ...rbac.PolicyRule) *rbac.Role { + return &rbac.Role{ObjectMeta: api.ObjectMeta{Namespace: namespace, Name: name}, Rules: rules} } -func newClusterRole(name string, rules ...rbac.PolicyRule) rbac.ClusterRole { - return rbac.ClusterRole{ObjectMeta: api.ObjectMeta{Name: name}, Rules: rules} +func newClusterRole(name string, rules ...rbac.PolicyRule) *rbac.ClusterRole { + return &rbac.ClusterRole{ObjectMeta: api.ObjectMeta{Name: name}, Rules: rules} } const ( @@ -50,8 +50,8 @@ const ( bindToClusterRole uint16 = 0x1 ) -func newClusterRoleBinding(roleName string, subjects ...string) rbac.ClusterRoleBinding { - r := rbac.ClusterRoleBinding{ +func newClusterRoleBinding(roleName string, subjects ...string) *rbac.ClusterRoleBinding { + r := &rbac.ClusterRoleBinding{ ObjectMeta: api.ObjectMeta{}, RoleRef: rbac.RoleRef{ APIGroup: rbac.GroupName, @@ -68,8 +68,8 @@ func newClusterRoleBinding(roleName string, subjects ...string) rbac.ClusterRole return r } -func newRoleBinding(namespace, roleName string, bindType uint16, subjects ...string) rbac.RoleBinding { - r := rbac.RoleBinding{ObjectMeta: api.ObjectMeta{Namespace: namespace}} +func newRoleBinding(namespace, roleName string, bindType uint16, subjects ...string) *rbac.RoleBinding { + r := &rbac.RoleBinding{ObjectMeta: api.ObjectMeta{Namespace: namespace}} switch bindType { case bindToRole: @@ -117,10 +117,10 @@ func (d *defaultAttributes) GetPath() string { return "" } func TestAuthorizer(t *testing.T) { tests := []struct { - roles []rbac.Role - roleBindings []rbac.RoleBinding - clusterRoles []rbac.ClusterRole - clusterRoleBindings []rbac.ClusterRoleBinding + roles []*rbac.Role + roleBindings []*rbac.RoleBinding + clusterRoles []*rbac.ClusterRole + clusterRoleBindings []*rbac.ClusterRoleBinding superUser string @@ -128,10 +128,10 @@ func TestAuthorizer(t *testing.T) { shouldFail []authorizer.Attributes }{ { - clusterRoles: []rbac.ClusterRole{ + clusterRoles: []*rbac.ClusterRole{ newClusterRole("admin", newRule("*", "*", "*", "*")), }, - roleBindings: []rbac.RoleBinding{ + roleBindings: []*rbac.RoleBinding{ newRoleBinding("ns1", "admin", bindToClusterRole, "User:admin", "Group:admins"), }, shouldPass: []authorizer.Attributes{ @@ -150,12 +150,12 @@ func TestAuthorizer(t *testing.T) { }, { // Non-resource-url tests - clusterRoles: []rbac.ClusterRole{ + clusterRoles: []*rbac.ClusterRole{ newClusterRole("non-resource-url-getter", newRule("get", "", "", "/apis")), newClusterRole("non-resource-url", newRule("*", "", "", "/apis")), newClusterRole("non-resource-url-prefix", newRule("get", "", "", "/apis/*")), }, - clusterRoleBindings: []rbac.ClusterRoleBinding{ + clusterRoleBindings: []*rbac.ClusterRoleBinding{ newClusterRoleBinding("non-resource-url-getter", "User:foo", "Group:bar"), newClusterRoleBinding("non-resource-url", "User:admin", "Group:admin"), newClusterRoleBinding("non-resource-url-prefix", "User:prefixed", "Group:prefixed"), @@ -191,10 +191,10 @@ func TestAuthorizer(t *testing.T) { }, { // test subresource resolution - clusterRoles: []rbac.ClusterRole{ + clusterRoles: []*rbac.ClusterRole{ newClusterRole("admin", newRule("*", "*", "pods", "*")), }, - roleBindings: []rbac.RoleBinding{ + roleBindings: []*rbac.RoleBinding{ newRoleBinding("ns1", "admin", bindToClusterRole, "User:admin", "Group:admins"), }, shouldPass: []authorizer.Attributes{ @@ -206,10 +206,10 @@ func TestAuthorizer(t *testing.T) { }, { // test subresource resolution - clusterRoles: []rbac.ClusterRole{ + clusterRoles: []*rbac.ClusterRole{ newClusterRole("admin", newRule("*", "*", "pods/status", "*")), }, - roleBindings: []rbac.RoleBinding{ + roleBindings: []*rbac.RoleBinding{ newRoleBinding("ns1", "admin", bindToClusterRole, "User:admin", "Group:admins"), }, shouldPass: []authorizer.Attributes{ diff --git a/test/integration/auth/rbac_test.go b/test/integration/auth/rbac_test.go index 3d74dd57cbc..ed94e58628f 100644 --- a/test/integration/auth/rbac_test.go +++ b/test/integration/auth/rbac_test.go @@ -91,10 +91,10 @@ func newRBACAuthorizer(t *testing.T, superUser string, config *master.Config) au return generic.RESTOptions{StorageConfig: storageConfig, Decorator: generic.UndecoratedStorage, ResourcePrefix: resource} } - roleRegistry := role.NewRegistry(roleetcd.NewREST(newRESTOptions("roles"))) - roleBindingRegistry := rolebinding.NewRegistry(rolebindingetcd.NewREST(newRESTOptions("rolebindings"))) - clusterRoleRegistry := clusterrole.NewRegistry(clusterroleetcd.NewREST(newRESTOptions("clusterroles"))) - clusterRoleBindingRegistry := clusterrolebinding.NewRegistry(clusterrolebindingetcd.NewREST(newRESTOptions("clusterrolebindings"))) + roleRegistry := role.AuthorizerAdapter{Registry: role.NewRegistry(roleetcd.NewREST(newRESTOptions("roles")))} + roleBindingRegistry := rolebinding.AuthorizerAdapter{Registry: rolebinding.NewRegistry(rolebindingetcd.NewREST(newRESTOptions("rolebindings")))} + clusterRoleRegistry := clusterrole.AuthorizerAdapter{Registry: clusterrole.NewRegistry(clusterroleetcd.NewREST(newRESTOptions("clusterroles")))} + clusterRoleBindingRegistry := clusterrolebinding.AuthorizerAdapter{Registry: clusterrolebinding.NewRegistry(clusterrolebindingetcd.NewREST(newRESTOptions("clusterrolebindings")))} return rbac.New(roleRegistry, roleBindingRegistry, clusterRoleRegistry, clusterRoleBindingRegistry, superUser) }