mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-08-05 10:19:50 +00:00
Merge pull request #34047 from deads2k/rbac-11-informer-cache
Automatic merge from submit-queue Run rbac authorizer from cache RBAC authorization can be run very effectively out of a cache. The cache is a normal reflector backed cache (shared informer). I've split this into three parts: 1. slim down the authorizer interfaces 1. boilerplate for adding rbac shared informers and associated listers which conform to the new interfaces 1. wiring @liggitt @ericchiang @kubernetes/sig-auth
This commit is contained in:
commit
c3742a8fbe
@ -39,7 +39,6 @@ import (
|
|||||||
"k8s.io/kubernetes/pkg/apis/autoscaling"
|
"k8s.io/kubernetes/pkg/apis/autoscaling"
|
||||||
"k8s.io/kubernetes/pkg/apis/batch"
|
"k8s.io/kubernetes/pkg/apis/batch"
|
||||||
"k8s.io/kubernetes/pkg/apis/extensions"
|
"k8s.io/kubernetes/pkg/apis/extensions"
|
||||||
"k8s.io/kubernetes/pkg/apis/rbac"
|
|
||||||
"k8s.io/kubernetes/pkg/apiserver"
|
"k8s.io/kubernetes/pkg/apiserver"
|
||||||
"k8s.io/kubernetes/pkg/apiserver/authenticator"
|
"k8s.io/kubernetes/pkg/apiserver/authenticator"
|
||||||
"k8s.io/kubernetes/pkg/apiserver/openapi"
|
"k8s.io/kubernetes/pkg/apiserver/openapi"
|
||||||
@ -52,20 +51,10 @@ import (
|
|||||||
generatedopenapi "k8s.io/kubernetes/pkg/generated/openapi"
|
generatedopenapi "k8s.io/kubernetes/pkg/generated/openapi"
|
||||||
"k8s.io/kubernetes/pkg/genericapiserver"
|
"k8s.io/kubernetes/pkg/genericapiserver"
|
||||||
"k8s.io/kubernetes/pkg/genericapiserver/authorizer"
|
"k8s.io/kubernetes/pkg/genericapiserver/authorizer"
|
||||||
genericoptions "k8s.io/kubernetes/pkg/genericapiserver/options"
|
|
||||||
genericvalidation "k8s.io/kubernetes/pkg/genericapiserver/validation"
|
genericvalidation "k8s.io/kubernetes/pkg/genericapiserver/validation"
|
||||||
kubeletclient "k8s.io/kubernetes/pkg/kubelet/client"
|
kubeletclient "k8s.io/kubernetes/pkg/kubelet/client"
|
||||||
"k8s.io/kubernetes/pkg/master"
|
"k8s.io/kubernetes/pkg/master"
|
||||||
"k8s.io/kubernetes/pkg/registry/cachesize"
|
"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/serviceaccount"
|
||||||
"k8s.io/kubernetes/pkg/util/wait"
|
"k8s.io/kubernetes/pkg/util/wait"
|
||||||
authenticatorunion "k8s.io/kubernetes/plugin/pkg/auth/authenticator/request/union"
|
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)
|
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()
|
privilegedLoopbackToken := uuid.NewRandom().String()
|
||||||
|
|
||||||
selfClientConfig, err := s.NewSelfClientConfig(privilegedLoopbackToken)
|
selfClientConfig, err := s.NewSelfClientConfig(privilegedLoopbackToken)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
glog.Fatalf("Failed to create clientset: %v", err)
|
glog.Fatalf("Failed to create clientset: %v", err)
|
||||||
@ -303,6 +251,23 @@ func Run(s *options.APIServer) error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
glog.Errorf("Failed to create clientset: %v", err)
|
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"
|
// TODO(dims): We probably need to add an option "EnableLoopbackToken"
|
||||||
if apiAuthenticator != nil {
|
if apiAuthenticator != nil {
|
||||||
@ -321,7 +286,6 @@ func Run(s *options.APIServer) error {
|
|||||||
apiAuthorizer = authorizerunion.New(tokenAuthorizer, apiAuthorizer)
|
apiAuthorizer = authorizerunion.New(tokenAuthorizer, apiAuthorizer)
|
||||||
}
|
}
|
||||||
|
|
||||||
sharedInformers := informers.NewSharedInformerFactory(client, 10*time.Minute)
|
|
||||||
pluginInitializer := admission.NewPluginInitializer(sharedInformers, apiAuthorizer)
|
pluginInitializer := admission.NewPluginInitializer(sharedInformers, apiAuthorizer)
|
||||||
|
|
||||||
admissionController, err := admission.NewFromPlugins(client, admissionControlPluginNames, s.AdmissionControlConfigFile, pluginInitializer)
|
admissionController, err := admission.NewFromPlugins(client, admissionControlPluginNames, s.AdmissionControlConfigFile, pluginInitializer)
|
||||||
|
@ -32,7 +32,6 @@ import (
|
|||||||
"k8s.io/kubernetes/pkg/admission"
|
"k8s.io/kubernetes/pkg/admission"
|
||||||
"k8s.io/kubernetes/pkg/api"
|
"k8s.io/kubernetes/pkg/api"
|
||||||
"k8s.io/kubernetes/pkg/api/unversioned"
|
"k8s.io/kubernetes/pkg/api/unversioned"
|
||||||
"k8s.io/kubernetes/pkg/apis/rbac"
|
|
||||||
"k8s.io/kubernetes/pkg/apiserver/authenticator"
|
"k8s.io/kubernetes/pkg/apiserver/authenticator"
|
||||||
apiserveropenapi "k8s.io/kubernetes/pkg/apiserver/openapi"
|
apiserveropenapi "k8s.io/kubernetes/pkg/apiserver/openapi"
|
||||||
authorizerunion "k8s.io/kubernetes/pkg/auth/authorizer/union"
|
authorizerunion "k8s.io/kubernetes/pkg/auth/authorizer/union"
|
||||||
@ -41,19 +40,10 @@ import (
|
|||||||
"k8s.io/kubernetes/pkg/generated/openapi"
|
"k8s.io/kubernetes/pkg/generated/openapi"
|
||||||
"k8s.io/kubernetes/pkg/genericapiserver"
|
"k8s.io/kubernetes/pkg/genericapiserver"
|
||||||
"k8s.io/kubernetes/pkg/genericapiserver/authorizer"
|
"k8s.io/kubernetes/pkg/genericapiserver/authorizer"
|
||||||
genericoptions "k8s.io/kubernetes/pkg/genericapiserver/options"
|
|
||||||
genericvalidation "k8s.io/kubernetes/pkg/genericapiserver/validation"
|
genericvalidation "k8s.io/kubernetes/pkg/genericapiserver/validation"
|
||||||
"k8s.io/kubernetes/pkg/registry/cachesize"
|
"k8s.io/kubernetes/pkg/registry/cachesize"
|
||||||
"k8s.io/kubernetes/pkg/registry/generic"
|
"k8s.io/kubernetes/pkg/registry/generic"
|
||||||
"k8s.io/kubernetes/pkg/registry/generic/registry"
|
"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/routes"
|
||||||
"k8s.io/kubernetes/pkg/util/wait"
|
"k8s.io/kubernetes/pkg/util/wait"
|
||||||
authenticatorunion "k8s.io/kubernetes/plugin/pkg/auth/authenticator/request/union"
|
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)
|
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()
|
privilegedLoopbackToken := uuid.NewRandom().String()
|
||||||
|
|
||||||
selfClientConfig, err := s.NewSelfClientConfig(privilegedLoopbackToken)
|
selfClientConfig, err := s.NewSelfClientConfig(privilegedLoopbackToken)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
glog.Fatalf("Failed to create clientset: %v", err)
|
glog.Fatalf("Failed to create clientset: %v", err)
|
||||||
@ -193,6 +142,23 @@ func Run(s *options.ServerRunOptions) error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
glog.Errorf("Failed to create clientset: %v", err)
|
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"
|
// TODO(dims): We probably need to add an option "EnableLoopbackToken"
|
||||||
if apiAuthenticator != nil {
|
if apiAuthenticator != nil {
|
||||||
@ -211,7 +177,6 @@ func Run(s *options.ServerRunOptions) error {
|
|||||||
apiAuthorizer = authorizerunion.New(tokenAuthorizer, apiAuthorizer)
|
apiAuthorizer = authorizerunion.New(tokenAuthorizer, apiAuthorizer)
|
||||||
}
|
}
|
||||||
|
|
||||||
sharedInformers := informers.NewSharedInformerFactory(client, 10*time.Minute)
|
|
||||||
pluginInitializer := admission.NewPluginInitializer(sharedInformers, apiAuthorizer)
|
pluginInitializer := admission.NewPluginInitializer(sharedInformers, apiAuthorizer)
|
||||||
|
|
||||||
admissionController, err := admission.NewFromPlugins(client, admissionControlPluginNames, s.AdmissionControlConfigFile, pluginInitializer)
|
admissionController, err := admission.NewFromPlugins(client, admissionControlPluginNames, s.AdmissionControlConfigFile, pluginInitializer)
|
||||||
|
@ -32,7 +32,7 @@ import (
|
|||||||
type AuthorizationRuleResolver interface {
|
type AuthorizationRuleResolver interface {
|
||||||
// GetRoleReferenceRules attempts to resolve the role reference of a RoleBinding or ClusterRoleBinding. The passed namespace should be the namepsace
|
// 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.
|
// 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
|
// 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
|
// 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 {
|
type RoleGetter interface {
|
||||||
GetRole(ctx api.Context, id string) (*rbac.Role, error)
|
GetRole(namespace, name string) (*rbac.Role, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
type RoleBindingLister interface {
|
type RoleBindingLister interface {
|
||||||
ListRoleBindings(ctx api.Context, options *api.ListOptions) (*rbac.RoleBindingList, error)
|
ListRoleBindings(namespace string) ([]*rbac.RoleBinding, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
type ClusterRoleGetter interface {
|
type ClusterRoleGetter interface {
|
||||||
GetClusterRole(ctx api.Context, id string) (*rbac.ClusterRole, error)
|
GetClusterRole(name string) (*rbac.ClusterRole, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
type ClusterRoleBindingLister interface {
|
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) {
|
func (r *DefaultRuleResolver) RulesFor(user user.Info, namespace string) ([]rbac.PolicyRule, error) {
|
||||||
policyRules := []rbac.PolicyRule{}
|
policyRules := []rbac.PolicyRule{}
|
||||||
errorlist := []error{}
|
errorlist := []error{}
|
||||||
|
|
||||||
ctx := api.NewContext()
|
if clusterRoleBindings, err := r.clusterRoleBindingLister.ListClusterRoleBindings(); err != nil {
|
||||||
if clusterRoleBindings, err := r.clusterRoleBindingLister.ListClusterRoleBindings(ctx, &api.ListOptions{}); err != nil {
|
|
||||||
errorlist = append(errorlist, err)
|
errorlist = append(errorlist, err)
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
for _, clusterRoleBinding := range clusterRoleBindings.Items {
|
for _, clusterRoleBinding := range clusterRoleBindings {
|
||||||
if !appliesTo(user, clusterRoleBinding.Subjects, "") {
|
if !appliesTo(user, clusterRoleBinding.Subjects, "") {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
rules, err := r.GetRoleReferenceRules(ctx, clusterRoleBinding.RoleRef, "")
|
rules, err := r.GetRoleReferenceRules(clusterRoleBinding.RoleRef, "")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
errorlist = append(errorlist, err)
|
errorlist = append(errorlist, err)
|
||||||
continue
|
continue
|
||||||
@ -115,17 +114,15 @@ func (r *DefaultRuleResolver) RulesFor(user user.Info, namespace string) ([]rbac
|
|||||||
}
|
}
|
||||||
|
|
||||||
if len(namespace) > 0 {
|
if len(namespace) > 0 {
|
||||||
ctx := api.WithNamespace(api.NewContext(), namespace)
|
if roleBindings, err := r.roleBindingLister.ListRoleBindings(namespace); err != nil {
|
||||||
|
|
||||||
if roleBindings, err := r.roleBindingLister.ListRoleBindings(ctx, &api.ListOptions{}); err != nil {
|
|
||||||
errorlist = append(errorlist, err)
|
errorlist = append(errorlist, err)
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
for _, roleBinding := range roleBindings.Items {
|
for _, roleBinding := range roleBindings {
|
||||||
if !appliesTo(user, roleBinding.Subjects, namespace) {
|
if !appliesTo(user, roleBinding.Subjects, namespace) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
rules, err := r.GetRoleReferenceRules(ctx, roleBinding.RoleRef, namespace)
|
rules, err := r.GetRoleReferenceRules(roleBinding.RoleRef, namespace)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
errorlist = append(errorlist, err)
|
errorlist = append(errorlist, err)
|
||||||
continue
|
continue
|
||||||
@ -139,17 +136,17 @@ func (r *DefaultRuleResolver) RulesFor(user user.Info, namespace string) ([]rbac
|
|||||||
}
|
}
|
||||||
|
|
||||||
// GetRoleReferenceRules attempts to resolve the RoleBinding or ClusterRoleBinding.
|
// 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 {
|
switch kind := rbac.RoleRefGroupKind(roleRef); kind {
|
||||||
case rbac.Kind("Role"):
|
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 {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return role.Rules, nil
|
return role.Rules, nil
|
||||||
|
|
||||||
case rbac.Kind("ClusterRole"):
|
case rbac.Kind("ClusterRole"):
|
||||||
clusterRole, err := r.clusterRoleGetter.GetClusterRole(api.WithNamespace(ctx, ""), roleRef.Name)
|
clusterRole, err := r.clusterRoleGetter.GetClusterRole(roleRef.Name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
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.
|
// 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{
|
r := staticRoles{
|
||||||
roles: roles,
|
roles: roles,
|
||||||
roleBindings: roleBindings,
|
roleBindings: roleBindings,
|
||||||
@ -208,62 +205,49 @@ func newMockRuleResolver(r *staticRoles) AuthorizationRuleResolver {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type staticRoles struct {
|
type staticRoles struct {
|
||||||
roles []rbac.Role
|
roles []*rbac.Role
|
||||||
roleBindings []rbac.RoleBinding
|
roleBindings []*rbac.RoleBinding
|
||||||
clusterRoles []rbac.ClusterRole
|
clusterRoles []*rbac.ClusterRole
|
||||||
clusterRoleBindings []rbac.ClusterRoleBinding
|
clusterRoleBindings []*rbac.ClusterRoleBinding
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *staticRoles) GetRole(ctx api.Context, id string) (*rbac.Role, error) {
|
func (r *staticRoles) GetRole(namespace, name string) (*rbac.Role, error) {
|
||||||
namespace, ok := api.NamespaceFrom(ctx)
|
if len(namespace) == 0 {
|
||||||
if !ok || namespace == "" {
|
|
||||||
return nil, errors.New("must provide namespace when getting role")
|
return nil, errors.New("must provide namespace when getting role")
|
||||||
}
|
}
|
||||||
for _, role := range r.roles {
|
for _, role := range r.roles {
|
||||||
if role.Namespace == namespace && role.Name == id {
|
if role.Namespace == namespace && role.Name == name {
|
||||||
return &role, nil
|
return role, nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return nil, errors.New("role not found")
|
return nil, errors.New("role not found")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *staticRoles) GetClusterRole(ctx api.Context, id string) (*rbac.ClusterRole, error) {
|
func (r *staticRoles) GetClusterRole(name string) (*rbac.ClusterRole, error) {
|
||||||
namespace, ok := api.NamespaceFrom(ctx)
|
|
||||||
if ok && namespace != "" {
|
|
||||||
return nil, errors.New("cannot provide namespace when getting cluster role")
|
|
||||||
}
|
|
||||||
for _, clusterRole := range r.clusterRoles {
|
for _, clusterRole := range r.clusterRoles {
|
||||||
if clusterRole.Namespace == namespace && clusterRole.Name == id {
|
if clusterRole.Name == name {
|
||||||
return &clusterRole, nil
|
return clusterRole, nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return nil, errors.New("role not found")
|
return nil, errors.New("role not found")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *staticRoles) ListRoleBindings(ctx api.Context, options *api.ListOptions) (*rbac.RoleBindingList, error) {
|
func (r *staticRoles) ListRoleBindings(namespace string) ([]*rbac.RoleBinding, error) {
|
||||||
namespace, ok := api.NamespaceFrom(ctx)
|
if len(namespace) == 0 {
|
||||||
if !ok || namespace == "" {
|
|
||||||
return nil, errors.New("must provide namespace when listing role bindings")
|
return nil, errors.New("must provide namespace when listing role bindings")
|
||||||
}
|
}
|
||||||
|
|
||||||
roleBindingList := new(rbac.RoleBindingList)
|
roleBindingList := []*rbac.RoleBinding{}
|
||||||
for _, roleBinding := range r.roleBindings {
|
for _, roleBinding := range r.roleBindings {
|
||||||
if roleBinding.Namespace != namespace {
|
if roleBinding.Namespace != namespace {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
// TODO(ericchiang): need to implement label selectors?
|
// TODO(ericchiang): need to implement label selectors?
|
||||||
roleBindingList.Items = append(roleBindingList.Items, roleBinding)
|
roleBindingList = append(roleBindingList, roleBinding)
|
||||||
}
|
}
|
||||||
return roleBindingList, nil
|
return roleBindingList, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *staticRoles) ListClusterRoleBindings(ctx api.Context, options *api.ListOptions) (*rbac.ClusterRoleBindingList, error) {
|
func (r *staticRoles) ListClusterRoleBindings() ([]*rbac.ClusterRoleBinding, error) {
|
||||||
namespace, ok := api.NamespaceFrom(ctx)
|
return r.clusterRoleBindings, nil
|
||||||
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
|
|
||||||
}
|
}
|
||||||
|
@ -73,13 +73,13 @@ func TestDefaultRuleResolver(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
staticRoles1 := staticRoles{
|
staticRoles1 := staticRoles{
|
||||||
roles: []rbac.Role{
|
roles: []*rbac.Role{
|
||||||
{
|
{
|
||||||
ObjectMeta: api.ObjectMeta{Namespace: "namespace1", Name: "readthings"},
|
ObjectMeta: api.ObjectMeta{Namespace: "namespace1", Name: "readthings"},
|
||||||
Rules: []rbac.PolicyRule{ruleReadPods, ruleReadServices},
|
Rules: []rbac.PolicyRule{ruleReadPods, ruleReadServices},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
clusterRoles: []rbac.ClusterRole{
|
clusterRoles: []*rbac.ClusterRole{
|
||||||
{
|
{
|
||||||
ObjectMeta: api.ObjectMeta{Name: "cluster-admin"},
|
ObjectMeta: api.ObjectMeta{Name: "cluster-admin"},
|
||||||
Rules: []rbac.PolicyRule{ruleAdmin},
|
Rules: []rbac.PolicyRule{ruleAdmin},
|
||||||
@ -89,7 +89,7 @@ func TestDefaultRuleResolver(t *testing.T) {
|
|||||||
Rules: []rbac.PolicyRule{ruleWriteNodes},
|
Rules: []rbac.PolicyRule{ruleWriteNodes},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
roleBindings: []rbac.RoleBinding{
|
roleBindings: []*rbac.RoleBinding{
|
||||||
{
|
{
|
||||||
ObjectMeta: api.ObjectMeta{Namespace: "namespace1"},
|
ObjectMeta: api.ObjectMeta{Namespace: "namespace1"},
|
||||||
Subjects: []rbac.Subject{
|
Subjects: []rbac.Subject{
|
||||||
@ -99,7 +99,7 @@ func TestDefaultRuleResolver(t *testing.T) {
|
|||||||
RoleRef: rbac.RoleRef{APIGroup: rbac.GroupName, Kind: "Role", Name: "readthings"},
|
RoleRef: rbac.RoleRef{APIGroup: rbac.GroupName, Kind: "Role", Name: "readthings"},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
clusterRoleBindings: []rbac.ClusterRoleBinding{
|
clusterRoleBindings: []*rbac.ClusterRoleBinding{
|
||||||
{
|
{
|
||||||
Subjects: []rbac.Subject{
|
Subjects: []rbac.Subject{
|
||||||
{Kind: rbac.UserKind, Name: "admin"},
|
{Kind: rbac.UserKind, Name: "admin"},
|
||||||
|
234
pkg/client/cache/listers_rbac.go
vendored
Normal file
234
pkg/client/cache/listers_rbac.go
vendored
Normal file
@ -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
|
||||||
|
}
|
@ -40,6 +40,11 @@ type SharedInformerFactory interface {
|
|||||||
DaemonSets() DaemonSetInformer
|
DaemonSets() DaemonSetInformer
|
||||||
Deployments() DeploymentInformer
|
Deployments() DeploymentInformer
|
||||||
ReplicaSets() ReplicaSetInformer
|
ReplicaSets() ReplicaSetInformer
|
||||||
|
|
||||||
|
ClusterRoles() ClusterRoleInformer
|
||||||
|
ClusterRoleBindings() ClusterRoleBindingInformer
|
||||||
|
Roles() RoleInformer
|
||||||
|
RoleBindings() RoleBindingInformer
|
||||||
}
|
}
|
||||||
|
|
||||||
type sharedInformerFactory struct {
|
type sharedInformerFactory struct {
|
||||||
@ -112,3 +117,19 @@ func (f *sharedInformerFactory) Deployments() DeploymentInformer {
|
|||||||
func (f *sharedInformerFactory) ReplicaSets() ReplicaSetInformer {
|
func (f *sharedInformerFactory) ReplicaSets() ReplicaSetInformer {
|
||||||
return &replicaSetInformer{sharedInformerFactory: f}
|
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}
|
||||||
|
}
|
||||||
|
187
pkg/controller/informers/rbac.go
Normal file
187
pkg/controller/informers/rbac.go
Normal file
@ -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())
|
||||||
|
}
|
@ -24,11 +24,8 @@ import (
|
|||||||
"k8s.io/kubernetes/pkg/auth/authorizer"
|
"k8s.io/kubernetes/pkg/auth/authorizer"
|
||||||
"k8s.io/kubernetes/pkg/auth/authorizer/abac"
|
"k8s.io/kubernetes/pkg/auth/authorizer/abac"
|
||||||
"k8s.io/kubernetes/pkg/auth/authorizer/union"
|
"k8s.io/kubernetes/pkg/auth/authorizer/union"
|
||||||
|
"k8s.io/kubernetes/pkg/controller/informers"
|
||||||
"k8s.io/kubernetes/pkg/genericapiserver/options"
|
"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/rbac"
|
||||||
"k8s.io/kubernetes/plugin/pkg/auth/authorizer/webhook"
|
"k8s.io/kubernetes/plugin/pkg/auth/authorizer/webhook"
|
||||||
)
|
)
|
||||||
@ -117,10 +114,7 @@ type AuthorizationConfig struct {
|
|||||||
// User which can bootstrap role policies
|
// User which can bootstrap role policies
|
||||||
RBACSuperUser string
|
RBACSuperUser string
|
||||||
|
|
||||||
RBACClusterRoleRegistry clusterrole.Registry
|
InformerFactory informers.SharedInformerFactory
|
||||||
RBACClusterRoleBindingRegistry clusterrolebinding.Registry
|
|
||||||
RBACRoleRegistry role.Registry
|
|
||||||
RBACRoleBindingRegistry rolebinding.Registry
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewAuthorizerFromAuthorizationConfig returns the right sort of union of multiple authorizer.Authorizer objects
|
// 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)
|
authorizers = append(authorizers, webhookAuthorizer)
|
||||||
case options.ModeRBAC:
|
case options.ModeRBAC:
|
||||||
rbacAuthorizer := rbac.New(
|
rbacAuthorizer := rbac.New(
|
||||||
config.RBACRoleRegistry,
|
config.InformerFactory.Roles().Lister(),
|
||||||
config.RBACRoleBindingRegistry,
|
config.InformerFactory.RoleBindings().Lister(),
|
||||||
config.RBACClusterRoleRegistry,
|
config.InformerFactory.ClusterRoles().Lister(),
|
||||||
config.RBACClusterRoleBindingRegistry,
|
config.InformerFactory.ClusterRoleBindings().Lister(),
|
||||||
config.RBACSuperUser,
|
config.RBACSuperUser,
|
||||||
)
|
)
|
||||||
authorizers = append(authorizers, rbacAuthorizer)
|
authorizers = append(authorizers, rbacAuthorizer)
|
||||||
|
@ -79,3 +79,12 @@ func (s *storage) DeleteClusterRole(ctx api.Context, name string) error {
|
|||||||
_, err := s.Delete(ctx, name, nil)
|
_, err := s.Delete(ctx, name, nil)
|
||||||
return err
|
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)
|
||||||
|
}
|
||||||
|
@ -48,7 +48,7 @@ func (s *Storage) Create(ctx api.Context, obj runtime.Object) (runtime.Object, e
|
|||||||
}
|
}
|
||||||
|
|
||||||
clusterRoleBinding := obj.(*rbac.ClusterRoleBinding)
|
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 {
|
if err != nil {
|
||||||
return nil, err
|
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) {
|
nonEscalatingInfo := wrapUpdatedObjectInfo(obj, func(ctx api.Context, obj runtime.Object, oldObj runtime.Object) (runtime.Object, error) {
|
||||||
clusterRoleBinding := obj.(*rbac.ClusterRoleBinding)
|
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 {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -79,3 +79,21 @@ func (s *storage) DeleteClusterRoleBinding(ctx api.Context, name string) error {
|
|||||||
_, err := s.Delete(ctx, name, nil)
|
_, err := s.Delete(ctx, name, nil)
|
||||||
return err
|
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
|
||||||
|
}
|
||||||
|
@ -71,10 +71,10 @@ func (p *RESTStorageProvider) v1alpha1Storage(apiResourceConfigSource genericapi
|
|||||||
newRuleValidator := func() rbacvalidation.AuthorizationRuleResolver {
|
newRuleValidator := func() rbacvalidation.AuthorizationRuleResolver {
|
||||||
once.Do(func() {
|
once.Do(func() {
|
||||||
authorizationRuleResolver = rbacvalidation.NewDefaultRuleResolver(
|
authorizationRuleResolver = rbacvalidation.NewDefaultRuleResolver(
|
||||||
role.NewRegistry(roleetcd.NewREST(restOptionsGetter(rbac.Resource("roles")))),
|
role.AuthorizerAdapter{Registry: role.NewRegistry(roleetcd.NewREST(restOptionsGetter(rbac.Resource("roles"))))},
|
||||||
rolebinding.NewRegistry(rolebindingetcd.NewREST(restOptionsGetter(rbac.Resource("rolebindings")))),
|
rolebinding.AuthorizerAdapter{Registry: rolebinding.NewRegistry(rolebindingetcd.NewREST(restOptionsGetter(rbac.Resource("rolebindings"))))},
|
||||||
clusterrole.NewRegistry(clusterroleetcd.NewREST(restOptionsGetter(rbac.Resource("clusterroles")))),
|
clusterrole.AuthorizerAdapter{Registry: clusterrole.NewRegistry(clusterroleetcd.NewREST(restOptionsGetter(rbac.Resource("clusterroles"))))},
|
||||||
clusterrolebinding.NewRegistry(clusterrolebindingetcd.NewREST(restOptionsGetter(rbac.Resource("clusterrolebindings")))),
|
clusterrolebinding.AuthorizerAdapter{Registry: clusterrolebinding.NewRegistry(clusterrolebindingetcd.NewREST(restOptionsGetter(rbac.Resource("clusterrolebindings"))))},
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
return authorizationRuleResolver
|
return authorizationRuleResolver
|
||||||
|
@ -79,3 +79,12 @@ func (s *storage) DeleteRole(ctx api.Context, name string) error {
|
|||||||
_, err := s.Delete(ctx, name, nil)
|
_, err := s.Delete(ctx, name, nil)
|
||||||
return err
|
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)
|
||||||
|
}
|
||||||
|
@ -48,7 +48,7 @@ func (s *Storage) Create(ctx api.Context, obj runtime.Object) (runtime.Object, e
|
|||||||
}
|
}
|
||||||
|
|
||||||
roleBinding := obj.(*rbac.RoleBinding)
|
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 {
|
if err != nil {
|
||||||
return nil, err
|
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) {
|
nonEscalatingInfo := wrapUpdatedObjectInfo(obj, func(ctx api.Context, obj runtime.Object, oldObj runtime.Object) (runtime.Object, error) {
|
||||||
roleBinding := obj.(*rbac.RoleBinding)
|
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 {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -80,3 +80,21 @@ func (s *storage) DeleteRoleBinding(ctx api.Context, name string) error {
|
|||||||
_, err := s.Delete(ctx, name, nil)
|
_, err := s.Delete(ctx, name, nil)
|
||||||
return err
|
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
|
||||||
|
}
|
||||||
|
@ -22,10 +22,6 @@ import (
|
|||||||
"k8s.io/kubernetes/pkg/apis/rbac/validation"
|
"k8s.io/kubernetes/pkg/apis/rbac/validation"
|
||||||
"k8s.io/kubernetes/pkg/auth/authorizer"
|
"k8s.io/kubernetes/pkg/auth/authorizer"
|
||||||
"k8s.io/kubernetes/pkg/auth/user"
|
"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 {
|
type RequestToRuleMapper interface {
|
||||||
@ -55,14 +51,11 @@ func (r *RBACAuthorizer) Authorize(requestAttributes authorizer.Attributes) (boo
|
|||||||
return false, "", ruleResolutionError
|
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{
|
authorizer := &RBACAuthorizer{
|
||||||
superUser: superUser,
|
superUser: superUser,
|
||||||
authorizationRuleResolver: validation.NewDefaultRuleResolver(
|
authorizationRuleResolver: validation.NewDefaultRuleResolver(
|
||||||
roleRegistry,
|
roles, roleBindings, clusterRoles, clusterRoleBindings,
|
||||||
roleBindingRegistry,
|
|
||||||
clusterRoleRegistry,
|
|
||||||
clusterRoleBindingRegistry,
|
|
||||||
),
|
),
|
||||||
}
|
}
|
||||||
return authorizer
|
return authorizer
|
||||||
|
@ -37,12 +37,12 @@ func newRule(verbs, apiGroups, resources, nonResourceURLs string) rbac.PolicyRul
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func newRole(name, namespace string, rules ...rbac.PolicyRule) rbac.Role {
|
func newRole(name, namespace string, rules ...rbac.PolicyRule) *rbac.Role {
|
||||||
return rbac.Role{ObjectMeta: api.ObjectMeta{Namespace: namespace, Name: name}, Rules: rules}
|
return &rbac.Role{ObjectMeta: api.ObjectMeta{Namespace: namespace, Name: name}, Rules: rules}
|
||||||
}
|
}
|
||||||
|
|
||||||
func newClusterRole(name string, rules ...rbac.PolicyRule) rbac.ClusterRole {
|
func newClusterRole(name string, rules ...rbac.PolicyRule) *rbac.ClusterRole {
|
||||||
return rbac.ClusterRole{ObjectMeta: api.ObjectMeta{Name: name}, Rules: rules}
|
return &rbac.ClusterRole{ObjectMeta: api.ObjectMeta{Name: name}, Rules: rules}
|
||||||
}
|
}
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@ -50,8 +50,8 @@ const (
|
|||||||
bindToClusterRole uint16 = 0x1
|
bindToClusterRole uint16 = 0x1
|
||||||
)
|
)
|
||||||
|
|
||||||
func newClusterRoleBinding(roleName string, subjects ...string) rbac.ClusterRoleBinding {
|
func newClusterRoleBinding(roleName string, subjects ...string) *rbac.ClusterRoleBinding {
|
||||||
r := rbac.ClusterRoleBinding{
|
r := &rbac.ClusterRoleBinding{
|
||||||
ObjectMeta: api.ObjectMeta{},
|
ObjectMeta: api.ObjectMeta{},
|
||||||
RoleRef: rbac.RoleRef{
|
RoleRef: rbac.RoleRef{
|
||||||
APIGroup: rbac.GroupName,
|
APIGroup: rbac.GroupName,
|
||||||
@ -68,8 +68,8 @@ func newClusterRoleBinding(roleName string, subjects ...string) rbac.ClusterRole
|
|||||||
return r
|
return r
|
||||||
}
|
}
|
||||||
|
|
||||||
func newRoleBinding(namespace, roleName string, bindType uint16, subjects ...string) rbac.RoleBinding {
|
func newRoleBinding(namespace, roleName string, bindType uint16, subjects ...string) *rbac.RoleBinding {
|
||||||
r := rbac.RoleBinding{ObjectMeta: api.ObjectMeta{Namespace: namespace}}
|
r := &rbac.RoleBinding{ObjectMeta: api.ObjectMeta{Namespace: namespace}}
|
||||||
|
|
||||||
switch bindType {
|
switch bindType {
|
||||||
case bindToRole:
|
case bindToRole:
|
||||||
@ -117,10 +117,10 @@ func (d *defaultAttributes) GetPath() string { return "" }
|
|||||||
|
|
||||||
func TestAuthorizer(t *testing.T) {
|
func TestAuthorizer(t *testing.T) {
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
roles []rbac.Role
|
roles []*rbac.Role
|
||||||
roleBindings []rbac.RoleBinding
|
roleBindings []*rbac.RoleBinding
|
||||||
clusterRoles []rbac.ClusterRole
|
clusterRoles []*rbac.ClusterRole
|
||||||
clusterRoleBindings []rbac.ClusterRoleBinding
|
clusterRoleBindings []*rbac.ClusterRoleBinding
|
||||||
|
|
||||||
superUser string
|
superUser string
|
||||||
|
|
||||||
@ -128,10 +128,10 @@ func TestAuthorizer(t *testing.T) {
|
|||||||
shouldFail []authorizer.Attributes
|
shouldFail []authorizer.Attributes
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
clusterRoles: []rbac.ClusterRole{
|
clusterRoles: []*rbac.ClusterRole{
|
||||||
newClusterRole("admin", newRule("*", "*", "*", "*")),
|
newClusterRole("admin", newRule("*", "*", "*", "*")),
|
||||||
},
|
},
|
||||||
roleBindings: []rbac.RoleBinding{
|
roleBindings: []*rbac.RoleBinding{
|
||||||
newRoleBinding("ns1", "admin", bindToClusterRole, "User:admin", "Group:admins"),
|
newRoleBinding("ns1", "admin", bindToClusterRole, "User:admin", "Group:admins"),
|
||||||
},
|
},
|
||||||
shouldPass: []authorizer.Attributes{
|
shouldPass: []authorizer.Attributes{
|
||||||
@ -150,12 +150,12 @@ func TestAuthorizer(t *testing.T) {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
// Non-resource-url tests
|
// Non-resource-url tests
|
||||||
clusterRoles: []rbac.ClusterRole{
|
clusterRoles: []*rbac.ClusterRole{
|
||||||
newClusterRole("non-resource-url-getter", newRule("get", "", "", "/apis")),
|
newClusterRole("non-resource-url-getter", newRule("get", "", "", "/apis")),
|
||||||
newClusterRole("non-resource-url", newRule("*", "", "", "/apis")),
|
newClusterRole("non-resource-url", newRule("*", "", "", "/apis")),
|
||||||
newClusterRole("non-resource-url-prefix", newRule("get", "", "", "/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-getter", "User:foo", "Group:bar"),
|
||||||
newClusterRoleBinding("non-resource-url", "User:admin", "Group:admin"),
|
newClusterRoleBinding("non-resource-url", "User:admin", "Group:admin"),
|
||||||
newClusterRoleBinding("non-resource-url-prefix", "User:prefixed", "Group:prefixed"),
|
newClusterRoleBinding("non-resource-url-prefix", "User:prefixed", "Group:prefixed"),
|
||||||
@ -191,10 +191,10 @@ func TestAuthorizer(t *testing.T) {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
// test subresource resolution
|
// test subresource resolution
|
||||||
clusterRoles: []rbac.ClusterRole{
|
clusterRoles: []*rbac.ClusterRole{
|
||||||
newClusterRole("admin", newRule("*", "*", "pods", "*")),
|
newClusterRole("admin", newRule("*", "*", "pods", "*")),
|
||||||
},
|
},
|
||||||
roleBindings: []rbac.RoleBinding{
|
roleBindings: []*rbac.RoleBinding{
|
||||||
newRoleBinding("ns1", "admin", bindToClusterRole, "User:admin", "Group:admins"),
|
newRoleBinding("ns1", "admin", bindToClusterRole, "User:admin", "Group:admins"),
|
||||||
},
|
},
|
||||||
shouldPass: []authorizer.Attributes{
|
shouldPass: []authorizer.Attributes{
|
||||||
@ -206,10 +206,10 @@ func TestAuthorizer(t *testing.T) {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
// test subresource resolution
|
// test subresource resolution
|
||||||
clusterRoles: []rbac.ClusterRole{
|
clusterRoles: []*rbac.ClusterRole{
|
||||||
newClusterRole("admin", newRule("*", "*", "pods/status", "*")),
|
newClusterRole("admin", newRule("*", "*", "pods/status", "*")),
|
||||||
},
|
},
|
||||||
roleBindings: []rbac.RoleBinding{
|
roleBindings: []*rbac.RoleBinding{
|
||||||
newRoleBinding("ns1", "admin", bindToClusterRole, "User:admin", "Group:admins"),
|
newRoleBinding("ns1", "admin", bindToClusterRole, "User:admin", "Group:admins"),
|
||||||
},
|
},
|
||||||
shouldPass: []authorizer.Attributes{
|
shouldPass: []authorizer.Attributes{
|
||||||
|
@ -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}
|
return generic.RESTOptions{StorageConfig: storageConfig, Decorator: generic.UndecoratedStorage, ResourcePrefix: resource}
|
||||||
}
|
}
|
||||||
|
|
||||||
roleRegistry := role.NewRegistry(roleetcd.NewREST(newRESTOptions("roles")))
|
roleRegistry := role.AuthorizerAdapter{Registry: role.NewRegistry(roleetcd.NewREST(newRESTOptions("roles")))}
|
||||||
roleBindingRegistry := rolebinding.NewRegistry(rolebindingetcd.NewREST(newRESTOptions("rolebindings")))
|
roleBindingRegistry := rolebinding.AuthorizerAdapter{Registry: rolebinding.NewRegistry(rolebindingetcd.NewREST(newRESTOptions("rolebindings")))}
|
||||||
clusterRoleRegistry := clusterrole.NewRegistry(clusterroleetcd.NewREST(newRESTOptions("clusterroles")))
|
clusterRoleRegistry := clusterrole.AuthorizerAdapter{Registry: clusterrole.NewRegistry(clusterroleetcd.NewREST(newRESTOptions("clusterroles")))}
|
||||||
clusterRoleBindingRegistry := clusterrolebinding.NewRegistry(clusterrolebindingetcd.NewREST(newRESTOptions("clusterrolebindings")))
|
clusterRoleBindingRegistry := clusterrolebinding.AuthorizerAdapter{Registry: clusterrolebinding.NewRegistry(clusterrolebindingetcd.NewREST(newRESTOptions("clusterrolebindings")))}
|
||||||
return rbac.New(roleRegistry, roleBindingRegistry, clusterRoleRegistry, clusterRoleBindingRegistry, superUser)
|
return rbac.New(roleRegistry, roleBindingRegistry, clusterRoleRegistry, clusterRoleBindingRegistry, superUser)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user