From 092714ea0fab9960f6ac452f49f2576d677f1f9e Mon Sep 17 00:00:00 2001 From: David Eads Date: Thu, 19 Apr 2018 07:57:45 -0400 Subject: [PATCH] switch rbac to external --- pkg/apis/rbac/helpers.go | 61 ---- pkg/apis/rbac/v1/BUILD | 2 + pkg/apis/rbac/v1/doc.go | 1 + pkg/apis/rbac/v1/evaluation_helpers.go | 179 ++++++++++ pkg/apis/rbac/v1/helpers.go | 103 +++++- pkg/apis/rbac/v1/zz_generated.deepcopy.go | 21 ++ pkg/kubeapiserver/authorizer/config.go | 8 +- pkg/kubectl/cmd/auth/BUILD | 7 +- pkg/kubectl/cmd/auth/reconcile.go | 37 +- pkg/printers/internalversion/BUILD | 2 + pkg/printers/internalversion/describe.go | 26 +- pkg/registry/rbac/clusterrole/BUILD | 4 +- .../rbac/clusterrole/policybased/storage.go | 8 +- pkg/registry/rbac/clusterrole/registry.go | 50 +-- pkg/registry/rbac/clusterrolebinding/BUILD | 4 +- .../rbac/clusterrolebinding/policybased/BUILD | 2 + .../clusterrolebinding/policybased/storage.go | 16 +- .../rbac/clusterrolebinding/registry.go | 48 +-- pkg/registry/rbac/reconciliation/BUILD | 10 +- .../reconciliation/clusterrole_interfaces.go | 16 +- .../clusterrolebinding_interfaces.go | 14 +- .../rbac/reconciliation/reconcile_role.go | 22 +- .../reconciliation/reconcile_role_test.go | 40 +-- .../reconciliation/reconcile_rolebindings.go | 18 +- .../reconcile_rolebindings_test.go | 32 +- .../rbac/reconciliation/role_interfaces.go | 24 +- .../reconciliation/rolebinding_interfaces.go | 22 +- .../reconciliation/zz_generated.deepcopy.go | 10 +- pkg/registry/rbac/rest/BUILD | 4 +- pkg/registry/rbac/rest/storage_rbac.go | 18 +- pkg/registry/rbac/role/BUILD | 4 +- pkg/registry/rbac/role/policybased/storage.go | 4 +- pkg/registry/rbac/role/registry.go | 51 +-- pkg/registry/rbac/rolebinding/BUILD | 4 +- .../rbac/rolebinding/policybased/BUILD | 2 + .../rbac/rolebinding/policybased/storage.go | 16 +- pkg/registry/rbac/rolebinding/registry.go | 49 +-- pkg/registry/rbac/validation/BUILD | 6 +- .../validation/internal_version_adapter.go | 39 +++ .../rbac/validation/policy_compact.go | 12 +- .../rbac/validation/policy_compact_test.go | 63 ++-- .../rbac/validation/policy_comparator.go | 26 +- .../rbac/validation/policy_comparator_test.go | 148 ++++---- pkg/registry/rbac/validation/rule.go | 78 ++--- pkg/registry/rbac/validation/rule_test.go | 104 +++--- plugin/pkg/auth/authorizer/node/BUILD | 2 +- .../auth/authorizer/node/node_authorizer.go | 6 +- plugin/pkg/auth/authorizer/rbac/BUILD | 8 +- .../authorizer/rbac/bootstrappolicy/BUILD | 5 +- .../rbac/bootstrappolicy/controller_policy.go | 327 +++++++++--------- .../rbac/bootstrappolicy/namespace_policy.go | 75 ++-- .../authorizer/rbac/bootstrappolicy/policy.go | 301 ++++++++-------- .../rbac/bootstrappolicy/policy_test.go | 42 +-- plugin/pkg/auth/authorizer/rbac/rbac.go | 38 +- plugin/pkg/auth/authorizer/rbac/rbac_test.go | 97 +++--- .../auth/authorizer/rbac/subject_locator.go | 14 +- .../authorizer/rbac/subject_locator_test.go | 88 ++--- test/integration/framework/master_utils.go | 3 + 58 files changed, 1319 insertions(+), 1102 deletions(-) create mode 100644 pkg/apis/rbac/v1/evaluation_helpers.go create mode 100644 pkg/apis/rbac/v1/zz_generated.deepcopy.go create mode 100644 pkg/registry/rbac/validation/internal_version_adapter.go diff --git a/pkg/apis/rbac/helpers.go b/pkg/apis/rbac/helpers.go index 373711500b..b7b4b78c81 100644 --- a/pkg/apis/rbac/helpers.go +++ b/pkg/apis/rbac/helpers.go @@ -21,40 +21,9 @@ import ( "strings" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/apimachinery/pkg/util/sets" ) -func RoleRefGroupKind(roleRef RoleRef) schema.GroupKind { - return schema.GroupKind{Group: roleRef.APIGroup, Kind: roleRef.Kind} -} - -func VerbMatches(rule *PolicyRule, requestedVerb string) bool { - for _, ruleVerb := range rule.Verbs { - if ruleVerb == VerbAll { - return true - } - if ruleVerb == requestedVerb { - return true - } - } - - return false -} - -func APIGroupMatches(rule *PolicyRule, requestedGroup string) bool { - for _, ruleGroup := range rule.APIGroups { - if ruleGroup == APIGroupAll { - return true - } - if ruleGroup == requestedGroup { - return true - } - } - - return false -} - func ResourceMatches(rule *PolicyRule, combinedRequestedResource, requestedSubresource string) bool { for _, ruleResource := range rule.Resources { // if everything is allowed, we match @@ -83,36 +52,6 @@ func ResourceMatches(rule *PolicyRule, combinedRequestedResource, requestedSubre return false } -func ResourceNameMatches(rule *PolicyRule, requestedName string) bool { - if len(rule.ResourceNames) == 0 { - return true - } - - for _, ruleName := range rule.ResourceNames { - if ruleName == requestedName { - return true - } - } - - return false -} - -func NonResourceURLMatches(rule *PolicyRule, requestedURL string) bool { - for _, ruleURL := range rule.NonResourceURLs { - if ruleURL == NonResourceAll { - return true - } - if ruleURL == requestedURL { - return true - } - if strings.HasSuffix(ruleURL, "*") && strings.HasPrefix(requestedURL, strings.TrimRight(ruleURL, "*")) { - return true - } - } - - return false -} - // subjectsStrings returns users, groups, serviceaccounts, unknown for display purposes. func SubjectsStrings(subjects []Subject) ([]string, []string, []string, []string) { users := []string{} diff --git a/pkg/apis/rbac/v1/BUILD b/pkg/apis/rbac/v1/BUILD index 5aa5b5fc76..9eb4029fcf 100644 --- a/pkg/apis/rbac/v1/BUILD +++ b/pkg/apis/rbac/v1/BUILD @@ -10,9 +10,11 @@ go_library( srcs = [ "defaults.go", "doc.go", + "evaluation_helpers.go", "helpers.go", "register.go", "zz_generated.conversion.go", + "zz_generated.deepcopy.go", "zz_generated.defaults.go", ], importpath = "k8s.io/kubernetes/pkg/apis/rbac/v1", diff --git a/pkg/apis/rbac/v1/doc.go b/pkg/apis/rbac/v1/doc.go index 1668eabe3b..5608caba70 100644 --- a/pkg/apis/rbac/v1/doc.go +++ b/pkg/apis/rbac/v1/doc.go @@ -18,6 +18,7 @@ limitations under the License. // +k8s:conversion-gen-external-types=k8s.io/api/rbac/v1 // +k8s:defaulter-gen=TypeMeta // +k8s:defaulter-gen-input=../../../../vendor/k8s.io/api/rbac/v1 +// +k8s:deepcopy-gen=package // +groupName=rbac.authorization.k8s.io package v1 // import "k8s.io/kubernetes/pkg/apis/rbac/v1" diff --git a/pkg/apis/rbac/v1/evaluation_helpers.go b/pkg/apis/rbac/v1/evaluation_helpers.go new file mode 100644 index 0000000000..3707760bf5 --- /dev/null +++ b/pkg/apis/rbac/v1/evaluation_helpers.go @@ -0,0 +1,179 @@ +/* +Copyright 2018 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 v1 + +import ( + "fmt" + "strings" + + rbacv1 "k8s.io/api/rbac/v1" + "k8s.io/apimachinery/pkg/runtime/schema" +) + +func RoleRefGroupKind(roleRef rbacv1.RoleRef) schema.GroupKind { + return schema.GroupKind{Group: roleRef.APIGroup, Kind: roleRef.Kind} +} + +func VerbMatches(rule *rbacv1.PolicyRule, requestedVerb string) bool { + for _, ruleVerb := range rule.Verbs { + if ruleVerb == rbacv1.VerbAll { + return true + } + if ruleVerb == requestedVerb { + return true + } + } + + return false +} + +func APIGroupMatches(rule *rbacv1.PolicyRule, requestedGroup string) bool { + for _, ruleGroup := range rule.APIGroups { + if ruleGroup == rbacv1.APIGroupAll { + return true + } + if ruleGroup == requestedGroup { + return true + } + } + + return false +} + +func ResourceMatches(rule *rbacv1.PolicyRule, combinedRequestedResource, requestedSubresource string) bool { + for _, ruleResource := range rule.Resources { + // if everything is allowed, we match + if ruleResource == rbacv1.ResourceAll { + return true + } + // if we have an exact match, we match + if ruleResource == combinedRequestedResource { + return true + } + + // We can also match a */subresource. + // if there isn't a subresource, then continue + if len(requestedSubresource) == 0 { + continue + } + // if the rule isn't in the format */subresource, then we don't match, continue + if len(ruleResource) == len(requestedSubresource)+2 && + strings.HasPrefix(ruleResource, "*/") && + strings.HasSuffix(ruleResource, requestedSubresource) { + return true + + } + } + + return false +} + +func ResourceNameMatches(rule *rbacv1.PolicyRule, requestedName string) bool { + if len(rule.ResourceNames) == 0 { + return true + } + + for _, ruleName := range rule.ResourceNames { + if ruleName == requestedName { + return true + } + } + + return false +} + +func NonResourceURLMatches(rule *rbacv1.PolicyRule, requestedURL string) bool { + for _, ruleURL := range rule.NonResourceURLs { + if ruleURL == rbacv1.NonResourceAll { + return true + } + if ruleURL == requestedURL { + return true + } + if strings.HasSuffix(ruleURL, "*") && strings.HasPrefix(requestedURL, strings.TrimRight(ruleURL, "*")) { + return true + } + } + + return false +} + +// subjectsStrings returns users, groups, serviceaccounts, unknown for display purposes. +func SubjectsStrings(subjects []rbacv1.Subject) ([]string, []string, []string, []string) { + users := []string{} + groups := []string{} + sas := []string{} + others := []string{} + + for _, subject := range subjects { + switch subject.Kind { + case rbacv1.ServiceAccountKind: + sas = append(sas, fmt.Sprintf("%s/%s", subject.Namespace, subject.Name)) + + case rbacv1.UserKind: + users = append(users, subject.Name) + + case rbacv1.GroupKind: + groups = append(groups, subject.Name) + + default: + others = append(others, fmt.Sprintf("%s/%s/%s", subject.Kind, subject.Namespace, subject.Name)) + } + } + + return users, groups, sas, others +} + +func String(r rbacv1.PolicyRule) string { + return "PolicyRule" + CompactString(r) +} + +// CompactString exposes a compact string representation for use in escalation error messages +func CompactString(r rbacv1.PolicyRule) string { + formatStringParts := []string{} + formatArgs := []interface{}{} + if len(r.APIGroups) > 0 { + formatStringParts = append(formatStringParts, "APIGroups:%q") + formatArgs = append(formatArgs, r.APIGroups) + } + if len(r.Resources) > 0 { + formatStringParts = append(formatStringParts, "Resources:%q") + formatArgs = append(formatArgs, r.Resources) + } + if len(r.NonResourceURLs) > 0 { + formatStringParts = append(formatStringParts, "NonResourceURLs:%q") + formatArgs = append(formatArgs, r.NonResourceURLs) + } + if len(r.ResourceNames) > 0 { + formatStringParts = append(formatStringParts, "ResourceNames:%q") + formatArgs = append(formatArgs, r.ResourceNames) + } + if len(r.Verbs) > 0 { + formatStringParts = append(formatStringParts, "Verbs:%q") + formatArgs = append(formatArgs, r.Verbs) + } + formatString := "{" + strings.Join(formatStringParts, ", ") + "}" + return fmt.Sprintf(formatString, formatArgs...) +} + +type SortableRuleSlice []rbacv1.PolicyRule + +func (s SortableRuleSlice) Len() int { return len(s) } +func (s SortableRuleSlice) Swap(i, j int) { s[i], s[j] = s[j], s[i] } +func (s SortableRuleSlice) Less(i, j int) bool { + return strings.Compare(s[i].String(), s[j].String()) < 0 +} diff --git a/pkg/apis/rbac/v1/helpers.go b/pkg/apis/rbac/v1/helpers.go index 6bde41408e..539fe85b46 100644 --- a/pkg/apis/rbac/v1/helpers.go +++ b/pkg/apis/rbac/v1/helpers.go @@ -21,9 +21,13 @@ import ( rbacv1 "k8s.io/api/rbac/v1" + "sort" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) +// +k8s:deepcopy-gen=false + // PolicyRuleBuilder let's us attach methods. A no-no for API types. // We use it to construct rules in code. It's more compact than trying to write them // out in a literal and allows us to perform some basic checking during construction @@ -87,9 +91,16 @@ func (r *PolicyRuleBuilder) Rule() (rbacv1.PolicyRule, error) { return rbacv1.PolicyRule{}, fmt.Errorf("a rule must have either nonResourceURLs or resources: %#v", r.PolicyRule) } + sort.Strings(r.PolicyRule.Resources) + sort.Strings(r.PolicyRule.ResourceNames) + sort.Strings(r.PolicyRule.APIGroups) + sort.Strings(r.PolicyRule.NonResourceURLs) + sort.Strings(r.PolicyRule.Verbs) return r.PolicyRule, nil } +// +k8s:deepcopy-gen=false + // ClusterRoleBindingBuilder let's us attach methods. A no-no for API types. // We use it to construct bindings in code. It's more compact than trying to write them // out in a literal. @@ -112,14 +123,14 @@ func NewClusterBinding(clusterRoleName string) *ClusterRoleBindingBuilder { func (r *ClusterRoleBindingBuilder) Groups(groups ...string) *ClusterRoleBindingBuilder { for _, group := range groups { - r.ClusterRoleBinding.Subjects = append(r.ClusterRoleBinding.Subjects, rbacv1.Subject{Kind: rbacv1.GroupKind, Name: group}) + r.ClusterRoleBinding.Subjects = append(r.ClusterRoleBinding.Subjects, rbacv1.Subject{APIGroup: rbacv1.GroupName, Kind: rbacv1.GroupKind, Name: group}) } return r } func (r *ClusterRoleBindingBuilder) Users(users ...string) *ClusterRoleBindingBuilder { for _, user := range users { - r.ClusterRoleBinding.Subjects = append(r.ClusterRoleBinding.Subjects, rbacv1.Subject{Kind: rbacv1.UserKind, Name: user}) + r.ClusterRoleBinding.Subjects = append(r.ClusterRoleBinding.Subjects, rbacv1.Subject{APIGroup: rbacv1.GroupName, Kind: rbacv1.UserKind, Name: user}) } return r } @@ -146,3 +157,91 @@ func (r *ClusterRoleBindingBuilder) Binding() (rbacv1.ClusterRoleBinding, error) return r.ClusterRoleBinding, nil } + +// +k8s:deepcopy-gen=false + +// RoleBindingBuilder let's us attach methods. It is similar to +// ClusterRoleBindingBuilder above. +type RoleBindingBuilder struct { + RoleBinding rbacv1.RoleBinding +} + +// NewRoleBinding creates a RoleBinding builder that can be used +// to define the subjects of a role binding. At least one of +// the `Groups`, `Users` or `SAs` method must be called before +// calling the `Binding*` methods. +func NewRoleBinding(roleName, namespace string) *RoleBindingBuilder { + return &RoleBindingBuilder{ + RoleBinding: rbacv1.RoleBinding{ + ObjectMeta: metav1.ObjectMeta{ + Name: roleName, + Namespace: namespace, + }, + RoleRef: rbacv1.RoleRef{ + APIGroup: GroupName, + Kind: "Role", + Name: roleName, + }, + }, + } +} + +func NewRoleBindingForClusterRole(roleName, namespace string) *RoleBindingBuilder { + return &RoleBindingBuilder{ + RoleBinding: rbacv1.RoleBinding{ + ObjectMeta: metav1.ObjectMeta{ + Name: roleName, + Namespace: namespace, + }, + RoleRef: rbacv1.RoleRef{ + APIGroup: GroupName, + Kind: "ClusterRole", + Name: roleName, + }, + }, + } +} + +// Groups adds the specified groups as the subjects of the RoleBinding. +func (r *RoleBindingBuilder) Groups(groups ...string) *RoleBindingBuilder { + for _, group := range groups { + r.RoleBinding.Subjects = append(r.RoleBinding.Subjects, rbacv1.Subject{Kind: rbacv1.GroupKind, APIGroup: GroupName, Name: group}) + } + return r +} + +// Users adds the specified users as the subjects of the RoleBinding. +func (r *RoleBindingBuilder) Users(users ...string) *RoleBindingBuilder { + for _, user := range users { + r.RoleBinding.Subjects = append(r.RoleBinding.Subjects, rbacv1.Subject{Kind: rbacv1.UserKind, APIGroup: GroupName, Name: user}) + } + return r +} + +// SAs adds the specified service accounts as the subjects of the +// RoleBinding. +func (r *RoleBindingBuilder) SAs(namespace string, serviceAccountNames ...string) *RoleBindingBuilder { + for _, saName := range serviceAccountNames { + r.RoleBinding.Subjects = append(r.RoleBinding.Subjects, rbacv1.Subject{Kind: rbacv1.ServiceAccountKind, Namespace: namespace, Name: saName}) + } + return r +} + +// BindingOrDie calls the binding method and panics if there is an error. +func (r *RoleBindingBuilder) BindingOrDie() rbacv1.RoleBinding { + ret, err := r.Binding() + if err != nil { + panic(err) + } + return ret +} + +// Binding builds and returns the RoleBinding API object from the builder +// object. +func (r *RoleBindingBuilder) Binding() (rbacv1.RoleBinding, error) { + if len(r.RoleBinding.Subjects) == 0 { + return rbacv1.RoleBinding{}, fmt.Errorf("subjects are required: %#v", r.RoleBinding) + } + + return r.RoleBinding, nil +} diff --git a/pkg/apis/rbac/v1/zz_generated.deepcopy.go b/pkg/apis/rbac/v1/zz_generated.deepcopy.go new file mode 100644 index 0000000000..1e699e9922 --- /dev/null +++ b/pkg/apis/rbac/v1/zz_generated.deepcopy.go @@ -0,0 +1,21 @@ +// +build !ignore_autogenerated + +/* +Copyright 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. +*/ + +// Code generated by conversion-gen. DO NOT EDIT. + +package v1 diff --git a/pkg/kubeapiserver/authorizer/config.go b/pkg/kubeapiserver/authorizer/config.go index 7646f80bc1..a72ba5ee63 100644 --- a/pkg/kubeapiserver/authorizer/config.go +++ b/pkg/kubeapiserver/authorizer/config.go @@ -108,10 +108,10 @@ func (config AuthorizationConfig) New() (authorizer.Authorizer, authorizer.RuleR ruleResolvers = append(ruleResolvers, webhookAuthorizer) case modes.ModeRBAC: rbacAuthorizer := rbac.New( - &rbac.RoleGetter{Lister: config.InformerFactory.Rbac().InternalVersion().Roles().Lister()}, - &rbac.RoleBindingLister{Lister: config.InformerFactory.Rbac().InternalVersion().RoleBindings().Lister()}, - &rbac.ClusterRoleGetter{Lister: config.InformerFactory.Rbac().InternalVersion().ClusterRoles().Lister()}, - &rbac.ClusterRoleBindingLister{Lister: config.InformerFactory.Rbac().InternalVersion().ClusterRoleBindings().Lister()}, + &rbac.RoleGetter{Lister: config.VersionedInformerFactory.Rbac().V1().Roles().Lister()}, + &rbac.RoleBindingLister{Lister: config.VersionedInformerFactory.Rbac().V1().RoleBindings().Lister()}, + &rbac.ClusterRoleGetter{Lister: config.VersionedInformerFactory.Rbac().V1().ClusterRoles().Lister()}, + &rbac.ClusterRoleBindingLister{Lister: config.VersionedInformerFactory.Rbac().V1().ClusterRoleBindings().Lister()}, ) authorizers = append(authorizers, rbacAuthorizer) ruleResolvers = append(ruleResolvers, rbacAuthorizer) diff --git a/pkg/kubectl/cmd/auth/BUILD b/pkg/kubectl/cmd/auth/BUILD index a56b7c5c59..d78bc102fc 100644 --- a/pkg/kubectl/cmd/auth/BUILD +++ b/pkg/kubectl/cmd/auth/BUILD @@ -16,12 +16,8 @@ go_library( "//build/visible_to:pkg_kubectl_cmd_auth_CONSUMERS", ], deps = [ - "//pkg/api/legacyscheme:go_default_library", "//pkg/apis/authorization:go_default_library", - "//pkg/apis/rbac:go_default_library", "//pkg/client/clientset_generated/internalclientset/typed/authorization/internalversion:go_default_library", - "//pkg/client/clientset_generated/internalclientset/typed/core/internalversion:go_default_library", - "//pkg/client/clientset_generated/internalclientset/typed/rbac/internalversion:go_default_library", "//pkg/kubectl/cmd/templates:go_default_library", "//pkg/kubectl/cmd/util:go_default_library", "//pkg/kubectl/genericclioptions:go_default_library", @@ -31,8 +27,11 @@ go_library( "//pkg/registry/rbac/reconciliation:go_default_library", "//vendor/github.com/golang/glog:go_default_library", "//vendor/github.com/spf13/cobra:go_default_library", + "//vendor/k8s.io/api/rbac/v1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/api/meta:go_default_library", "//vendor/k8s.io/apimachinery/pkg/runtime/schema:go_default_library", + "//vendor/k8s.io/client-go/kubernetes/typed/core/v1:go_default_library", + "//vendor/k8s.io/client-go/kubernetes/typed/rbac/v1:go_default_library", ], ) diff --git a/pkg/kubectl/cmd/auth/reconcile.go b/pkg/kubectl/cmd/auth/reconcile.go index fd82e2ccdc..ef62092e6f 100644 --- a/pkg/kubectl/cmd/auth/reconcile.go +++ b/pkg/kubectl/cmd/auth/reconcile.go @@ -22,10 +22,9 @@ import ( "github.com/golang/glog" "github.com/spf13/cobra" - "k8s.io/kubernetes/pkg/api/legacyscheme" - "k8s.io/kubernetes/pkg/apis/rbac" - internalcoreclient "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/core/internalversion" - internalrbacclient "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/rbac/internalversion" + rbacv1 "k8s.io/api/rbac/v1" + corev1client "k8s.io/client-go/kubernetes/typed/core/v1" + rbacv1client "k8s.io/client-go/kubernetes/typed/rbac/v1" "k8s.io/kubernetes/pkg/kubectl/cmd/templates" cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util" "k8s.io/kubernetes/pkg/kubectl/genericclioptions" @@ -42,8 +41,8 @@ type ReconcileOptions struct { FilenameOptions *resource.FilenameOptions Visitor resource.Visitor - RBACClient internalrbacclient.RbacInterface - NamespaceClient internalcoreclient.NamespaceInterface + RBACClient rbacv1client.RbacV1Interface + NamespaceClient corev1client.CoreV1Interface PrintObject printers.ResourcePrinterFunc @@ -104,7 +103,7 @@ func (o *ReconcileOptions) Complete(cmd *cobra.Command, f cmdutil.Factory, args } r := f.NewBuilder(). - WithScheme(legacyscheme.Scheme). + WithScheme(scheme.Scheme, scheme.Scheme.PrioritizedVersionsAllGroups()...). ContinueOnError(). NamespaceParam(namespace).DefaultNamespace(). FilenameParam(enforceNamespace, o.FilenameOptions). @@ -116,12 +115,18 @@ func (o *ReconcileOptions) Complete(cmd *cobra.Command, f cmdutil.Factory, args } o.Visitor = r - client, err := f.ClientSet() + clientConfig, err := f.ToRESTConfig() + if err != nil { + return err + } + o.RBACClient, err = rbacv1client.NewForConfig(clientConfig) + if err != nil { + return err + } + o.NamespaceClient, err = corev1client.NewForConfig(clientConfig) if err != nil { return err } - o.RBACClient = client.Rbac() - o.NamespaceClient = client.Core().Namespaces() printer, err := o.PrintFlags.ToPrinter() if err != nil { @@ -161,13 +166,13 @@ func (o *ReconcileOptions) RunReconcile() error { } switch t := info.Object.(type) { - case *rbac.Role: + case *rbacv1.Role: reconcileOptions := reconciliation.ReconcileRoleOptions{ Confirm: true, RemoveExtraPermissions: false, Role: reconciliation.RoleRuleOwner{Role: t}, Client: reconciliation.RoleModifier{ - NamespaceClient: o.NamespaceClient, + NamespaceClient: o.NamespaceClient.Namespaces(), Client: o.RBACClient, }, } @@ -177,7 +182,7 @@ func (o *ReconcileOptions) RunReconcile() error { } o.PrintObject(result.Role.GetObject(), o.Out) - case *rbac.ClusterRole: + case *rbacv1.ClusterRole: reconcileOptions := reconciliation.ReconcileRoleOptions{ Confirm: true, RemoveExtraPermissions: false, @@ -192,14 +197,14 @@ func (o *ReconcileOptions) RunReconcile() error { } o.PrintObject(result.Role.GetObject(), o.Out) - case *rbac.RoleBinding: + case *rbacv1.RoleBinding: reconcileOptions := reconciliation.ReconcileRoleBindingOptions{ Confirm: true, RemoveExtraSubjects: false, RoleBinding: reconciliation.RoleBindingAdapter{RoleBinding: t}, Client: reconciliation.RoleBindingClientAdapter{ Client: o.RBACClient, - NamespaceClient: o.NamespaceClient, + NamespaceClient: o.NamespaceClient.Namespaces(), }, } result, err := reconcileOptions.Run() @@ -208,7 +213,7 @@ func (o *ReconcileOptions) RunReconcile() error { } o.PrintObject(result.RoleBinding.GetObject(), o.Out) - case *rbac.ClusterRoleBinding: + case *rbacv1.ClusterRoleBinding: reconcileOptions := reconciliation.ReconcileRoleBindingOptions{ Confirm: true, RemoveExtraSubjects: false, diff --git a/pkg/printers/internalversion/BUILD b/pkg/printers/internalversion/BUILD index c28c99c094..aeac7a5675 100644 --- a/pkg/printers/internalversion/BUILD +++ b/pkg/printers/internalversion/BUILD @@ -70,6 +70,7 @@ go_library( "//pkg/apis/networking:go_default_library", "//pkg/apis/policy:go_default_library", "//pkg/apis/rbac:go_default_library", + "//pkg/apis/rbac/v1:go_default_library", "//pkg/apis/scheduling:go_default_library", "//pkg/apis/storage:go_default_library", "//pkg/apis/storage/util:go_default_library", @@ -90,6 +91,7 @@ go_library( "//vendor/k8s.io/api/certificates/v1beta1:go_default_library", "//vendor/k8s.io/api/core/v1:go_default_library", "//vendor/k8s.io/api/extensions/v1beta1:go_default_library", + "//vendor/k8s.io/api/rbac/v1:go_default_library", "//vendor/k8s.io/api/rbac/v1beta1:go_default_library", "//vendor/k8s.io/api/storage/v1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/api/errors:go_default_library", diff --git a/pkg/printers/internalversion/describe.go b/pkg/printers/internalversion/describe.go index edc5edebe5..ca414aef62 100644 --- a/pkg/printers/internalversion/describe.go +++ b/pkg/printers/internalversion/describe.go @@ -35,6 +35,7 @@ import ( "github.com/fatih/camelcase" versionedextension "k8s.io/api/extensions/v1beta1" + rbacv1 "k8s.io/api/rbac/v1" "k8s.io/apimachinery/pkg/api/errors" "k8s.io/apimachinery/pkg/api/meta" "k8s.io/apimachinery/pkg/api/resource" @@ -63,6 +64,7 @@ import ( "k8s.io/kubernetes/pkg/apis/networking" "k8s.io/kubernetes/pkg/apis/policy" "k8s.io/kubernetes/pkg/apis/rbac" + rbacv1helpers "k8s.io/kubernetes/pkg/apis/rbac/v1" "k8s.io/kubernetes/pkg/apis/scheduling" "k8s.io/kubernetes/pkg/apis/storage" storageutil "k8s.io/kubernetes/pkg/apis/storage/util" @@ -166,10 +168,10 @@ func describerMap(clientConfig *rest.Config) (map[schema.GroupKind]printers.Desc certificates.Kind("CertificateSigningRequest"): &CertificateSigningRequestDescriber{c}, storage.Kind("StorageClass"): &StorageClassDescriber{c}, policy.Kind("PodDisruptionBudget"): &PodDisruptionBudgetDescriber{c}, - rbac.Kind("Role"): &RoleDescriber{c}, - rbac.Kind("ClusterRole"): &ClusterRoleDescriber{c}, - rbac.Kind("RoleBinding"): &RoleBindingDescriber{c}, - rbac.Kind("ClusterRoleBinding"): &ClusterRoleBindingDescriber{c}, + rbac.Kind("Role"): &RoleDescriber{externalclient}, + rbac.Kind("ClusterRole"): &ClusterRoleDescriber{externalclient}, + rbac.Kind("RoleBinding"): &RoleBindingDescriber{externalclient}, + rbac.Kind("ClusterRoleBinding"): &ClusterRoleBindingDescriber{externalclient}, networking.Kind("NetworkPolicy"): &NetworkPolicyDescriber{c}, scheduling.Kind("PriorityClass"): &PriorityClassDescriber{c}, } @@ -2443,7 +2445,7 @@ func describeServiceAccount(serviceAccount *api.ServiceAccount, tokens []api.Sec // RoleDescriber generates information about a node. type RoleDescriber struct { - clientset.Interface + externalclient.Interface } func (d *RoleDescriber) Describe(namespace, name string, describerSettings printers.DescriberSettings) (string, error) { @@ -2452,7 +2454,7 @@ func (d *RoleDescriber) Describe(namespace, name string, describerSettings print return "", err } - breakdownRules := []rbac.PolicyRule{} + breakdownRules := []rbacv1.PolicyRule{} for _, rule := range role.Rules { breakdownRules = append(breakdownRules, validation.BreakdownRule(rule)...) } @@ -2461,7 +2463,7 @@ func (d *RoleDescriber) Describe(namespace, name string, describerSettings print if err != nil { return "", err } - sort.Stable(rbac.SortableRuleSlice(compactRules)) + sort.Stable(rbacv1helpers.SortableRuleSlice(compactRules)) return tabbedString(func(out io.Writer) error { w := NewPrefixWriter(out) @@ -2482,7 +2484,7 @@ func (d *RoleDescriber) Describe(namespace, name string, describerSettings print // ClusterRoleDescriber generates information about a node. type ClusterRoleDescriber struct { - clientset.Interface + externalclient.Interface } func (d *ClusterRoleDescriber) Describe(namespace, name string, describerSettings printers.DescriberSettings) (string, error) { @@ -2491,7 +2493,7 @@ func (d *ClusterRoleDescriber) Describe(namespace, name string, describerSetting return "", err } - breakdownRules := []rbac.PolicyRule{} + breakdownRules := []rbacv1.PolicyRule{} for _, rule := range role.Rules { breakdownRules = append(breakdownRules, validation.BreakdownRule(rule)...) } @@ -2500,7 +2502,7 @@ func (d *ClusterRoleDescriber) Describe(namespace, name string, describerSetting if err != nil { return "", err } - sort.Stable(rbac.SortableRuleSlice(compactRules)) + sort.Stable(rbacv1helpers.SortableRuleSlice(compactRules)) return tabbedString(func(out io.Writer) error { w := NewPrefixWriter(out) @@ -2538,7 +2540,7 @@ func combineResourceGroup(resource, group []string) string { // RoleBindingDescriber generates information about a node. type RoleBindingDescriber struct { - clientset.Interface + externalclient.Interface } func (d *RoleBindingDescriber) Describe(namespace, name string, describerSettings printers.DescriberSettings) (string, error) { @@ -2570,7 +2572,7 @@ func (d *RoleBindingDescriber) Describe(namespace, name string, describerSetting // ClusterRoleBindingDescriber generates information about a node. type ClusterRoleBindingDescriber struct { - clientset.Interface + externalclient.Interface } func (d *ClusterRoleBindingDescriber) Describe(namespace, name string, describerSettings printers.DescriberSettings) (string, error) { diff --git a/pkg/registry/rbac/clusterrole/BUILD b/pkg/registry/rbac/clusterrole/BUILD index 57fac87d96..c4fda28a5f 100644 --- a/pkg/registry/rbac/clusterrole/BUILD +++ b/pkg/registry/rbac/clusterrole/BUILD @@ -16,12 +16,12 @@ go_library( deps = [ "//pkg/api/legacyscheme:go_default_library", "//pkg/apis/rbac:go_default_library", + "//pkg/apis/rbac/v1:go_default_library", "//pkg/apis/rbac/validation:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/apis/meta/internalversion:go_default_library", + "//vendor/k8s.io/api/rbac/v1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/validation/field:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/watch:go_default_library", "//vendor/k8s.io/apiserver/pkg/endpoints/request:go_default_library", "//vendor/k8s.io/apiserver/pkg/registry/rest:go_default_library", "//vendor/k8s.io/apiserver/pkg/storage/names:go_default_library", diff --git a/pkg/registry/rbac/clusterrole/policybased/storage.go b/pkg/registry/rbac/clusterrole/policybased/storage.go index 8782a67935..767673d252 100644 --- a/pkg/registry/rbac/clusterrole/policybased/storage.go +++ b/pkg/registry/rbac/clusterrole/policybased/storage.go @@ -58,12 +58,12 @@ func (s *Storage) Create(ctx context.Context, obj runtime.Object, createValidati clusterRole := obj.(*rbac.ClusterRole) rules := clusterRole.Rules - if err := rbacregistryvalidation.ConfirmNoEscalation(ctx, s.ruleResolver, rules); err != nil { + if err := rbacregistryvalidation.ConfirmNoEscalationInternal(ctx, s.ruleResolver, rules); err != nil { return nil, apierrors.NewForbidden(groupResource, clusterRole.Name, err) } // to set the aggregation rule, since it can gather anything, requires * on *.* if hasAggregationRule(clusterRole) { - if err := rbacregistryvalidation.ConfirmNoEscalation(ctx, s.ruleResolver, fullAuthority); err != nil { + if err := rbacregistryvalidation.ConfirmNoEscalationInternal(ctx, s.ruleResolver, fullAuthority); err != nil { return nil, apierrors.NewForbidden(groupResource, clusterRole.Name, errors.New("must have cluster-admin privileges to use the aggregationRule")) } } @@ -86,12 +86,12 @@ func (s *Storage) Update(ctx context.Context, name string, obj rest.UpdatedObjec } rules := clusterRole.Rules - if err := rbacregistryvalidation.ConfirmNoEscalation(ctx, s.ruleResolver, rules); err != nil { + if err := rbacregistryvalidation.ConfirmNoEscalationInternal(ctx, s.ruleResolver, rules); err != nil { return nil, apierrors.NewForbidden(groupResource, clusterRole.Name, err) } // to change the aggregation rule, since it can gather anything and prevent tightening, requires * on *.* if hasAggregationRule(clusterRole) || hasAggregationRule(oldClusterRole) { - if err := rbacregistryvalidation.ConfirmNoEscalation(ctx, s.ruleResolver, fullAuthority); err != nil { + if err := rbacregistryvalidation.ConfirmNoEscalationInternal(ctx, s.ruleResolver, fullAuthority); err != nil { return nil, apierrors.NewForbidden(groupResource, clusterRole.Name, errors.New("must have cluster-admin privileges to use the aggregationRule")) } } diff --git a/pkg/registry/rbac/clusterrole/registry.go b/pkg/registry/rbac/clusterrole/registry.go index a6244ac087..5fdc5024df 100644 --- a/pkg/registry/rbac/clusterrole/registry.go +++ b/pkg/registry/rbac/clusterrole/registry.go @@ -19,27 +19,22 @@ package clusterrole import ( "context" - metainternalversion "k8s.io/apimachinery/pkg/apis/meta/internalversion" + rbacv1 "k8s.io/api/rbac/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/watch" genericapirequest "k8s.io/apiserver/pkg/endpoints/request" "k8s.io/apiserver/pkg/registry/rest" "k8s.io/kubernetes/pkg/apis/rbac" + rbacv1helpers "k8s.io/kubernetes/pkg/apis/rbac/v1" ) // Registry is an interface for things that know how to store ClusterRoles. type Registry interface { - ListClusterRoles(ctx context.Context, options *metainternalversion.ListOptions) (*rbac.ClusterRoleList, error) - CreateClusterRole(ctx context.Context, clusterRole *rbac.ClusterRole, createValidation rest.ValidateObjectFunc) error - UpdateClusterRole(ctx context.Context, clusterRole *rbac.ClusterRole, createValidation rest.ValidateObjectFunc, updateValidation rest.ValidateObjectUpdateFunc) error - GetClusterRole(ctx context.Context, name string, options *metav1.GetOptions) (*rbac.ClusterRole, error) - DeleteClusterRole(ctx context.Context, name string) error - WatchClusterRoles(ctx context.Context, options *metainternalversion.ListOptions) (watch.Interface, error) + GetClusterRole(ctx context.Context, name string, options *metav1.GetOptions) (*rbacv1.ClusterRole, error) } // storage puts strong typing around storage calls type storage struct { - rest.StandardStorage + rest.Getter } // NewRegistry returns a new Registry interface for the given Storage. Any mismatched @@ -48,40 +43,17 @@ func NewRegistry(s rest.StandardStorage) Registry { return &storage{s} } -func (s *storage) ListClusterRoles(ctx context.Context, options *metainternalversion.ListOptions) (*rbac.ClusterRoleList, error) { - obj, err := s.List(ctx, options) - if err != nil { - return nil, err - } - - return obj.(*rbac.ClusterRoleList), nil -} - -func (s *storage) CreateClusterRole(ctx context.Context, clusterRole *rbac.ClusterRole, createValidation rest.ValidateObjectFunc) error { - _, err := s.Create(ctx, clusterRole, createValidation, false) - return err -} - -func (s *storage) UpdateClusterRole(ctx context.Context, clusterRole *rbac.ClusterRole, createValidation rest.ValidateObjectFunc, updateValidation rest.ValidateObjectUpdateFunc) error { - _, _, err := s.Update(ctx, clusterRole.Name, rest.DefaultUpdatedObjectInfo(clusterRole), createValidation, updateValidation) - return err -} - -func (s *storage) WatchClusterRoles(ctx context.Context, options *metainternalversion.ListOptions) (watch.Interface, error) { - return s.Watch(ctx, options) -} - -func (s *storage) GetClusterRole(ctx context.Context, name string, options *metav1.GetOptions) (*rbac.ClusterRole, error) { +func (s *storage) GetClusterRole(ctx context.Context, name string, options *metav1.GetOptions) (*rbacv1.ClusterRole, error) { obj, err := s.Get(ctx, name, options) if err != nil { return nil, err } - return obj.(*rbac.ClusterRole), nil -} -func (s *storage) DeleteClusterRole(ctx context.Context, name string) error { - _, _, err := s.Delete(ctx, name, nil) - return err + ret := &rbacv1.ClusterRole{} + if err := rbacv1helpers.Convert_rbac_ClusterRole_To_v1_ClusterRole(obj.(*rbac.ClusterRole), ret, nil); err != nil { + return nil, err + } + return ret, nil } // AuthorizerAdapter adapts the registry to the authorizer interface @@ -89,6 +61,6 @@ type AuthorizerAdapter struct { Registry Registry } -func (a AuthorizerAdapter) GetClusterRole(name string) (*rbac.ClusterRole, error) { +func (a AuthorizerAdapter) GetClusterRole(name string) (*rbacv1.ClusterRole, error) { return a.Registry.GetClusterRole(genericapirequest.NewContext(), name, &metav1.GetOptions{}) } diff --git a/pkg/registry/rbac/clusterrolebinding/BUILD b/pkg/registry/rbac/clusterrolebinding/BUILD index 3f7f3015b0..5b327e8768 100644 --- a/pkg/registry/rbac/clusterrolebinding/BUILD +++ b/pkg/registry/rbac/clusterrolebinding/BUILD @@ -16,12 +16,12 @@ go_library( deps = [ "//pkg/api/legacyscheme:go_default_library", "//pkg/apis/rbac:go_default_library", + "//pkg/apis/rbac/v1:go_default_library", "//pkg/apis/rbac/validation:go_default_library", + "//vendor/k8s.io/api/rbac/v1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/apis/meta/internalversion:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/validation/field:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/watch:go_default_library", "//vendor/k8s.io/apiserver/pkg/endpoints/request:go_default_library", "//vendor/k8s.io/apiserver/pkg/registry/rest:go_default_library", "//vendor/k8s.io/apiserver/pkg/storage/names:go_default_library", diff --git a/pkg/registry/rbac/clusterrolebinding/policybased/BUILD b/pkg/registry/rbac/clusterrolebinding/policybased/BUILD index 66d61e93d1..db396f2b7a 100644 --- a/pkg/registry/rbac/clusterrolebinding/policybased/BUILD +++ b/pkg/registry/rbac/clusterrolebinding/policybased/BUILD @@ -12,8 +12,10 @@ go_library( deps = [ "//pkg/apis/core/helper:go_default_library", "//pkg/apis/rbac:go_default_library", + "//pkg/apis/rbac/v1:go_default_library", "//pkg/registry/rbac:go_default_library", "//pkg/registry/rbac/validation:go_default_library", + "//vendor/k8s.io/api/rbac/v1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/api/errors:go_default_library", "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library", diff --git a/pkg/registry/rbac/clusterrolebinding/policybased/storage.go b/pkg/registry/rbac/clusterrolebinding/policybased/storage.go index f31e3a0491..0217fcc353 100644 --- a/pkg/registry/rbac/clusterrolebinding/policybased/storage.go +++ b/pkg/registry/rbac/clusterrolebinding/policybased/storage.go @@ -20,6 +20,7 @@ package policybased import ( "context" + rbacv1 "k8s.io/api/rbac/v1" "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" @@ -27,6 +28,7 @@ import ( "k8s.io/apiserver/pkg/registry/rest" kapihelper "k8s.io/kubernetes/pkg/apis/core/helper" "k8s.io/kubernetes/pkg/apis/rbac" + rbacv1helpers "k8s.io/kubernetes/pkg/apis/rbac/v1" rbacregistry "k8s.io/kubernetes/pkg/registry/rbac" rbacregistryvalidation "k8s.io/kubernetes/pkg/registry/rbac/validation" ) @@ -59,7 +61,12 @@ func (s *Storage) Create(ctx context.Context, obj runtime.Object, createValidati return s.StandardStorage.Create(ctx, obj, createValidation, includeUninitialized) } - rules, err := s.ruleResolver.GetRoleReferenceRules(clusterRoleBinding.RoleRef, metav1.NamespaceNone) + v1RoleRef := rbacv1.RoleRef{} + err := rbacv1helpers.Convert_rbac_RoleRef_To_v1_RoleRef(&clusterRoleBinding.RoleRef, &v1RoleRef, nil) + if err != nil { + return nil, err + } + rules, err := s.ruleResolver.GetRoleReferenceRules(v1RoleRef, metav1.NamespaceNone) if err != nil { return nil, err } @@ -88,7 +95,12 @@ func (s *Storage) Update(ctx context.Context, name string, obj rest.UpdatedObjec } // Otherwise, see if we already have all the permissions contained in the referenced clusterrole - rules, err := s.ruleResolver.GetRoleReferenceRules(clusterRoleBinding.RoleRef, metav1.NamespaceNone) + v1RoleRef := rbacv1.RoleRef{} + err := rbacv1helpers.Convert_rbac_RoleRef_To_v1_RoleRef(&clusterRoleBinding.RoleRef, &v1RoleRef, nil) + if err != nil { + return nil, err + } + rules, err := s.ruleResolver.GetRoleReferenceRules(v1RoleRef, metav1.NamespaceNone) if err != nil { return nil, err } diff --git a/pkg/registry/rbac/clusterrolebinding/registry.go b/pkg/registry/rbac/clusterrolebinding/registry.go index 02ba53bf8c..34f5b73a9e 100644 --- a/pkg/registry/rbac/clusterrolebinding/registry.go +++ b/pkg/registry/rbac/clusterrolebinding/registry.go @@ -19,27 +19,22 @@ package clusterrolebinding import ( "context" + rbacv1 "k8s.io/api/rbac/v1" metainternalversion "k8s.io/apimachinery/pkg/apis/meta/internalversion" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/watch" genericapirequest "k8s.io/apiserver/pkg/endpoints/request" "k8s.io/apiserver/pkg/registry/rest" "k8s.io/kubernetes/pkg/apis/rbac" + rbacv1helpers "k8s.io/kubernetes/pkg/apis/rbac/v1" ) // Registry is an interface for things that know how to store ClusterRoleBindings. type Registry interface { - ListClusterRoleBindings(ctx context.Context, options *metainternalversion.ListOptions) (*rbac.ClusterRoleBindingList, error) - CreateClusterRoleBinding(ctx context.Context, clusterRoleBinding *rbac.ClusterRoleBinding, createValidation rest.ValidateObjectFunc) error - UpdateClusterRoleBinding(ctx context.Context, clusterRoleBinding *rbac.ClusterRoleBinding, createValidation rest.ValidateObjectFunc, updateValidation rest.ValidateObjectUpdateFunc) error - GetClusterRoleBinding(ctx context.Context, name string, options *metav1.GetOptions) (*rbac.ClusterRoleBinding, error) - DeleteClusterRoleBinding(ctx context.Context, name string) error - WatchClusterRoleBindings(ctx context.Context, options *metainternalversion.ListOptions) (watch.Interface, error) + ListClusterRoleBindings(ctx context.Context, options *metainternalversion.ListOptions) (*rbacv1.ClusterRoleBindingList, error) } // storage puts strong typing around storage calls type storage struct { - rest.StandardStorage + rest.Lister } // NewRegistry returns a new Registry interface for the given Storage. Any mismatched @@ -48,40 +43,17 @@ func NewRegistry(s rest.StandardStorage) Registry { return &storage{s} } -func (s *storage) ListClusterRoleBindings(ctx context.Context, options *metainternalversion.ListOptions) (*rbac.ClusterRoleBindingList, error) { +func (s *storage) ListClusterRoleBindings(ctx context.Context, options *metainternalversion.ListOptions) (*rbacv1.ClusterRoleBindingList, error) { obj, err := s.List(ctx, options) if err != nil { return nil, err } - return obj.(*rbac.ClusterRoleBindingList), nil -} - -func (s *storage) CreateClusterRoleBinding(ctx context.Context, clusterRoleBinding *rbac.ClusterRoleBinding, createValidation rest.ValidateObjectFunc) error { - _, err := s.Create(ctx, clusterRoleBinding, createValidation, false) - return err -} - -func (s *storage) UpdateClusterRoleBinding(ctx context.Context, clusterRoleBinding *rbac.ClusterRoleBinding, createValidation rest.ValidateObjectFunc, updateValidation rest.ValidateObjectUpdateFunc) error { - _, _, err := s.Update(ctx, clusterRoleBinding.Name, rest.DefaultUpdatedObjectInfo(clusterRoleBinding), createValidation, updateValidation) - return err -} - -func (s *storage) WatchClusterRoleBindings(ctx context.Context, options *metainternalversion.ListOptions) (watch.Interface, error) { - return s.Watch(ctx, options) -} - -func (s *storage) GetClusterRoleBinding(ctx context.Context, name string, options *metav1.GetOptions) (*rbac.ClusterRoleBinding, error) { - obj, err := s.Get(ctx, name, options) - if err != nil { + ret := &rbacv1.ClusterRoleBindingList{} + if err := rbacv1helpers.Convert_rbac_ClusterRoleBindingList_To_v1_ClusterRoleBindingList(obj.(*rbac.ClusterRoleBindingList), ret, nil); err != nil { return nil, err } - return obj.(*rbac.ClusterRoleBinding), nil -} - -func (s *storage) DeleteClusterRoleBinding(ctx context.Context, name string) error { - _, _, err := s.Delete(ctx, name, nil) - return err + return ret, nil } // AuthorizerAdapter adapts the registry to the authorizer interface @@ -89,13 +61,13 @@ type AuthorizerAdapter struct { Registry Registry } -func (a AuthorizerAdapter) ListClusterRoleBindings() ([]*rbac.ClusterRoleBinding, error) { +func (a AuthorizerAdapter) ListClusterRoleBindings() ([]*rbacv1.ClusterRoleBinding, error) { list, err := a.Registry.ListClusterRoleBindings(genericapirequest.NewContext(), &metainternalversion.ListOptions{}) if err != nil { return nil, err } - ret := []*rbac.ClusterRoleBinding{} + ret := []*rbacv1.ClusterRoleBinding{} for i := range list.Items { ret = append(ret, &list.Items[i]) } diff --git a/pkg/registry/rbac/reconciliation/BUILD b/pkg/registry/rbac/reconciliation/BUILD index 4b14eed1c6..42ff2c2101 100644 --- a/pkg/registry/rbac/reconciliation/BUILD +++ b/pkg/registry/rbac/reconciliation/BUILD @@ -15,7 +15,7 @@ go_test( embed = [":go_default_library"], deps = [ "//pkg/apis/core/helper:go_default_library", - "//pkg/apis/rbac:go_default_library", + "//vendor/k8s.io/api/rbac/v1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/diff:go_default_library", ], @@ -34,16 +34,16 @@ go_library( ], importpath = "k8s.io/kubernetes/pkg/registry/rbac/reconciliation", deps = [ - "//pkg/apis/core:go_default_library", - "//pkg/apis/rbac:go_default_library", - "//pkg/client/clientset_generated/internalclientset/typed/core/internalversion:go_default_library", - "//pkg/client/clientset_generated/internalclientset/typed/rbac/internalversion:go_default_library", "//pkg/registry/rbac/validation:go_default_library", + "//vendor/k8s.io/api/core/v1:go_default_library", + "//vendor/k8s.io/api/rbac/v1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/api/equality:go_default_library", "//vendor/k8s.io/apimachinery/pkg/api/errors:go_default_library", "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library", "//vendor/k8s.io/apimachinery/pkg/types:go_default_library", + "//vendor/k8s.io/client-go/kubernetes/typed/core/v1:go_default_library", + "//vendor/k8s.io/client-go/kubernetes/typed/rbac/v1:go_default_library", ], ) diff --git a/pkg/registry/rbac/reconciliation/clusterrole_interfaces.go b/pkg/registry/rbac/reconciliation/clusterrole_interfaces.go index 419cc1df26..68dc97fd3f 100644 --- a/pkg/registry/rbac/reconciliation/clusterrole_interfaces.go +++ b/pkg/registry/rbac/reconciliation/clusterrole_interfaces.go @@ -17,17 +17,17 @@ limitations under the License. package reconciliation import ( + rbacv1 "k8s.io/api/rbac/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" - "k8s.io/kubernetes/pkg/apis/rbac" - "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/rbac/internalversion" + rbacv1client "k8s.io/client-go/kubernetes/typed/rbac/v1" ) // +k8s:deepcopy-gen=true // +k8s:deepcopy-gen:interfaces=k8s.io/kubernetes/pkg/registry/rbac/reconciliation.RuleOwner // +k8s:deepcopy-gen:nonpointer-interfaces=true type ClusterRoleRuleOwner struct { - ClusterRole *rbac.ClusterRole + ClusterRole *rbacv1.ClusterRole } func (o ClusterRoleRuleOwner) GetObject() runtime.Object { @@ -58,24 +58,24 @@ func (o ClusterRoleRuleOwner) SetAnnotations(in map[string]string) { o.ClusterRole.Annotations = in } -func (o ClusterRoleRuleOwner) GetRules() []rbac.PolicyRule { +func (o ClusterRoleRuleOwner) GetRules() []rbacv1.PolicyRule { return o.ClusterRole.Rules } -func (o ClusterRoleRuleOwner) SetRules(in []rbac.PolicyRule) { +func (o ClusterRoleRuleOwner) SetRules(in []rbacv1.PolicyRule) { o.ClusterRole.Rules = in } -func (o ClusterRoleRuleOwner) GetAggregationRule() *rbac.AggregationRule { +func (o ClusterRoleRuleOwner) GetAggregationRule() *rbacv1.AggregationRule { return o.ClusterRole.AggregationRule } -func (o ClusterRoleRuleOwner) SetAggregationRule(in *rbac.AggregationRule) { +func (o ClusterRoleRuleOwner) SetAggregationRule(in *rbacv1.AggregationRule) { o.ClusterRole.AggregationRule = in } type ClusterRoleModifier struct { - Client internalversion.ClusterRoleInterface + Client rbacv1client.ClusterRoleInterface } func (c ClusterRoleModifier) Get(namespace, name string) (RuleOwner, error) { diff --git a/pkg/registry/rbac/reconciliation/clusterrolebinding_interfaces.go b/pkg/registry/rbac/reconciliation/clusterrolebinding_interfaces.go index aa07f107f8..b669a59515 100644 --- a/pkg/registry/rbac/reconciliation/clusterrolebinding_interfaces.go +++ b/pkg/registry/rbac/reconciliation/clusterrolebinding_interfaces.go @@ -17,18 +17,18 @@ limitations under the License. package reconciliation import ( + rbacv1 "k8s.io/api/rbac/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/types" - "k8s.io/kubernetes/pkg/apis/rbac" - "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/rbac/internalversion" + rbacv1client "k8s.io/client-go/kubernetes/typed/rbac/v1" ) // +k8s:deepcopy-gen=true // +k8s:deepcopy-gen:interfaces=k8s.io/kubernetes/pkg/registry/rbac/reconciliation.RoleBinding // +k8s:deepcopy-gen:nonpointer-interfaces=true type ClusterRoleBindingAdapter struct { - ClusterRoleBinding *rbac.ClusterRoleBinding + ClusterRoleBinding *rbacv1.ClusterRoleBinding } func (o ClusterRoleBindingAdapter) GetObject() runtime.Object { @@ -63,20 +63,20 @@ func (o ClusterRoleBindingAdapter) SetAnnotations(in map[string]string) { o.ClusterRoleBinding.Annotations = in } -func (o ClusterRoleBindingAdapter) GetRoleRef() rbac.RoleRef { +func (o ClusterRoleBindingAdapter) GetRoleRef() rbacv1.RoleRef { return o.ClusterRoleBinding.RoleRef } -func (o ClusterRoleBindingAdapter) GetSubjects() []rbac.Subject { +func (o ClusterRoleBindingAdapter) GetSubjects() []rbacv1.Subject { return o.ClusterRoleBinding.Subjects } -func (o ClusterRoleBindingAdapter) SetSubjects(in []rbac.Subject) { +func (o ClusterRoleBindingAdapter) SetSubjects(in []rbacv1.Subject) { o.ClusterRoleBinding.Subjects = in } type ClusterRoleBindingClientAdapter struct { - Client internalversion.ClusterRoleBindingInterface + Client rbacv1client.ClusterRoleBindingInterface } func (c ClusterRoleBindingClientAdapter) Get(namespace, name string) (RoleBinding, error) { diff --git a/pkg/registry/rbac/reconciliation/reconcile_role.go b/pkg/registry/rbac/reconciliation/reconcile_role.go index 1ab840c759..8197b9f759 100644 --- a/pkg/registry/rbac/reconciliation/reconcile_role.go +++ b/pkg/registry/rbac/reconciliation/reconcile_role.go @@ -20,11 +20,11 @@ import ( "fmt" "reflect" + rbacv1 "k8s.io/api/rbac/v1" "k8s.io/apimachinery/pkg/api/equality" "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" - "k8s.io/kubernetes/pkg/apis/rbac" "k8s.io/kubernetes/pkg/registry/rbac/validation" ) @@ -51,10 +51,10 @@ type RuleOwner interface { SetLabels(map[string]string) GetAnnotations() map[string]string SetAnnotations(map[string]string) - GetRules() []rbac.PolicyRule - SetRules([]rbac.PolicyRule) - GetAggregationRule() *rbac.AggregationRule - SetAggregationRule(*rbac.AggregationRule) + GetRules() []rbacv1.PolicyRule + SetRules([]rbacv1.PolicyRule) + GetAggregationRule() *rbacv1.AggregationRule + SetAggregationRule(*rbacv1.AggregationRule) DeepCopyRuleOwner() RuleOwner } @@ -75,9 +75,9 @@ type ReconcileClusterRoleResult struct { Role RuleOwner // MissingRules contains expected rules that were missing from the currently persisted role - MissingRules []rbac.PolicyRule + MissingRules []rbacv1.PolicyRule // ExtraRules contains extra permissions the currently persisted role had - ExtraRules []rbac.PolicyRule + ExtraRules []rbacv1.PolicyRule // MissingAggregationRuleSelectors contains expected selectors that were missing from the currently persisted role MissingAggregationRuleSelectors []metav1.LabelSelector @@ -112,7 +112,7 @@ func (o *ReconcileRoleOptions) run(attempts int) (*ReconcileClusterRoleResult, e case errors.IsNotFound(err): aggregationRule := o.Role.GetAggregationRule() if aggregationRule == nil { - aggregationRule = &rbac.AggregationRule{} + aggregationRule = &rbacv1.AggregationRule{} } result = &ReconcileClusterRoleResult{ Role: o.Role, @@ -178,7 +178,7 @@ func (o *ReconcileRoleOptions) run(attempts int) (*ReconcileClusterRoleResult, e func computeReconciledRole(existing, expected RuleOwner, removeExtraPermissions bool) (*ReconcileClusterRoleResult, error) { result := &ReconcileClusterRoleResult{Operation: ReconcileNone} - result.Protected = (existing.GetAnnotations()[rbac.AutoUpdateAnnotationKey] == "false") + result.Protected = (existing.GetAnnotations()[rbacv1.AutoUpdateAnnotationKey] == "false") // Start with a copy of the existing object result.Role = existing.DeepCopyRuleOwner() @@ -223,7 +223,7 @@ func computeReconciledRole(existing, expected RuleOwner, removeExtraPermissions // add missing rules in the union case aggregationRule := result.Role.GetAggregationRule() if aggregationRule == nil { - aggregationRule = &rbac.AggregationRule{} + aggregationRule = &rbacv1.AggregationRule{} } aggregationRule.ClusterRoleSelectors = append(aggregationRule.ClusterRoleSelectors, result.MissingAggregationRuleSelectors...) result.Role.SetAggregationRule(aggregationRule) @@ -254,7 +254,7 @@ func merge(maps ...map[string]string) map[string]string { // aggregationRuleCovers determines whether or not the ownerSelectors cover the servantSelectors in terms of semantically // equal label selectors. // It returns whether or not the ownerSelectors cover and a list of the rules that the ownerSelectors do not cover. -func aggregationRuleCovers(ownerRule, servantRule *rbac.AggregationRule) (bool, []metav1.LabelSelector) { +func aggregationRuleCovers(ownerRule, servantRule *rbacv1.AggregationRule) (bool, []metav1.LabelSelector) { switch { case ownerRule == nil && servantRule == nil: return true, []metav1.LabelSelector{} diff --git a/pkg/registry/rbac/reconciliation/reconcile_role_test.go b/pkg/registry/rbac/reconciliation/reconcile_role_test.go index 6a7f632b48..be37127988 100644 --- a/pkg/registry/rbac/reconciliation/reconcile_role_test.go +++ b/pkg/registry/rbac/reconciliation/reconcile_role_test.go @@ -19,23 +19,23 @@ package reconciliation import ( "testing" + rbacv1 "k8s.io/api/rbac/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/util/diff" "k8s.io/kubernetes/pkg/apis/core/helper" - "k8s.io/kubernetes/pkg/apis/rbac" ) -func role(rules []rbac.PolicyRule, labels map[string]string, annotations map[string]string) *rbac.ClusterRole { - return &rbac.ClusterRole{ +func role(rules []rbacv1.PolicyRule, labels map[string]string, annotations map[string]string) *rbacv1.ClusterRole { + return &rbacv1.ClusterRole{ Rules: rules, ObjectMeta: metav1.ObjectMeta{Labels: labels, Annotations: annotations}, } } -func rules(resources ...string) []rbac.PolicyRule { - r := []rbac.PolicyRule{} +func rules(resources ...string) []rbacv1.PolicyRule { + r := []rbacv1.PolicyRule{} for _, resource := range resources { - r = append(r, rbac.PolicyRule{APIGroups: []string{""}, Verbs: []string{"get"}, Resources: []string{resource}}) + r = append(r, rbacv1.PolicyRule{APIGroups: []string{""}, Verbs: []string{"get"}, Resources: []string{resource}}) } return r } @@ -44,11 +44,11 @@ type ss map[string]string func TestComputeReconciledRoleRules(t *testing.T) { tests := map[string]struct { - expectedRole *rbac.ClusterRole - actualRole *rbac.ClusterRole + expectedRole *rbacv1.ClusterRole + actualRole *rbacv1.ClusterRole removeExtraPermissions bool - expectedReconciledRole *rbac.ClusterRole + expectedReconciledRole *rbacv1.ClusterRole expectedReconciliationNeeded bool }{ "empty": { @@ -278,14 +278,14 @@ func TestComputeReconciledRoleRules(t *testing.T) { } } -func aggregatedRole(aggregationRule *rbac.AggregationRule) *rbac.ClusterRole { - return &rbac.ClusterRole{ +func aggregatedRole(aggregationRule *rbacv1.AggregationRule) *rbacv1.ClusterRole { + return &rbacv1.ClusterRole{ AggregationRule: aggregationRule, } } -func aggregationrule(selectors []map[string]string) *rbac.AggregationRule { - ret := &rbac.AggregationRule{} +func aggregationrule(selectors []map[string]string) *rbacv1.AggregationRule { + ret := &rbacv1.AggregationRule{} for _, selector := range selectors { ret.ClusterRoleSelectors = append(ret.ClusterRoleSelectors, metav1.LabelSelector{MatchLabels: selector}) @@ -295,15 +295,15 @@ func aggregationrule(selectors []map[string]string) *rbac.AggregationRule { func TestComputeReconciledRoleAggregationRules(t *testing.T) { tests := map[string]struct { - expectedRole *rbac.ClusterRole - actualRole *rbac.ClusterRole + expectedRole *rbacv1.ClusterRole + actualRole *rbacv1.ClusterRole removeExtraPermissions bool - expectedReconciledRole *rbac.ClusterRole + expectedReconciledRole *rbacv1.ClusterRole expectedReconciliationNeeded bool }{ "empty": { - expectedRole: aggregatedRole(&rbac.AggregationRule{}), + expectedRole: aggregatedRole(&rbacv1.AggregationRule{}), actualRole: aggregatedRole(nil), removeExtraPermissions: true, @@ -311,8 +311,8 @@ func TestComputeReconciledRoleAggregationRules(t *testing.T) { expectedReconciliationNeeded: false, }, "empty-2": { - expectedRole: aggregatedRole(&rbac.AggregationRule{}), - actualRole: aggregatedRole(&rbac.AggregationRule{}), + expectedRole: aggregatedRole(&rbacv1.AggregationRule{}), + actualRole: aggregatedRole(&rbacv1.AggregationRule{}), removeExtraPermissions: true, expectedReconciledRole: nil, @@ -365,7 +365,7 @@ func TestComputeReconciledRoleAggregationRules(t *testing.T) { // desired role is not aggregated expectedRole: role(rules("pods", "nodes", "secrets"), nil, nil), // existing role is aggregated and has other permissions - actualRole: func() *rbac.ClusterRole { + actualRole: func() *rbacv1.ClusterRole { r := aggregatedRole(aggregationrule([]map[string]string{{"alpha": "bravo"}})) r.Rules = rules("deployments") return r diff --git a/pkg/registry/rbac/reconciliation/reconcile_rolebindings.go b/pkg/registry/rbac/reconciliation/reconcile_rolebindings.go index ac138da584..65ca2bd1a3 100644 --- a/pkg/registry/rbac/reconciliation/reconcile_rolebindings.go +++ b/pkg/registry/rbac/reconciliation/reconcile_rolebindings.go @@ -20,10 +20,10 @@ import ( "fmt" "reflect" + rbacv1 "k8s.io/api/rbac/v1" "k8s.io/apimachinery/pkg/api/errors" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/types" - "k8s.io/kubernetes/pkg/apis/rbac" ) type RoleBindingModifier interface { @@ -42,9 +42,9 @@ type RoleBinding interface { SetLabels(map[string]string) GetAnnotations() map[string]string SetAnnotations(map[string]string) - GetRoleRef() rbac.RoleRef - GetSubjects() []rbac.Subject - SetSubjects([]rbac.Subject) + GetRoleRef() rbacv1.RoleRef + GetSubjects() []rbacv1.Subject + SetSubjects([]rbacv1.Subject) DeepCopyRoleBinding() RoleBinding } @@ -67,9 +67,9 @@ type ReconcileClusterRoleBindingResult struct { RoleBinding RoleBinding // MissingSubjects contains expected subjects that were missing from the currently persisted rolebinding - MissingSubjects []rbac.Subject + MissingSubjects []rbacv1.Subject // ExtraSubjects contains extra subjects the currently persisted rolebinding had - ExtraSubjects []rbac.Subject + ExtraSubjects []rbacv1.Subject // Operation is the API operation required to reconcile. // If no reconciliation was needed, it is set to ReconcileNone. @@ -176,7 +176,7 @@ func (o *ReconcileRoleBindingOptions) run(attempts int) (*ReconcileClusterRoleBi func computeReconciledRoleBinding(existing, expected RoleBinding, removeExtraSubjects bool) (*ReconcileClusterRoleBindingResult, error) { result := &ReconcileClusterRoleBindingResult{Operation: ReconcileNone} - result.Protected = (existing.GetAnnotations()[rbac.AutoUpdateAnnotationKey] == "false") + result.Protected = (existing.GetAnnotations()[rbacv1.AutoUpdateAnnotationKey] == "false") // Reset the binding completely if the roleRef is different if expected.GetRoleRef() != existing.GetRoleRef() { @@ -216,7 +216,7 @@ func computeReconciledRoleBinding(existing, expected RoleBinding, removeExtraSub return result, nil } -func contains(list []rbac.Subject, item rbac.Subject) bool { +func contains(list []rbacv1.Subject, item rbacv1.Subject) bool { for _, listItem := range list { if listItem == item { return true @@ -229,7 +229,7 @@ func contains(list []rbac.Subject, item rbac.Subject) bool { // list1Only = list1 - list2 // list2Only = list2 - list1 // if both returned lists are empty, the provided lists are equal -func diffSubjectLists(list1 []rbac.Subject, list2 []rbac.Subject) (list1Only []rbac.Subject, list2Only []rbac.Subject) { +func diffSubjectLists(list1 []rbacv1.Subject, list2 []rbacv1.Subject) (list1Only []rbacv1.Subject, list2Only []rbacv1.Subject) { for _, list1Item := range list1 { if !contains(list2, list1Item) { if !contains(list1Only, list1Item) { diff --git a/pkg/registry/rbac/reconciliation/reconcile_rolebindings_test.go b/pkg/registry/rbac/reconciliation/reconcile_rolebindings_test.go index 0cdd3cf46b..6abb09081b 100644 --- a/pkg/registry/rbac/reconciliation/reconcile_rolebindings_test.go +++ b/pkg/registry/rbac/reconciliation/reconcile_rolebindings_test.go @@ -19,24 +19,24 @@ package reconciliation import ( "testing" + rbacv1 "k8s.io/api/rbac/v1" "k8s.io/kubernetes/pkg/apis/core/helper" - "k8s.io/kubernetes/pkg/apis/rbac" ) -func binding(roleRef rbac.RoleRef, subjects []rbac.Subject) *rbac.ClusterRoleBinding { - return &rbac.ClusterRoleBinding{RoleRef: roleRef, Subjects: subjects} +func binding(roleRef rbacv1.RoleRef, subjects []rbacv1.Subject) *rbacv1.ClusterRoleBinding { + return &rbacv1.ClusterRoleBinding{RoleRef: roleRef, Subjects: subjects} } -func ref(name string) rbac.RoleRef { - return rbac.RoleRef{Name: name} +func ref(name string) rbacv1.RoleRef { + return rbacv1.RoleRef{Name: name} } -func subject(name string) rbac.Subject { - return rbac.Subject{Name: name} +func subject(name string) rbacv1.Subject { + return rbacv1.Subject{Name: name} } -func subjects(names ...string) []rbac.Subject { - r := []rbac.Subject{} +func subjects(names ...string) []rbacv1.Subject { + r := []rbacv1.Subject{} for _, name := range names { r = append(r, subject(name)) } @@ -45,10 +45,10 @@ func subjects(names ...string) []rbac.Subject { func TestDiffObjectReferenceLists(t *testing.T) { tests := map[string]struct { - A []rbac.Subject - B []rbac.Subject - ExpectedOnlyA []rbac.Subject - ExpectedOnlyB []rbac.Subject + A []rbacv1.Subject + B []rbacv1.Subject + ExpectedOnlyA []rbacv1.Subject + ExpectedOnlyB []rbacv1.Subject }{ "empty": {}, @@ -92,11 +92,11 @@ func TestDiffObjectReferenceLists(t *testing.T) { func TestComputeUpdate(t *testing.T) { tests := map[string]struct { - ExpectedBinding *rbac.ClusterRoleBinding - ActualBinding *rbac.ClusterRoleBinding + ExpectedBinding *rbacv1.ClusterRoleBinding + ActualBinding *rbacv1.ClusterRoleBinding RemoveExtraSubjects bool - ExpectedUpdatedBinding *rbac.ClusterRoleBinding + ExpectedUpdatedBinding *rbacv1.ClusterRoleBinding ExpectedUpdateNeeded bool }{ "match without union": { diff --git a/pkg/registry/rbac/reconciliation/role_interfaces.go b/pkg/registry/rbac/reconciliation/role_interfaces.go index b46e9e872e..24cb7899d3 100644 --- a/pkg/registry/rbac/reconciliation/role_interfaces.go +++ b/pkg/registry/rbac/reconciliation/role_interfaces.go @@ -17,20 +17,20 @@ limitations under the License. package reconciliation import ( + corev1 "k8s.io/api/core/v1" + rbacv1 "k8s.io/api/rbac/v1" apierrors "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" - api "k8s.io/kubernetes/pkg/apis/core" - "k8s.io/kubernetes/pkg/apis/rbac" - core "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/core/internalversion" - "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/rbac/internalversion" + corev1client "k8s.io/client-go/kubernetes/typed/core/v1" + rbacv1client "k8s.io/client-go/kubernetes/typed/rbac/v1" ) // +k8s:deepcopy-gen=true // +k8s:deepcopy-gen:interfaces=k8s.io/kubernetes/pkg/registry/rbac/reconciliation.RuleOwner // +k8s:deepcopy-gen:nonpointer-interfaces=true type RoleRuleOwner struct { - Role *rbac.Role + Role *rbacv1.Role } func (o RoleRuleOwner) GetObject() runtime.Object { @@ -61,24 +61,24 @@ func (o RoleRuleOwner) SetAnnotations(in map[string]string) { o.Role.Annotations = in } -func (o RoleRuleOwner) GetRules() []rbac.PolicyRule { +func (o RoleRuleOwner) GetRules() []rbacv1.PolicyRule { return o.Role.Rules } -func (o RoleRuleOwner) SetRules(in []rbac.PolicyRule) { +func (o RoleRuleOwner) SetRules(in []rbacv1.PolicyRule) { o.Role.Rules = in } -func (o RoleRuleOwner) GetAggregationRule() *rbac.AggregationRule { +func (o RoleRuleOwner) GetAggregationRule() *rbacv1.AggregationRule { return nil } -func (o RoleRuleOwner) SetAggregationRule(in *rbac.AggregationRule) { +func (o RoleRuleOwner) SetAggregationRule(in *rbacv1.AggregationRule) { } type RoleModifier struct { - Client internalversion.RolesGetter - NamespaceClient core.NamespaceInterface + Client rbacv1client.RolesGetter + NamespaceClient corev1client.NamespaceInterface } func (c RoleModifier) Get(namespace, name string) (RuleOwner, error) { @@ -90,7 +90,7 @@ func (c RoleModifier) Get(namespace, name string) (RuleOwner, error) { } func (c RoleModifier) Create(in RuleOwner) (RuleOwner, error) { - ns := &api.Namespace{ObjectMeta: metav1.ObjectMeta{Name: in.GetNamespace()}} + ns := &corev1.Namespace{ObjectMeta: metav1.ObjectMeta{Name: in.GetNamespace()}} if _, err := c.NamespaceClient.Create(ns); err != nil && !apierrors.IsAlreadyExists(err) { return nil, err } diff --git a/pkg/registry/rbac/reconciliation/rolebinding_interfaces.go b/pkg/registry/rbac/reconciliation/rolebinding_interfaces.go index 126f479cb1..23bf6b653a 100644 --- a/pkg/registry/rbac/reconciliation/rolebinding_interfaces.go +++ b/pkg/registry/rbac/reconciliation/rolebinding_interfaces.go @@ -17,21 +17,21 @@ limitations under the License. package reconciliation import ( + corev1 "k8s.io/api/core/v1" + rbacv1 "k8s.io/api/rbac/v1" apierrors "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/types" - api "k8s.io/kubernetes/pkg/apis/core" - "k8s.io/kubernetes/pkg/apis/rbac" - core "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/core/internalversion" - "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/rbac/internalversion" + corev1client "k8s.io/client-go/kubernetes/typed/core/v1" + rbacv1client "k8s.io/client-go/kubernetes/typed/rbac/v1" ) // +k8s:deepcopy-gen=true // +k8s:deepcopy-gen:interfaces=k8s.io/kubernetes/pkg/registry/rbac/reconciliation.RoleBinding // +k8s:deepcopy-gen:nonpointer-interfaces=true type RoleBindingAdapter struct { - RoleBinding *rbac.RoleBinding + RoleBinding *rbacv1.RoleBinding } func (o RoleBindingAdapter) GetObject() runtime.Object { @@ -66,21 +66,21 @@ func (o RoleBindingAdapter) SetAnnotations(in map[string]string) { o.RoleBinding.Annotations = in } -func (o RoleBindingAdapter) GetRoleRef() rbac.RoleRef { +func (o RoleBindingAdapter) GetRoleRef() rbacv1.RoleRef { return o.RoleBinding.RoleRef } -func (o RoleBindingAdapter) GetSubjects() []rbac.Subject { +func (o RoleBindingAdapter) GetSubjects() []rbacv1.Subject { return o.RoleBinding.Subjects } -func (o RoleBindingAdapter) SetSubjects(in []rbac.Subject) { +func (o RoleBindingAdapter) SetSubjects(in []rbacv1.Subject) { o.RoleBinding.Subjects = in } type RoleBindingClientAdapter struct { - Client internalversion.RoleBindingsGetter - NamespaceClient core.NamespaceInterface + Client rbacv1client.RoleBindingsGetter + NamespaceClient corev1client.NamespaceInterface } func (c RoleBindingClientAdapter) Get(namespace, name string) (RoleBinding, error) { @@ -92,7 +92,7 @@ func (c RoleBindingClientAdapter) Get(namespace, name string) (RoleBinding, erro } func (c RoleBindingClientAdapter) Create(in RoleBinding) (RoleBinding, error) { - ns := &api.Namespace{ObjectMeta: metav1.ObjectMeta{Name: in.GetNamespace()}} + ns := &corev1.Namespace{ObjectMeta: metav1.ObjectMeta{Name: in.GetNamespace()}} if _, err := c.NamespaceClient.Create(ns); err != nil && !apierrors.IsAlreadyExists(err) { return nil, err } diff --git a/pkg/registry/rbac/reconciliation/zz_generated.deepcopy.go b/pkg/registry/rbac/reconciliation/zz_generated.deepcopy.go index 3347ccdfe0..411cfbd48a 100644 --- a/pkg/registry/rbac/reconciliation/zz_generated.deepcopy.go +++ b/pkg/registry/rbac/reconciliation/zz_generated.deepcopy.go @@ -21,7 +21,7 @@ limitations under the License. package reconciliation import ( - rbac "k8s.io/kubernetes/pkg/apis/rbac" + v1 "k8s.io/api/rbac/v1" ) // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. @@ -32,7 +32,7 @@ func (in *ClusterRoleBindingAdapter) DeepCopyInto(out *ClusterRoleBindingAdapter if *in == nil { *out = nil } else { - *out = new(rbac.ClusterRoleBinding) + *out = new(v1.ClusterRoleBinding) (*in).DeepCopyInto(*out) } } @@ -62,7 +62,7 @@ func (in *ClusterRoleRuleOwner) DeepCopyInto(out *ClusterRoleRuleOwner) { if *in == nil { *out = nil } else { - *out = new(rbac.ClusterRole) + *out = new(v1.ClusterRole) (*in).DeepCopyInto(*out) } } @@ -92,7 +92,7 @@ func (in *RoleBindingAdapter) DeepCopyInto(out *RoleBindingAdapter) { if *in == nil { *out = nil } else { - *out = new(rbac.RoleBinding) + *out = new(v1.RoleBinding) (*in).DeepCopyInto(*out) } } @@ -122,7 +122,7 @@ func (in *RoleRuleOwner) DeepCopyInto(out *RoleRuleOwner) { if *in == nil { *out = nil } else { - *out = new(rbac.Role) + *out = new(v1.Role) (*in).DeepCopyInto(*out) } } diff --git a/pkg/registry/rbac/rest/BUILD b/pkg/registry/rbac/rest/BUILD index 685a8334bf..0d84ad2f85 100644 --- a/pkg/registry/rbac/rest/BUILD +++ b/pkg/registry/rbac/rest/BUILD @@ -12,8 +12,6 @@ go_library( deps = [ "//pkg/api/legacyscheme:go_default_library", "//pkg/apis/rbac:go_default_library", - "//pkg/client/clientset_generated/internalclientset/typed/core/internalversion:go_default_library", - "//pkg/client/clientset_generated/internalclientset/typed/rbac/internalversion:go_default_library", "//pkg/registry/rbac/clusterrole:go_default_library", "//pkg/registry/rbac/clusterrole/policybased:go_default_library", "//pkg/registry/rbac/clusterrole/storage:go_default_library", @@ -43,6 +41,8 @@ go_library( "//vendor/k8s.io/apiserver/pkg/registry/rest:go_default_library", "//vendor/k8s.io/apiserver/pkg/server:go_default_library", "//vendor/k8s.io/apiserver/pkg/server/storage:go_default_library", + "//vendor/k8s.io/client-go/kubernetes/typed/core/v1:go_default_library", + "//vendor/k8s.io/client-go/kubernetes/typed/rbac/v1:go_default_library", "//vendor/k8s.io/client-go/util/retry:go_default_library", ], ) diff --git a/pkg/registry/rbac/rest/storage_rbac.go b/pkg/registry/rbac/rest/storage_rbac.go index 1622d067b3..53ace70eb9 100644 --- a/pkg/registry/rbac/rest/storage_rbac.go +++ b/pkg/registry/rbac/rest/storage_rbac.go @@ -35,11 +35,11 @@ import ( "k8s.io/apiserver/pkg/registry/rest" genericapiserver "k8s.io/apiserver/pkg/server" serverstorage "k8s.io/apiserver/pkg/server/storage" + corev1client "k8s.io/client-go/kubernetes/typed/core/v1" + rbacv1client "k8s.io/client-go/kubernetes/typed/rbac/v1" "k8s.io/client-go/util/retry" "k8s.io/kubernetes/pkg/api/legacyscheme" "k8s.io/kubernetes/pkg/apis/rbac" - coreclient "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/core/internalversion" - rbacclient "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/rbac/internalversion" "k8s.io/kubernetes/pkg/registry/rbac/clusterrole" clusterrolepolicybased "k8s.io/kubernetes/pkg/registry/rbac/clusterrole/policybased" clusterrolestore "k8s.io/kubernetes/pkg/registry/rbac/clusterrole/storage" @@ -124,10 +124,10 @@ func (p RESTStorageProvider) PostStartHook() (string, genericapiserver.PostStart } type PolicyData struct { - ClusterRoles []rbac.ClusterRole - ClusterRoleBindings []rbac.ClusterRoleBinding - Roles map[string][]rbac.Role - RoleBindings map[string][]rbac.RoleBinding + ClusterRoles []rbacapiv1.ClusterRole + ClusterRoleBindings []rbacapiv1.ClusterRoleBinding + Roles map[string][]rbacapiv1.Role + RoleBindings map[string][]rbacapiv1.RoleBinding // ClusterRolesToAggregate maps from previous clusterrole name to the new clusterrole name ClusterRolesToAggregate map[string]string } @@ -138,13 +138,13 @@ func (p *PolicyData) EnsureRBACPolicy() genericapiserver.PostStartHookFunc { // starts, the roles don't initialize, and nothing works. err := wait.Poll(1*time.Second, 30*time.Second, func() (done bool, err error) { - coreclientset, err := coreclient.NewForConfig(hookContext.LoopbackClientConfig) + coreclientset, err := corev1client.NewForConfig(hookContext.LoopbackClientConfig) if err != nil { utilruntime.HandleError(fmt.Errorf("unable to initialize client: %v", err)) return false, nil } - clientset, err := rbacclient.NewForConfig(hookContext.LoopbackClientConfig) + clientset, err := rbacv1client.NewForConfig(hookContext.LoopbackClientConfig) if err != nil { utilruntime.HandleError(fmt.Errorf("unable to initialize client: %v", err)) return false, nil @@ -303,7 +303,7 @@ func (p RESTStorageProvider) GroupName() string { // primeAggregatedClusterRoles copies roles that have transitioned to aggregated roles and may need to pick up changes // that were done to the legacy roles. -func primeAggregatedClusterRoles(clusterRolesToAggregate map[string]string, clusterRoleClient rbacclient.ClusterRolesGetter) error { +func primeAggregatedClusterRoles(clusterRolesToAggregate map[string]string, clusterRoleClient rbacv1client.ClusterRolesGetter) error { for oldName, newName := range clusterRolesToAggregate { _, err := clusterRoleClient.ClusterRoles().Get(newName, metav1.GetOptions{}) if err == nil { diff --git a/pkg/registry/rbac/role/BUILD b/pkg/registry/rbac/role/BUILD index a4fde9839b..03c6f598e0 100644 --- a/pkg/registry/rbac/role/BUILD +++ b/pkg/registry/rbac/role/BUILD @@ -16,12 +16,12 @@ go_library( deps = [ "//pkg/api/legacyscheme:go_default_library", "//pkg/apis/rbac:go_default_library", + "//pkg/apis/rbac/v1:go_default_library", "//pkg/apis/rbac/validation:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/apis/meta/internalversion:go_default_library", + "//vendor/k8s.io/api/rbac/v1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/validation/field:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/watch:go_default_library", "//vendor/k8s.io/apiserver/pkg/endpoints/request:go_default_library", "//vendor/k8s.io/apiserver/pkg/registry/rest:go_default_library", "//vendor/k8s.io/apiserver/pkg/storage/names:go_default_library", diff --git a/pkg/registry/rbac/role/policybased/storage.go b/pkg/registry/rbac/role/policybased/storage.go index 3aa1c4f946..447cd1178a 100644 --- a/pkg/registry/rbac/role/policybased/storage.go +++ b/pkg/registry/rbac/role/policybased/storage.go @@ -52,7 +52,7 @@ func (s *Storage) Create(ctx context.Context, obj runtime.Object, createValidati role := obj.(*rbac.Role) rules := role.Rules - if err := rbacregistryvalidation.ConfirmNoEscalation(ctx, s.ruleResolver, rules); err != nil { + if err := rbacregistryvalidation.ConfirmNoEscalationInternal(ctx, s.ruleResolver, rules); err != nil { return nil, errors.NewForbidden(groupResource, role.Name, err) } return s.StandardStorage.Create(ctx, obj, createValidation, includeUninitialized) @@ -72,7 +72,7 @@ func (s *Storage) Update(ctx context.Context, name string, obj rest.UpdatedObjec } rules := role.Rules - if err := rbacregistryvalidation.ConfirmNoEscalation(ctx, s.ruleResolver, rules); err != nil { + if err := rbacregistryvalidation.ConfirmNoEscalationInternal(ctx, s.ruleResolver, rules); err != nil { return nil, errors.NewForbidden(groupResource, role.Name, err) } return obj, nil diff --git a/pkg/registry/rbac/role/registry.go b/pkg/registry/rbac/role/registry.go index 6f026b0164..30626acf4e 100644 --- a/pkg/registry/rbac/role/registry.go +++ b/pkg/registry/rbac/role/registry.go @@ -19,27 +19,22 @@ package role import ( "context" - metainternalversion "k8s.io/apimachinery/pkg/apis/meta/internalversion" + rbacv1 "k8s.io/api/rbac/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/watch" genericapirequest "k8s.io/apiserver/pkg/endpoints/request" "k8s.io/apiserver/pkg/registry/rest" "k8s.io/kubernetes/pkg/apis/rbac" + rbacv1helpers "k8s.io/kubernetes/pkg/apis/rbac/v1" ) // Registry is an interface for things that know how to store Roles. type Registry interface { - ListRoles(ctx context.Context, options *metainternalversion.ListOptions) (*rbac.RoleList, error) - CreateRole(ctx context.Context, role *rbac.Role, createValidation rest.ValidateObjectFunc) error - UpdateRole(ctx context.Context, role *rbac.Role, createValidation rest.ValidateObjectFunc, updateValidation rest.ValidateObjectUpdateFunc) error - GetRole(ctx context.Context, name string, options *metav1.GetOptions) (*rbac.Role, error) - DeleteRole(ctx context.Context, name string) error - WatchRoles(ctx context.Context, options *metainternalversion.ListOptions) (watch.Interface, error) + GetRole(ctx context.Context, name string, options *metav1.GetOptions) (*rbacv1.Role, error) } // storage puts strong typing around storage calls type storage struct { - rest.StandardStorage + rest.Getter } // NewRegistry returns a new Registry interface for the given Storage. Any mismatched @@ -48,41 +43,17 @@ func NewRegistry(s rest.StandardStorage) Registry { return &storage{s} } -func (s *storage) ListRoles(ctx context.Context, options *metainternalversion.ListOptions) (*rbac.RoleList, error) { - obj, err := s.List(ctx, options) - if err != nil { - return nil, err - } - - return obj.(*rbac.RoleList), nil -} - -func (s *storage) CreateRole(ctx context.Context, role *rbac.Role, createValidation rest.ValidateObjectFunc) error { - _, err := s.Create(ctx, role, createValidation, false) - return err -} - -func (s *storage) UpdateRole(ctx context.Context, role *rbac.Role, createValidation rest.ValidateObjectFunc, updateValidation rest.ValidateObjectUpdateFunc) error { - // TODO: any admission? - _, _, err := s.Update(ctx, role.Name, rest.DefaultUpdatedObjectInfo(role), createValidation, updateValidation) - return err -} - -func (s *storage) WatchRoles(ctx context.Context, options *metainternalversion.ListOptions) (watch.Interface, error) { - return s.Watch(ctx, options) -} - -func (s *storage) GetRole(ctx context.Context, name string, options *metav1.GetOptions) (*rbac.Role, error) { +func (s *storage) GetRole(ctx context.Context, name string, options *metav1.GetOptions) (*rbacv1.Role, error) { obj, err := s.Get(ctx, name, options) if err != nil { return nil, err } - return obj.(*rbac.Role), nil -} -func (s *storage) DeleteRole(ctx context.Context, name string) error { - _, _, err := s.Delete(ctx, name, nil) - return err + ret := &rbacv1.Role{} + if err := rbacv1helpers.Convert_rbac_Role_To_v1_Role(obj.(*rbac.Role), ret, nil); err != nil { + return nil, err + } + return ret, nil } // AuthorizerAdapter adapts the registry to the authorizer interface @@ -90,6 +61,6 @@ type AuthorizerAdapter struct { Registry Registry } -func (a AuthorizerAdapter) GetRole(namespace, name string) (*rbac.Role, error) { +func (a AuthorizerAdapter) GetRole(namespace, name string) (*rbacv1.Role, error) { return a.Registry.GetRole(genericapirequest.WithNamespace(genericapirequest.NewContext(), namespace), name, &metav1.GetOptions{}) } diff --git a/pkg/registry/rbac/rolebinding/BUILD b/pkg/registry/rbac/rolebinding/BUILD index e307253113..63ad286997 100644 --- a/pkg/registry/rbac/rolebinding/BUILD +++ b/pkg/registry/rbac/rolebinding/BUILD @@ -16,12 +16,12 @@ go_library( deps = [ "//pkg/api/legacyscheme:go_default_library", "//pkg/apis/rbac:go_default_library", + "//pkg/apis/rbac/v1:go_default_library", "//pkg/apis/rbac/validation:go_default_library", + "//vendor/k8s.io/api/rbac/v1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/apis/meta/internalversion:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/validation/field:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/watch:go_default_library", "//vendor/k8s.io/apiserver/pkg/endpoints/request:go_default_library", "//vendor/k8s.io/apiserver/pkg/registry/rest:go_default_library", "//vendor/k8s.io/apiserver/pkg/storage/names:go_default_library", diff --git a/pkg/registry/rbac/rolebinding/policybased/BUILD b/pkg/registry/rbac/rolebinding/policybased/BUILD index fd05f21b46..eaca045436 100644 --- a/pkg/registry/rbac/rolebinding/policybased/BUILD +++ b/pkg/registry/rbac/rolebinding/policybased/BUILD @@ -12,8 +12,10 @@ go_library( deps = [ "//pkg/apis/core/helper:go_default_library", "//pkg/apis/rbac:go_default_library", + "//pkg/apis/rbac/v1:go_default_library", "//pkg/registry/rbac:go_default_library", "//pkg/registry/rbac/validation:go_default_library", + "//vendor/k8s.io/api/rbac/v1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/api/errors:go_default_library", "//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library", "//vendor/k8s.io/apiserver/pkg/authorization/authorizer:go_default_library", diff --git a/pkg/registry/rbac/rolebinding/policybased/storage.go b/pkg/registry/rbac/rolebinding/policybased/storage.go index 5adc0003bd..b71821c0c2 100644 --- a/pkg/registry/rbac/rolebinding/policybased/storage.go +++ b/pkg/registry/rbac/rolebinding/policybased/storage.go @@ -20,6 +20,7 @@ package policybased import ( "context" + rbacv1 "k8s.io/api/rbac/v1" "k8s.io/apimachinery/pkg/api/errors" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apiserver/pkg/authorization/authorizer" @@ -27,6 +28,7 @@ import ( "k8s.io/apiserver/pkg/registry/rest" kapihelper "k8s.io/kubernetes/pkg/apis/core/helper" "k8s.io/kubernetes/pkg/apis/rbac" + rbacv1helpers "k8s.io/kubernetes/pkg/apis/rbac/v1" rbacregistry "k8s.io/kubernetes/pkg/registry/rbac" rbacregistryvalidation "k8s.io/kubernetes/pkg/registry/rbac/validation" ) @@ -66,7 +68,12 @@ func (s *Storage) Create(ctx context.Context, obj runtime.Object, createValidati return s.StandardStorage.Create(ctx, obj, createValidation, includeUninitialized) } - rules, err := s.ruleResolver.GetRoleReferenceRules(roleBinding.RoleRef, namespace) + v1RoleRef := rbacv1.RoleRef{} + err := rbacv1helpers.Convert_rbac_RoleRef_To_v1_RoleRef(&roleBinding.RoleRef, &v1RoleRef, nil) + if err != nil { + return nil, err + } + rules, err := s.ruleResolver.GetRoleReferenceRules(v1RoleRef, namespace) if err != nil { return nil, err } @@ -102,7 +109,12 @@ func (s *Storage) Update(ctx context.Context, name string, obj rest.UpdatedObjec } // Otherwise, see if we already have all the permissions contained in the referenced role - rules, err := s.ruleResolver.GetRoleReferenceRules(roleBinding.RoleRef, namespace) + v1RoleRef := rbacv1.RoleRef{} + err := rbacv1helpers.Convert_rbac_RoleRef_To_v1_RoleRef(&roleBinding.RoleRef, &v1RoleRef, nil) + if err != nil { + return nil, err + } + rules, err := s.ruleResolver.GetRoleReferenceRules(v1RoleRef, namespace) if err != nil { return nil, err } diff --git a/pkg/registry/rbac/rolebinding/registry.go b/pkg/registry/rbac/rolebinding/registry.go index cd0fc2c746..af78c1a499 100644 --- a/pkg/registry/rbac/rolebinding/registry.go +++ b/pkg/registry/rbac/rolebinding/registry.go @@ -19,27 +19,22 @@ package rolebinding import ( "context" + rbacv1 "k8s.io/api/rbac/v1" metainternalversion "k8s.io/apimachinery/pkg/apis/meta/internalversion" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/watch" genericapirequest "k8s.io/apiserver/pkg/endpoints/request" "k8s.io/apiserver/pkg/registry/rest" "k8s.io/kubernetes/pkg/apis/rbac" + rbacv1helpers "k8s.io/kubernetes/pkg/apis/rbac/v1" ) // Registry is an interface for things that know how to store RoleBindings. type Registry interface { - ListRoleBindings(ctx context.Context, options *metainternalversion.ListOptions) (*rbac.RoleBindingList, error) - CreateRoleBinding(ctx context.Context, roleBinding *rbac.RoleBinding, createValidation rest.ValidateObjectFunc) error - UpdateRoleBinding(ctx context.Context, roleBinding *rbac.RoleBinding, createValidation rest.ValidateObjectFunc, updateValidation rest.ValidateObjectUpdateFunc) error - GetRoleBinding(ctx context.Context, name string, options *metav1.GetOptions) (*rbac.RoleBinding, error) - DeleteRoleBinding(ctx context.Context, name string) error - WatchRoleBindings(ctx context.Context, options *metainternalversion.ListOptions) (watch.Interface, error) + ListRoleBindings(ctx context.Context, options *metainternalversion.ListOptions) (*rbacv1.RoleBindingList, error) } // storage puts strong typing around storage calls type storage struct { - rest.StandardStorage + rest.Lister } // NewRegistry returns a new Registry interface for the given Storage. Any mismatched @@ -48,41 +43,17 @@ func NewRegistry(s rest.StandardStorage) Registry { return &storage{s} } -func (s *storage) ListRoleBindings(ctx context.Context, options *metainternalversion.ListOptions) (*rbac.RoleBindingList, error) { +func (s *storage) ListRoleBindings(ctx context.Context, options *metainternalversion.ListOptions) (*rbacv1.RoleBindingList, error) { obj, err := s.List(ctx, options) if err != nil { return nil, err } - return obj.(*rbac.RoleBindingList), nil -} - -func (s *storage) CreateRoleBinding(ctx context.Context, roleBinding *rbac.RoleBinding, createValidation rest.ValidateObjectFunc) error { - // TODO(ericchiang): add additional validation - _, err := s.Create(ctx, roleBinding, createValidation, false) - return err -} - -func (s *storage) UpdateRoleBinding(ctx context.Context, roleBinding *rbac.RoleBinding, createValidation rest.ValidateObjectFunc, updateValidation rest.ValidateObjectUpdateFunc) error { - _, _, err := s.Update(ctx, roleBinding.Name, rest.DefaultUpdatedObjectInfo(roleBinding), createValidation, updateValidation) - return err -} - -func (s *storage) WatchRoleBindings(ctx context.Context, options *metainternalversion.ListOptions) (watch.Interface, error) { - return s.Watch(ctx, options) -} - -func (s *storage) GetRoleBinding(ctx context.Context, name string, options *metav1.GetOptions) (*rbac.RoleBinding, error) { - obj, err := s.Get(ctx, name, options) - if err != nil { + ret := &rbacv1.RoleBindingList{} + if err := rbacv1helpers.Convert_rbac_RoleBindingList_To_v1_RoleBindingList(obj.(*rbac.RoleBindingList), ret, nil); err != nil { return nil, err } - return obj.(*rbac.RoleBinding), nil -} - -func (s *storage) DeleteRoleBinding(ctx context.Context, name string) error { - _, _, err := s.Delete(ctx, name, nil) - return err + return ret, nil } // AuthorizerAdapter adapts the registry to the authorizer interface @@ -90,13 +61,13 @@ type AuthorizerAdapter struct { Registry Registry } -func (a AuthorizerAdapter) ListRoleBindings(namespace string) ([]*rbac.RoleBinding, error) { +func (a AuthorizerAdapter) ListRoleBindings(namespace string) ([]*rbacv1.RoleBinding, error) { list, err := a.Registry.ListRoleBindings(genericapirequest.WithNamespace(genericapirequest.NewContext(), namespace), &metainternalversion.ListOptions{}) if err != nil { return nil, err } - ret := []*rbac.RoleBinding{} + ret := []*rbacv1.RoleBinding{} for i := range list.Items { ret = append(ret, &list.Items[i]) } diff --git a/pkg/registry/rbac/validation/BUILD b/pkg/registry/rbac/validation/BUILD index ddfb6431fb..152ae0387e 100644 --- a/pkg/registry/rbac/validation/BUILD +++ b/pkg/registry/rbac/validation/BUILD @@ -15,7 +15,8 @@ go_test( ], embed = [":go_default_library"], deps = [ - "//pkg/apis/rbac:go_default_library", + "//pkg/apis/rbac/v1:go_default_library", + "//vendor/k8s.io/api/rbac/v1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/diff:go_default_library", "//vendor/k8s.io/apiserver/pkg/authentication/user:go_default_library", @@ -25,6 +26,7 @@ go_test( go_library( name = "go_default_library", srcs = [ + "internal_version_adapter.go", "policy_compact.go", "policy_comparator.go", "rule.go", @@ -32,7 +34,9 @@ go_library( importpath = "k8s.io/kubernetes/pkg/registry/rbac/validation", deps = [ "//pkg/apis/rbac:go_default_library", + "//pkg/apis/rbac/v1:go_default_library", "//vendor/github.com/golang/glog:go_default_library", + "//vendor/k8s.io/api/rbac/v1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/api/errors:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/errors:go_default_library", "//vendor/k8s.io/apiserver/pkg/authentication/serviceaccount:go_default_library", diff --git a/pkg/registry/rbac/validation/internal_version_adapter.go b/pkg/registry/rbac/validation/internal_version_adapter.go new file mode 100644 index 0000000000..bfb57242df --- /dev/null +++ b/pkg/registry/rbac/validation/internal_version_adapter.go @@ -0,0 +1,39 @@ +/* +Copyright 2018 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 validation + +import ( + "context" + + rbacv1 "k8s.io/api/rbac/v1" + "k8s.io/kubernetes/pkg/apis/rbac" + rbacv1helpers "k8s.io/kubernetes/pkg/apis/rbac/v1" +) + +func ConfirmNoEscalationInternal(ctx context.Context, ruleResolver AuthorizationRuleResolver, inRules []rbac.PolicyRule) error { + rules := []rbacv1.PolicyRule{} + for i := range inRules { + v1Rule := rbacv1.PolicyRule{} + err := rbacv1helpers.Convert_rbac_PolicyRule_To_v1_PolicyRule(&inRules[i], &v1Rule, nil) + if err != nil { + return err + } + rules = append(rules, v1Rule) + } + + return ConfirmNoEscalation(ctx, ruleResolver, rules) +} diff --git a/pkg/registry/rbac/validation/policy_compact.go b/pkg/registry/rbac/validation/policy_compact.go index 303bbc7a07..182657b1ca 100644 --- a/pkg/registry/rbac/validation/policy_compact.go +++ b/pkg/registry/rbac/validation/policy_compact.go @@ -19,7 +19,7 @@ package validation import ( "reflect" - "k8s.io/kubernetes/pkg/apis/rbac" + rbacv1 "k8s.io/api/rbac/v1" ) type simpleResource struct { @@ -31,10 +31,10 @@ type simpleResource struct { // CompactRules combines rules that contain a single APIGroup/Resource, differ only by verb, and contain no other attributes. // this is a fast check, and works well with the decomposed "missing rules" list from a Covers check. -func CompactRules(rules []rbac.PolicyRule) ([]rbac.PolicyRule, error) { - compacted := make([]rbac.PolicyRule, 0, len(rules)) +func CompactRules(rules []rbacv1.PolicyRule) ([]rbacv1.PolicyRule, error) { + compacted := make([]rbacv1.PolicyRule, 0, len(rules)) - simpleRules := map[simpleResource]*rbac.PolicyRule{} + simpleRules := map[simpleResource]*rbacv1.PolicyRule{} for _, rule := range rules { if resource, isSimple := isSimpleResourceRule(&rule); isSimple { if existingRule, ok := simpleRules[resource]; ok { @@ -61,7 +61,7 @@ func CompactRules(rules []rbac.PolicyRule) ([]rbac.PolicyRule, error) { } // isSimpleResourceRule returns true if the given rule contains verbs, a single resource, a single API group, at most one Resource Name, and no other values -func isSimpleResourceRule(rule *rbac.PolicyRule) (simpleResource, bool) { +func isSimpleResourceRule(rule *rbacv1.PolicyRule) (simpleResource, bool) { resource := simpleResource{} // If we have "complex" rule attributes, return early without allocations or expensive comparisons @@ -74,7 +74,7 @@ func isSimpleResourceRule(rule *rbac.PolicyRule) (simpleResource, bool) { } // Test if this rule only contains APIGroups/Resources/Verbs/ResourceNames - simpleRule := &rbac.PolicyRule{APIGroups: rule.APIGroups, Resources: rule.Resources, Verbs: rule.Verbs, ResourceNames: rule.ResourceNames} + simpleRule := &rbacv1.PolicyRule{APIGroups: rule.APIGroups, Resources: rule.Resources, Verbs: rule.Verbs, ResourceNames: rule.ResourceNames} if !reflect.DeepEqual(simpleRule, rule) { return resource, false } diff --git a/pkg/registry/rbac/validation/policy_compact_test.go b/pkg/registry/rbac/validation/policy_compact_test.go index 2149261321..4444657be7 100644 --- a/pkg/registry/rbac/validation/policy_compact_test.go +++ b/pkg/registry/rbac/validation/policy_compact_test.go @@ -21,20 +21,21 @@ import ( "sort" "testing" - "k8s.io/kubernetes/pkg/apis/rbac" + rbacv1 "k8s.io/api/rbac/v1" + rbacv1helpers "k8s.io/kubernetes/pkg/apis/rbac/v1" ) func TestCompactRules(t *testing.T) { testcases := map[string]struct { - Rules []rbac.PolicyRule - Expected []rbac.PolicyRule + Rules []rbacv1.PolicyRule + Expected []rbacv1.PolicyRule }{ "empty": { - Rules: []rbac.PolicyRule{}, - Expected: []rbac.PolicyRule{}, + Rules: []rbacv1.PolicyRule{}, + Expected: []rbacv1.PolicyRule{}, }, "simple": { - Rules: []rbac.PolicyRule{ + Rules: []rbacv1.PolicyRule{ {Verbs: []string{"get"}, APIGroups: []string{""}, Resources: []string{"builds"}}, {Verbs: []string{"list"}, APIGroups: []string{""}, Resources: []string{"builds"}}, {Verbs: []string{"update", "patch"}, APIGroups: []string{""}, Resources: []string{"builds"}}, @@ -55,7 +56,7 @@ func TestCompactRules(t *testing.T) { {Verbs: nil, APIGroups: []string{""}, Resources: []string{"pods"}}, {Verbs: []string{"create"}, APIGroups: []string{""}, Resources: []string{"pods"}}, }, - Expected: []rbac.PolicyRule{ + Expected: []rbacv1.PolicyRule{ {Verbs: []string{"create", "delete"}, APIGroups: []string{"extensions"}, Resources: []string{"daemonsets"}}, {Verbs: []string{"patch"}, APIGroups: []string{"extensions"}, Resources: []string{"daemonsets"}, ResourceNames: []string{""}}, {Verbs: []string{"get", "list"}, APIGroups: []string{"extensions"}, Resources: []string{"daemonsets"}, ResourceNames: []string{"foo"}}, @@ -66,44 +67,44 @@ func TestCompactRules(t *testing.T) { }, }, "complex multi-group": { - Rules: []rbac.PolicyRule{ + Rules: []rbacv1.PolicyRule{ {Verbs: []string{"get"}, APIGroups: []string{"", "builds.openshift.io"}, Resources: []string{"builds"}}, {Verbs: []string{"list"}, APIGroups: []string{"", "builds.openshift.io"}, Resources: []string{"builds"}}, }, - Expected: []rbac.PolicyRule{ + Expected: []rbacv1.PolicyRule{ {Verbs: []string{"get"}, APIGroups: []string{"", "builds.openshift.io"}, Resources: []string{"builds"}}, {Verbs: []string{"list"}, APIGroups: []string{"", "builds.openshift.io"}, Resources: []string{"builds"}}, }, }, "complex multi-resource": { - Rules: []rbac.PolicyRule{ + Rules: []rbacv1.PolicyRule{ {Verbs: []string{"get"}, APIGroups: []string{""}, Resources: []string{"builds", "images"}}, {Verbs: []string{"list"}, APIGroups: []string{""}, Resources: []string{"builds", "images"}}, }, - Expected: []rbac.PolicyRule{ + Expected: []rbacv1.PolicyRule{ {Verbs: []string{"get"}, APIGroups: []string{""}, Resources: []string{"builds", "images"}}, {Verbs: []string{"list"}, APIGroups: []string{""}, Resources: []string{"builds", "images"}}, }, }, "complex named-resource": { - Rules: []rbac.PolicyRule{ + Rules: []rbacv1.PolicyRule{ {Verbs: []string{"get"}, APIGroups: []string{""}, Resources: []string{"builds"}, ResourceNames: []string{"mybuild"}}, {Verbs: []string{"list"}, APIGroups: []string{""}, Resources: []string{"builds"}, ResourceNames: []string{"mybuild2"}}, }, - Expected: []rbac.PolicyRule{ + Expected: []rbacv1.PolicyRule{ {Verbs: []string{"get"}, APIGroups: []string{""}, Resources: []string{"builds"}, ResourceNames: []string{"mybuild"}}, {Verbs: []string{"list"}, APIGroups: []string{""}, Resources: []string{"builds"}, ResourceNames: []string{"mybuild2"}}, }, }, "complex non-resource": { - Rules: []rbac.PolicyRule{ + Rules: []rbacv1.PolicyRule{ {Verbs: []string{"get"}, APIGroups: []string{""}, Resources: []string{"builds"}, NonResourceURLs: []string{"/"}}, {Verbs: []string{"get"}, APIGroups: []string{""}, Resources: []string{"builds"}, NonResourceURLs: []string{"/foo"}}, }, - Expected: []rbac.PolicyRule{ + Expected: []rbacv1.PolicyRule{ {Verbs: []string{"get"}, APIGroups: []string{""}, Resources: []string{"builds"}, NonResourceURLs: []string{"/"}}, {Verbs: []string{"get"}, APIGroups: []string{""}, Resources: []string{"builds"}, NonResourceURLs: []string{"/foo"}}, }, @@ -112,7 +113,7 @@ func TestCompactRules(t *testing.T) { for k, tc := range testcases { rules := tc.Rules - originalRules := make([]rbac.PolicyRule, len(tc.Rules)) + originalRules := make([]rbacv1.PolicyRule, len(tc.Rules)) for i := range tc.Rules { originalRules[i] = *tc.Rules[i].DeepCopy() } @@ -134,8 +135,8 @@ func TestCompactRules(t *testing.T) { continue } - sort.Stable(rbac.SortableRuleSlice(compacted)) - sort.Stable(rbac.SortableRuleSlice(tc.Expected)) + sort.Stable(rbacv1helpers.SortableRuleSlice(compacted)) + sort.Stable(rbacv1helpers.SortableRuleSlice(tc.Expected)) if !reflect.DeepEqual(compacted, tc.Expected) { t.Errorf("%s: Expected\n%#v\ngot\n%#v", k, tc.Expected, compacted) continue @@ -145,68 +146,68 @@ func TestCompactRules(t *testing.T) { func TestIsSimpleResourceRule(t *testing.T) { testcases := map[string]struct { - Rule rbac.PolicyRule + Rule rbacv1.PolicyRule Simple bool Resource simpleResource }{ "simple, no verbs": { - Rule: rbac.PolicyRule{Verbs: []string{}, APIGroups: []string{""}, Resources: []string{"builds"}}, + Rule: rbacv1.PolicyRule{Verbs: []string{}, APIGroups: []string{""}, Resources: []string{"builds"}}, Simple: true, Resource: simpleResource{Group: "", Resource: "builds"}, }, "simple, one verb": { - Rule: rbac.PolicyRule{Verbs: []string{"get"}, APIGroups: []string{""}, Resources: []string{"builds"}}, + Rule: rbacv1.PolicyRule{Verbs: []string{"get"}, APIGroups: []string{""}, Resources: []string{"builds"}}, Simple: true, Resource: simpleResource{Group: "", Resource: "builds"}, }, "simple, one empty resource name": { - Rule: rbac.PolicyRule{Verbs: []string{"get"}, APIGroups: []string{""}, Resources: []string{"builds"}, ResourceNames: []string{""}}, + Rule: rbacv1.PolicyRule{Verbs: []string{"get"}, APIGroups: []string{""}, Resources: []string{"builds"}, ResourceNames: []string{""}}, Simple: true, Resource: simpleResource{Group: "", Resource: "builds", ResourceNameExist: true, ResourceName: ""}, }, "simple, one resource name": { - Rule: rbac.PolicyRule{Verbs: []string{"get"}, APIGroups: []string{""}, Resources: []string{"builds"}, ResourceNames: []string{"foo"}}, + Rule: rbacv1.PolicyRule{Verbs: []string{"get"}, APIGroups: []string{""}, Resources: []string{"builds"}, ResourceNames: []string{"foo"}}, Simple: true, Resource: simpleResource{Group: "", Resource: "builds", ResourceNameExist: true, ResourceName: "foo"}, }, "simple, multi verb": { - Rule: rbac.PolicyRule{Verbs: []string{"get", "list"}, APIGroups: []string{""}, Resources: []string{"builds"}}, + Rule: rbacv1.PolicyRule{Verbs: []string{"get", "list"}, APIGroups: []string{""}, Resources: []string{"builds"}}, Simple: true, Resource: simpleResource{Group: "", Resource: "builds"}, }, "complex, empty": { - Rule: rbac.PolicyRule{}, + Rule: rbacv1.PolicyRule{}, Simple: false, Resource: simpleResource{}, }, "complex, no group": { - Rule: rbac.PolicyRule{Verbs: []string{"get"}, APIGroups: []string{}, Resources: []string{"builds"}}, + Rule: rbacv1.PolicyRule{Verbs: []string{"get"}, APIGroups: []string{}, Resources: []string{"builds"}}, Simple: false, Resource: simpleResource{}, }, "complex, multi group": { - Rule: rbac.PolicyRule{Verbs: []string{"get"}, APIGroups: []string{"a", "b"}, Resources: []string{"builds"}}, + Rule: rbacv1.PolicyRule{Verbs: []string{"get"}, APIGroups: []string{"a", "b"}, Resources: []string{"builds"}}, Simple: false, Resource: simpleResource{}, }, "complex, no resource": { - Rule: rbac.PolicyRule{Verbs: []string{"get"}, APIGroups: []string{""}, Resources: []string{}}, + Rule: rbacv1.PolicyRule{Verbs: []string{"get"}, APIGroups: []string{""}, Resources: []string{}}, Simple: false, Resource: simpleResource{}, }, "complex, multi resource": { - Rule: rbac.PolicyRule{Verbs: []string{"get"}, APIGroups: []string{""}, Resources: []string{"builds", "images"}}, + Rule: rbacv1.PolicyRule{Verbs: []string{"get"}, APIGroups: []string{""}, Resources: []string{"builds", "images"}}, Simple: false, Resource: simpleResource{}, }, "complex, resource names": { - Rule: rbac.PolicyRule{Verbs: []string{"get"}, APIGroups: []string{""}, Resources: []string{"builds"}, ResourceNames: []string{"foo", "bar"}}, + Rule: rbacv1.PolicyRule{Verbs: []string{"get"}, APIGroups: []string{""}, Resources: []string{"builds"}, ResourceNames: []string{"foo", "bar"}}, Simple: false, Resource: simpleResource{}, }, "complex, non-resource urls": { - Rule: rbac.PolicyRule{Verbs: []string{"get"}, APIGroups: []string{""}, Resources: []string{"builds"}, NonResourceURLs: []string{"/"}}, + Rule: rbacv1.PolicyRule{Verbs: []string{"get"}, APIGroups: []string{""}, Resources: []string{"builds"}, NonResourceURLs: []string{"/"}}, Simple: false, Resource: simpleResource{}, }, diff --git a/pkg/registry/rbac/validation/policy_comparator.go b/pkg/registry/rbac/validation/policy_comparator.go index 4b2ba51581..7a0268b5e9 100644 --- a/pkg/registry/rbac/validation/policy_comparator.go +++ b/pkg/registry/rbac/validation/policy_comparator.go @@ -19,23 +19,23 @@ package validation import ( "strings" - "k8s.io/kubernetes/pkg/apis/rbac" + rbacv1 "k8s.io/api/rbac/v1" ) // Covers determines whether or not the ownerRules cover the servantRules in terms of allowed actions. // It returns whether or not the ownerRules cover and a list of the rules that the ownerRules do not cover. -func Covers(ownerRules, servantRules []rbac.PolicyRule) (bool, []rbac.PolicyRule) { +func Covers(ownerRules, servantRules []rbacv1.PolicyRule) (bool, []rbacv1.PolicyRule) { // 1. Break every servantRule into individual rule tuples: group, verb, resource, resourceName // 2. Compare the mini-rules against each owner rule. Because the breakdown is down to the most atomic level, we're guaranteed that each mini-servant rule will be either fully covered or not covered by a single owner rule // 3. Any left over mini-rules means that we are not covered and we have a nice list of them. // TODO: it might be nice to collapse the list down into something more human readable - subrules := []rbac.PolicyRule{} + subrules := []rbacv1.PolicyRule{} for _, servantRule := range servantRules { subrules = append(subrules, BreakdownRule(servantRule)...) } - uncoveredRules := []rbac.PolicyRule{} + uncoveredRules := []rbacv1.PolicyRule{} for _, subrule := range subrules { covered := false for _, ownerRule := range ownerRules { @@ -55,18 +55,18 @@ func Covers(ownerRules, servantRules []rbac.PolicyRule) (bool, []rbac.PolicyRule // BreadownRule takes a rule and builds an equivalent list of rules that each have at most one verb, one // resource, and one resource name -func BreakdownRule(rule rbac.PolicyRule) []rbac.PolicyRule { - subrules := []rbac.PolicyRule{} +func BreakdownRule(rule rbacv1.PolicyRule) []rbacv1.PolicyRule { + subrules := []rbacv1.PolicyRule{} for _, group := range rule.APIGroups { for _, resource := range rule.Resources { for _, verb := range rule.Verbs { if len(rule.ResourceNames) > 0 { for _, resourceName := range rule.ResourceNames { - subrules = append(subrules, rbac.PolicyRule{APIGroups: []string{group}, Resources: []string{resource}, Verbs: []string{verb}, ResourceNames: []string{resourceName}}) + subrules = append(subrules, rbacv1.PolicyRule{APIGroups: []string{group}, Resources: []string{resource}, Verbs: []string{verb}, ResourceNames: []string{resourceName}}) } } else { - subrules = append(subrules, rbac.PolicyRule{APIGroups: []string{group}, Resources: []string{resource}, Verbs: []string{verb}}) + subrules = append(subrules, rbacv1.PolicyRule{APIGroups: []string{group}, Resources: []string{resource}, Verbs: []string{verb}}) } } @@ -76,7 +76,7 @@ func BreakdownRule(rule rbac.PolicyRule) []rbac.PolicyRule { // Non-resource URLs are unique because they only combine with verbs. for _, nonResourceURL := range rule.NonResourceURLs { for _, verb := range rule.Verbs { - subrules = append(subrules, rbac.PolicyRule{NonResourceURLs: []string{nonResourceURL}, Verbs: []string{verb}}) + subrules = append(subrules, rbacv1.PolicyRule{NonResourceURLs: []string{nonResourceURL}, Verbs: []string{verb}}) } } @@ -107,7 +107,7 @@ func hasAll(set, contains []string) bool { func resourceCoversAll(setResources, coversResources []string) bool { // if we have a star or an exact match on all resources, then we match - if has(setResources, rbac.ResourceAll) || hasAll(setResources, coversResources) { + if has(setResources, rbacv1.ResourceAll) || hasAll(setResources, coversResources) { return true } @@ -155,9 +155,9 @@ func nonResourceURLCovers(ownerPath, subPath string) bool { // ruleCovers determines whether the ownerRule (which may have multiple verbs, resources, and resourceNames) covers // the subrule (which may only contain at most one verb, resource, and resourceName) -func ruleCovers(ownerRule, subRule rbac.PolicyRule) bool { - verbMatches := has(ownerRule.Verbs, rbac.VerbAll) || hasAll(ownerRule.Verbs, subRule.Verbs) - groupMatches := has(ownerRule.APIGroups, rbac.APIGroupAll) || hasAll(ownerRule.APIGroups, subRule.APIGroups) +func ruleCovers(ownerRule, subRule rbacv1.PolicyRule) bool { + verbMatches := has(ownerRule.Verbs, rbacv1.VerbAll) || hasAll(ownerRule.Verbs, subRule.Verbs) + groupMatches := has(ownerRule.APIGroups, rbacv1.APIGroupAll) || hasAll(ownerRule.APIGroups, subRule.APIGroups) resourceMatches := resourceCoversAll(ownerRule.Resources, subRule.Resources) nonResourceURLMatches := nonResourceURLsCoversAll(ownerRule.NonResourceURLs, subRule.NonResourceURLs) diff --git a/pkg/registry/rbac/validation/policy_comparator_test.go b/pkg/registry/rbac/validation/policy_comparator_test.go index b8b947f72e..e983c2abcf 100644 --- a/pkg/registry/rbac/validation/policy_comparator_test.go +++ b/pkg/registry/rbac/validation/policy_comparator_test.go @@ -20,65 +20,65 @@ import ( "reflect" "testing" - "k8s.io/kubernetes/pkg/apis/rbac" + rbacv1 "k8s.io/api/rbac/v1" ) type escalationTest struct { - ownerRules []rbac.PolicyRule - servantRules []rbac.PolicyRule + ownerRules []rbacv1.PolicyRule + servantRules []rbacv1.PolicyRule expectedCovered bool - expectedUncoveredRules []rbac.PolicyRule + expectedUncoveredRules []rbacv1.PolicyRule } func TestCoversExactMatch(t *testing.T) { escalationTest{ - ownerRules: []rbac.PolicyRule{ + ownerRules: []rbacv1.PolicyRule{ {APIGroups: []string{"v1"}, Verbs: []string{"get"}, Resources: []string{"builds"}}, }, - servantRules: []rbac.PolicyRule{ + servantRules: []rbacv1.PolicyRule{ {APIGroups: []string{"v1"}, Verbs: []string{"get"}, Resources: []string{"builds"}}, }, expectedCovered: true, - expectedUncoveredRules: []rbac.PolicyRule{}, + expectedUncoveredRules: []rbacv1.PolicyRule{}, }.test(t) } func TestCoversSubresourceWildcard(t *testing.T) { escalationTest{ - ownerRules: []rbac.PolicyRule{ + ownerRules: []rbacv1.PolicyRule{ {APIGroups: []string{"v1"}, Verbs: []string{"get"}, Resources: []string{"*/scale"}}, }, - servantRules: []rbac.PolicyRule{ + servantRules: []rbacv1.PolicyRule{ {APIGroups: []string{"v1"}, Verbs: []string{"get"}, Resources: []string{"foo/scale"}}, }, expectedCovered: true, - expectedUncoveredRules: []rbac.PolicyRule{}, + expectedUncoveredRules: []rbacv1.PolicyRule{}, }.test(t) } func TestCoversMultipleRulesCoveringSingleRule(t *testing.T) { escalationTest{ - ownerRules: []rbac.PolicyRule{ + ownerRules: []rbacv1.PolicyRule{ {APIGroups: []string{"v1"}, Verbs: []string{"delete"}, Resources: []string{"deployments"}}, {APIGroups: []string{"v1"}, Verbs: []string{"delete"}, Resources: []string{"builds"}}, {APIGroups: []string{"v1"}, Verbs: []string{"update"}, Resources: []string{"builds", "deployments"}}, }, - servantRules: []rbac.PolicyRule{ + servantRules: []rbacv1.PolicyRule{ {APIGroups: []string{"v1"}, Verbs: []string{"delete", "update"}, Resources: []string{"builds", "deployments"}}, }, expectedCovered: true, - expectedUncoveredRules: []rbac.PolicyRule{}, + expectedUncoveredRules: []rbacv1.PolicyRule{}, }.test(t) } func TestCoversMultipleAPIGroupsCoveringSingleRule(t *testing.T) { escalationTest{ - ownerRules: []rbac.PolicyRule{ + ownerRules: []rbacv1.PolicyRule{ {APIGroups: []string{"group1"}, Verbs: []string{"delete"}, Resources: []string{"deployments"}}, {APIGroups: []string{"group1"}, Verbs: []string{"delete"}, Resources: []string{"builds"}}, {APIGroups: []string{"group1"}, Verbs: []string{"update"}, Resources: []string{"builds", "deployments"}}, @@ -86,22 +86,22 @@ func TestCoversMultipleAPIGroupsCoveringSingleRule(t *testing.T) { {APIGroups: []string{"group2"}, Verbs: []string{"delete"}, Resources: []string{"builds"}}, {APIGroups: []string{"group2"}, Verbs: []string{"update"}, Resources: []string{"builds", "deployments"}}, }, - servantRules: []rbac.PolicyRule{ + servantRules: []rbacv1.PolicyRule{ {APIGroups: []string{"group1", "group2"}, Verbs: []string{"delete", "update"}, Resources: []string{"builds", "deployments"}}, }, expectedCovered: true, - expectedUncoveredRules: []rbac.PolicyRule{}, + expectedUncoveredRules: []rbacv1.PolicyRule{}, }.test(t) } func TestCoversSingleAPIGroupsCoveringMultiple(t *testing.T) { escalationTest{ - ownerRules: []rbac.PolicyRule{ + ownerRules: []rbacv1.PolicyRule{ {APIGroups: []string{"group1", "group2"}, Verbs: []string{"delete", "update"}, Resources: []string{"builds", "deployments"}}, }, - servantRules: []rbac.PolicyRule{ + servantRules: []rbacv1.PolicyRule{ {APIGroups: []string{"group1"}, Verbs: []string{"delete"}, Resources: []string{"deployments"}}, {APIGroups: []string{"group1"}, Verbs: []string{"delete"}, Resources: []string{"builds"}}, {APIGroups: []string{"group1"}, Verbs: []string{"update"}, Resources: []string{"builds", "deployments"}}, @@ -111,23 +111,23 @@ func TestCoversSingleAPIGroupsCoveringMultiple(t *testing.T) { }, expectedCovered: true, - expectedUncoveredRules: []rbac.PolicyRule{}, + expectedUncoveredRules: []rbacv1.PolicyRule{}, }.test(t) } func TestCoversMultipleRulesMissingSingleVerbResourceCombination(t *testing.T) { escalationTest{ - ownerRules: []rbac.PolicyRule{ + ownerRules: []rbacv1.PolicyRule{ {APIGroups: []string{"v1"}, Verbs: []string{"delete", "update"}, Resources: []string{"builds", "deployments"}}, {APIGroups: []string{"v1"}, Verbs: []string{"delete"}, Resources: []string{"pods"}}, }, - servantRules: []rbac.PolicyRule{ + servantRules: []rbacv1.PolicyRule{ {APIGroups: []string{"v1"}, Verbs: []string{"delete", "update"}, Resources: []string{"builds", "deployments", "pods"}}, }, expectedCovered: false, - expectedUncoveredRules: []rbac.PolicyRule{ + expectedUncoveredRules: []rbacv1.PolicyRule{ {APIGroups: []string{"v1"}, Verbs: []string{"update"}, Resources: []string{"pods"}}, }, }.test(t) @@ -135,29 +135,29 @@ func TestCoversMultipleRulesMissingSingleVerbResourceCombination(t *testing.T) { func TestCoversAPIGroupStarCoveringMultiple(t *testing.T) { escalationTest{ - ownerRules: []rbac.PolicyRule{ + ownerRules: []rbacv1.PolicyRule{ {APIGroups: []string{"*"}, Verbs: []string{"get"}, Resources: []string{"roles"}}, }, - servantRules: []rbac.PolicyRule{ + servantRules: []rbacv1.PolicyRule{ {APIGroups: []string{"group1", "group2"}, Verbs: []string{"get"}, Resources: []string{"roles"}}, }, expectedCovered: true, - expectedUncoveredRules: []rbac.PolicyRule{}, + expectedUncoveredRules: []rbacv1.PolicyRule{}, }.test(t) } func TestCoversEnumerationNotCoveringAPIGroupStar(t *testing.T) { escalationTest{ - ownerRules: []rbac.PolicyRule{ + ownerRules: []rbacv1.PolicyRule{ {APIGroups: []string{"dummy-group"}, Verbs: []string{"get"}, Resources: []string{"roles"}}, }, - servantRules: []rbac.PolicyRule{ + servantRules: []rbacv1.PolicyRule{ {APIGroups: []string{"*"}, Verbs: []string{"get"}, Resources: []string{"roles"}}, }, expectedCovered: false, - expectedUncoveredRules: []rbac.PolicyRule{ + expectedUncoveredRules: []rbacv1.PolicyRule{ {APIGroups: []string{"*"}, Verbs: []string{"get"}, Resources: []string{"roles"}}, }, }.test(t) @@ -165,43 +165,43 @@ func TestCoversEnumerationNotCoveringAPIGroupStar(t *testing.T) { func TestCoversAPIGroupStarCoveringStar(t *testing.T) { escalationTest{ - ownerRules: []rbac.PolicyRule{ + ownerRules: []rbacv1.PolicyRule{ {APIGroups: []string{"*"}, Verbs: []string{"get"}, Resources: []string{"roles"}}, }, - servantRules: []rbac.PolicyRule{ + servantRules: []rbacv1.PolicyRule{ {APIGroups: []string{"*"}, Verbs: []string{"get"}, Resources: []string{"roles"}}, }, expectedCovered: true, - expectedUncoveredRules: []rbac.PolicyRule{}, + expectedUncoveredRules: []rbacv1.PolicyRule{}, }.test(t) } func TestCoversVerbStarCoveringMultiple(t *testing.T) { escalationTest{ - ownerRules: []rbac.PolicyRule{ + ownerRules: []rbacv1.PolicyRule{ {APIGroups: []string{"v1"}, Verbs: []string{"*"}, Resources: []string{"roles"}}, }, - servantRules: []rbac.PolicyRule{ + servantRules: []rbacv1.PolicyRule{ {APIGroups: []string{"v1"}, Verbs: []string{"watch", "list"}, Resources: []string{"roles"}}, }, expectedCovered: true, - expectedUncoveredRules: []rbac.PolicyRule{}, + expectedUncoveredRules: []rbacv1.PolicyRule{}, }.test(t) } func TestCoversEnumerationNotCoveringVerbStar(t *testing.T) { escalationTest{ - ownerRules: []rbac.PolicyRule{ + ownerRules: []rbacv1.PolicyRule{ {APIGroups: []string{"v1"}, Verbs: []string{"get", "list", "watch", "create", "update", "delete", "exec"}, Resources: []string{"roles"}}, }, - servantRules: []rbac.PolicyRule{ + servantRules: []rbacv1.PolicyRule{ {APIGroups: []string{"v1"}, Verbs: []string{"*"}, Resources: []string{"roles"}}, }, expectedCovered: false, - expectedUncoveredRules: []rbac.PolicyRule{ + expectedUncoveredRules: []rbacv1.PolicyRule{ {APIGroups: []string{"v1"}, Verbs: []string{"*"}, Resources: []string{"roles"}}, }, }.test(t) @@ -209,43 +209,43 @@ func TestCoversEnumerationNotCoveringVerbStar(t *testing.T) { func TestCoversVerbStarCoveringStar(t *testing.T) { escalationTest{ - ownerRules: []rbac.PolicyRule{ + ownerRules: []rbacv1.PolicyRule{ {APIGroups: []string{"v1"}, Verbs: []string{"*"}, Resources: []string{"roles"}}, }, - servantRules: []rbac.PolicyRule{ + servantRules: []rbacv1.PolicyRule{ {APIGroups: []string{"v1"}, Verbs: []string{"*"}, Resources: []string{"roles"}}, }, expectedCovered: true, - expectedUncoveredRules: []rbac.PolicyRule{}, + expectedUncoveredRules: []rbacv1.PolicyRule{}, }.test(t) } func TestCoversResourceStarCoveringMultiple(t *testing.T) { escalationTest{ - ownerRules: []rbac.PolicyRule{ + ownerRules: []rbacv1.PolicyRule{ {APIGroups: []string{"v1"}, Verbs: []string{"get"}, Resources: []string{"*"}}, }, - servantRules: []rbac.PolicyRule{ + servantRules: []rbacv1.PolicyRule{ {APIGroups: []string{"v1"}, Verbs: []string{"get"}, Resources: []string{"resourcegroup:deployments"}}, }, expectedCovered: true, - expectedUncoveredRules: []rbac.PolicyRule{}, + expectedUncoveredRules: []rbacv1.PolicyRule{}, }.test(t) } func TestCoversEnumerationNotCoveringResourceStar(t *testing.T) { escalationTest{ - ownerRules: []rbac.PolicyRule{ + ownerRules: []rbacv1.PolicyRule{ {APIGroups: []string{"v1"}, Verbs: []string{"get"}, Resources: []string{"roles", "resourcegroup:deployments"}}, }, - servantRules: []rbac.PolicyRule{ + servantRules: []rbacv1.PolicyRule{ {APIGroups: []string{"v1"}, Verbs: []string{"get"}, Resources: []string{"*"}}, }, expectedCovered: false, - expectedUncoveredRules: []rbac.PolicyRule{ + expectedUncoveredRules: []rbacv1.PolicyRule{ {APIGroups: []string{"v1"}, Verbs: []string{"get"}, Resources: []string{"*"}}, }, }.test(t) @@ -253,43 +253,43 @@ func TestCoversEnumerationNotCoveringResourceStar(t *testing.T) { func TestCoversResourceStarCoveringStar(t *testing.T) { escalationTest{ - ownerRules: []rbac.PolicyRule{ + ownerRules: []rbacv1.PolicyRule{ {APIGroups: []string{"v1"}, Verbs: []string{"get"}, Resources: []string{"*"}}, }, - servantRules: []rbac.PolicyRule{ + servantRules: []rbacv1.PolicyRule{ {APIGroups: []string{"v1"}, Verbs: []string{"get"}, Resources: []string{"*"}}, }, expectedCovered: true, - expectedUncoveredRules: []rbac.PolicyRule{}, + expectedUncoveredRules: []rbacv1.PolicyRule{}, }.test(t) } func TestCoversResourceNameEmptyCoveringMultiple(t *testing.T) { escalationTest{ - ownerRules: []rbac.PolicyRule{ + ownerRules: []rbacv1.PolicyRule{ {APIGroups: []string{"v1"}, Verbs: []string{"get"}, Resources: []string{"pods"}, ResourceNames: []string{}}, }, - servantRules: []rbac.PolicyRule{ + servantRules: []rbacv1.PolicyRule{ {APIGroups: []string{"v1"}, Verbs: []string{"get"}, Resources: []string{"pods"}, ResourceNames: []string{"foo", "bar"}}, }, expectedCovered: true, - expectedUncoveredRules: []rbac.PolicyRule{}, + expectedUncoveredRules: []rbacv1.PolicyRule{}, }.test(t) } func TestCoversEnumerationNotCoveringResourceNameEmpty(t *testing.T) { escalationTest{ - ownerRules: []rbac.PolicyRule{ + ownerRules: []rbacv1.PolicyRule{ {APIGroups: []string{"v1"}, Verbs: []string{"get"}, Resources: []string{"pods"}, ResourceNames: []string{"foo", "bar"}}, }, - servantRules: []rbac.PolicyRule{ + servantRules: []rbacv1.PolicyRule{ {APIGroups: []string{"v1"}, Verbs: []string{"get"}, Resources: []string{"pods"}, ResourceNames: []string{}}, }, expectedCovered: false, - expectedUncoveredRules: []rbac.PolicyRule{ + expectedUncoveredRules: []rbacv1.PolicyRule{ {APIGroups: []string{"v1"}, Verbs: []string{"get"}, Resources: []string{"pods"}}, }, }.test(t) @@ -297,43 +297,43 @@ func TestCoversEnumerationNotCoveringResourceNameEmpty(t *testing.T) { func TestCoversNonResourceURLs(t *testing.T) { escalationTest{ - ownerRules: []rbac.PolicyRule{ + ownerRules: []rbacv1.PolicyRule{ {NonResourceURLs: []string{"/apis"}, Verbs: []string{"*"}}, }, - servantRules: []rbac.PolicyRule{ + servantRules: []rbacv1.PolicyRule{ {NonResourceURLs: []string{"/apis"}, Verbs: []string{"*"}}, }, expectedCovered: true, - expectedUncoveredRules: []rbac.PolicyRule{}, + expectedUncoveredRules: []rbacv1.PolicyRule{}, }.test(t) } func TestCoversNonResourceURLsStar(t *testing.T) { escalationTest{ - ownerRules: []rbac.PolicyRule{ + ownerRules: []rbacv1.PolicyRule{ {NonResourceURLs: []string{"*"}, Verbs: []string{"*"}}, }, - servantRules: []rbac.PolicyRule{ + servantRules: []rbacv1.PolicyRule{ {NonResourceURLs: []string{"/apis", "/apis/v1", "/"}, Verbs: []string{"*"}}, }, expectedCovered: true, - expectedUncoveredRules: []rbac.PolicyRule{}, + expectedUncoveredRules: []rbacv1.PolicyRule{}, }.test(t) } func TestCoversNonResourceURLsStarAfterPrefixDoesntCover(t *testing.T) { escalationTest{ - ownerRules: []rbac.PolicyRule{ + ownerRules: []rbacv1.PolicyRule{ {NonResourceURLs: []string{"/apis/*"}, Verbs: []string{"*"}}, }, - servantRules: []rbac.PolicyRule{ + servantRules: []rbacv1.PolicyRule{ {NonResourceURLs: []string{"/apis", "/apis/v1"}, Verbs: []string{"get"}}, }, expectedCovered: false, - expectedUncoveredRules: []rbac.PolicyRule{ + expectedUncoveredRules: []rbacv1.PolicyRule{ {NonResourceURLs: []string{"/apis"}, Verbs: []string{"get"}}, }, }.test(t) @@ -341,43 +341,43 @@ func TestCoversNonResourceURLsStarAfterPrefixDoesntCover(t *testing.T) { func TestCoversNonResourceURLsStarAfterPrefix(t *testing.T) { escalationTest{ - ownerRules: []rbac.PolicyRule{ + ownerRules: []rbacv1.PolicyRule{ {NonResourceURLs: []string{"/apis/*"}, Verbs: []string{"*"}}, }, - servantRules: []rbac.PolicyRule{ + servantRules: []rbacv1.PolicyRule{ {NonResourceURLs: []string{"/apis/v1/foo", "/apis/v1"}, Verbs: []string{"get"}}, }, expectedCovered: true, - expectedUncoveredRules: []rbac.PolicyRule{}, + expectedUncoveredRules: []rbacv1.PolicyRule{}, }.test(t) } func TestCoversNonResourceURLsWithOtherFields(t *testing.T) { escalationTest{ - ownerRules: []rbac.PolicyRule{ + ownerRules: []rbacv1.PolicyRule{ {APIGroups: []string{"v1"}, Verbs: []string{"get"}, Resources: []string{"builds"}, NonResourceURLs: []string{"/apis"}}, }, - servantRules: []rbac.PolicyRule{ + servantRules: []rbacv1.PolicyRule{ {APIGroups: []string{"v1"}, Verbs: []string{"get"}, Resources: []string{"builds"}, NonResourceURLs: []string{"/apis"}}, }, expectedCovered: true, - expectedUncoveredRules: []rbac.PolicyRule{}, + expectedUncoveredRules: []rbacv1.PolicyRule{}, }.test(t) } func TestCoversNonResourceURLsWithOtherFieldsFailure(t *testing.T) { escalationTest{ - ownerRules: []rbac.PolicyRule{ + ownerRules: []rbacv1.PolicyRule{ {APIGroups: []string{"v1"}, Verbs: []string{"get"}, Resources: []string{"builds"}}, }, - servantRules: []rbac.PolicyRule{ + servantRules: []rbacv1.PolicyRule{ {APIGroups: []string{"v1"}, Verbs: []string{"get"}, Resources: []string{"builds"}, NonResourceURLs: []string{"/apis"}}, }, expectedCovered: false, - expectedUncoveredRules: []rbac.PolicyRule{{NonResourceURLs: []string{"/apis"}, Verbs: []string{"get"}}}, + expectedUncoveredRules: []rbacv1.PolicyRule{{NonResourceURLs: []string{"/apis"}, Verbs: []string{"get"}}}, }.test(t) } @@ -393,7 +393,7 @@ func (test escalationTest) test(t *testing.T) { } } -func rulesMatch(expectedRules, actualRules []rbac.PolicyRule) bool { +func rulesMatch(expectedRules, actualRules []rbacv1.PolicyRule) bool { if len(expectedRules) != len(actualRules) { return false } diff --git a/pkg/registry/rbac/validation/rule.go b/pkg/registry/rbac/validation/rule.go index e101470ce4..366a9a97b1 100644 --- a/pkg/registry/rbac/validation/rule.go +++ b/pkg/registry/rbac/validation/rule.go @@ -23,31 +23,31 @@ import ( "github.com/golang/glog" + rbacv1 "k8s.io/api/rbac/v1" apierrors "k8s.io/apimachinery/pkg/api/errors" utilerrors "k8s.io/apimachinery/pkg/util/errors" "k8s.io/apiserver/pkg/authentication/serviceaccount" "k8s.io/apiserver/pkg/authentication/user" genericapirequest "k8s.io/apiserver/pkg/endpoints/request" - "k8s.io/kubernetes/pkg/apis/rbac" ) 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(roleRef rbac.RoleRef, namespace string) ([]rbac.PolicyRule, error) + GetRoleReferenceRules(roleRef rbacv1.RoleRef, namespace string) ([]rbacv1.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 // can be made on the basis of those rules that are found. - RulesFor(user user.Info, namespace string) ([]rbac.PolicyRule, error) + RulesFor(user user.Info, namespace string) ([]rbacv1.PolicyRule, error) // VisitRulesFor invokes visitor() with each rule that applies to a given user in a given namespace, and each error encountered resolving those rules. // If visitor() returns false, visiting is short-circuited. - VisitRulesFor(user user.Info, namespace string, visitor func(source fmt.Stringer, rule *rbac.PolicyRule, err error) bool) + VisitRulesFor(user user.Info, namespace string, visitor func(source fmt.Stringer, rule *rbacv1.PolicyRule, err error) bool) } // ConfirmNoEscalation determines if the roles for a given user in a given namespace encompass the provided role. -func ConfirmNoEscalation(ctx context.Context, ruleResolver AuthorizationRuleResolver, rules []rbac.PolicyRule) error { +func ConfirmNoEscalation(ctx context.Context, ruleResolver AuthorizationRuleResolver, rules []rbacv1.PolicyRule) error { ruleResolutionErrors := []error{} user, ok := genericapirequest.UserFrom(ctx) @@ -82,33 +82,33 @@ func NewDefaultRuleResolver(roleGetter RoleGetter, roleBindingLister RoleBinding } type RoleGetter interface { - GetRole(namespace, name string) (*rbac.Role, error) + GetRole(namespace, name string) (*rbacv1.Role, error) } type RoleBindingLister interface { - ListRoleBindings(namespace string) ([]*rbac.RoleBinding, error) + ListRoleBindings(namespace string) ([]*rbacv1.RoleBinding, error) } type ClusterRoleGetter interface { - GetClusterRole(name string) (*rbac.ClusterRole, error) + GetClusterRole(name string) (*rbacv1.ClusterRole, error) } type ClusterRoleBindingLister interface { - ListClusterRoleBindings() ([]*rbac.ClusterRoleBinding, error) + ListClusterRoleBindings() ([]*rbacv1.ClusterRoleBinding, error) } -func (r *DefaultRuleResolver) RulesFor(user user.Info, namespace string) ([]rbac.PolicyRule, error) { +func (r *DefaultRuleResolver) RulesFor(user user.Info, namespace string) ([]rbacv1.PolicyRule, error) { visitor := &ruleAccumulator{} r.VisitRulesFor(user, namespace, visitor.visit) return visitor.rules, utilerrors.NewAggregate(visitor.errors) } type ruleAccumulator struct { - rules []rbac.PolicyRule + rules []rbacv1.PolicyRule errors []error } -func (r *ruleAccumulator) visit(source fmt.Stringer, rule *rbac.PolicyRule, err error) bool { +func (r *ruleAccumulator) visit(source fmt.Stringer, rule *rbacv1.PolicyRule, err error) bool { if rule != nil { r.rules = append(r.rules, *rule) } @@ -118,9 +118,9 @@ func (r *ruleAccumulator) visit(source fmt.Stringer, rule *rbac.PolicyRule, err return true } -func describeSubject(s *rbac.Subject, bindingNamespace string) string { +func describeSubject(s *rbacv1.Subject, bindingNamespace string) string { switch s.Kind { - case rbac.ServiceAccountKind: + case rbacv1.ServiceAccountKind: if len(s.Namespace) > 0 { return fmt.Sprintf("%s %q", s.Kind, s.Name+"/"+s.Namespace) } @@ -131,8 +131,8 @@ func describeSubject(s *rbac.Subject, bindingNamespace string) string { } type clusterRoleBindingDescriber struct { - binding *rbac.ClusterRoleBinding - subject *rbac.Subject + binding *rbacv1.ClusterRoleBinding + subject *rbacv1.Subject } func (d *clusterRoleBindingDescriber) String() string { @@ -145,8 +145,8 @@ func (d *clusterRoleBindingDescriber) String() string { } type roleBindingDescriber struct { - binding *rbac.RoleBinding - subject *rbac.Subject + binding *rbacv1.RoleBinding + subject *rbacv1.Subject } func (d *roleBindingDescriber) String() string { @@ -158,7 +158,7 @@ func (d *roleBindingDescriber) String() string { ) } -func (r *DefaultRuleResolver) VisitRulesFor(user user.Info, namespace string, visitor func(source fmt.Stringer, rule *rbac.PolicyRule, err error) bool) { +func (r *DefaultRuleResolver) VisitRulesFor(user user.Info, namespace string, visitor func(source fmt.Stringer, rule *rbacv1.PolicyRule, err error) bool) { if clusterRoleBindings, err := r.clusterRoleBindingLister.ListClusterRoleBindings(); err != nil { if !visitor(nil, nil, err) { return @@ -219,16 +219,16 @@ func (r *DefaultRuleResolver) VisitRulesFor(user user.Info, namespace string, vi } // GetRoleReferenceRules attempts to resolve the RoleBinding or ClusterRoleBinding. -func (r *DefaultRuleResolver) GetRoleReferenceRules(roleRef rbac.RoleRef, bindingNamespace string) ([]rbac.PolicyRule, error) { - switch kind := rbac.RoleRefGroupKind(roleRef); kind { - case rbac.Kind("Role"): +func (r *DefaultRuleResolver) GetRoleReferenceRules(roleRef rbacv1.RoleRef, bindingNamespace string) ([]rbacv1.PolicyRule, error) { + switch roleRef.Kind { + case "Role": role, err := r.roleGetter.GetRole(bindingNamespace, roleRef.Name) if err != nil { return nil, err } return role.Rules, nil - case rbac.Kind("ClusterRole"): + case "ClusterRole": clusterRole, err := r.clusterRoleGetter.GetClusterRole(roleRef.Name) if err != nil { return nil, err @@ -236,13 +236,13 @@ func (r *DefaultRuleResolver) GetRoleReferenceRules(roleRef rbac.RoleRef, bindin return clusterRole.Rules, nil default: - return nil, fmt.Errorf("unsupported role reference kind: %q", kind) + return nil, fmt.Errorf("unsupported role reference kind: %q", roleRef.Kind) } } // appliesTo returns whether any of the bindingSubjects applies to the specified subject, // and if true, the index of the first subject that applies -func appliesTo(user user.Info, bindingSubjects []rbac.Subject, namespace string) (int, bool) { +func appliesTo(user user.Info, bindingSubjects []rbacv1.Subject, namespace string) (int, bool) { for i, bindingSubject := range bindingSubjects { if appliesToUser(user, bindingSubject, namespace) { return i, true @@ -251,15 +251,15 @@ func appliesTo(user user.Info, bindingSubjects []rbac.Subject, namespace string) return 0, false } -func appliesToUser(user user.Info, subject rbac.Subject, namespace string) bool { +func appliesToUser(user user.Info, subject rbacv1.Subject, namespace string) bool { switch subject.Kind { - case rbac.UserKind: + case rbacv1.UserKind: return user.GetName() == subject.Name - case rbac.GroupKind: + case rbacv1.GroupKind: return has(user.GetGroups(), subject.Name) - case rbac.ServiceAccountKind: + case rbacv1.ServiceAccountKind: // default the namespace to namespace we're working in if its available. This allows rolebindings that reference // SAs in th local namespace to avoid having to qualify them. saNamespace := namespace @@ -276,7 +276,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, *StaticRoles) { +func NewTestRuleResolver(roles []*rbacv1.Role, roleBindings []*rbacv1.RoleBinding, clusterRoles []*rbacv1.ClusterRole, clusterRoleBindings []*rbacv1.ClusterRoleBinding) (AuthorizationRuleResolver, *StaticRoles) { r := StaticRoles{ roles: roles, roleBindings: roleBindings, @@ -292,13 +292,13 @@ func newMockRuleResolver(r *StaticRoles) AuthorizationRuleResolver { // StaticRoles is a rule resolver that resolves from lists of role objects. type StaticRoles struct { - roles []*rbac.Role - roleBindings []*rbac.RoleBinding - clusterRoles []*rbac.ClusterRole - clusterRoleBindings []*rbac.ClusterRoleBinding + roles []*rbacv1.Role + roleBindings []*rbacv1.RoleBinding + clusterRoles []*rbacv1.ClusterRole + clusterRoleBindings []*rbacv1.ClusterRoleBinding } -func (r *StaticRoles) GetRole(namespace, name string) (*rbac.Role, error) { +func (r *StaticRoles) GetRole(namespace, name string) (*rbacv1.Role, error) { if len(namespace) == 0 { return nil, errors.New("must provide namespace when getting role") } @@ -310,7 +310,7 @@ func (r *StaticRoles) GetRole(namespace, name string) (*rbac.Role, error) { return nil, errors.New("role not found") } -func (r *StaticRoles) GetClusterRole(name string) (*rbac.ClusterRole, error) { +func (r *StaticRoles) GetClusterRole(name string) (*rbacv1.ClusterRole, error) { for _, clusterRole := range r.clusterRoles { if clusterRole.Name == name { return clusterRole, nil @@ -319,12 +319,12 @@ func (r *StaticRoles) GetClusterRole(name string) (*rbac.ClusterRole, error) { return nil, errors.New("clusterrole not found") } -func (r *StaticRoles) ListRoleBindings(namespace string) ([]*rbac.RoleBinding, error) { +func (r *StaticRoles) ListRoleBindings(namespace string) ([]*rbacv1.RoleBinding, error) { if len(namespace) == 0 { return nil, errors.New("must provide namespace when listing role bindings") } - roleBindingList := []*rbac.RoleBinding{} + roleBindingList := []*rbacv1.RoleBinding{} for _, roleBinding := range r.roleBindings { if roleBinding.Namespace != namespace { continue @@ -335,6 +335,6 @@ func (r *StaticRoles) ListRoleBindings(namespace string) ([]*rbac.RoleBinding, e return roleBindingList, nil } -func (r *StaticRoles) ListClusterRoleBindings() ([]*rbac.ClusterRoleBinding, error) { +func (r *StaticRoles) ListClusterRoleBindings() ([]*rbacv1.ClusterRoleBinding, error) { return r.clusterRoleBindings, nil } diff --git a/pkg/registry/rbac/validation/rule_test.go b/pkg/registry/rbac/validation/rule_test.go index 1a176126bd..b892f501a3 100644 --- a/pkg/registry/rbac/validation/rule_test.go +++ b/pkg/registry/rbac/validation/rule_test.go @@ -23,14 +23,14 @@ import ( "sort" "testing" + rbacv1 "k8s.io/api/rbac/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/util/diff" "k8s.io/apiserver/pkg/authentication/user" - "k8s.io/kubernetes/pkg/apis/rbac" ) // compute a hash of a policy rule so we can sort in a deterministic order -func hashOf(p rbac.PolicyRule) string { +func hashOf(p rbacv1.PolicyRule) string { hash := fnv.New32() writeStrings := func(slis ...[]string) { for _, sli := range slis { @@ -44,68 +44,68 @@ func hashOf(p rbac.PolicyRule) string { } // byHash sorts a set of policy rules by a hash of its fields -type byHash []rbac.PolicyRule +type byHash []rbacv1.PolicyRule func (b byHash) Len() int { return len(b) } func (b byHash) Less(i, j int) bool { return hashOf(b[i]) < hashOf(b[j]) } func (b byHash) Swap(i, j int) { b[i], b[j] = b[j], b[i] } func TestDefaultRuleResolver(t *testing.T) { - ruleReadPods := rbac.PolicyRule{ + ruleReadPods := rbacv1.PolicyRule{ Verbs: []string{"GET", "WATCH"}, APIGroups: []string{"v1"}, Resources: []string{"pods"}, } - ruleReadServices := rbac.PolicyRule{ + ruleReadServices := rbacv1.PolicyRule{ Verbs: []string{"GET", "WATCH"}, APIGroups: []string{"v1"}, Resources: []string{"services"}, } - ruleWriteNodes := rbac.PolicyRule{ + ruleWriteNodes := rbacv1.PolicyRule{ Verbs: []string{"PUT", "CREATE", "UPDATE"}, APIGroups: []string{"v1"}, Resources: []string{"nodes"}, } - ruleAdmin := rbac.PolicyRule{ + ruleAdmin := rbacv1.PolicyRule{ Verbs: []string{"*"}, APIGroups: []string{"*"}, Resources: []string{"*"}, } staticRoles1 := StaticRoles{ - roles: []*rbac.Role{ + roles: []*rbacv1.Role{ { ObjectMeta: metav1.ObjectMeta{Namespace: "namespace1", Name: "readthings"}, - Rules: []rbac.PolicyRule{ruleReadPods, ruleReadServices}, + Rules: []rbacv1.PolicyRule{ruleReadPods, ruleReadServices}, }, }, - clusterRoles: []*rbac.ClusterRole{ + clusterRoles: []*rbacv1.ClusterRole{ { ObjectMeta: metav1.ObjectMeta{Name: "cluster-admin"}, - Rules: []rbac.PolicyRule{ruleAdmin}, + Rules: []rbacv1.PolicyRule{ruleAdmin}, }, { ObjectMeta: metav1.ObjectMeta{Name: "write-nodes"}, - Rules: []rbac.PolicyRule{ruleWriteNodes}, + Rules: []rbacv1.PolicyRule{ruleWriteNodes}, }, }, - roleBindings: []*rbac.RoleBinding{ + roleBindings: []*rbacv1.RoleBinding{ { ObjectMeta: metav1.ObjectMeta{Namespace: "namespace1"}, - Subjects: []rbac.Subject{ - {Kind: rbac.UserKind, Name: "foobar"}, - {Kind: rbac.GroupKind, Name: "group1"}, + Subjects: []rbacv1.Subject{ + {Kind: rbacv1.UserKind, Name: "foobar"}, + {Kind: rbacv1.GroupKind, Name: "group1"}, }, - RoleRef: rbac.RoleRef{APIGroup: rbac.GroupName, Kind: "Role", Name: "readthings"}, + RoleRef: rbacv1.RoleRef{APIGroup: rbacv1.GroupName, Kind: "Role", Name: "readthings"}, }, }, - clusterRoleBindings: []*rbac.ClusterRoleBinding{ + clusterRoleBindings: []*rbacv1.ClusterRoleBinding{ { - Subjects: []rbac.Subject{ - {Kind: rbac.UserKind, Name: "admin"}, - {Kind: rbac.GroupKind, Name: "admin"}, + Subjects: []rbacv1.Subject{ + {Kind: rbacv1.UserKind, Name: "admin"}, + {Kind: rbacv1.GroupKind, Name: "admin"}, }, - RoleRef: rbac.RoleRef{APIGroup: rbac.GroupName, Kind: "ClusterRole", Name: "cluster-admin"}, + RoleRef: rbacv1.RoleRef{APIGroup: rbacv1.GroupName, Kind: "ClusterRole", Name: "cluster-admin"}, }, }, } @@ -116,13 +116,13 @@ func TestDefaultRuleResolver(t *testing.T) { // For a given context, what are the rules that apply? user user.Info namespace string - effectiveRules []rbac.PolicyRule + effectiveRules []rbacv1.PolicyRule }{ { StaticRoles: staticRoles1, user: &user.DefaultInfo{Name: "foobar"}, namespace: "namespace1", - effectiveRules: []rbac.PolicyRule{ruleReadPods, ruleReadServices}, + effectiveRules: []rbacv1.PolicyRule{ruleReadPods, ruleReadServices}, }, { StaticRoles: staticRoles1, @@ -134,7 +134,7 @@ func TestDefaultRuleResolver(t *testing.T) { StaticRoles: staticRoles1, // Same as above but without a namespace. Only cluster rules should apply. user: &user.DefaultInfo{Name: "foobar", Groups: []string{"admin"}}, - effectiveRules: []rbac.PolicyRule{ruleAdmin}, + effectiveRules: []rbacv1.PolicyRule{ruleAdmin}, }, { StaticRoles: staticRoles1, @@ -164,7 +164,7 @@ func TestDefaultRuleResolver(t *testing.T) { func TestAppliesTo(t *testing.T) { tests := []struct { - subjects []rbac.Subject + subjects []rbacv1.Subject user user.Info namespace string appliesTo bool @@ -172,8 +172,8 @@ func TestAppliesTo(t *testing.T) { testCase string }{ { - subjects: []rbac.Subject{ - {Kind: rbac.UserKind, Name: "foobar"}, + subjects: []rbacv1.Subject{ + {Kind: rbacv1.UserKind, Name: "foobar"}, }, user: &user.DefaultInfo{Name: "foobar"}, appliesTo: true, @@ -181,9 +181,9 @@ func TestAppliesTo(t *testing.T) { testCase: "single subject that matches username", }, { - subjects: []rbac.Subject{ - {Kind: rbac.UserKind, Name: "barfoo"}, - {Kind: rbac.UserKind, Name: "foobar"}, + subjects: []rbacv1.Subject{ + {Kind: rbacv1.UserKind, Name: "barfoo"}, + {Kind: rbacv1.UserKind, Name: "foobar"}, }, user: &user.DefaultInfo{Name: "foobar"}, appliesTo: true, @@ -191,18 +191,18 @@ func TestAppliesTo(t *testing.T) { testCase: "multiple subjects, one that matches username", }, { - subjects: []rbac.Subject{ - {Kind: rbac.UserKind, Name: "barfoo"}, - {Kind: rbac.UserKind, Name: "foobar"}, + subjects: []rbacv1.Subject{ + {Kind: rbacv1.UserKind, Name: "barfoo"}, + {Kind: rbacv1.UserKind, Name: "foobar"}, }, user: &user.DefaultInfo{Name: "zimzam"}, appliesTo: false, testCase: "multiple subjects, none that match username", }, { - subjects: []rbac.Subject{ - {Kind: rbac.UserKind, Name: "barfoo"}, - {Kind: rbac.GroupKind, Name: "foobar"}, + subjects: []rbacv1.Subject{ + {Kind: rbacv1.UserKind, Name: "barfoo"}, + {Kind: rbacv1.GroupKind, Name: "foobar"}, }, user: &user.DefaultInfo{Name: "zimzam", Groups: []string{"foobar"}}, appliesTo: true, @@ -210,9 +210,9 @@ func TestAppliesTo(t *testing.T) { testCase: "multiple subjects, one that match group", }, { - subjects: []rbac.Subject{ - {Kind: rbac.UserKind, Name: "barfoo"}, - {Kind: rbac.GroupKind, Name: "foobar"}, + subjects: []rbacv1.Subject{ + {Kind: rbacv1.UserKind, Name: "barfoo"}, + {Kind: rbacv1.GroupKind, Name: "foobar"}, }, user: &user.DefaultInfo{Name: "zimzam", Groups: []string{"foobar"}}, namespace: "namespace1", @@ -221,10 +221,10 @@ func TestAppliesTo(t *testing.T) { testCase: "multiple subjects, one that match group, should ignore namespace", }, { - subjects: []rbac.Subject{ - {Kind: rbac.UserKind, Name: "barfoo"}, - {Kind: rbac.GroupKind, Name: "foobar"}, - {Kind: rbac.ServiceAccountKind, Namespace: "kube-system", Name: "default"}, + subjects: []rbacv1.Subject{ + {Kind: rbacv1.UserKind, Name: "barfoo"}, + {Kind: rbacv1.GroupKind, Name: "foobar"}, + {Kind: rbacv1.ServiceAccountKind, Namespace: "kube-system", Name: "default"}, }, user: &user.DefaultInfo{Name: "system:serviceaccount:kube-system:default"}, namespace: "default", @@ -233,8 +233,8 @@ func TestAppliesTo(t *testing.T) { testCase: "multiple subjects with a service account that matches", }, { - subjects: []rbac.Subject{ - {Kind: rbac.UserKind, Name: "*"}, + subjects: []rbacv1.Subject{ + {Kind: rbacv1.UserKind, Name: "*"}, }, user: &user.DefaultInfo{Name: "foobar"}, namespace: "default", @@ -242,9 +242,9 @@ func TestAppliesTo(t *testing.T) { testCase: "* user subject name doesn't match all users", }, { - subjects: []rbac.Subject{ - {Kind: rbac.GroupKind, Name: user.AllAuthenticated}, - {Kind: rbac.GroupKind, Name: user.AllUnauthenticated}, + subjects: []rbacv1.Subject{ + {Kind: rbacv1.GroupKind, Name: user.AllAuthenticated}, + {Kind: rbacv1.GroupKind, Name: user.AllUnauthenticated}, }, user: &user.DefaultInfo{Name: "foobar", Groups: []string{user.AllAuthenticated}}, namespace: "default", @@ -253,9 +253,9 @@ func TestAppliesTo(t *testing.T) { testCase: "binding to all authenticated and unauthenticated subjects matches authenticated user", }, { - subjects: []rbac.Subject{ - {Kind: rbac.GroupKind, Name: user.AllAuthenticated}, - {Kind: rbac.GroupKind, Name: user.AllUnauthenticated}, + subjects: []rbacv1.Subject{ + {Kind: rbacv1.GroupKind, Name: user.AllAuthenticated}, + {Kind: rbacv1.GroupKind, Name: user.AllUnauthenticated}, }, user: &user.DefaultInfo{Name: "system:anonymous", Groups: []string{user.AllUnauthenticated}}, namespace: "default", diff --git a/plugin/pkg/auth/authorizer/node/BUILD b/plugin/pkg/auth/authorizer/node/BUILD index 8618c56348..5d73814efc 100644 --- a/plugin/pkg/auth/authorizer/node/BUILD +++ b/plugin/pkg/auth/authorizer/node/BUILD @@ -42,7 +42,6 @@ go_library( "//pkg/api/persistentvolume:go_default_library", "//pkg/api/pod:go_default_library", "//pkg/apis/core:go_default_library", - "//pkg/apis/rbac:go_default_library", "//pkg/apis/storage:go_default_library", "//pkg/auth/nodeidentifier:go_default_library", "//pkg/client/informers/informers_generated/internalversion/core/internalversion:go_default_library", @@ -52,6 +51,7 @@ go_library( "//third_party/forked/gonum/graph/simple:go_default_library", "//third_party/forked/gonum/graph/traverse:go_default_library", "//vendor/github.com/golang/glog:go_default_library", + "//vendor/k8s.io/api/rbac/v1:go_default_library", "//vendor/k8s.io/api/storage/v1beta1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/runtime/schema:go_default_library", "//vendor/k8s.io/apiserver/pkg/authorization/authorizer:go_default_library", diff --git a/plugin/pkg/auth/authorizer/node/node_authorizer.go b/plugin/pkg/auth/authorizer/node/node_authorizer.go index 0239ababd3..371df74a8b 100644 --- a/plugin/pkg/auth/authorizer/node/node_authorizer.go +++ b/plugin/pkg/auth/authorizer/node/node_authorizer.go @@ -21,11 +21,11 @@ import ( "github.com/golang/glog" + rbacv1 "k8s.io/api/rbac/v1" "k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/apiserver/pkg/authorization/authorizer" utilfeature "k8s.io/apiserver/pkg/util/feature" api "k8s.io/kubernetes/pkg/apis/core" - rbacapi "k8s.io/kubernetes/pkg/apis/rbac" storageapi "k8s.io/kubernetes/pkg/apis/storage" "k8s.io/kubernetes/pkg/auth/nodeidentifier" "k8s.io/kubernetes/pkg/features" @@ -49,14 +49,14 @@ import ( type NodeAuthorizer struct { graph *Graph identifier nodeidentifier.NodeIdentifier - nodeRules []rbacapi.PolicyRule + nodeRules []rbacv1.PolicyRule // allows overriding for testing features utilfeature.FeatureGate } // NewAuthorizer returns a new node authorizer -func NewAuthorizer(graph *Graph, identifier nodeidentifier.NodeIdentifier, rules []rbacapi.PolicyRule) authorizer.Authorizer { +func NewAuthorizer(graph *Graph, identifier nodeidentifier.NodeIdentifier, rules []rbacv1.PolicyRule) authorizer.Authorizer { return &NodeAuthorizer{ graph: graph, identifier: identifier, diff --git a/plugin/pkg/auth/authorizer/rbac/BUILD b/plugin/pkg/auth/authorizer/rbac/BUILD index 258c860c5f..cc7848ece8 100644 --- a/plugin/pkg/auth/authorizer/rbac/BUILD +++ b/plugin/pkg/auth/authorizer/rbac/BUILD @@ -14,14 +14,15 @@ go_library( ], importpath = "k8s.io/kubernetes/plugin/pkg/auth/authorizer/rbac", deps = [ - "//pkg/apis/rbac:go_default_library", - "//pkg/client/listers/rbac/internalversion:go_default_library", + "//pkg/apis/rbac/v1:go_default_library", "//pkg/registry/rbac/validation:go_default_library", "//vendor/github.com/golang/glog:go_default_library", + "//vendor/k8s.io/api/rbac/v1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/labels:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/errors:go_default_library", "//vendor/k8s.io/apiserver/pkg/authentication/user:go_default_library", "//vendor/k8s.io/apiserver/pkg/authorization/authorizer:go_default_library", + "//vendor/k8s.io/client-go/listers/rbac/v1:go_default_library", ], ) @@ -33,9 +34,10 @@ go_test( ], embed = [":go_default_library"], deps = [ - "//pkg/apis/rbac:go_default_library", + "//pkg/apis/rbac/v1:go_default_library", "//pkg/registry/rbac/validation:go_default_library", "//plugin/pkg/auth/authorizer/rbac/bootstrappolicy:go_default_library", + "//vendor/k8s.io/api/rbac/v1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", "//vendor/k8s.io/apiserver/pkg/authentication/user:go_default_library", "//vendor/k8s.io/apiserver/pkg/authorization/authorizer:go_default_library", diff --git a/plugin/pkg/auth/authorizer/rbac/bootstrappolicy/BUILD b/plugin/pkg/auth/authorizer/rbac/bootstrappolicy/BUILD index 4c891015f9..83b98d2211 100644 --- a/plugin/pkg/auth/authorizer/rbac/bootstrappolicy/BUILD +++ b/plugin/pkg/auth/authorizer/rbac/bootstrappolicy/BUILD @@ -15,9 +15,10 @@ go_library( ], importpath = "k8s.io/kubernetes/plugin/pkg/auth/authorizer/rbac/bootstrappolicy", deps = [ - "//pkg/apis/rbac:go_default_library", + "//pkg/apis/rbac/v1:go_default_library", "//pkg/features:go_default_library", "//vendor/github.com/golang/glog:go_default_library", + "//vendor/k8s.io/api/rbac/v1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/api/meta:go_default_library", "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library", @@ -37,8 +38,8 @@ go_test( "//pkg/api/legacyscheme:go_default_library", "//pkg/apis/core:go_default_library", "//pkg/apis/core/install:go_default_library", - "//pkg/apis/rbac:go_default_library", "//pkg/apis/rbac/install:go_default_library", + "//pkg/apis/rbac/v1:go_default_library", "//pkg/registry/rbac/validation:go_default_library", "//vendor/github.com/ghodss/yaml:go_default_library", "//vendor/k8s.io/api/core/v1:go_default_library", diff --git a/plugin/pkg/auth/authorizer/rbac/bootstrappolicy/controller_policy.go b/plugin/pkg/auth/authorizer/rbac/bootstrappolicy/controller_policy.go index af7e16edcc..5dfbaa6f23 100644 --- a/plugin/pkg/auth/authorizer/rbac/bootstrappolicy/controller_policy.go +++ b/plugin/pkg/auth/authorizer/rbac/bootstrappolicy/controller_policy.go @@ -21,15 +21,16 @@ import ( "github.com/golang/glog" + rbacv1 "k8s.io/api/rbac/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" utilfeature "k8s.io/apiserver/pkg/util/feature" - rbac "k8s.io/kubernetes/pkg/apis/rbac" + rbacv1helpers "k8s.io/kubernetes/pkg/apis/rbac/v1" "k8s.io/kubernetes/pkg/features" ) const saRolePrefix = "system:controller:" -func addControllerRole(controllerRoles *[]rbac.ClusterRole, controllerRoleBindings *[]rbac.ClusterRoleBinding, role rbac.ClusterRole) { +func addControllerRole(controllerRoles *[]rbacv1.ClusterRole, controllerRoleBindings *[]rbacv1.ClusterRoleBinding, role rbacv1.ClusterRole) { if !strings.HasPrefix(role.Name, saRolePrefix) { glog.Fatalf(`role %q must start with %q`, role.Name, saRolePrefix) } @@ -44,298 +45,298 @@ func addControllerRole(controllerRoles *[]rbac.ClusterRole, controllerRoleBindin addClusterRoleLabel(*controllerRoles) *controllerRoleBindings = append(*controllerRoleBindings, - rbac.NewClusterBinding(role.Name).SAs("kube-system", role.Name[len(saRolePrefix):]).BindingOrDie()) + rbacv1helpers.NewClusterBinding(role.Name).SAs("kube-system", role.Name[len(saRolePrefix):]).BindingOrDie()) addClusterRoleBindingLabel(*controllerRoleBindings) } -func eventsRule() rbac.PolicyRule { - return rbac.NewRule("create", "update", "patch").Groups(legacyGroup).Resources("events").RuleOrDie() +func eventsRule() rbacv1.PolicyRule { + return rbacv1helpers.NewRule("create", "update", "patch").Groups(legacyGroup).Resources("events").RuleOrDie() } -func buildControllerRoles() ([]rbac.ClusterRole, []rbac.ClusterRoleBinding) { +func buildControllerRoles() ([]rbacv1.ClusterRole, []rbacv1.ClusterRoleBinding) { // controllerRoles is a slice of roles used for controllers - controllerRoles := []rbac.ClusterRole{} + controllerRoles := []rbacv1.ClusterRole{} // controllerRoleBindings is a slice of roles used for controllers - controllerRoleBindings := []rbac.ClusterRoleBinding{} + controllerRoleBindings := []rbacv1.ClusterRoleBinding{} - addControllerRole(&controllerRoles, &controllerRoleBindings, func() rbac.ClusterRole { - role := rbac.ClusterRole{ + addControllerRole(&controllerRoles, &controllerRoleBindings, func() rbacv1.ClusterRole { + role := rbacv1.ClusterRole{ ObjectMeta: metav1.ObjectMeta{Name: saRolePrefix + "attachdetach-controller"}, - Rules: []rbac.PolicyRule{ - rbac.NewRule("list", "watch").Groups(legacyGroup).Resources("persistentvolumes", "persistentvolumeclaims").RuleOrDie(), - rbac.NewRule("get", "list", "watch").Groups(legacyGroup).Resources("nodes").RuleOrDie(), - rbac.NewRule("patch", "update").Groups(legacyGroup).Resources("nodes/status").RuleOrDie(), - rbac.NewRule("list", "watch").Groups(legacyGroup).Resources("pods").RuleOrDie(), + Rules: []rbacv1.PolicyRule{ + rbacv1helpers.NewRule("list", "watch").Groups(legacyGroup).Resources("persistentvolumes", "persistentvolumeclaims").RuleOrDie(), + rbacv1helpers.NewRule("get", "list", "watch").Groups(legacyGroup).Resources("nodes").RuleOrDie(), + rbacv1helpers.NewRule("patch", "update").Groups(legacyGroup).Resources("nodes/status").RuleOrDie(), + rbacv1helpers.NewRule("list", "watch").Groups(legacyGroup).Resources("pods").RuleOrDie(), eventsRule(), }, } if utilfeature.DefaultFeatureGate.Enabled(features.CSIPersistentVolume) { - role.Rules = append(role.Rules, rbac.NewRule("get", "create", "delete", "list", "watch").Groups(storageGroup).Resources("volumeattachments").RuleOrDie()) + role.Rules = append(role.Rules, rbacv1helpers.NewRule("get", "create", "delete", "list", "watch").Groups(storageGroup).Resources("volumeattachments").RuleOrDie()) } return role }()) - addControllerRole(&controllerRoles, &controllerRoleBindings, rbac.ClusterRole{ + addControllerRole(&controllerRoles, &controllerRoleBindings, rbacv1.ClusterRole{ ObjectMeta: metav1.ObjectMeta{Name: saRolePrefix + "clusterrole-aggregation-controller"}, - Rules: []rbac.PolicyRule{ + Rules: []rbacv1.PolicyRule{ // this controller must have full permissions to allow it to mutate any role in any way - rbac.NewRule("*").Groups("*").Resources("*").RuleOrDie(), - rbac.NewRule("*").URLs("*").RuleOrDie(), + rbacv1helpers.NewRule("*").Groups("*").Resources("*").RuleOrDie(), + rbacv1helpers.NewRule("*").URLs("*").RuleOrDie(), }, }) - addControllerRole(&controllerRoles, &controllerRoleBindings, rbac.ClusterRole{ + addControllerRole(&controllerRoles, &controllerRoleBindings, rbacv1.ClusterRole{ ObjectMeta: metav1.ObjectMeta{Name: saRolePrefix + "cronjob-controller"}, - Rules: []rbac.PolicyRule{ - rbac.NewRule("get", "list", "watch", "update").Groups(batchGroup).Resources("cronjobs").RuleOrDie(), - rbac.NewRule("get", "list", "watch", "create", "update", "delete", "patch").Groups(batchGroup).Resources("jobs").RuleOrDie(), - rbac.NewRule("update").Groups(batchGroup).Resources("cronjobs/status").RuleOrDie(), - rbac.NewRule("update").Groups(batchGroup).Resources("cronjobs/finalizers").RuleOrDie(), - rbac.NewRule("list", "delete").Groups(legacyGroup).Resources("pods").RuleOrDie(), + Rules: []rbacv1.PolicyRule{ + rbacv1helpers.NewRule("get", "list", "watch", "update").Groups(batchGroup).Resources("cronjobs").RuleOrDie(), + rbacv1helpers.NewRule("get", "list", "watch", "create", "update", "delete", "patch").Groups(batchGroup).Resources("jobs").RuleOrDie(), + rbacv1helpers.NewRule("update").Groups(batchGroup).Resources("cronjobs/status").RuleOrDie(), + rbacv1helpers.NewRule("update").Groups(batchGroup).Resources("cronjobs/finalizers").RuleOrDie(), + rbacv1helpers.NewRule("list", "delete").Groups(legacyGroup).Resources("pods").RuleOrDie(), eventsRule(), }, }) - addControllerRole(&controllerRoles, &controllerRoleBindings, rbac.ClusterRole{ + addControllerRole(&controllerRoles, &controllerRoleBindings, rbacv1.ClusterRole{ ObjectMeta: metav1.ObjectMeta{Name: saRolePrefix + "daemon-set-controller"}, - Rules: []rbac.PolicyRule{ - rbac.NewRule("get", "list", "watch").Groups(extensionsGroup, appsGroup).Resources("daemonsets").RuleOrDie(), - rbac.NewRule("update").Groups(extensionsGroup, appsGroup).Resources("daemonsets/status").RuleOrDie(), - rbac.NewRule("update").Groups(extensionsGroup, appsGroup).Resources("daemonsets/finalizers").RuleOrDie(), - rbac.NewRule("list", "watch").Groups(legacyGroup).Resources("nodes").RuleOrDie(), - rbac.NewRule("list", "watch", "create", "delete", "patch").Groups(legacyGroup).Resources("pods").RuleOrDie(), - rbac.NewRule("create").Groups(legacyGroup).Resources("pods/binding").RuleOrDie(), - rbac.NewRule("get", "list", "watch", "create", "delete", "update", "patch").Groups(appsGroup).Resources("controllerrevisions").RuleOrDie(), + Rules: []rbacv1.PolicyRule{ + rbacv1helpers.NewRule("get", "list", "watch").Groups(extensionsGroup, appsGroup).Resources("daemonsets").RuleOrDie(), + rbacv1helpers.NewRule("update").Groups(extensionsGroup, appsGroup).Resources("daemonsets/status").RuleOrDie(), + rbacv1helpers.NewRule("update").Groups(extensionsGroup, appsGroup).Resources("daemonsets/finalizers").RuleOrDie(), + rbacv1helpers.NewRule("list", "watch").Groups(legacyGroup).Resources("nodes").RuleOrDie(), + rbacv1helpers.NewRule("list", "watch", "create", "delete", "patch").Groups(legacyGroup).Resources("pods").RuleOrDie(), + rbacv1helpers.NewRule("create").Groups(legacyGroup).Resources("pods/binding").RuleOrDie(), + rbacv1helpers.NewRule("get", "list", "watch", "create", "delete", "update", "patch").Groups(appsGroup).Resources("controllerrevisions").RuleOrDie(), eventsRule(), }, }) - addControllerRole(&controllerRoles, &controllerRoleBindings, rbac.ClusterRole{ + addControllerRole(&controllerRoles, &controllerRoleBindings, rbacv1.ClusterRole{ ObjectMeta: metav1.ObjectMeta{Name: saRolePrefix + "deployment-controller"}, - Rules: []rbac.PolicyRule{ - rbac.NewRule("get", "list", "watch", "update").Groups(extensionsGroup, appsGroup).Resources("deployments").RuleOrDie(), - rbac.NewRule("update").Groups(extensionsGroup, appsGroup).Resources("deployments/status").RuleOrDie(), - rbac.NewRule("update").Groups(extensionsGroup, appsGroup).Resources("deployments/finalizers").RuleOrDie(), - rbac.NewRule("get", "list", "watch", "create", "update", "patch", "delete").Groups(appsGroup, extensionsGroup).Resources("replicasets").RuleOrDie(), + Rules: []rbacv1.PolicyRule{ + rbacv1helpers.NewRule("get", "list", "watch", "update").Groups(extensionsGroup, appsGroup).Resources("deployments").RuleOrDie(), + rbacv1helpers.NewRule("update").Groups(extensionsGroup, appsGroup).Resources("deployments/status").RuleOrDie(), + rbacv1helpers.NewRule("update").Groups(extensionsGroup, appsGroup).Resources("deployments/finalizers").RuleOrDie(), + rbacv1helpers.NewRule("get", "list", "watch", "create", "update", "patch", "delete").Groups(appsGroup, extensionsGroup).Resources("replicasets").RuleOrDie(), // TODO: remove "update" once // https://github.com/kubernetes/kubernetes/issues/36897 is resolved. - rbac.NewRule("get", "list", "watch", "update").Groups(legacyGroup).Resources("pods").RuleOrDie(), + rbacv1helpers.NewRule("get", "list", "watch", "update").Groups(legacyGroup).Resources("pods").RuleOrDie(), eventsRule(), }, }) - addControllerRole(&controllerRoles, &controllerRoleBindings, rbac.ClusterRole{ + addControllerRole(&controllerRoles, &controllerRoleBindings, rbacv1.ClusterRole{ ObjectMeta: metav1.ObjectMeta{Name: saRolePrefix + "disruption-controller"}, - Rules: []rbac.PolicyRule{ - rbac.NewRule("get", "list", "watch").Groups(extensionsGroup, appsGroup).Resources("deployments").RuleOrDie(), - rbac.NewRule("get", "list", "watch").Groups(appsGroup, extensionsGroup).Resources("replicasets").RuleOrDie(), - rbac.NewRule("get", "list", "watch").Groups(legacyGroup).Resources("replicationcontrollers").RuleOrDie(), - rbac.NewRule("get", "list", "watch").Groups(policyGroup).Resources("poddisruptionbudgets").RuleOrDie(), - rbac.NewRule("get", "list", "watch").Groups(appsGroup).Resources("statefulsets").RuleOrDie(), - rbac.NewRule("update").Groups(policyGroup).Resources("poddisruptionbudgets/status").RuleOrDie(), + Rules: []rbacv1.PolicyRule{ + rbacv1helpers.NewRule("get", "list", "watch").Groups(extensionsGroup, appsGroup).Resources("deployments").RuleOrDie(), + rbacv1helpers.NewRule("get", "list", "watch").Groups(appsGroup, extensionsGroup).Resources("replicasets").RuleOrDie(), + rbacv1helpers.NewRule("get", "list", "watch").Groups(legacyGroup).Resources("replicationcontrollers").RuleOrDie(), + rbacv1helpers.NewRule("get", "list", "watch").Groups(policyGroup).Resources("poddisruptionbudgets").RuleOrDie(), + rbacv1helpers.NewRule("get", "list", "watch").Groups(appsGroup).Resources("statefulsets").RuleOrDie(), + rbacv1helpers.NewRule("update").Groups(policyGroup).Resources("poddisruptionbudgets/status").RuleOrDie(), eventsRule(), }, }) - addControllerRole(&controllerRoles, &controllerRoleBindings, rbac.ClusterRole{ + addControllerRole(&controllerRoles, &controllerRoleBindings, rbacv1.ClusterRole{ ObjectMeta: metav1.ObjectMeta{Name: saRolePrefix + "endpoint-controller"}, - Rules: []rbac.PolicyRule{ - rbac.NewRule("get", "list", "watch").Groups(legacyGroup).Resources("services", "pods").RuleOrDie(), - rbac.NewRule("get", "list", "create", "update", "delete").Groups(legacyGroup).Resources("endpoints").RuleOrDie(), - rbac.NewRule("create").Groups(legacyGroup).Resources("endpoints/restricted").RuleOrDie(), + Rules: []rbacv1.PolicyRule{ + rbacv1helpers.NewRule("get", "list", "watch").Groups(legacyGroup).Resources("services", "pods").RuleOrDie(), + rbacv1helpers.NewRule("get", "list", "create", "update", "delete").Groups(legacyGroup).Resources("endpoints").RuleOrDie(), + rbacv1helpers.NewRule("create").Groups(legacyGroup).Resources("endpoints/restricted").RuleOrDie(), eventsRule(), }, }) if utilfeature.DefaultFeatureGate.Enabled(features.ExpandPersistentVolumes) { - addControllerRole(&controllerRoles, &controllerRoleBindings, rbac.ClusterRole{ + addControllerRole(&controllerRoles, &controllerRoleBindings, rbacv1.ClusterRole{ ObjectMeta: metav1.ObjectMeta{Name: saRolePrefix + "expand-controller"}, - Rules: []rbac.PolicyRule{ - rbac.NewRule("get", "list", "watch", "update", "patch").Groups(legacyGroup).Resources("persistentvolumes").RuleOrDie(), - rbac.NewRule("update", "patch").Groups(legacyGroup).Resources("persistentvolumeclaims/status").RuleOrDie(), - rbac.NewRule("get", "list", "watch").Groups(legacyGroup).Resources("persistentvolumeclaims").RuleOrDie(), + Rules: []rbacv1.PolicyRule{ + rbacv1helpers.NewRule("get", "list", "watch", "update", "patch").Groups(legacyGroup).Resources("persistentvolumes").RuleOrDie(), + rbacv1helpers.NewRule("update", "patch").Groups(legacyGroup).Resources("persistentvolumeclaims/status").RuleOrDie(), + rbacv1helpers.NewRule("get", "list", "watch").Groups(legacyGroup).Resources("persistentvolumeclaims").RuleOrDie(), // glusterfs - rbac.NewRule("get", "list", "watch").Groups(storageGroup).Resources("storageclasses").RuleOrDie(), - rbac.NewRule("get").Groups(legacyGroup).Resources("services", "endpoints").RuleOrDie(), - rbac.NewRule("get").Groups(legacyGroup).Resources("secrets").RuleOrDie(), + rbacv1helpers.NewRule("get", "list", "watch").Groups(storageGroup).Resources("storageclasses").RuleOrDie(), + rbacv1helpers.NewRule("get").Groups(legacyGroup).Resources("services", "endpoints").RuleOrDie(), + rbacv1helpers.NewRule("get").Groups(legacyGroup).Resources("secrets").RuleOrDie(), eventsRule(), }, }) } - addControllerRole(&controllerRoles, &controllerRoleBindings, rbac.ClusterRole{ + addControllerRole(&controllerRoles, &controllerRoleBindings, rbacv1.ClusterRole{ ObjectMeta: metav1.ObjectMeta{Name: saRolePrefix + "generic-garbage-collector"}, - Rules: []rbac.PolicyRule{ + Rules: []rbacv1.PolicyRule{ // the GC controller needs to run list/watches, selective gets, and updates against any resource - rbac.NewRule("get", "list", "watch", "patch", "update", "delete").Groups("*").Resources("*").RuleOrDie(), + rbacv1helpers.NewRule("get", "list", "watch", "patch", "update", "delete").Groups("*").Resources("*").RuleOrDie(), eventsRule(), }, }) - addControllerRole(&controllerRoles, &controllerRoleBindings, rbac.ClusterRole{ + addControllerRole(&controllerRoles, &controllerRoleBindings, rbacv1.ClusterRole{ ObjectMeta: metav1.ObjectMeta{Name: saRolePrefix + "horizontal-pod-autoscaler"}, - Rules: []rbac.PolicyRule{ - rbac.NewRule("get", "list", "watch").Groups(autoscalingGroup).Resources("horizontalpodautoscalers").RuleOrDie(), - rbac.NewRule("update").Groups(autoscalingGroup).Resources("horizontalpodautoscalers/status").RuleOrDie(), - rbac.NewRule("get", "update").Groups("*").Resources("*/scale").RuleOrDie(), - rbac.NewRule("list").Groups(legacyGroup).Resources("pods").RuleOrDie(), + Rules: []rbacv1.PolicyRule{ + rbacv1helpers.NewRule("get", "list", "watch").Groups(autoscalingGroup).Resources("horizontalpodautoscalers").RuleOrDie(), + rbacv1helpers.NewRule("update").Groups(autoscalingGroup).Resources("horizontalpodautoscalers/status").RuleOrDie(), + rbacv1helpers.NewRule("get", "update").Groups("*").Resources("*/scale").RuleOrDie(), + rbacv1helpers.NewRule("list").Groups(legacyGroup).Resources("pods").RuleOrDie(), // TODO: restrict this to the appropriate namespace - rbac.NewRule("get").Groups(legacyGroup).Resources("services/proxy").Names("https:heapster:", "http:heapster:").RuleOrDie(), + rbacv1helpers.NewRule("get").Groups(legacyGroup).Resources("services/proxy").Names("https:heapster:", "http:heapster:").RuleOrDie(), // allow listing resource metrics and custom metrics - rbac.NewRule("list").Groups(resMetricsGroup).Resources("pods").RuleOrDie(), - rbac.NewRule("get", "list").Groups(customMetricsGroup).Resources("*").RuleOrDie(), + rbacv1helpers.NewRule("list").Groups(resMetricsGroup).Resources("pods").RuleOrDie(), + rbacv1helpers.NewRule("get", "list").Groups(customMetricsGroup).Resources("*").RuleOrDie(), eventsRule(), }, }) - addControllerRole(&controllerRoles, &controllerRoleBindings, rbac.ClusterRole{ + addControllerRole(&controllerRoles, &controllerRoleBindings, rbacv1.ClusterRole{ ObjectMeta: metav1.ObjectMeta{Name: saRolePrefix + "job-controller"}, - Rules: []rbac.PolicyRule{ - rbac.NewRule("get", "list", "watch", "update").Groups(batchGroup).Resources("jobs").RuleOrDie(), - rbac.NewRule("update").Groups(batchGroup).Resources("jobs/status").RuleOrDie(), - rbac.NewRule("update").Groups(batchGroup).Resources("jobs/finalizers").RuleOrDie(), - rbac.NewRule("list", "watch", "create", "delete", "patch").Groups(legacyGroup).Resources("pods").RuleOrDie(), + Rules: []rbacv1.PolicyRule{ + rbacv1helpers.NewRule("get", "list", "watch", "update").Groups(batchGroup).Resources("jobs").RuleOrDie(), + rbacv1helpers.NewRule("update").Groups(batchGroup).Resources("jobs/status").RuleOrDie(), + rbacv1helpers.NewRule("update").Groups(batchGroup).Resources("jobs/finalizers").RuleOrDie(), + rbacv1helpers.NewRule("list", "watch", "create", "delete", "patch").Groups(legacyGroup).Resources("pods").RuleOrDie(), eventsRule(), }, }) - addControllerRole(&controllerRoles, &controllerRoleBindings, rbac.ClusterRole{ + addControllerRole(&controllerRoles, &controllerRoleBindings, rbacv1.ClusterRole{ ObjectMeta: metav1.ObjectMeta{Name: saRolePrefix + "namespace-controller"}, - Rules: []rbac.PolicyRule{ - rbac.NewRule("get", "list", "watch", "delete").Groups(legacyGroup).Resources("namespaces").RuleOrDie(), - rbac.NewRule("update").Groups(legacyGroup).Resources("namespaces/finalize", "namespaces/status").RuleOrDie(), - rbac.NewRule("get", "list", "delete", "deletecollection").Groups("*").Resources("*").RuleOrDie(), + Rules: []rbacv1.PolicyRule{ + rbacv1helpers.NewRule("get", "list", "watch", "delete").Groups(legacyGroup).Resources("namespaces").RuleOrDie(), + rbacv1helpers.NewRule("update").Groups(legacyGroup).Resources("namespaces/finalize", "namespaces/status").RuleOrDie(), + rbacv1helpers.NewRule("get", "list", "delete", "deletecollection").Groups("*").Resources("*").RuleOrDie(), }, }) - addControllerRole(&controllerRoles, &controllerRoleBindings, rbac.ClusterRole{ + addControllerRole(&controllerRoles, &controllerRoleBindings, rbacv1.ClusterRole{ ObjectMeta: metav1.ObjectMeta{Name: saRolePrefix + "node-controller"}, - Rules: []rbac.PolicyRule{ - rbac.NewRule("get", "list", "update", "delete", "patch").Groups(legacyGroup).Resources("nodes").RuleOrDie(), - rbac.NewRule("patch", "update").Groups(legacyGroup).Resources("nodes/status").RuleOrDie(), + Rules: []rbacv1.PolicyRule{ + rbacv1helpers.NewRule("get", "list", "update", "delete", "patch").Groups(legacyGroup).Resources("nodes").RuleOrDie(), + rbacv1helpers.NewRule("patch", "update").Groups(legacyGroup).Resources("nodes/status").RuleOrDie(), // used for pod eviction - rbac.NewRule("update").Groups(legacyGroup).Resources("pods/status").RuleOrDie(), - rbac.NewRule("list", "delete").Groups(legacyGroup).Resources("pods").RuleOrDie(), + rbacv1helpers.NewRule("update").Groups(legacyGroup).Resources("pods/status").RuleOrDie(), + rbacv1helpers.NewRule("list", "delete").Groups(legacyGroup).Resources("pods").RuleOrDie(), eventsRule(), }, }) - addControllerRole(&controllerRoles, &controllerRoleBindings, rbac.ClusterRole{ + addControllerRole(&controllerRoles, &controllerRoleBindings, rbacv1.ClusterRole{ ObjectMeta: metav1.ObjectMeta{Name: saRolePrefix + "persistent-volume-binder"}, - Rules: []rbac.PolicyRule{ - rbac.NewRule("get", "list", "watch", "update", "create", "delete").Groups(legacyGroup).Resources("persistentvolumes").RuleOrDie(), - rbac.NewRule("update").Groups(legacyGroup).Resources("persistentvolumes/status").RuleOrDie(), - rbac.NewRule("get", "list", "watch", "update").Groups(legacyGroup).Resources("persistentvolumeclaims").RuleOrDie(), - rbac.NewRule("update").Groups(legacyGroup).Resources("persistentvolumeclaims/status").RuleOrDie(), - rbac.NewRule("list", "watch", "get", "create", "delete").Groups(legacyGroup).Resources("pods").RuleOrDie(), + Rules: []rbacv1.PolicyRule{ + rbacv1helpers.NewRule("get", "list", "watch", "update", "create", "delete").Groups(legacyGroup).Resources("persistentvolumes").RuleOrDie(), + rbacv1helpers.NewRule("update").Groups(legacyGroup).Resources("persistentvolumes/status").RuleOrDie(), + rbacv1helpers.NewRule("get", "list", "watch", "update").Groups(legacyGroup).Resources("persistentvolumeclaims").RuleOrDie(), + rbacv1helpers.NewRule("update").Groups(legacyGroup).Resources("persistentvolumeclaims/status").RuleOrDie(), + rbacv1helpers.NewRule("list", "watch", "get", "create", "delete").Groups(legacyGroup).Resources("pods").RuleOrDie(), // glusterfs - rbac.NewRule("get", "list", "watch").Groups(storageGroup).Resources("storageclasses").RuleOrDie(), - rbac.NewRule("get", "create", "delete").Groups(legacyGroup).Resources("services", "endpoints").RuleOrDie(), - rbac.NewRule("get").Groups(legacyGroup).Resources("secrets").RuleOrDie(), + rbacv1helpers.NewRule("get", "list", "watch").Groups(storageGroup).Resources("storageclasses").RuleOrDie(), + rbacv1helpers.NewRule("get", "create", "delete").Groups(legacyGroup).Resources("services", "endpoints").RuleOrDie(), + rbacv1helpers.NewRule("get").Groups(legacyGroup).Resources("secrets").RuleOrDie(), // openstack - rbac.NewRule("get", "list").Groups(legacyGroup).Resources("nodes").RuleOrDie(), + rbacv1helpers.NewRule("get", "list").Groups(legacyGroup).Resources("nodes").RuleOrDie(), // recyclerClient.WatchPod - rbac.NewRule("watch").Groups(legacyGroup).Resources("events").RuleOrDie(), + rbacv1helpers.NewRule("watch").Groups(legacyGroup).Resources("events").RuleOrDie(), eventsRule(), }, }) - addControllerRole(&controllerRoles, &controllerRoleBindings, rbac.ClusterRole{ + addControllerRole(&controllerRoles, &controllerRoleBindings, rbacv1.ClusterRole{ ObjectMeta: metav1.ObjectMeta{Name: saRolePrefix + "pod-garbage-collector"}, - Rules: []rbac.PolicyRule{ - rbac.NewRule("list", "watch", "delete").Groups(legacyGroup).Resources("pods").RuleOrDie(), - rbac.NewRule("list").Groups(legacyGroup).Resources("nodes").RuleOrDie(), + Rules: []rbacv1.PolicyRule{ + rbacv1helpers.NewRule("list", "watch", "delete").Groups(legacyGroup).Resources("pods").RuleOrDie(), + rbacv1helpers.NewRule("list").Groups(legacyGroup).Resources("nodes").RuleOrDie(), }, }) - addControllerRole(&controllerRoles, &controllerRoleBindings, rbac.ClusterRole{ + addControllerRole(&controllerRoles, &controllerRoleBindings, rbacv1.ClusterRole{ ObjectMeta: metav1.ObjectMeta{Name: saRolePrefix + "replicaset-controller"}, - Rules: []rbac.PolicyRule{ - rbac.NewRule("get", "list", "watch", "update").Groups(appsGroup, extensionsGroup).Resources("replicasets").RuleOrDie(), - rbac.NewRule("update").Groups(appsGroup, extensionsGroup).Resources("replicasets/status").RuleOrDie(), - rbac.NewRule("update").Groups(appsGroup, extensionsGroup).Resources("replicasets/finalizers").RuleOrDie(), - rbac.NewRule("list", "watch", "patch", "create", "delete").Groups(legacyGroup).Resources("pods").RuleOrDie(), + Rules: []rbacv1.PolicyRule{ + rbacv1helpers.NewRule("get", "list", "watch", "update").Groups(appsGroup, extensionsGroup).Resources("replicasets").RuleOrDie(), + rbacv1helpers.NewRule("update").Groups(appsGroup, extensionsGroup).Resources("replicasets/status").RuleOrDie(), + rbacv1helpers.NewRule("update").Groups(appsGroup, extensionsGroup).Resources("replicasets/finalizers").RuleOrDie(), + rbacv1helpers.NewRule("list", "watch", "patch", "create", "delete").Groups(legacyGroup).Resources("pods").RuleOrDie(), eventsRule(), }, }) - addControllerRole(&controllerRoles, &controllerRoleBindings, rbac.ClusterRole{ + addControllerRole(&controllerRoles, &controllerRoleBindings, rbacv1.ClusterRole{ ObjectMeta: metav1.ObjectMeta{Name: saRolePrefix + "replication-controller"}, - Rules: []rbac.PolicyRule{ + Rules: []rbacv1.PolicyRule{ // 1.0 controllers needed get, update, so without these old controllers break on new servers - rbac.NewRule("get", "list", "watch", "update").Groups(legacyGroup).Resources("replicationcontrollers").RuleOrDie(), - rbac.NewRule("update").Groups(legacyGroup).Resources("replicationcontrollers/status").RuleOrDie(), - rbac.NewRule("update").Groups(legacyGroup).Resources("replicationcontrollers/finalizers").RuleOrDie(), - rbac.NewRule("list", "watch", "patch", "create", "delete").Groups(legacyGroup).Resources("pods").RuleOrDie(), + rbacv1helpers.NewRule("get", "list", "watch", "update").Groups(legacyGroup).Resources("replicationcontrollers").RuleOrDie(), + rbacv1helpers.NewRule("update").Groups(legacyGroup).Resources("replicationcontrollers/status").RuleOrDie(), + rbacv1helpers.NewRule("update").Groups(legacyGroup).Resources("replicationcontrollers/finalizers").RuleOrDie(), + rbacv1helpers.NewRule("list", "watch", "patch", "create", "delete").Groups(legacyGroup).Resources("pods").RuleOrDie(), eventsRule(), }, }) - addControllerRole(&controllerRoles, &controllerRoleBindings, rbac.ClusterRole{ + addControllerRole(&controllerRoles, &controllerRoleBindings, rbacv1.ClusterRole{ ObjectMeta: metav1.ObjectMeta{Name: saRolePrefix + "resourcequota-controller"}, - Rules: []rbac.PolicyRule{ + Rules: []rbacv1.PolicyRule{ // quota can count quota on anything for reconciliation, so it needs full viewing powers - rbac.NewRule("list", "watch").Groups("*").Resources("*").RuleOrDie(), - rbac.NewRule("update").Groups(legacyGroup).Resources("resourcequotas/status").RuleOrDie(), + rbacv1helpers.NewRule("list", "watch").Groups("*").Resources("*").RuleOrDie(), + rbacv1helpers.NewRule("update").Groups(legacyGroup).Resources("resourcequotas/status").RuleOrDie(), eventsRule(), }, }) - addControllerRole(&controllerRoles, &controllerRoleBindings, rbac.ClusterRole{ + addControllerRole(&controllerRoles, &controllerRoleBindings, rbacv1.ClusterRole{ ObjectMeta: metav1.ObjectMeta{Name: saRolePrefix + "route-controller"}, - Rules: []rbac.PolicyRule{ - rbac.NewRule("list", "watch").Groups(legacyGroup).Resources("nodes").RuleOrDie(), - rbac.NewRule("patch").Groups(legacyGroup).Resources("nodes/status").RuleOrDie(), + Rules: []rbacv1.PolicyRule{ + rbacv1helpers.NewRule("list", "watch").Groups(legacyGroup).Resources("nodes").RuleOrDie(), + rbacv1helpers.NewRule("patch").Groups(legacyGroup).Resources("nodes/status").RuleOrDie(), eventsRule(), }, }) - addControllerRole(&controllerRoles, &controllerRoleBindings, rbac.ClusterRole{ + addControllerRole(&controllerRoles, &controllerRoleBindings, rbacv1.ClusterRole{ ObjectMeta: metav1.ObjectMeta{Name: saRolePrefix + "service-account-controller"}, - Rules: []rbac.PolicyRule{ - rbac.NewRule("create").Groups(legacyGroup).Resources("serviceaccounts").RuleOrDie(), + Rules: []rbacv1.PolicyRule{ + rbacv1helpers.NewRule("create").Groups(legacyGroup).Resources("serviceaccounts").RuleOrDie(), eventsRule(), }, }) - addControllerRole(&controllerRoles, &controllerRoleBindings, rbac.ClusterRole{ + addControllerRole(&controllerRoles, &controllerRoleBindings, rbacv1.ClusterRole{ ObjectMeta: metav1.ObjectMeta{Name: saRolePrefix + "service-controller"}, - Rules: []rbac.PolicyRule{ - rbac.NewRule("get", "list", "watch").Groups(legacyGroup).Resources("services").RuleOrDie(), - rbac.NewRule("update").Groups(legacyGroup).Resources("services/status").RuleOrDie(), - rbac.NewRule("list", "watch").Groups(legacyGroup).Resources("nodes").RuleOrDie(), + Rules: []rbacv1.PolicyRule{ + rbacv1helpers.NewRule("get", "list", "watch").Groups(legacyGroup).Resources("services").RuleOrDie(), + rbacv1helpers.NewRule("update").Groups(legacyGroup).Resources("services/status").RuleOrDie(), + rbacv1helpers.NewRule("list", "watch").Groups(legacyGroup).Resources("nodes").RuleOrDie(), eventsRule(), }, }) - addControllerRole(&controllerRoles, &controllerRoleBindings, rbac.ClusterRole{ + addControllerRole(&controllerRoles, &controllerRoleBindings, rbacv1.ClusterRole{ ObjectMeta: metav1.ObjectMeta{Name: saRolePrefix + "statefulset-controller"}, - Rules: []rbac.PolicyRule{ - rbac.NewRule("list", "watch").Groups(legacyGroup).Resources("pods").RuleOrDie(), - rbac.NewRule("get", "list", "watch").Groups(appsGroup).Resources("statefulsets").RuleOrDie(), - rbac.NewRule("update").Groups(appsGroup).Resources("statefulsets/status").RuleOrDie(), - rbac.NewRule("update").Groups(appsGroup).Resources("statefulsets/finalizers").RuleOrDie(), - rbac.NewRule("get", "create", "delete", "update", "patch").Groups(legacyGroup).Resources("pods").RuleOrDie(), - rbac.NewRule("get", "create", "delete", "update", "patch", "list", "watch").Groups(appsGroup).Resources("controllerrevisions").RuleOrDie(), - rbac.NewRule("get", "create").Groups(legacyGroup).Resources("persistentvolumeclaims").RuleOrDie(), + Rules: []rbacv1.PolicyRule{ + rbacv1helpers.NewRule("list", "watch").Groups(legacyGroup).Resources("pods").RuleOrDie(), + rbacv1helpers.NewRule("get", "list", "watch").Groups(appsGroup).Resources("statefulsets").RuleOrDie(), + rbacv1helpers.NewRule("update").Groups(appsGroup).Resources("statefulsets/status").RuleOrDie(), + rbacv1helpers.NewRule("update").Groups(appsGroup).Resources("statefulsets/finalizers").RuleOrDie(), + rbacv1helpers.NewRule("get", "create", "delete", "update", "patch").Groups(legacyGroup).Resources("pods").RuleOrDie(), + rbacv1helpers.NewRule("get", "create", "delete", "update", "patch", "list", "watch").Groups(appsGroup).Resources("controllerrevisions").RuleOrDie(), + rbacv1helpers.NewRule("get", "create").Groups(legacyGroup).Resources("persistentvolumeclaims").RuleOrDie(), eventsRule(), }, }) - addControllerRole(&controllerRoles, &controllerRoleBindings, rbac.ClusterRole{ + addControllerRole(&controllerRoles, &controllerRoleBindings, rbacv1.ClusterRole{ ObjectMeta: metav1.ObjectMeta{Name: saRolePrefix + "ttl-controller"}, - Rules: []rbac.PolicyRule{ - rbac.NewRule("update", "patch", "list", "watch").Groups(legacyGroup).Resources("nodes").RuleOrDie(), + Rules: []rbacv1.PolicyRule{ + rbacv1helpers.NewRule("update", "patch", "list", "watch").Groups(legacyGroup).Resources("nodes").RuleOrDie(), eventsRule(), }, }) - addControllerRole(&controllerRoles, &controllerRoleBindings, rbac.ClusterRole{ + addControllerRole(&controllerRoles, &controllerRoleBindings, rbacv1.ClusterRole{ ObjectMeta: metav1.ObjectMeta{Name: saRolePrefix + "certificate-controller"}, - Rules: []rbac.PolicyRule{ - rbac.NewRule("get", "list", "watch", "delete").Groups(certificatesGroup).Resources("certificatesigningrequests").RuleOrDie(), - rbac.NewRule("update").Groups(certificatesGroup).Resources("certificatesigningrequests/status", "certificatesigningrequests/approval").RuleOrDie(), - rbac.NewRule("create").Groups(authorizationGroup).Resources("subjectaccessreviews").RuleOrDie(), + Rules: []rbacv1.PolicyRule{ + rbacv1helpers.NewRule("get", "list", "watch", "delete").Groups(certificatesGroup).Resources("certificatesigningrequests").RuleOrDie(), + rbacv1helpers.NewRule("update").Groups(certificatesGroup).Resources("certificatesigningrequests/status", "certificatesigningrequests/approval").RuleOrDie(), + rbacv1helpers.NewRule("create").Groups(authorizationGroup).Resources("subjectaccessreviews").RuleOrDie(), eventsRule(), }, }) - addControllerRole(&controllerRoles, &controllerRoleBindings, rbac.ClusterRole{ + addControllerRole(&controllerRoles, &controllerRoleBindings, rbacv1.ClusterRole{ ObjectMeta: metav1.ObjectMeta{Name: saRolePrefix + "pvc-protection-controller"}, - Rules: []rbac.PolicyRule{ - rbac.NewRule("get", "list", "watch", "update").Groups(legacyGroup).Resources("persistentvolumeclaims").RuleOrDie(), - rbac.NewRule("list", "watch", "get").Groups(legacyGroup).Resources("pods").RuleOrDie(), + Rules: []rbacv1.PolicyRule{ + rbacv1helpers.NewRule("get", "list", "watch", "update").Groups(legacyGroup).Resources("persistentvolumeclaims").RuleOrDie(), + rbacv1helpers.NewRule("list", "watch", "get").Groups(legacyGroup).Resources("pods").RuleOrDie(), eventsRule(), }, }) - addControllerRole(&controllerRoles, &controllerRoleBindings, rbac.ClusterRole{ + addControllerRole(&controllerRoles, &controllerRoleBindings, rbacv1.ClusterRole{ ObjectMeta: metav1.ObjectMeta{Name: saRolePrefix + "pv-protection-controller"}, - Rules: []rbac.PolicyRule{ - rbac.NewRule("get", "list", "watch", "update").Groups(legacyGroup).Resources("persistentvolumes").RuleOrDie(), + Rules: []rbacv1.PolicyRule{ + rbacv1helpers.NewRule("get", "list", "watch", "update").Groups(legacyGroup).Resources("persistentvolumes").RuleOrDie(), eventsRule(), }, }) @@ -344,13 +345,13 @@ func buildControllerRoles() ([]rbac.ClusterRole, []rbac.ClusterRoleBinding) { } // ControllerRoles returns the cluster roles used by controllers -func ControllerRoles() []rbac.ClusterRole { +func ControllerRoles() []rbacv1.ClusterRole { controllerRoles, _ := buildControllerRoles() return controllerRoles } // ControllerRoleBindings returns the role bindings used by controllers -func ControllerRoleBindings() []rbac.ClusterRoleBinding { +func ControllerRoleBindings() []rbacv1.ClusterRoleBinding { _, controllerRoleBindings := buildControllerRoles() return controllerRoleBindings } diff --git a/plugin/pkg/auth/authorizer/rbac/bootstrappolicy/namespace_policy.go b/plugin/pkg/auth/authorizer/rbac/bootstrappolicy/namespace_policy.go index 16590fffc8..fefe26d2ce 100644 --- a/plugin/pkg/auth/authorizer/rbac/bootstrappolicy/namespace_policy.go +++ b/plugin/pkg/auth/authorizer/rbac/bootstrappolicy/namespace_policy.go @@ -21,19 +21,20 @@ import ( "github.com/golang/glog" + rbacv1 "k8s.io/api/rbac/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - rbac "k8s.io/kubernetes/pkg/apis/rbac" + rbacv1helpers "k8s.io/kubernetes/pkg/apis/rbac/v1" ) var ( // namespaceRoles is a map of namespace to slice of roles to create - namespaceRoles = map[string][]rbac.Role{} + namespaceRoles = map[string][]rbacv1.Role{} // namespaceRoleBindings is a map of namespace to slice of roleBindings to create - namespaceRoleBindings = map[string][]rbac.RoleBinding{} + namespaceRoleBindings = map[string][]rbacv1.RoleBinding{} ) -func addNamespaceRole(namespace string, role rbac.Role) { +func addNamespaceRole(namespace string, role rbacv1.Role) { if !strings.HasPrefix(namespace, "kube-") { glog.Fatalf(`roles can only be bootstrapped into reserved namespaces starting with "kube-", not %q`, namespace) } @@ -51,7 +52,7 @@ func addNamespaceRole(namespace string, role rbac.Role) { namespaceRoles[namespace] = existingRoles } -func addNamespaceRoleBinding(namespace string, roleBinding rbac.RoleBinding) { +func addNamespaceRoleBinding(namespace string, roleBinding rbacv1.RoleBinding) { if !strings.HasPrefix(namespace, "kube-") { glog.Fatalf(`rolebindings can only be bootstrapped into reserved namespaces starting with "kube-", not %q`, namespace) } @@ -70,86 +71,86 @@ func addNamespaceRoleBinding(namespace string, roleBinding rbac.RoleBinding) { } func init() { - addNamespaceRole(metav1.NamespaceSystem, rbac.Role{ + addNamespaceRole(metav1.NamespaceSystem, rbacv1.Role{ // role for finding authentication config info for starting a server ObjectMeta: metav1.ObjectMeta{Name: "extension-apiserver-authentication-reader"}, - Rules: []rbac.PolicyRule{ + Rules: []rbacv1.PolicyRule{ // this particular config map is exposed and contains authentication configuration information - rbac.NewRule("get").Groups(legacyGroup).Resources("configmaps").Names("extension-apiserver-authentication").RuleOrDie(), + rbacv1helpers.NewRule("get").Groups(legacyGroup).Resources("configmaps").Names("extension-apiserver-authentication").RuleOrDie(), }, }) - addNamespaceRole(metav1.NamespaceSystem, rbac.Role{ + addNamespaceRole(metav1.NamespaceSystem, rbacv1.Role{ // role for the bootstrap signer to be able to inspect kube-system secrets ObjectMeta: metav1.ObjectMeta{Name: saRolePrefix + "bootstrap-signer"}, - Rules: []rbac.PolicyRule{ - rbac.NewRule("get", "list", "watch").Groups(legacyGroup).Resources("secrets").RuleOrDie(), + Rules: []rbacv1.PolicyRule{ + rbacv1helpers.NewRule("get", "list", "watch").Groups(legacyGroup).Resources("secrets").RuleOrDie(), }, }) - addNamespaceRole(metav1.NamespaceSystem, rbac.Role{ + addNamespaceRole(metav1.NamespaceSystem, rbacv1.Role{ // role for the cloud providers to access/create kube-system configmaps // Deprecated starting Kubernetes 1.10 and will be deleted according to GA deprecation policy. ObjectMeta: metav1.ObjectMeta{Name: saRolePrefix + "cloud-provider"}, - Rules: []rbac.PolicyRule{ - rbac.NewRule("create", "get", "list", "watch").Groups(legacyGroup).Resources("configmaps").RuleOrDie(), + Rules: []rbacv1.PolicyRule{ + rbacv1helpers.NewRule("create", "get", "list", "watch").Groups(legacyGroup).Resources("configmaps").RuleOrDie(), }, }) - addNamespaceRole(metav1.NamespaceSystem, rbac.Role{ + addNamespaceRole(metav1.NamespaceSystem, rbacv1.Role{ // role for the token-cleaner to be able to remove secrets, but only in kube-system ObjectMeta: metav1.ObjectMeta{Name: saRolePrefix + "token-cleaner"}, - Rules: []rbac.PolicyRule{ - rbac.NewRule("get", "list", "watch", "delete").Groups(legacyGroup).Resources("secrets").RuleOrDie(), + Rules: []rbacv1.PolicyRule{ + rbacv1helpers.NewRule("get", "list", "watch", "delete").Groups(legacyGroup).Resources("secrets").RuleOrDie(), eventsRule(), }, }) // TODO: Create util on Role+Binding for leader locking if more cases evolve. - addNamespaceRole(metav1.NamespaceSystem, rbac.Role{ + addNamespaceRole(metav1.NamespaceSystem, rbacv1.Role{ // role for the leader locking on supplied configmap ObjectMeta: metav1.ObjectMeta{Name: "system::leader-locking-kube-controller-manager"}, - Rules: []rbac.PolicyRule{ - rbac.NewRule("watch").Groups(legacyGroup).Resources("configmaps").RuleOrDie(), - rbac.NewRule("get", "update").Groups(legacyGroup).Resources("configmaps").Names("kube-controller-manager").RuleOrDie(), + Rules: []rbacv1.PolicyRule{ + rbacv1helpers.NewRule("watch").Groups(legacyGroup).Resources("configmaps").RuleOrDie(), + rbacv1helpers.NewRule("get", "update").Groups(legacyGroup).Resources("configmaps").Names("kube-controller-manager").RuleOrDie(), }, }) - addNamespaceRole(metav1.NamespaceSystem, rbac.Role{ + addNamespaceRole(metav1.NamespaceSystem, rbacv1.Role{ // role for the leader locking on supplied configmap ObjectMeta: metav1.ObjectMeta{Name: "system::leader-locking-kube-scheduler"}, - Rules: []rbac.PolicyRule{ - rbac.NewRule("watch").Groups(legacyGroup).Resources("configmaps").RuleOrDie(), - rbac.NewRule("get", "update").Groups(legacyGroup).Resources("configmaps").Names("kube-scheduler").RuleOrDie(), + Rules: []rbacv1.PolicyRule{ + rbacv1helpers.NewRule("watch").Groups(legacyGroup).Resources("configmaps").RuleOrDie(), + rbacv1helpers.NewRule("get", "update").Groups(legacyGroup).Resources("configmaps").Names("kube-scheduler").RuleOrDie(), }, }) addNamespaceRoleBinding(metav1.NamespaceSystem, - rbac.NewRoleBinding("system::leader-locking-kube-controller-manager", metav1.NamespaceSystem).SAs(metav1.NamespaceSystem, "kube-controller-manager").BindingOrDie()) + rbacv1helpers.NewRoleBinding("system::leader-locking-kube-controller-manager", metav1.NamespaceSystem).SAs(metav1.NamespaceSystem, "kube-controller-manager").BindingOrDie()) addNamespaceRoleBinding(metav1.NamespaceSystem, - rbac.NewRoleBinding("system::leader-locking-kube-scheduler", metav1.NamespaceSystem).SAs(metav1.NamespaceSystem, "kube-scheduler").BindingOrDie()) + rbacv1helpers.NewRoleBinding("system::leader-locking-kube-scheduler", metav1.NamespaceSystem).SAs(metav1.NamespaceSystem, "kube-scheduler").BindingOrDie()) addNamespaceRoleBinding(metav1.NamespaceSystem, - rbac.NewRoleBinding(saRolePrefix+"bootstrap-signer", metav1.NamespaceSystem).SAs(metav1.NamespaceSystem, "bootstrap-signer").BindingOrDie()) + rbacv1helpers.NewRoleBinding(saRolePrefix+"bootstrap-signer", metav1.NamespaceSystem).SAs(metav1.NamespaceSystem, "bootstrap-signer").BindingOrDie()) // cloud-provider is deprecated starting Kubernetes 1.10 and will be deleted according to GA deprecation policy. addNamespaceRoleBinding(metav1.NamespaceSystem, - rbac.NewRoleBinding(saRolePrefix+"cloud-provider", metav1.NamespaceSystem).SAs(metav1.NamespaceSystem, "cloud-provider").BindingOrDie()) + rbacv1helpers.NewRoleBinding(saRolePrefix+"cloud-provider", metav1.NamespaceSystem).SAs(metav1.NamespaceSystem, "cloud-provider").BindingOrDie()) addNamespaceRoleBinding(metav1.NamespaceSystem, - rbac.NewRoleBinding(saRolePrefix+"token-cleaner", metav1.NamespaceSystem).SAs(metav1.NamespaceSystem, "token-cleaner").BindingOrDie()) + rbacv1helpers.NewRoleBinding(saRolePrefix+"token-cleaner", metav1.NamespaceSystem).SAs(metav1.NamespaceSystem, "token-cleaner").BindingOrDie()) - addNamespaceRole(metav1.NamespacePublic, rbac.Role{ + addNamespaceRole(metav1.NamespacePublic, rbacv1.Role{ // role for the bootstrap signer to be able to write its configmap ObjectMeta: metav1.ObjectMeta{Name: saRolePrefix + "bootstrap-signer"}, - Rules: []rbac.PolicyRule{ - rbac.NewRule("get", "list", "watch").Groups(legacyGroup).Resources("configmaps").RuleOrDie(), - rbac.NewRule("update").Groups(legacyGroup).Resources("configmaps").Names("cluster-info").RuleOrDie(), + Rules: []rbacv1.PolicyRule{ + rbacv1helpers.NewRule("get", "list", "watch").Groups(legacyGroup).Resources("configmaps").RuleOrDie(), + rbacv1helpers.NewRule("update").Groups(legacyGroup).Resources("configmaps").Names("cluster-info").RuleOrDie(), eventsRule(), }, }) addNamespaceRoleBinding(metav1.NamespacePublic, - rbac.NewRoleBinding(saRolePrefix+"bootstrap-signer", metav1.NamespacePublic).SAs(metav1.NamespaceSystem, "bootstrap-signer").BindingOrDie()) + rbacv1helpers.NewRoleBinding(saRolePrefix+"bootstrap-signer", metav1.NamespacePublic).SAs(metav1.NamespaceSystem, "bootstrap-signer").BindingOrDie()) } // NamespaceRoles returns a map of namespace to slice of roles to create -func NamespaceRoles() map[string][]rbac.Role { +func NamespaceRoles() map[string][]rbacv1.Role { return namespaceRoles } // NamespaceRoleBindings returns a map of namespace to slice of roles to create -func NamespaceRoleBindings() map[string][]rbac.RoleBinding { +func NamespaceRoleBindings() map[string][]rbacv1.RoleBinding { return namespaceRoleBindings } diff --git a/plugin/pkg/auth/authorizer/rbac/bootstrappolicy/policy.go b/plugin/pkg/auth/authorizer/rbac/bootstrappolicy/policy.go index b1f3c564b8..5aed8c6819 100644 --- a/plugin/pkg/auth/authorizer/rbac/bootstrappolicy/policy.go +++ b/plugin/pkg/auth/authorizer/rbac/bootstrappolicy/policy.go @@ -17,12 +17,13 @@ limitations under the License. package bootstrappolicy import ( + rbacv1 "k8s.io/api/rbac/v1" "k8s.io/apimachinery/pkg/api/meta" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apiserver/pkg/authentication/user" utilfeature "k8s.io/apiserver/pkg/util/feature" - rbac "k8s.io/kubernetes/pkg/apis/rbac" + rbacv1helpers "k8s.io/kubernetes/pkg/apis/rbac/v1" "k8s.io/kubernetes/pkg/features" ) @@ -32,7 +33,7 @@ var ( ReadUpdate = []string{"get", "list", "watch", "update", "patch"} Label = map[string]string{"kubernetes.io/bootstrapping": "rbac-defaults"} - Annotation = map[string]string{rbac.AutoUpdateAnnotationKey: "true"} + Annotation = map[string]string{rbacv1.AutoUpdateAnnotationKey: "true"} ) const ( @@ -78,105 +79,105 @@ func addDefaultMetadata(obj runtime.Object) { metadata.SetAnnotations(annotations) } -func addClusterRoleLabel(roles []rbac.ClusterRole) { +func addClusterRoleLabel(roles []rbacv1.ClusterRole) { for i := range roles { addDefaultMetadata(&roles[i]) } return } -func addClusterRoleBindingLabel(rolebindings []rbac.ClusterRoleBinding) { +func addClusterRoleBindingLabel(rolebindings []rbacv1.ClusterRoleBinding) { for i := range rolebindings { addDefaultMetadata(&rolebindings[i]) } return } -func NodeRules() []rbac.PolicyRule { - nodePolicyRules := []rbac.PolicyRule{ +func NodeRules() []rbacv1.PolicyRule { + nodePolicyRules := []rbacv1.PolicyRule{ // Needed to check API access. These creates are non-mutating - rbac.NewRule("create").Groups(authenticationGroup).Resources("tokenreviews").RuleOrDie(), - rbac.NewRule("create").Groups(authorizationGroup).Resources("subjectaccessreviews", "localsubjectaccessreviews").RuleOrDie(), + rbacv1helpers.NewRule("create").Groups(authenticationGroup).Resources("tokenreviews").RuleOrDie(), + rbacv1helpers.NewRule("create").Groups(authorizationGroup).Resources("subjectaccessreviews", "localsubjectaccessreviews").RuleOrDie(), // Needed to build serviceLister, to populate env vars for services - rbac.NewRule(Read...).Groups(legacyGroup).Resources("services").RuleOrDie(), + rbacv1helpers.NewRule(Read...).Groups(legacyGroup).Resources("services").RuleOrDie(), // Nodes can register Node API objects and report status. // Use the NodeRestriction admission plugin to limit a node to creating/updating its own API object. - rbac.NewRule("create", "get", "list", "watch").Groups(legacyGroup).Resources("nodes").RuleOrDie(), - rbac.NewRule("update", "patch").Groups(legacyGroup).Resources("nodes/status").RuleOrDie(), - rbac.NewRule("update", "patch", "delete").Groups(legacyGroup).Resources("nodes").RuleOrDie(), + rbacv1helpers.NewRule("create", "get", "list", "watch").Groups(legacyGroup).Resources("nodes").RuleOrDie(), + rbacv1helpers.NewRule("update", "patch").Groups(legacyGroup).Resources("nodes/status").RuleOrDie(), + rbacv1helpers.NewRule("update", "patch", "delete").Groups(legacyGroup).Resources("nodes").RuleOrDie(), // TODO: restrict to the bound node as creator in the NodeRestrictions admission plugin - rbac.NewRule("create", "update", "patch").Groups(legacyGroup).Resources("events").RuleOrDie(), + rbacv1helpers.NewRule("create", "update", "patch").Groups(legacyGroup).Resources("events").RuleOrDie(), // TODO: restrict to pods scheduled on the bound node once field selectors are supported by list/watch authorization - rbac.NewRule(Read...).Groups(legacyGroup).Resources("pods").RuleOrDie(), + rbacv1helpers.NewRule(Read...).Groups(legacyGroup).Resources("pods").RuleOrDie(), // Needed for the node to create/delete mirror pods. // Use the NodeRestriction admission plugin to limit a node to creating/deleting mirror pods bound to itself. - rbac.NewRule("create", "delete").Groups(legacyGroup).Resources("pods").RuleOrDie(), + rbacv1helpers.NewRule("create", "delete").Groups(legacyGroup).Resources("pods").RuleOrDie(), // Needed for the node to report status of pods it is running. // Use the NodeRestriction admission plugin to limit a node to updating status of pods bound to itself. - rbac.NewRule("update").Groups(legacyGroup).Resources("pods/status").RuleOrDie(), + rbacv1helpers.NewRule("update").Groups(legacyGroup).Resources("pods/status").RuleOrDie(), // Needed for the node to create pod evictions. // Use the NodeRestriction admission plugin to limit a node to creating evictions for pods bound to itself. - rbac.NewRule("create").Groups(legacyGroup).Resources("pods/eviction").RuleOrDie(), + rbacv1helpers.NewRule("create").Groups(legacyGroup).Resources("pods/eviction").RuleOrDie(), // Needed for imagepullsecrets, rbd/ceph and secret volumes, and secrets in envs // Needed for configmap volume and envs // Use the Node authorization mode to limit a node to get secrets/configmaps referenced by pods bound to itself. - rbac.NewRule("get", "list", "watch").Groups(legacyGroup).Resources("secrets", "configmaps").RuleOrDie(), + rbacv1helpers.NewRule("get", "list", "watch").Groups(legacyGroup).Resources("secrets", "configmaps").RuleOrDie(), // Needed for persistent volumes // Use the Node authorization mode to limit a node to get pv/pvc objects referenced by pods bound to itself. - rbac.NewRule("get").Groups(legacyGroup).Resources("persistentvolumeclaims", "persistentvolumes").RuleOrDie(), + rbacv1helpers.NewRule("get").Groups(legacyGroup).Resources("persistentvolumeclaims", "persistentvolumes").RuleOrDie(), // TODO: add to the Node authorizer and restrict to endpoints referenced by pods or PVs bound to the node // Needed for glusterfs volumes - rbac.NewRule("get").Groups(legacyGroup).Resources("endpoints").RuleOrDie(), + rbacv1helpers.NewRule("get").Groups(legacyGroup).Resources("endpoints").RuleOrDie(), // Used to create a certificatesigningrequest for a node-specific client certificate, and watch // for it to be signed. This allows the kubelet to rotate it's own certificate. - rbac.NewRule("create", "get", "list", "watch").Groups(certificatesGroup).Resources("certificatesigningrequests").RuleOrDie(), + rbacv1helpers.NewRule("create", "get", "list", "watch").Groups(certificatesGroup).Resources("certificatesigningrequests").RuleOrDie(), } if utilfeature.DefaultFeatureGate.Enabled(features.ExpandPersistentVolumes) { // Use the Node authorization mode to limit a node to update status of pvc objects referenced by pods bound to itself. // Use the NodeRestriction admission plugin to limit a node to just update the status stanza. - pvcStatusPolicyRule := rbac.NewRule("get", "update", "patch").Groups(legacyGroup).Resources("persistentvolumeclaims/status").RuleOrDie() + pvcStatusPolicyRule := rbacv1helpers.NewRule("get", "update", "patch").Groups(legacyGroup).Resources("persistentvolumeclaims/status").RuleOrDie() nodePolicyRules = append(nodePolicyRules, pvcStatusPolicyRule) } if utilfeature.DefaultFeatureGate.Enabled(features.TokenRequest) { // Use the Node authorization to limit a node to create tokens for service accounts running on that node // Use the NodeRestriction admission plugin to limit a node to create tokens bound to pods on that node - tokenRequestRule := rbac.NewRule("create").Groups(legacyGroup).Resources("serviceaccounts/token").RuleOrDie() + tokenRequestRule := rbacv1helpers.NewRule("create").Groups(legacyGroup).Resources("serviceaccounts/token").RuleOrDie() nodePolicyRules = append(nodePolicyRules, tokenRequestRule) } // CSI if utilfeature.DefaultFeatureGate.Enabled(features.CSIPersistentVolume) { - volAttachRule := rbac.NewRule("get").Groups(storageGroup).Resources("volumeattachments").RuleOrDie() + volAttachRule := rbacv1helpers.NewRule("get").Groups(storageGroup).Resources("volumeattachments").RuleOrDie() nodePolicyRules = append(nodePolicyRules, volAttachRule) } return nodePolicyRules } // ClusterRoles returns the cluster roles to bootstrap an API server with -func ClusterRoles() []rbac.ClusterRole { - roles := []rbac.ClusterRole{ +func ClusterRoles() []rbacv1.ClusterRole { + roles := []rbacv1.ClusterRole{ { // a "root" role which can do absolutely anything ObjectMeta: metav1.ObjectMeta{Name: "cluster-admin"}, - Rules: []rbac.PolicyRule{ - rbac.NewRule("*").Groups("*").Resources("*").RuleOrDie(), - rbac.NewRule("*").URLs("*").RuleOrDie(), + Rules: []rbacv1.PolicyRule{ + rbacv1helpers.NewRule("*").Groups("*").Resources("*").RuleOrDie(), + rbacv1helpers.NewRule("*").URLs("*").RuleOrDie(), }, }, { // a role which provides just enough power to determine if the server is ready and discover API versions for negotiation ObjectMeta: metav1.ObjectMeta{Name: "system:discovery"}, - Rules: []rbac.PolicyRule{ - rbac.NewRule("get").URLs( + Rules: []rbacv1.PolicyRule{ + rbacv1helpers.NewRule("get").URLs( "/healthz", "/version", "/version/", // remove once swagger 1.2 support is removed "/swaggerapi", "/swaggerapi/*", @@ -192,16 +193,16 @@ func ClusterRoles() []rbac.ClusterRole { { // a role which provides minimal resource access to allow a "normal" user to learn information about themselves ObjectMeta: metav1.ObjectMeta{Name: "system:basic-user"}, - Rules: []rbac.PolicyRule{ + Rules: []rbacv1.PolicyRule{ // TODO add future selfsubjectrulesreview, project request APIs, project listing APIs - rbac.NewRule("create").Groups(authorizationGroup).Resources("selfsubjectaccessreviews", "selfsubjectrulesreviews").RuleOrDie(), + rbacv1helpers.NewRule("create").Groups(authorizationGroup).Resources("selfsubjectaccessreviews", "selfsubjectrulesreviews").RuleOrDie(), }, }, { // a role for a namespace level admin. It is `edit` plus the power to grant permissions to other users. ObjectMeta: metav1.ObjectMeta{Name: "admin"}, - AggregationRule: &rbac.AggregationRule{ + AggregationRule: &rbacv1.AggregationRule{ ClusterRoleSelectors: []metav1.LabelSelector{{MatchLabels: map[string]string{"rbac.authorization.k8s.io/aggregate-to-admin": "true"}}}, }, }, @@ -210,7 +211,7 @@ func ClusterRoles() []rbac.ClusterRole { // It does not grant powers for "privileged" resources which are domain of the system: `/status` // subresources or `quota`/`limits` which are used to control namespaces ObjectMeta: metav1.ObjectMeta{Name: "edit"}, - AggregationRule: &rbac.AggregationRule{ + AggregationRule: &rbacv1.AggregationRule{ ClusterRoleSelectors: []metav1.LabelSelector{{MatchLabels: map[string]string{"rbac.authorization.k8s.io/aggregate-to-edit": "true"}}}, }, }, @@ -218,46 +219,46 @@ func ClusterRoles() []rbac.ClusterRole { // a role for namespace level viewing. It grants Read-only access to non-escalating resources in // a namespace. ObjectMeta: metav1.ObjectMeta{Name: "view"}, - AggregationRule: &rbac.AggregationRule{ + AggregationRule: &rbacv1.AggregationRule{ ClusterRoleSelectors: []metav1.LabelSelector{{MatchLabels: map[string]string{"rbac.authorization.k8s.io/aggregate-to-view": "true"}}}, }, }, { // a role for a namespace level admin. It is `edit` plus the power to grant permissions to other users. ObjectMeta: metav1.ObjectMeta{Name: "system:aggregate-to-admin", Labels: map[string]string{"rbac.authorization.k8s.io/aggregate-to-admin": "true"}}, - Rules: []rbac.PolicyRule{ - rbac.NewRule(ReadWrite...).Groups(legacyGroup).Resources("pods", "pods/attach", "pods/proxy", "pods/exec", "pods/portforward").RuleOrDie(), - rbac.NewRule(ReadWrite...).Groups(legacyGroup).Resources("replicationcontrollers", "replicationcontrollers/scale", "serviceaccounts", + Rules: []rbacv1.PolicyRule{ + rbacv1helpers.NewRule(ReadWrite...).Groups(legacyGroup).Resources("pods", "pods/attach", "pods/proxy", "pods/exec", "pods/portforward").RuleOrDie(), + rbacv1helpers.NewRule(ReadWrite...).Groups(legacyGroup).Resources("replicationcontrollers", "replicationcontrollers/scale", "serviceaccounts", "services", "services/proxy", "endpoints", "persistentvolumeclaims", "configmaps", "secrets").RuleOrDie(), - rbac.NewRule(Read...).Groups(legacyGroup).Resources("limitranges", "resourcequotas", "bindings", "events", + rbacv1helpers.NewRule(Read...).Groups(legacyGroup).Resources("limitranges", "resourcequotas", "bindings", "events", "pods/status", "resourcequotas/status", "namespaces/status", "replicationcontrollers/status", "pods/log").RuleOrDie(), // read access to namespaces at the namespace scope means you can read *this* namespace. This can be used as an // indicator of which namespaces you have access to. - rbac.NewRule(Read...).Groups(legacyGroup).Resources("namespaces").RuleOrDie(), - rbac.NewRule("impersonate").Groups(legacyGroup).Resources("serviceaccounts").RuleOrDie(), + rbacv1helpers.NewRule(Read...).Groups(legacyGroup).Resources("namespaces").RuleOrDie(), + rbacv1helpers.NewRule("impersonate").Groups(legacyGroup).Resources("serviceaccounts").RuleOrDie(), - rbac.NewRule(ReadWrite...).Groups(appsGroup).Resources( + rbacv1helpers.NewRule(ReadWrite...).Groups(appsGroup).Resources( "statefulsets", "statefulsets/scale", "daemonsets", "deployments", "deployments/scale", "deployments/rollback", "replicasets", "replicasets/scale").RuleOrDie(), - rbac.NewRule(ReadWrite...).Groups(autoscalingGroup).Resources("horizontalpodautoscalers").RuleOrDie(), + rbacv1helpers.NewRule(ReadWrite...).Groups(autoscalingGroup).Resources("horizontalpodautoscalers").RuleOrDie(), - rbac.NewRule(ReadWrite...).Groups(batchGroup).Resources("jobs", "cronjobs").RuleOrDie(), + rbacv1helpers.NewRule(ReadWrite...).Groups(batchGroup).Resources("jobs", "cronjobs").RuleOrDie(), - rbac.NewRule(ReadWrite...).Groups(extensionsGroup).Resources("daemonsets", + rbacv1helpers.NewRule(ReadWrite...).Groups(extensionsGroup).Resources("daemonsets", "deployments", "deployments/scale", "deployments/rollback", "ingresses", "replicasets", "replicasets/scale", "replicationcontrollers/scale", "networkpolicies").RuleOrDie(), - rbac.NewRule(ReadWrite...).Groups(policyGroup).Resources("poddisruptionbudgets").RuleOrDie(), + rbacv1helpers.NewRule(ReadWrite...).Groups(policyGroup).Resources("poddisruptionbudgets").RuleOrDie(), - rbac.NewRule(ReadWrite...).Groups(networkingGroup).Resources("networkpolicies").RuleOrDie(), + rbacv1helpers.NewRule(ReadWrite...).Groups(networkingGroup).Resources("networkpolicies").RuleOrDie(), // additional admin powers - rbac.NewRule("create").Groups(authorizationGroup).Resources("localsubjectaccessreviews").RuleOrDie(), - rbac.NewRule(ReadWrite...).Groups(rbacGroup).Resources("roles", "rolebindings").RuleOrDie(), + rbacv1helpers.NewRule("create").Groups(authorizationGroup).Resources("localsubjectaccessreviews").RuleOrDie(), + rbacv1helpers.NewRule(ReadWrite...).Groups(rbacGroup).Resources("roles", "rolebindings").RuleOrDie(), }, }, { @@ -265,75 +266,75 @@ func ClusterRoles() []rbac.ClusterRole { // It does not grant powers for "privileged" resources which are domain of the system: `/status` // subresources or `quota`/`limits` which are used to control namespaces ObjectMeta: metav1.ObjectMeta{Name: "system:aggregate-to-edit", Labels: map[string]string{"rbac.authorization.k8s.io/aggregate-to-edit": "true"}}, - Rules: []rbac.PolicyRule{ - rbac.NewRule(ReadWrite...).Groups(legacyGroup).Resources("pods", "pods/attach", "pods/proxy", "pods/exec", "pods/portforward").RuleOrDie(), - rbac.NewRule(ReadWrite...).Groups(legacyGroup).Resources("replicationcontrollers", "replicationcontrollers/scale", "serviceaccounts", + Rules: []rbacv1.PolicyRule{ + rbacv1helpers.NewRule(ReadWrite...).Groups(legacyGroup).Resources("pods", "pods/attach", "pods/proxy", "pods/exec", "pods/portforward").RuleOrDie(), + rbacv1helpers.NewRule(ReadWrite...).Groups(legacyGroup).Resources("replicationcontrollers", "replicationcontrollers/scale", "serviceaccounts", "services", "services/proxy", "endpoints", "persistentvolumeclaims", "configmaps", "secrets").RuleOrDie(), - rbac.NewRule(Read...).Groups(legacyGroup).Resources("limitranges", "resourcequotas", "bindings", "events", + rbacv1helpers.NewRule(Read...).Groups(legacyGroup).Resources("limitranges", "resourcequotas", "bindings", "events", "pods/status", "resourcequotas/status", "namespaces/status", "replicationcontrollers/status", "pods/log").RuleOrDie(), // read access to namespaces at the namespace scope means you can read *this* namespace. This can be used as an // indicator of which namespaces you have access to. - rbac.NewRule(Read...).Groups(legacyGroup).Resources("namespaces").RuleOrDie(), - rbac.NewRule("impersonate").Groups(legacyGroup).Resources("serviceaccounts").RuleOrDie(), + rbacv1helpers.NewRule(Read...).Groups(legacyGroup).Resources("namespaces").RuleOrDie(), + rbacv1helpers.NewRule("impersonate").Groups(legacyGroup).Resources("serviceaccounts").RuleOrDie(), - rbac.NewRule(ReadWrite...).Groups(appsGroup).Resources( + rbacv1helpers.NewRule(ReadWrite...).Groups(appsGroup).Resources( "statefulsets", "statefulsets/scale", "daemonsets", "deployments", "deployments/scale", "deployments/rollback", "replicasets", "replicasets/scale").RuleOrDie(), - rbac.NewRule(ReadWrite...).Groups(autoscalingGroup).Resources("horizontalpodautoscalers").RuleOrDie(), + rbacv1helpers.NewRule(ReadWrite...).Groups(autoscalingGroup).Resources("horizontalpodautoscalers").RuleOrDie(), - rbac.NewRule(ReadWrite...).Groups(batchGroup).Resources("jobs", "cronjobs").RuleOrDie(), + rbacv1helpers.NewRule(ReadWrite...).Groups(batchGroup).Resources("jobs", "cronjobs").RuleOrDie(), - rbac.NewRule(ReadWrite...).Groups(extensionsGroup).Resources("daemonsets", + rbacv1helpers.NewRule(ReadWrite...).Groups(extensionsGroup).Resources("daemonsets", "deployments", "deployments/scale", "deployments/rollback", "ingresses", "replicasets", "replicasets/scale", "replicationcontrollers/scale", "networkpolicies").RuleOrDie(), - rbac.NewRule(ReadWrite...).Groups(policyGroup).Resources("poddisruptionbudgets").RuleOrDie(), + rbacv1helpers.NewRule(ReadWrite...).Groups(policyGroup).Resources("poddisruptionbudgets").RuleOrDie(), - rbac.NewRule(ReadWrite...).Groups(networkingGroup).Resources("networkpolicies").RuleOrDie(), + rbacv1helpers.NewRule(ReadWrite...).Groups(networkingGroup).Resources("networkpolicies").RuleOrDie(), }, }, { // a role for namespace level viewing. It grants Read-only access to non-escalating resources in // a namespace. ObjectMeta: metav1.ObjectMeta{Name: "system:aggregate-to-view", Labels: map[string]string{"rbac.authorization.k8s.io/aggregate-to-view": "true"}}, - Rules: []rbac.PolicyRule{ - rbac.NewRule(Read...).Groups(legacyGroup).Resources("pods", "replicationcontrollers", "replicationcontrollers/scale", "serviceaccounts", + Rules: []rbacv1.PolicyRule{ + rbacv1helpers.NewRule(Read...).Groups(legacyGroup).Resources("pods", "replicationcontrollers", "replicationcontrollers/scale", "serviceaccounts", "services", "endpoints", "persistentvolumeclaims", "configmaps").RuleOrDie(), - rbac.NewRule(Read...).Groups(legacyGroup).Resources("limitranges", "resourcequotas", "bindings", "events", + rbacv1helpers.NewRule(Read...).Groups(legacyGroup).Resources("limitranges", "resourcequotas", "bindings", "events", "pods/status", "resourcequotas/status", "namespaces/status", "replicationcontrollers/status", "pods/log").RuleOrDie(), // read access to namespaces at the namespace scope means you can read *this* namespace. This can be used as an // indicator of which namespaces you have access to. - rbac.NewRule(Read...).Groups(legacyGroup).Resources("namespaces").RuleOrDie(), + rbacv1helpers.NewRule(Read...).Groups(legacyGroup).Resources("namespaces").RuleOrDie(), - rbac.NewRule(Read...).Groups(appsGroup).Resources( + rbacv1helpers.NewRule(Read...).Groups(appsGroup).Resources( "statefulsets", "statefulsets/scale", "daemonsets", "deployments", "deployments/scale", "replicasets", "replicasets/scale").RuleOrDie(), - rbac.NewRule(Read...).Groups(autoscalingGroup).Resources("horizontalpodautoscalers").RuleOrDie(), + rbacv1helpers.NewRule(Read...).Groups(autoscalingGroup).Resources("horizontalpodautoscalers").RuleOrDie(), - rbac.NewRule(Read...).Groups(batchGroup).Resources("jobs", "cronjobs").RuleOrDie(), + rbacv1helpers.NewRule(Read...).Groups(batchGroup).Resources("jobs", "cronjobs").RuleOrDie(), - rbac.NewRule(Read...).Groups(extensionsGroup).Resources("daemonsets", "deployments", "deployments/scale", + rbacv1helpers.NewRule(Read...).Groups(extensionsGroup).Resources("daemonsets", "deployments", "deployments/scale", "ingresses", "replicasets", "replicasets/scale", "replicationcontrollers/scale", "networkpolicies").RuleOrDie(), - rbac.NewRule(Read...).Groups(policyGroup).Resources("poddisruptionbudgets").RuleOrDie(), + rbacv1helpers.NewRule(Read...).Groups(policyGroup).Resources("poddisruptionbudgets").RuleOrDie(), - rbac.NewRule(Read...).Groups(networkingGroup).Resources("networkpolicies").RuleOrDie(), + rbacv1helpers.NewRule(Read...).Groups(networkingGroup).Resources("networkpolicies").RuleOrDie(), }, }, { // a role to use for heapster's connections back to the API server ObjectMeta: metav1.ObjectMeta{Name: "system:heapster"}, - Rules: []rbac.PolicyRule{ - rbac.NewRule(Read...).Groups(legacyGroup).Resources("events", "pods", "nodes", "namespaces").RuleOrDie(), - rbac.NewRule(Read...).Groups(extensionsGroup).Resources("deployments").RuleOrDie(), + Rules: []rbacv1.PolicyRule{ + rbacv1helpers.NewRule(Read...).Groups(legacyGroup).Resources("events", "pods", "nodes", "namespaces").RuleOrDie(), + rbacv1helpers.NewRule(Read...).Groups(extensionsGroup).Resources("deployments").RuleOrDie(), }, }, { @@ -345,19 +346,19 @@ func ClusterRoles() []rbac.ClusterRole { // a role to use for node-problem-detector access. It does not get bound to default location since // deployment locations can reasonably vary. ObjectMeta: metav1.ObjectMeta{Name: "system:node-problem-detector"}, - Rules: []rbac.PolicyRule{ - rbac.NewRule("get").Groups(legacyGroup).Resources("nodes").RuleOrDie(), - rbac.NewRule("patch").Groups(legacyGroup).Resources("nodes/status").RuleOrDie(), + Rules: []rbacv1.PolicyRule{ + rbacv1helpers.NewRule("get").Groups(legacyGroup).Resources("nodes").RuleOrDie(), + rbacv1helpers.NewRule("patch").Groups(legacyGroup).Resources("nodes/status").RuleOrDie(), eventsRule(), }, }, { // a role to use for setting up a proxy ObjectMeta: metav1.ObjectMeta{Name: "system:node-proxier"}, - Rules: []rbac.PolicyRule{ + Rules: []rbacv1.PolicyRule{ // Used to build serviceLister - rbac.NewRule("list", "watch").Groups(legacyGroup).Resources("services", "endpoints").RuleOrDie(), - rbac.NewRule("get").Groups(legacyGroup).Resources("nodes").RuleOrDie(), + rbacv1helpers.NewRule("list", "watch").Groups(legacyGroup).Resources("services", "endpoints").RuleOrDie(), + rbacv1helpers.NewRule("get").Groups(legacyGroup).Resources("nodes").RuleOrDie(), eventsRule(), }, @@ -365,98 +366,98 @@ func ClusterRoles() []rbac.ClusterRole { { // a role to use for full access to the kubelet API ObjectMeta: metav1.ObjectMeta{Name: "system:kubelet-api-admin"}, - Rules: []rbac.PolicyRule{ + Rules: []rbacv1.PolicyRule{ // Allow read-only access to the Node API objects - rbac.NewRule("get", "list", "watch").Groups(legacyGroup).Resources("nodes").RuleOrDie(), + rbacv1helpers.NewRule("get", "list", "watch").Groups(legacyGroup).Resources("nodes").RuleOrDie(), // Allow all API calls to the nodes - rbac.NewRule("proxy").Groups(legacyGroup).Resources("nodes").RuleOrDie(), - rbac.NewRule("*").Groups(legacyGroup).Resources("nodes/proxy", "nodes/metrics", "nodes/spec", "nodes/stats", "nodes/log").RuleOrDie(), + rbacv1helpers.NewRule("proxy").Groups(legacyGroup).Resources("nodes").RuleOrDie(), + rbacv1helpers.NewRule("*").Groups(legacyGroup).Resources("nodes/proxy", "nodes/metrics", "nodes/spec", "nodes/stats", "nodes/log").RuleOrDie(), }, }, { // a role to use for bootstrapping a node's client certificates ObjectMeta: metav1.ObjectMeta{Name: "system:node-bootstrapper"}, - Rules: []rbac.PolicyRule{ + Rules: []rbacv1.PolicyRule{ // used to create a certificatesigningrequest for a node-specific client certificate, and watch for it to be signed - rbac.NewRule("create", "get", "list", "watch").Groups(certificatesGroup).Resources("certificatesigningrequests").RuleOrDie(), + rbacv1helpers.NewRule("create", "get", "list", "watch").Groups(certificatesGroup).Resources("certificatesigningrequests").RuleOrDie(), }, }, { // a role to use for allowing authentication and authorization delegation ObjectMeta: metav1.ObjectMeta{Name: "system:auth-delegator"}, - Rules: []rbac.PolicyRule{ + Rules: []rbacv1.PolicyRule{ // These creates are non-mutating - rbac.NewRule("create").Groups(authenticationGroup).Resources("tokenreviews").RuleOrDie(), - rbac.NewRule("create").Groups(authorizationGroup).Resources("subjectaccessreviews").RuleOrDie(), + rbacv1helpers.NewRule("create").Groups(authenticationGroup).Resources("tokenreviews").RuleOrDie(), + rbacv1helpers.NewRule("create").Groups(authorizationGroup).Resources("subjectaccessreviews").RuleOrDie(), }, }, { // a role to use for the API registry, summarization, and proxy handling ObjectMeta: metav1.ObjectMeta{Name: "system:kube-aggregator"}, - Rules: []rbac.PolicyRule{ + Rules: []rbacv1.PolicyRule{ // it needs to see all services so that it knows whether the ones it points to exist or not - rbac.NewRule(Read...).Groups(legacyGroup).Resources("services", "endpoints").RuleOrDie(), + rbacv1helpers.NewRule(Read...).Groups(legacyGroup).Resources("services", "endpoints").RuleOrDie(), }, }, { // a role to use for bootstrapping the kube-controller-manager so it can create the shared informers // service accounts, and secrets that we need to create separate identities for other controllers ObjectMeta: metav1.ObjectMeta{Name: "system:kube-controller-manager"}, - Rules: []rbac.PolicyRule{ + Rules: []rbacv1.PolicyRule{ eventsRule(), - rbac.NewRule("create").Groups(legacyGroup).Resources("endpoints", "secrets", "serviceaccounts").RuleOrDie(), - rbac.NewRule("delete").Groups(legacyGroup).Resources("secrets").RuleOrDie(), - rbac.NewRule("get").Groups(legacyGroup).Resources("endpoints", "namespaces", "secrets", "serviceaccounts").RuleOrDie(), - rbac.NewRule("update").Groups(legacyGroup).Resources("endpoints", "secrets", "serviceaccounts").RuleOrDie(), + rbacv1helpers.NewRule("create").Groups(legacyGroup).Resources("endpoints", "secrets", "serviceaccounts").RuleOrDie(), + rbacv1helpers.NewRule("delete").Groups(legacyGroup).Resources("secrets").RuleOrDie(), + rbacv1helpers.NewRule("get").Groups(legacyGroup).Resources("endpoints", "namespaces", "secrets", "serviceaccounts").RuleOrDie(), + rbacv1helpers.NewRule("update").Groups(legacyGroup).Resources("endpoints", "secrets", "serviceaccounts").RuleOrDie(), // Needed to check API access. These creates are non-mutating - rbac.NewRule("create").Groups(authenticationGroup).Resources("tokenreviews").RuleOrDie(), + rbacv1helpers.NewRule("create").Groups(authenticationGroup).Resources("tokenreviews").RuleOrDie(), // Needed for all shared informers - rbac.NewRule("list", "watch").Groups("*").Resources("*").RuleOrDie(), + rbacv1helpers.NewRule("list", "watch").Groups("*").Resources("*").RuleOrDie(), }, }, { // a role to use for the kube-scheduler ObjectMeta: metav1.ObjectMeta{Name: "system:kube-scheduler"}, - Rules: []rbac.PolicyRule{ + Rules: []rbacv1.PolicyRule{ eventsRule(), // this is for leaderlease access // TODO: scope this to the kube-system namespace - rbac.NewRule("create").Groups(legacyGroup).Resources("endpoints").RuleOrDie(), - rbac.NewRule("get", "update", "patch", "delete").Groups(legacyGroup).Resources("endpoints").Names("kube-scheduler").RuleOrDie(), + rbacv1helpers.NewRule("create").Groups(legacyGroup).Resources("endpoints").RuleOrDie(), + rbacv1helpers.NewRule("get", "update", "patch", "delete").Groups(legacyGroup).Resources("endpoints").Names("kube-scheduler").RuleOrDie(), // fundamental resources - rbac.NewRule(Read...).Groups(legacyGroup).Resources("nodes").RuleOrDie(), - rbac.NewRule("get", "list", "watch", "delete").Groups(legacyGroup).Resources("pods").RuleOrDie(), - rbac.NewRule("create").Groups(legacyGroup).Resources("pods/binding", "bindings").RuleOrDie(), - rbac.NewRule("patch", "update").Groups(legacyGroup).Resources("pods/status").RuleOrDie(), + rbacv1helpers.NewRule(Read...).Groups(legacyGroup).Resources("nodes").RuleOrDie(), + rbacv1helpers.NewRule("get", "list", "watch", "delete").Groups(legacyGroup).Resources("pods").RuleOrDie(), + rbacv1helpers.NewRule("create").Groups(legacyGroup).Resources("pods/binding", "bindings").RuleOrDie(), + rbacv1helpers.NewRule("patch", "update").Groups(legacyGroup).Resources("pods/status").RuleOrDie(), // things that select pods - rbac.NewRule(Read...).Groups(legacyGroup).Resources("services", "replicationcontrollers").RuleOrDie(), - rbac.NewRule(Read...).Groups(appsGroup, extensionsGroup).Resources("replicasets").RuleOrDie(), - rbac.NewRule(Read...).Groups(appsGroup).Resources("statefulsets").RuleOrDie(), + rbacv1helpers.NewRule(Read...).Groups(legacyGroup).Resources("services", "replicationcontrollers").RuleOrDie(), + rbacv1helpers.NewRule(Read...).Groups(appsGroup, extensionsGroup).Resources("replicasets").RuleOrDie(), + rbacv1helpers.NewRule(Read...).Groups(appsGroup).Resources("statefulsets").RuleOrDie(), // things that pods use or applies to them - rbac.NewRule(Read...).Groups(policyGroup).Resources("poddisruptionbudgets").RuleOrDie(), - rbac.NewRule(Read...).Groups(legacyGroup).Resources("persistentvolumeclaims", "persistentvolumes").RuleOrDie(), + rbacv1helpers.NewRule(Read...).Groups(policyGroup).Resources("poddisruptionbudgets").RuleOrDie(), + rbacv1helpers.NewRule(Read...).Groups(legacyGroup).Resources("persistentvolumeclaims", "persistentvolumes").RuleOrDie(), }, }, { // a role to use for the kube-dns pod ObjectMeta: metav1.ObjectMeta{Name: "system:kube-dns"}, - Rules: []rbac.PolicyRule{ - rbac.NewRule("list", "watch").Groups(legacyGroup).Resources("endpoints", "services").RuleOrDie(), + Rules: []rbacv1.PolicyRule{ + rbacv1helpers.NewRule("list", "watch").Groups(legacyGroup).Resources("endpoints", "services").RuleOrDie(), }, }, { // a role for an external/out-of-tree persistent volume provisioner ObjectMeta: metav1.ObjectMeta{Name: "system:persistent-volume-provisioner"}, - Rules: []rbac.PolicyRule{ - rbac.NewRule("get", "list", "watch", "create", "delete").Groups(legacyGroup).Resources("persistentvolumes").RuleOrDie(), + Rules: []rbacv1.PolicyRule{ + rbacv1helpers.NewRule("get", "list", "watch", "create", "delete").Groups(legacyGroup).Resources("persistentvolumes").RuleOrDie(), // update is needed in addition to read access for setting lock annotations on PVCs - rbac.NewRule("get", "list", "watch", "update").Groups(legacyGroup).Resources("persistentvolumeclaims").RuleOrDie(), - rbac.NewRule(Read...).Groups(storageGroup).Resources("storageclasses").RuleOrDie(), + rbacv1helpers.NewRule("get", "list", "watch", "update").Groups(legacyGroup).Resources("persistentvolumeclaims").RuleOrDie(), + rbacv1helpers.NewRule(Read...).Groups(storageGroup).Resources("storageclasses").RuleOrDie(), // Needed for watching provisioning success and failure events - rbac.NewRule("watch").Groups(legacyGroup).Resources("events").RuleOrDie(), + rbacv1helpers.NewRule("watch").Groups(legacyGroup).Resources("events").RuleOrDie(), eventsRule(), }, @@ -464,52 +465,52 @@ func ClusterRoles() []rbac.ClusterRole { { // a role for the csi external provisioner ObjectMeta: metav1.ObjectMeta{Name: "system:csi-external-provisioner"}, - Rules: []rbac.PolicyRule{ - rbac.NewRule("create", "delete", "list", "watch").Groups(legacyGroup).Resources("persistentvolumes").RuleOrDie(), - rbac.NewRule("get", "list", "watch", "update", "patch").Groups(legacyGroup).Resources("persistentvolumeclaims").RuleOrDie(), - rbac.NewRule("list", "watch").Groups(storageGroup).Resources("storageclasses").RuleOrDie(), - rbac.NewRule("get", "list", "watch", "create", "update", "patch").Groups(legacyGroup).Resources("events").RuleOrDie(), + Rules: []rbacv1.PolicyRule{ + rbacv1helpers.NewRule("create", "delete", "list", "watch").Groups(legacyGroup).Resources("persistentvolumes").RuleOrDie(), + rbacv1helpers.NewRule("get", "list", "watch", "update", "patch").Groups(legacyGroup).Resources("persistentvolumeclaims").RuleOrDie(), + rbacv1helpers.NewRule("list", "watch").Groups(storageGroup).Resources("storageclasses").RuleOrDie(), + rbacv1helpers.NewRule("get", "list", "watch", "create", "update", "patch").Groups(legacyGroup).Resources("events").RuleOrDie(), }, }, { // a role for the csi external attacher ObjectMeta: metav1.ObjectMeta{Name: "system:csi-external-attacher"}, - Rules: []rbac.PolicyRule{ - rbac.NewRule("get", "list", "watch", "update", "patch").Groups(legacyGroup).Resources("persistentvolumes").RuleOrDie(), - rbac.NewRule("get", "list", "watch").Groups(legacyGroup).Resources("nodes").RuleOrDie(), - rbac.NewRule("get", "list", "watch", "update", "patch").Groups(storageGroup).Resources("volumeattachments").RuleOrDie(), - rbac.NewRule("get", "list", "watch", "create", "update", "patch").Groups(legacyGroup).Resources("events").RuleOrDie(), + Rules: []rbacv1.PolicyRule{ + rbacv1helpers.NewRule("get", "list", "watch", "update", "patch").Groups(legacyGroup).Resources("persistentvolumes").RuleOrDie(), + rbacv1helpers.NewRule("get", "list", "watch").Groups(legacyGroup).Resources("nodes").RuleOrDie(), + rbacv1helpers.NewRule("get", "list", "watch", "update", "patch").Groups(storageGroup).Resources("volumeattachments").RuleOrDie(), + rbacv1helpers.NewRule("get", "list", "watch", "create", "update", "patch").Groups(legacyGroup).Resources("events").RuleOrDie(), }, }, { ObjectMeta: metav1.ObjectMeta{Name: "system:aws-cloud-provider"}, - Rules: []rbac.PolicyRule{ - rbac.NewRule("get", "patch").Groups(legacyGroup).Resources("nodes").RuleOrDie(), + Rules: []rbacv1.PolicyRule{ + rbacv1helpers.NewRule("get", "patch").Groups(legacyGroup).Resources("nodes").RuleOrDie(), eventsRule(), }, }, { // a role making the csrapprover controller approve a node client CSR ObjectMeta: metav1.ObjectMeta{Name: "system:certificates.k8s.io:certificatesigningrequests:nodeclient"}, - Rules: []rbac.PolicyRule{ - rbac.NewRule("create").Groups(certificatesGroup).Resources("certificatesigningrequests/nodeclient").RuleOrDie(), + Rules: []rbacv1.PolicyRule{ + rbacv1helpers.NewRule("create").Groups(certificatesGroup).Resources("certificatesigningrequests/nodeclient").RuleOrDie(), }, }, { // a role making the csrapprover controller approve a node client CSR requested by the node itself ObjectMeta: metav1.ObjectMeta{Name: "system:certificates.k8s.io:certificatesigningrequests:selfnodeclient"}, - Rules: []rbac.PolicyRule{ - rbac.NewRule("create").Groups(certificatesGroup).Resources("certificatesigningrequests/selfnodeclient").RuleOrDie(), + Rules: []rbacv1.PolicyRule{ + rbacv1helpers.NewRule("create").Groups(certificatesGroup).Resources("certificatesigningrequests/selfnodeclient").RuleOrDie(), }, }, } if utilfeature.DefaultFeatureGate.Enabled(features.VolumeScheduling) { - roles = append(roles, rbac.ClusterRole{ + roles = append(roles, rbacv1.ClusterRole{ ObjectMeta: metav1.ObjectMeta{Name: "system:volume-scheduler"}, - Rules: []rbac.PolicyRule{ - rbac.NewRule(ReadUpdate...).Groups(legacyGroup).Resources("persistentvolumes").RuleOrDie(), - rbac.NewRule(Read...).Groups(storageGroup).Resources("storageclasses").RuleOrDie(), + Rules: []rbacv1.PolicyRule{ + rbacv1helpers.NewRule(ReadUpdate...).Groups(legacyGroup).Resources("persistentvolumes").RuleOrDie(), + rbacv1helpers.NewRule(Read...).Groups(storageGroup).Resources("storageclasses").RuleOrDie(), }, }) } @@ -521,27 +522,27 @@ func ClusterRoles() []rbac.ClusterRole { const systemNodeRoleName = "system:node" // ClusterRoleBindings return default rolebindings to the default roles -func ClusterRoleBindings() []rbac.ClusterRoleBinding { - rolebindings := []rbac.ClusterRoleBinding{ - rbac.NewClusterBinding("cluster-admin").Groups(user.SystemPrivilegedGroup).BindingOrDie(), - rbac.NewClusterBinding("system:discovery").Groups(user.AllAuthenticated, user.AllUnauthenticated).BindingOrDie(), - rbac.NewClusterBinding("system:basic-user").Groups(user.AllAuthenticated, user.AllUnauthenticated).BindingOrDie(), - rbac.NewClusterBinding("system:node-proxier").Users(user.KubeProxy).BindingOrDie(), - rbac.NewClusterBinding("system:kube-controller-manager").Users(user.KubeControllerManager).BindingOrDie(), - rbac.NewClusterBinding("system:kube-dns").SAs("kube-system", "kube-dns").BindingOrDie(), - rbac.NewClusterBinding("system:kube-scheduler").Users(user.KubeScheduler).BindingOrDie(), - rbac.NewClusterBinding("system:aws-cloud-provider").SAs("kube-system", "aws-cloud-provider").BindingOrDie(), +func ClusterRoleBindings() []rbacv1.ClusterRoleBinding { + rolebindings := []rbacv1.ClusterRoleBinding{ + rbacv1helpers.NewClusterBinding("cluster-admin").Groups(user.SystemPrivilegedGroup).BindingOrDie(), + rbacv1helpers.NewClusterBinding("system:discovery").Groups(user.AllAuthenticated, user.AllUnauthenticated).BindingOrDie(), + rbacv1helpers.NewClusterBinding("system:basic-user").Groups(user.AllAuthenticated, user.AllUnauthenticated).BindingOrDie(), + rbacv1helpers.NewClusterBinding("system:node-proxier").Users(user.KubeProxy).BindingOrDie(), + rbacv1helpers.NewClusterBinding("system:kube-controller-manager").Users(user.KubeControllerManager).BindingOrDie(), + rbacv1helpers.NewClusterBinding("system:kube-dns").SAs("kube-system", "kube-dns").BindingOrDie(), + rbacv1helpers.NewClusterBinding("system:kube-scheduler").Users(user.KubeScheduler).BindingOrDie(), + rbacv1helpers.NewClusterBinding("system:aws-cloud-provider").SAs("kube-system", "aws-cloud-provider").BindingOrDie(), // This default binding of the system:node role to the system:nodes group is deprecated in 1.7 with the availability of the Node authorizer. // This leaves the binding, but with an empty set of subjects, so that tightening reconciliation can remove the subject. { ObjectMeta: metav1.ObjectMeta{Name: systemNodeRoleName}, - RoleRef: rbac.RoleRef{APIGroup: rbac.GroupName, Kind: "ClusterRole", Name: systemNodeRoleName}, + RoleRef: rbacv1.RoleRef{APIGroup: rbacv1.GroupName, Kind: "ClusterRole", Name: systemNodeRoleName}, }, } if utilfeature.DefaultFeatureGate.Enabled(features.VolumeScheduling) { - rolebindings = append(rolebindings, rbac.NewClusterBinding("system:volume-scheduler").Users(user.KubeScheduler).BindingOrDie()) + rolebindings = append(rolebindings, rbacv1helpers.NewClusterBinding("system:volume-scheduler").Users(user.KubeScheduler).BindingOrDie()) } addClusterRoleBindingLabel(rolebindings) diff --git a/plugin/pkg/auth/authorizer/rbac/bootstrappolicy/policy_test.go b/plugin/pkg/auth/authorizer/rbac/bootstrappolicy/policy_test.go index 830d92576f..1b024c4414 100644 --- a/plugin/pkg/auth/authorizer/rbac/bootstrappolicy/policy_test.go +++ b/plugin/pkg/auth/authorizer/rbac/bootstrappolicy/policy_test.go @@ -34,8 +34,8 @@ import ( "k8s.io/kubernetes/pkg/api/legacyscheme" api "k8s.io/kubernetes/pkg/apis/core" _ "k8s.io/kubernetes/pkg/apis/core/install" - "k8s.io/kubernetes/pkg/apis/rbac" _ "k8s.io/kubernetes/pkg/apis/rbac/install" + rbacv1helpers "k8s.io/kubernetes/pkg/apis/rbac/v1" rbacregistryvalidation "k8s.io/kubernetes/pkg/registry/rbac/validation" "k8s.io/kubernetes/plugin/pkg/auth/authorizer/rbac/bootstrappolicy" ) @@ -43,12 +43,12 @@ import ( // semanticRoles is a few enumerated roles for which the relationships are well established // and we want to maintain symmetric roles type semanticRoles struct { - admin *rbac.ClusterRole - edit *rbac.ClusterRole - view *rbac.ClusterRole + admin *rbacv1.ClusterRole + edit *rbacv1.ClusterRole + view *rbacv1.ClusterRole } -func getSemanticRoles(roles []rbac.ClusterRole) semanticRoles { +func getSemanticRoles(roles []rbacv1.ClusterRole) semanticRoles { ret := semanticRoles{} for i := range roles { role := roles[i] @@ -81,10 +81,10 @@ func TestCovers(t *testing.T) { // additionalAdminPowers is the list of powers that we expect to be different than the editor role. // one resource per rule to make the "does not already contain" check easy -var additionalAdminPowers = []rbac.PolicyRule{ - rbac.NewRule("create").Groups("authorization.k8s.io").Resources("localsubjectaccessreviews").RuleOrDie(), - rbac.NewRule(bootstrappolicy.ReadWrite...).Groups("rbac.authorization.k8s.io").Resources("rolebindings").RuleOrDie(), - rbac.NewRule(bootstrappolicy.ReadWrite...).Groups("rbac.authorization.k8s.io").Resources("roles").RuleOrDie(), +var additionalAdminPowers = []rbacv1.PolicyRule{ + rbacv1helpers.NewRule("create").Groups("authorization.k8s.io").Resources("localsubjectaccessreviews").RuleOrDie(), + rbacv1helpers.NewRule(bootstrappolicy.ReadWrite...).Groups("rbac.authorization.k8s.io").Resources("rolebindings").RuleOrDie(), + rbacv1helpers.NewRule(bootstrappolicy.ReadWrite...).Groups("rbac.authorization.k8s.io").Resources("roles").RuleOrDie(), } func TestAdminEditRelationship(t *testing.T) { @@ -92,7 +92,7 @@ func TestAdminEditRelationship(t *testing.T) { // confirm that the edit role doesn't already have extra powers for _, rule := range additionalAdminPowers { - if covers, _ := rbacregistryvalidation.Covers(semanticRoles.edit.Rules, []rbac.PolicyRule{rule}); covers { + if covers, _ := rbacregistryvalidation.Covers(semanticRoles.edit.Rules, []rbacv1.PolicyRule{rule}); covers { t.Errorf("edit has extra powers: %#v", rule) } } @@ -109,19 +109,19 @@ func TestAdminEditRelationship(t *testing.T) { // viewEscalatingNamespaceResources is the list of rules that would allow privilege escalation attacks based on // ability to view (GET) them -var viewEscalatingNamespaceResources = []rbac.PolicyRule{ - rbac.NewRule(bootstrappolicy.Read...).Groups("").Resources("pods/attach").RuleOrDie(), - rbac.NewRule(bootstrappolicy.Read...).Groups("").Resources("pods/proxy").RuleOrDie(), - rbac.NewRule(bootstrappolicy.Read...).Groups("").Resources("pods/exec").RuleOrDie(), - rbac.NewRule(bootstrappolicy.Read...).Groups("").Resources("pods/portforward").RuleOrDie(), - rbac.NewRule(bootstrappolicy.Read...).Groups("").Resources("secrets").RuleOrDie(), - rbac.NewRule(bootstrappolicy.Read...).Groups("").Resources("services/proxy").RuleOrDie(), +var viewEscalatingNamespaceResources = []rbacv1.PolicyRule{ + rbacv1helpers.NewRule(bootstrappolicy.Read...).Groups("").Resources("pods/attach").RuleOrDie(), + rbacv1helpers.NewRule(bootstrappolicy.Read...).Groups("").Resources("pods/proxy").RuleOrDie(), + rbacv1helpers.NewRule(bootstrappolicy.Read...).Groups("").Resources("pods/exec").RuleOrDie(), + rbacv1helpers.NewRule(bootstrappolicy.Read...).Groups("").Resources("pods/portforward").RuleOrDie(), + rbacv1helpers.NewRule(bootstrappolicy.Read...).Groups("").Resources("secrets").RuleOrDie(), + rbacv1helpers.NewRule(bootstrappolicy.Read...).Groups("").Resources("services/proxy").RuleOrDie(), } // ungettableResources is the list of rules that don't allow to view (GET) them // this is purposefully separate list to distinguish from escalating privs -var ungettableResources = []rbac.PolicyRule{ - rbac.NewRule(bootstrappolicy.Read...).Groups("apps", "extensions").Resources("deployments/rollback").RuleOrDie(), +var ungettableResources = []rbacv1.PolicyRule{ + rbacv1helpers.NewRule(bootstrappolicy.Read...).Groups("apps", "extensions").Resources("deployments/rollback").RuleOrDie(), } func TestEditViewRelationship(t *testing.T) { @@ -143,7 +143,7 @@ func TestEditViewRelationship(t *testing.T) { // confirm that the view role doesn't already have extra powers for _, rule := range viewEscalatingNamespaceResources { - if covers, _ := rbacregistryvalidation.Covers(semanticRoles.view.Rules, []rbac.PolicyRule{rule}); covers { + if covers, _ := rbacregistryvalidation.Covers(semanticRoles.view.Rules, []rbacv1.PolicyRule{rule}); covers { t.Errorf("view has extra powers: %#v", rule) } } @@ -151,7 +151,7 @@ func TestEditViewRelationship(t *testing.T) { // confirm that the view role doesn't have ungettable resources for _, rule := range ungettableResources { - if covers, _ := rbacregistryvalidation.Covers(semanticRoles.view.Rules, []rbac.PolicyRule{rule}); covers { + if covers, _ := rbacregistryvalidation.Covers(semanticRoles.view.Rules, []rbacv1.PolicyRule{rule}); covers { t.Errorf("view has ungettable resource: %#v", rule) } } diff --git a/plugin/pkg/auth/authorizer/rbac/rbac.go b/plugin/pkg/auth/authorizer/rbac/rbac.go index 122a10b2f3..a0f173c393 100644 --- a/plugin/pkg/auth/authorizer/rbac/rbac.go +++ b/plugin/pkg/auth/authorizer/rbac/rbac.go @@ -18,18 +18,18 @@ limitations under the License. package rbac import ( + "bytes" "fmt" "github.com/golang/glog" - "bytes" - + rbacv1 "k8s.io/api/rbac/v1" "k8s.io/apimachinery/pkg/labels" utilerrors "k8s.io/apimachinery/pkg/util/errors" "k8s.io/apiserver/pkg/authentication/user" "k8s.io/apiserver/pkg/authorization/authorizer" - "k8s.io/kubernetes/pkg/apis/rbac" - rbaclisters "k8s.io/kubernetes/pkg/client/listers/rbac/internalversion" + rbaclisters "k8s.io/client-go/listers/rbac/v1" + rbacv1helpers "k8s.io/kubernetes/pkg/apis/rbac/v1" rbacregistryvalidation "k8s.io/kubernetes/pkg/registry/rbac/validation" ) @@ -38,12 +38,12 @@ type RequestToRuleMapper interface { // Any rule returned is still valid, since rules are deny by default. If you can pass with the rules // supplied, you do not have to fail the request. If you cannot, you should indicate the error along // with your denial. - RulesFor(subject user.Info, namespace string) ([]rbac.PolicyRule, error) + RulesFor(subject user.Info, namespace string) ([]rbacv1.PolicyRule, error) // VisitRulesFor invokes visitor() with each rule that applies to a given user in a given namespace, // and each error encountered resolving those rules. Rule may be nil if err is non-nil. // If visitor() returns false, visiting is short-circuited. - VisitRulesFor(user user.Info, namespace string, visitor func(source fmt.Stringer, rule *rbac.PolicyRule, err error) bool) + VisitRulesFor(user user.Info, namespace string, visitor func(source fmt.Stringer, rule *rbacv1.PolicyRule, err error) bool) } type RBACAuthorizer struct { @@ -59,7 +59,7 @@ type authorizingVisitor struct { errors []error } -func (v *authorizingVisitor) visit(source fmt.Stringer, rule *rbac.PolicyRule, err error) bool { +func (v *authorizingVisitor) visit(source fmt.Stringer, rule *rbacv1.PolicyRule, err error) bool { if rule != nil && RuleAllows(v.requestAttributes, rule) { v.allowed = true v.reason = fmt.Sprintf("RBAC: allowed by %s", source.String()) @@ -164,7 +164,7 @@ func New(roles rbacregistryvalidation.RoleGetter, roleBindings rbacregistryvalid return authorizer } -func RulesAllow(requestAttributes authorizer.Attributes, rules ...rbac.PolicyRule) bool { +func RulesAllow(requestAttributes authorizer.Attributes, rules ...rbacv1.PolicyRule) bool { for i := range rules { if RuleAllows(requestAttributes, &rules[i]) { return true @@ -174,28 +174,28 @@ func RulesAllow(requestAttributes authorizer.Attributes, rules ...rbac.PolicyRul return false } -func RuleAllows(requestAttributes authorizer.Attributes, rule *rbac.PolicyRule) bool { +func RuleAllows(requestAttributes authorizer.Attributes, rule *rbacv1.PolicyRule) bool { if requestAttributes.IsResourceRequest() { combinedResource := requestAttributes.GetResource() if len(requestAttributes.GetSubresource()) > 0 { combinedResource = requestAttributes.GetResource() + "/" + requestAttributes.GetSubresource() } - return rbac.VerbMatches(rule, requestAttributes.GetVerb()) && - rbac.APIGroupMatches(rule, requestAttributes.GetAPIGroup()) && - rbac.ResourceMatches(rule, combinedResource, requestAttributes.GetSubresource()) && - rbac.ResourceNameMatches(rule, requestAttributes.GetName()) + return rbacv1helpers.VerbMatches(rule, requestAttributes.GetVerb()) && + rbacv1helpers.APIGroupMatches(rule, requestAttributes.GetAPIGroup()) && + rbacv1helpers.ResourceMatches(rule, combinedResource, requestAttributes.GetSubresource()) && + rbacv1helpers.ResourceNameMatches(rule, requestAttributes.GetName()) } - return rbac.VerbMatches(rule, requestAttributes.GetVerb()) && - rbac.NonResourceURLMatches(rule, requestAttributes.GetPath()) + return rbacv1helpers.VerbMatches(rule, requestAttributes.GetVerb()) && + rbacv1helpers.NonResourceURLMatches(rule, requestAttributes.GetPath()) } type RoleGetter struct { Lister rbaclisters.RoleLister } -func (g *RoleGetter) GetRole(namespace, name string) (*rbac.Role, error) { +func (g *RoleGetter) GetRole(namespace, name string) (*rbacv1.Role, error) { return g.Lister.Roles(namespace).Get(name) } @@ -203,7 +203,7 @@ type RoleBindingLister struct { Lister rbaclisters.RoleBindingLister } -func (l *RoleBindingLister) ListRoleBindings(namespace string) ([]*rbac.RoleBinding, error) { +func (l *RoleBindingLister) ListRoleBindings(namespace string) ([]*rbacv1.RoleBinding, error) { return l.Lister.RoleBindings(namespace).List(labels.Everything()) } @@ -211,7 +211,7 @@ type ClusterRoleGetter struct { Lister rbaclisters.ClusterRoleLister } -func (g *ClusterRoleGetter) GetClusterRole(name string) (*rbac.ClusterRole, error) { +func (g *ClusterRoleGetter) GetClusterRole(name string) (*rbacv1.ClusterRole, error) { return g.Lister.Get(name) } @@ -219,6 +219,6 @@ type ClusterRoleBindingLister struct { Lister rbaclisters.ClusterRoleBindingLister } -func (l *ClusterRoleBindingLister) ListClusterRoleBindings() ([]*rbac.ClusterRoleBinding, error) { +func (l *ClusterRoleBindingLister) ListClusterRoleBindings() ([]*rbacv1.ClusterRoleBinding, error) { return l.Lister.List(labels.Everything()) } diff --git a/plugin/pkg/auth/authorizer/rbac/rbac_test.go b/plugin/pkg/auth/authorizer/rbac/rbac_test.go index d4425a6047..1b2a8e1ef3 100644 --- a/plugin/pkg/auth/authorizer/rbac/rbac_test.go +++ b/plugin/pkg/auth/authorizer/rbac/rbac_test.go @@ -21,16 +21,17 @@ import ( "strings" "testing" + rbacv1 "k8s.io/api/rbac/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apiserver/pkg/authentication/user" "k8s.io/apiserver/pkg/authorization/authorizer" - "k8s.io/kubernetes/pkg/apis/rbac" + rbacv1helpers "k8s.io/kubernetes/pkg/apis/rbac/v1" rbacregistryvalidation "k8s.io/kubernetes/pkg/registry/rbac/validation" "k8s.io/kubernetes/plugin/pkg/auth/authorizer/rbac/bootstrappolicy" ) -func newRule(verbs, apiGroups, resources, nonResourceURLs string) rbac.PolicyRule { - return rbac.PolicyRule{ +func newRule(verbs, apiGroups, resources, nonResourceURLs string) rbacv1.PolicyRule { + return rbacv1.PolicyRule{ Verbs: strings.Split(verbs, ","), APIGroups: strings.Split(apiGroups, ","), Resources: strings.Split(resources, ","), @@ -38,12 +39,12 @@ func newRule(verbs, apiGroups, resources, nonResourceURLs string) rbac.PolicyRul } } -func newRole(name, namespace string, rules ...rbac.PolicyRule) *rbac.Role { - return &rbac.Role{ObjectMeta: metav1.ObjectMeta{Namespace: namespace, Name: name}, Rules: rules} +func newRole(name, namespace string, rules ...rbacv1.PolicyRule) *rbacv1.Role { + return &rbacv1.Role{ObjectMeta: metav1.ObjectMeta{Namespace: namespace, Name: name}, Rules: rules} } -func newClusterRole(name string, rules ...rbac.PolicyRule) *rbac.ClusterRole { - return &rbac.ClusterRole{ObjectMeta: metav1.ObjectMeta{Name: name}, Rules: rules} +func newClusterRole(name string, rules ...rbacv1.PolicyRule) *rbacv1.ClusterRole { + return &rbacv1.ClusterRole{ObjectMeta: metav1.ObjectMeta{Name: name}, Rules: rules} } const ( @@ -51,26 +52,26 @@ const ( bindToClusterRole uint16 = 0x1 ) -func newClusterRoleBinding(roleName string, subjects ...string) *rbac.ClusterRoleBinding { - r := &rbac.ClusterRoleBinding{ +func newClusterRoleBinding(roleName string, subjects ...string) *rbacv1.ClusterRoleBinding { + r := &rbacv1.ClusterRoleBinding{ ObjectMeta: metav1.ObjectMeta{}, - RoleRef: rbac.RoleRef{ - APIGroup: rbac.GroupName, + RoleRef: rbacv1.RoleRef{ + APIGroup: rbacv1.GroupName, Kind: "ClusterRole", // ClusterRoleBindings can only refer to ClusterRole Name: roleName, }, } - r.Subjects = make([]rbac.Subject, len(subjects)) + r.Subjects = make([]rbacv1.Subject, len(subjects)) for i, subject := range subjects { split := strings.SplitN(subject, ":", 2) r.Subjects[i].Kind, r.Subjects[i].Name = split[0], split[1] switch r.Subjects[i].Kind { - case rbac.ServiceAccountKind: + case rbacv1.ServiceAccountKind: r.Subjects[i].APIGroup = "" - case rbac.UserKind, rbac.GroupKind: - r.Subjects[i].APIGroup = rbac.GroupName + case rbacv1.UserKind, rbacv1.GroupKind: + r.Subjects[i].APIGroup = rbacv1.GroupName default: panic(fmt.Errorf("invalid kind %s", r.Subjects[i].Kind)) } @@ -78,26 +79,26 @@ func newClusterRoleBinding(roleName string, subjects ...string) *rbac.ClusterRol return r } -func newRoleBinding(namespace, roleName string, bindType uint16, subjects ...string) *rbac.RoleBinding { - r := &rbac.RoleBinding{ObjectMeta: metav1.ObjectMeta{Namespace: namespace}} +func newRoleBinding(namespace, roleName string, bindType uint16, subjects ...string) *rbacv1.RoleBinding { + r := &rbacv1.RoleBinding{ObjectMeta: metav1.ObjectMeta{Namespace: namespace}} switch bindType { case bindToRole: - r.RoleRef = rbac.RoleRef{APIGroup: rbac.GroupName, Kind: "Role", Name: roleName} + r.RoleRef = rbacv1.RoleRef{APIGroup: rbacv1.GroupName, Kind: "Role", Name: roleName} case bindToClusterRole: - r.RoleRef = rbac.RoleRef{APIGroup: rbac.GroupName, Kind: "ClusterRole", Name: roleName} + r.RoleRef = rbacv1.RoleRef{APIGroup: rbacv1.GroupName, Kind: "ClusterRole", Name: roleName} } - r.Subjects = make([]rbac.Subject, len(subjects)) + r.Subjects = make([]rbacv1.Subject, len(subjects)) for i, subject := range subjects { split := strings.SplitN(subject, ":", 2) r.Subjects[i].Kind, r.Subjects[i].Name = split[0], split[1] switch r.Subjects[i].Kind { - case rbac.ServiceAccountKind: + case rbacv1.ServiceAccountKind: r.Subjects[i].APIGroup = "" - case rbac.UserKind, rbac.GroupKind: - r.Subjects[i].APIGroup = rbac.GroupName + case rbacv1.UserKind, rbacv1.GroupKind: + r.Subjects[i].APIGroup = rbacv1.GroupName default: panic(fmt.Errorf("invalid kind %s", r.Subjects[i].Kind)) } @@ -136,19 +137,19 @@ 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 []*rbacv1.Role + roleBindings []*rbacv1.RoleBinding + clusterRoles []*rbacv1.ClusterRole + clusterRoleBindings []*rbacv1.ClusterRoleBinding shouldPass []authorizer.Attributes shouldFail []authorizer.Attributes }{ { - clusterRoles: []*rbac.ClusterRole{ + clusterRoles: []*rbacv1.ClusterRole{ newClusterRole("admin", newRule("*", "*", "*", "*")), }, - roleBindings: []*rbac.RoleBinding{ + roleBindings: []*rbacv1.RoleBinding{ newRoleBinding("ns1", "admin", bindToClusterRole, "User:admin", "Group:admins"), }, shouldPass: []authorizer.Attributes{ @@ -167,12 +168,12 @@ func TestAuthorizer(t *testing.T) { }, { // Non-resource-url tests - clusterRoles: []*rbac.ClusterRole{ + clusterRoles: []*rbacv1.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: []*rbacv1.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"), @@ -208,10 +209,10 @@ func TestAuthorizer(t *testing.T) { }, { // test subresource resolution - clusterRoles: []*rbac.ClusterRole{ + clusterRoles: []*rbacv1.ClusterRole{ newClusterRole("admin", newRule("*", "*", "pods", "*")), }, - roleBindings: []*rbac.RoleBinding{ + roleBindings: []*rbacv1.RoleBinding{ newRoleBinding("ns1", "admin", bindToClusterRole, "User:admin", "Group:admins"), }, shouldPass: []authorizer.Attributes{ @@ -223,13 +224,13 @@ func TestAuthorizer(t *testing.T) { }, { // test subresource resolution - clusterRoles: []*rbac.ClusterRole{ + clusterRoles: []*rbacv1.ClusterRole{ newClusterRole("admin", newRule("*", "*", "pods/status", "*"), newRule("*", "*", "*/scale", "*"), ), }, - roleBindings: []*rbac.RoleBinding{ + roleBindings: []*rbacv1.RoleBinding{ newRoleBinding("ns1", "admin", bindToClusterRole, "User:admin", "Group:admins"), }, shouldPass: []authorizer.Attributes{ @@ -263,13 +264,13 @@ func TestAuthorizer(t *testing.T) { func TestRuleMatches(t *testing.T) { tests := []struct { name string - rule rbac.PolicyRule + rule rbacv1.PolicyRule requestsToExpected map[authorizer.AttributesRecord]bool }{ { name: "star verb, exact match other", - rule: rbac.NewRule("*").Groups("group1").Resources("resource1").RuleOrDie(), + rule: rbacv1helpers.NewRule("*").Groups("group1").Resources("resource1").RuleOrDie(), requestsToExpected: map[authorizer.AttributesRecord]bool{ resourceRequest("verb1").Group("group1").Resource("resource1").New(): true, resourceRequest("verb1").Group("group2").Resource("resource1").New(): false, @@ -283,7 +284,7 @@ func TestRuleMatches(t *testing.T) { }, { name: "star group, exact match other", - rule: rbac.NewRule("verb1").Groups("*").Resources("resource1").RuleOrDie(), + rule: rbacv1helpers.NewRule("verb1").Groups("*").Resources("resource1").RuleOrDie(), requestsToExpected: map[authorizer.AttributesRecord]bool{ resourceRequest("verb1").Group("group1").Resource("resource1").New(): true, resourceRequest("verb1").Group("group2").Resource("resource1").New(): true, @@ -297,7 +298,7 @@ func TestRuleMatches(t *testing.T) { }, { name: "star resource, exact match other", - rule: rbac.NewRule("verb1").Groups("group1").Resources("*").RuleOrDie(), + rule: rbacv1helpers.NewRule("verb1").Groups("group1").Resources("*").RuleOrDie(), requestsToExpected: map[authorizer.AttributesRecord]bool{ resourceRequest("verb1").Group("group1").Resource("resource1").New(): true, resourceRequest("verb1").Group("group2").Resource("resource1").New(): false, @@ -311,7 +312,7 @@ func TestRuleMatches(t *testing.T) { }, { name: "tuple expansion", - rule: rbac.NewRule("verb1", "verb2").Groups("group1", "group2").Resources("resource1", "resource2").RuleOrDie(), + rule: rbacv1helpers.NewRule("verb1", "verb2").Groups("group1", "group2").Resources("resource1", "resource2").RuleOrDie(), requestsToExpected: map[authorizer.AttributesRecord]bool{ resourceRequest("verb1").Group("group1").Resource("resource1").New(): true, resourceRequest("verb1").Group("group2").Resource("resource1").New(): true, @@ -325,7 +326,7 @@ func TestRuleMatches(t *testing.T) { }, { name: "subresource expansion", - rule: rbac.NewRule("*").Groups("*").Resources("resource1/subresource1").RuleOrDie(), + rule: rbacv1helpers.NewRule("*").Groups("*").Resources("resource1/subresource1").RuleOrDie(), requestsToExpected: map[authorizer.AttributesRecord]bool{ resourceRequest("verb1").Group("group1").Resource("resource1").Subresource("subresource1").New(): true, resourceRequest("verb1").Group("group2").Resource("resource1").Subresource("subresource2").New(): false, @@ -339,7 +340,7 @@ func TestRuleMatches(t *testing.T) { }, { name: "star nonresource, exact match other", - rule: rbac.NewRule("verb1").URLs("*").RuleOrDie(), + rule: rbacv1helpers.NewRule("verb1").URLs("*").RuleOrDie(), requestsToExpected: map[authorizer.AttributesRecord]bool{ nonresourceRequest("verb1").URL("/foo").New(): true, nonresourceRequest("verb1").URL("/foo/bar").New(): true, @@ -355,7 +356,7 @@ func TestRuleMatches(t *testing.T) { }, { name: "star nonresource subpath", - rule: rbac.NewRule("verb1").URLs("/foo/*").RuleOrDie(), + rule: rbacv1helpers.NewRule("verb1").URLs("/foo/*").RuleOrDie(), requestsToExpected: map[authorizer.AttributesRecord]bool{ nonresourceRequest("verb1").URL("/foo").New(): false, nonresourceRequest("verb1").URL("/foo/bar").New(): true, @@ -371,7 +372,7 @@ func TestRuleMatches(t *testing.T) { }, { name: "star verb, exact nonresource", - rule: rbac.NewRule("*").URLs("/foo", "/foo/bar/one").RuleOrDie(), + rule: rbacv1helpers.NewRule("*").URLs("/foo", "/foo/bar/one").RuleOrDie(), requestsToExpected: map[authorizer.AttributesRecord]bool{ nonresourceRequest("verb1").URL("/foo").New(): true, nonresourceRequest("verb1").URL("/foo/bar").New(): false, @@ -441,19 +442,19 @@ func (r *requestAttributeBuilder) New() authorizer.AttributesRecord { } func BenchmarkAuthorize(b *testing.B) { - bootstrapRoles := []rbac.ClusterRole{} + bootstrapRoles := []rbacv1.ClusterRole{} bootstrapRoles = append(bootstrapRoles, bootstrappolicy.ControllerRoles()...) bootstrapRoles = append(bootstrapRoles, bootstrappolicy.ClusterRoles()...) - bootstrapBindings := []rbac.ClusterRoleBinding{} + bootstrapBindings := []rbacv1.ClusterRoleBinding{} bootstrapBindings = append(bootstrapBindings, bootstrappolicy.ClusterRoleBindings()...) bootstrapBindings = append(bootstrapBindings, bootstrappolicy.ControllerRoleBindings()...) - clusterRoles := []*rbac.ClusterRole{} + clusterRoles := []*rbacv1.ClusterRole{} for i := range bootstrapRoles { clusterRoles = append(clusterRoles, &bootstrapRoles[i]) } - clusterRoleBindings := []*rbac.ClusterRoleBinding{} + clusterRoleBindings := []*rbacv1.ClusterRoleBinding{} for i := range bootstrapBindings { clusterRoleBindings = append(clusterRoleBindings, &bootstrapBindings[i]) } diff --git a/plugin/pkg/auth/authorizer/rbac/subject_locator.go b/plugin/pkg/auth/authorizer/rbac/subject_locator.go index 0f5f413b9a..cdd327e5b7 100644 --- a/plugin/pkg/auth/authorizer/rbac/subject_locator.go +++ b/plugin/pkg/auth/authorizer/rbac/subject_locator.go @@ -18,21 +18,21 @@ limitations under the License. package rbac import ( + rbacv1 "k8s.io/api/rbac/v1" utilerrors "k8s.io/apimachinery/pkg/util/errors" "k8s.io/apiserver/pkg/authentication/user" "k8s.io/apiserver/pkg/authorization/authorizer" - "k8s.io/kubernetes/pkg/apis/rbac" rbacregistryvalidation "k8s.io/kubernetes/pkg/registry/rbac/validation" ) type RoleToRuleMapper interface { // GetRoleReferenceRules attempts to resolve the role reference of a RoleBinding or ClusterRoleBinding. The passed namespace should be the namespace // of the role binding, the empty string if a cluster role binding. - GetRoleReferenceRules(roleRef rbac.RoleRef, namespace string) ([]rbac.PolicyRule, error) + GetRoleReferenceRules(roleRef rbacv1.RoleRef, namespace string) ([]rbacv1.PolicyRule, error) } type SubjectLocator interface { - AllowedSubjects(attributes authorizer.Attributes) ([]rbac.Subject, error) + AllowedSubjects(attributes authorizer.Attributes) ([]rbacv1.Subject, error) } var _ = SubjectLocator(&SubjectAccessEvaluator{}) @@ -59,10 +59,10 @@ func NewSubjectAccessEvaluator(roles rbacregistryvalidation.RoleGetter, roleBind // AllowedSubjects returns the subjects that can perform an action and any errors encountered while computing the list. // It is possible to have both subjects and errors returned if some rolebindings couldn't be resolved, but others could be. -func (r *SubjectAccessEvaluator) AllowedSubjects(requestAttributes authorizer.Attributes) ([]rbac.Subject, error) { - subjects := []rbac.Subject{{Kind: rbac.GroupKind, APIGroup: rbac.GroupName, Name: user.SystemPrivilegedGroup}} +func (r *SubjectAccessEvaluator) AllowedSubjects(requestAttributes authorizer.Attributes) ([]rbacv1.Subject, error) { + subjects := []rbacv1.Subject{{Kind: rbacv1.GroupKind, APIGroup: rbacv1.GroupName, Name: user.SystemPrivilegedGroup}} if len(r.superUser) > 0 { - subjects = append(subjects, rbac.Subject{Kind: rbac.UserKind, APIGroup: rbac.GroupName, Name: r.superUser}) + subjects = append(subjects, rbacv1.Subject{Kind: rbacv1.UserKind, APIGroup: rbacv1.GroupName, Name: r.superUser}) } errorlist := []error{} @@ -104,7 +104,7 @@ func (r *SubjectAccessEvaluator) AllowedSubjects(requestAttributes authorizer.At } } - dedupedSubjects := []rbac.Subject{} + dedupedSubjects := []rbacv1.Subject{} for _, subject := range subjects { found := false for _, curr := range dedupedSubjects { diff --git a/plugin/pkg/auth/authorizer/rbac/subject_locator_test.go b/plugin/pkg/auth/authorizer/rbac/subject_locator_test.go index 1182a28b54..d798494885 100644 --- a/plugin/pkg/auth/authorizer/rbac/subject_locator_test.go +++ b/plugin/pkg/auth/authorizer/rbac/subject_locator_test.go @@ -20,24 +20,24 @@ import ( "reflect" "testing" + rbacv1 "k8s.io/api/rbac/v1" "k8s.io/apiserver/pkg/authentication/user" "k8s.io/apiserver/pkg/authorization/authorizer" - "k8s.io/kubernetes/pkg/apis/rbac" rbacregistryvalidation "k8s.io/kubernetes/pkg/registry/rbac/validation" ) func TestSubjectLocator(t *testing.T) { type actionToSubjects struct { action authorizer.Attributes - subjects []rbac.Subject + subjects []rbacv1.Subject } tests := []struct { name string - roles []*rbac.Role - roleBindings []*rbac.RoleBinding - clusterRoles []*rbac.ClusterRole - clusterRoleBindings []*rbac.ClusterRoleBinding + roles []*rbacv1.Role + roleBindings []*rbacv1.RoleBinding + clusterRoles []*rbacv1.ClusterRole + clusterRoleBindings []*rbacv1.ClusterRoleBinding superUser string @@ -45,42 +45,42 @@ func TestSubjectLocator(t *testing.T) { }{ { name: "no super user, star matches star", - clusterRoles: []*rbac.ClusterRole{ + clusterRoles: []*rbacv1.ClusterRole{ newClusterRole("admin", newRule("*", "*", "*", "*")), }, - clusterRoleBindings: []*rbac.ClusterRoleBinding{ + clusterRoleBindings: []*rbacv1.ClusterRoleBinding{ newClusterRoleBinding("admin", "User:super-admin", "Group:super-admins"), }, - roleBindings: []*rbac.RoleBinding{ + roleBindings: []*rbacv1.RoleBinding{ newRoleBinding("ns1", "admin", bindToClusterRole, "User:admin", "Group:admins"), }, actionsToSubjects: []actionToSubjects{ { &defaultAttributes{"", "", "get", "Pods", "", "ns1", ""}, - []rbac.Subject{ - {Kind: rbac.GroupKind, APIGroup: rbac.GroupName, Name: user.SystemPrivilegedGroup}, - {Kind: rbac.UserKind, APIGroup: rbac.GroupName, Name: "super-admin"}, - {Kind: rbac.GroupKind, APIGroup: rbac.GroupName, Name: "super-admins"}, - {Kind: rbac.UserKind, APIGroup: rbac.GroupName, Name: "admin"}, - {Kind: rbac.GroupKind, APIGroup: rbac.GroupName, Name: "admins"}, + []rbacv1.Subject{ + {Kind: rbacv1.GroupKind, APIGroup: rbacv1.GroupName, Name: user.SystemPrivilegedGroup}, + {Kind: rbacv1.UserKind, APIGroup: rbacv1.GroupName, Name: "super-admin"}, + {Kind: rbacv1.GroupKind, APIGroup: rbacv1.GroupName, Name: "super-admins"}, + {Kind: rbacv1.UserKind, APIGroup: rbacv1.GroupName, Name: "admin"}, + {Kind: rbacv1.GroupKind, APIGroup: rbacv1.GroupName, Name: "admins"}, }, }, { // cluster role matches star in namespace &defaultAttributes{"", "", "*", "Pods", "", "*", ""}, - []rbac.Subject{ - {Kind: rbac.GroupKind, APIGroup: rbac.GroupName, Name: user.SystemPrivilegedGroup}, - {Kind: rbac.UserKind, APIGroup: rbac.GroupName, Name: "super-admin"}, - {Kind: rbac.GroupKind, APIGroup: rbac.GroupName, Name: "super-admins"}, + []rbacv1.Subject{ + {Kind: rbacv1.GroupKind, APIGroup: rbacv1.GroupName, Name: user.SystemPrivilegedGroup}, + {Kind: rbacv1.UserKind, APIGroup: rbacv1.GroupName, Name: "super-admin"}, + {Kind: rbacv1.GroupKind, APIGroup: rbacv1.GroupName, Name: "super-admins"}, }, }, { // empty ns &defaultAttributes{"", "", "*", "Pods", "", "", ""}, - []rbac.Subject{ - {Kind: rbac.GroupKind, APIGroup: rbac.GroupName, Name: user.SystemPrivilegedGroup}, - {Kind: rbac.UserKind, APIGroup: rbac.GroupName, Name: "super-admin"}, - {Kind: rbac.GroupKind, APIGroup: rbac.GroupName, Name: "super-admins"}, + []rbacv1.Subject{ + {Kind: rbacv1.GroupKind, APIGroup: rbacv1.GroupName, Name: user.SystemPrivilegedGroup}, + {Kind: rbacv1.UserKind, APIGroup: rbacv1.GroupName, Name: "super-admin"}, + {Kind: rbacv1.GroupKind, APIGroup: rbacv1.GroupName, Name: "super-admins"}, }, }, }, @@ -88,48 +88,48 @@ func TestSubjectLocator(t *testing.T) { { name: "super user, local roles work", superUser: "foo", - clusterRoles: []*rbac.ClusterRole{ + clusterRoles: []*rbacv1.ClusterRole{ newClusterRole("admin", newRule("*", "*", "*", "*")), }, - clusterRoleBindings: []*rbac.ClusterRoleBinding{ + clusterRoleBindings: []*rbacv1.ClusterRoleBinding{ newClusterRoleBinding("admin", "User:super-admin", "Group:super-admins"), }, - roles: []*rbac.Role{ + roles: []*rbacv1.Role{ newRole("admin", "ns1", newRule("get", "*", "Pods", "*")), }, - roleBindings: []*rbac.RoleBinding{ + roleBindings: []*rbacv1.RoleBinding{ newRoleBinding("ns1", "admin", bindToRole, "User:admin", "Group:admins"), }, actionsToSubjects: []actionToSubjects{ { &defaultAttributes{"", "", "get", "Pods", "", "ns1", ""}, - []rbac.Subject{ - {Kind: rbac.GroupKind, APIGroup: rbac.GroupName, Name: user.SystemPrivilegedGroup}, - {Kind: rbac.UserKind, APIGroup: rbac.GroupName, Name: "foo"}, - {Kind: rbac.UserKind, APIGroup: rbac.GroupName, Name: "super-admin"}, - {Kind: rbac.GroupKind, APIGroup: rbac.GroupName, Name: "super-admins"}, - {Kind: rbac.UserKind, APIGroup: rbac.GroupName, Name: "admin"}, - {Kind: rbac.GroupKind, APIGroup: rbac.GroupName, Name: "admins"}, + []rbacv1.Subject{ + {Kind: rbacv1.GroupKind, APIGroup: rbacv1.GroupName, Name: user.SystemPrivilegedGroup}, + {Kind: rbacv1.UserKind, APIGroup: rbacv1.GroupName, Name: "foo"}, + {Kind: rbacv1.UserKind, APIGroup: rbacv1.GroupName, Name: "super-admin"}, + {Kind: rbacv1.GroupKind, APIGroup: rbacv1.GroupName, Name: "super-admins"}, + {Kind: rbacv1.UserKind, APIGroup: rbacv1.GroupName, Name: "admin"}, + {Kind: rbacv1.GroupKind, APIGroup: rbacv1.GroupName, Name: "admins"}, }, }, { // verb matchies correctly &defaultAttributes{"", "", "create", "Pods", "", "ns1", ""}, - []rbac.Subject{ - {Kind: rbac.GroupKind, APIGroup: rbac.GroupName, Name: user.SystemPrivilegedGroup}, - {Kind: rbac.UserKind, APIGroup: rbac.GroupName, Name: "foo"}, - {Kind: rbac.UserKind, APIGroup: rbac.GroupName, Name: "super-admin"}, - {Kind: rbac.GroupKind, APIGroup: rbac.GroupName, Name: "super-admins"}, + []rbacv1.Subject{ + {Kind: rbacv1.GroupKind, APIGroup: rbacv1.GroupName, Name: user.SystemPrivilegedGroup}, + {Kind: rbacv1.UserKind, APIGroup: rbacv1.GroupName, Name: "foo"}, + {Kind: rbacv1.UserKind, APIGroup: rbacv1.GroupName, Name: "super-admin"}, + {Kind: rbacv1.GroupKind, APIGroup: rbacv1.GroupName, Name: "super-admins"}, }, }, { // binding only works in correct ns &defaultAttributes{"", "", "get", "Pods", "", "ns2", ""}, - []rbac.Subject{ - {Kind: rbac.GroupKind, APIGroup: rbac.GroupName, Name: user.SystemPrivilegedGroup}, - {Kind: rbac.UserKind, APIGroup: rbac.GroupName, Name: "foo"}, - {Kind: rbac.UserKind, APIGroup: rbac.GroupName, Name: "super-admin"}, - {Kind: rbac.GroupKind, APIGroup: rbac.GroupName, Name: "super-admins"}, + []rbacv1.Subject{ + {Kind: rbacv1.GroupKind, APIGroup: rbacv1.GroupName, Name: user.SystemPrivilegedGroup}, + {Kind: rbacv1.UserKind, APIGroup: rbacv1.GroupName, Name: "foo"}, + {Kind: rbacv1.UserKind, APIGroup: rbacv1.GroupName, Name: "super-admin"}, + {Kind: rbacv1.GroupKind, APIGroup: rbacv1.GroupName, Name: "super-admins"}, }, }, }, diff --git a/test/integration/framework/master_utils.go b/test/integration/framework/master_utils.go index 387d3bb4d4..f7d6e50d9c 100644 --- a/test/integration/framework/master_utils.go +++ b/test/integration/framework/master_utils.go @@ -199,6 +199,7 @@ func startMasterOrDie(masterConfig *master.Config, incomingServer *httptest.Serv closeFn() glog.Fatal(err) } + var lastHealthContent []byte err = wait.PollImmediate(100*time.Millisecond, 30*time.Second, func() (bool, error) { result := privilegedClient.Get().AbsPath("/healthz").Do() status := 0 @@ -206,10 +207,12 @@ func startMasterOrDie(masterConfig *master.Config, incomingServer *httptest.Serv if status == 200 { return true, nil } + lastHealthContent, _ = result.Raw() return false, nil }) if err != nil { closeFn() + glog.Errorf("last health content: %q", string(lastHealthContent)) glog.Fatal(err) }