From 8c788233e778f3b0ebef560762c1433c12ea1d43 Mon Sep 17 00:00:00 2001 From: deads2k Date: Wed, 24 Aug 2016 14:23:27 -0400 Subject: [PATCH] change rbac roleref type --- pkg/api/testing/fuzzer.go | 9 + pkg/apis/rbac/helpers.go | 25 +++ pkg/apis/rbac/types.go | 14 +- pkg/apis/rbac/v1alpha1/defaults.go | 36 ++++ pkg/apis/rbac/v1alpha1/register.go | 7 +- pkg/apis/rbac/v1alpha1/types.go | 14 +- pkg/apis/rbac/validation/rulevalidation.go | 25 +-- .../rbac/validation/rulevalidation_test.go | 4 +- pkg/apis/rbac/validation/validation.go | 32 ++-- pkg/apis/rbac/validation/validation_test.go | 159 ++++++++++++++++-- plugin/pkg/auth/authorizer/rbac/rbac_test.go | 11 +- test/integration/auth/rbac_test.go | 6 +- 12 files changed, 281 insertions(+), 61 deletions(-) create mode 100644 pkg/apis/rbac/helpers.go create mode 100644 pkg/apis/rbac/v1alpha1/defaults.go diff --git a/pkg/api/testing/fuzzer.go b/pkg/api/testing/fuzzer.go index 86dac4b645a..cc6888e8e58 100644 --- a/pkg/api/testing/fuzzer.go +++ b/pkg/api/testing/fuzzer.go @@ -30,6 +30,7 @@ import ( "k8s.io/kubernetes/pkg/apis/autoscaling" "k8s.io/kubernetes/pkg/apis/batch" "k8s.io/kubernetes/pkg/apis/extensions" + "k8s.io/kubernetes/pkg/apis/rbac" "k8s.io/kubernetes/pkg/fields" "k8s.io/kubernetes/pkg/labels" "k8s.io/kubernetes/pkg/runtime" @@ -498,6 +499,14 @@ func FuzzerFor(t *testing.T, version unversioned.GroupVersion, src rand.Source) } } }, + func(r *rbac.RoleRef, c fuzz.Continue) { + c.FuzzNoCustom(r) // fuzz self without calling this function again + + // match defaulter + if len(r.APIGroup) == 0 { + r.APIGroup = rbac.GroupName + } + }, func(r *runtime.RawExtension, c fuzz.Continue) { // Pick an arbitrary type and fuzz it types := []runtime.Object{&api.Pod{}, &extensions.Deployment{}, &api.Service{}} diff --git a/pkg/apis/rbac/helpers.go b/pkg/apis/rbac/helpers.go new file mode 100644 index 00000000000..ff805d3180d --- /dev/null +++ b/pkg/apis/rbac/helpers.go @@ -0,0 +1,25 @@ +/* +Copyright 2016 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package rbac + +import ( + "k8s.io/kubernetes/pkg/api/unversioned" +) + +func RoleRefGroupKind(roleRef RoleRef) unversioned.GroupKind { + return unversioned.GroupKind{Group: roleRef.APIGroup, Kind: roleRef.Kind} +} diff --git a/pkg/apis/rbac/types.go b/pkg/apis/rbac/types.go index ba7fa2b17fe..361654f479c 100644 --- a/pkg/apis/rbac/types.go +++ b/pkg/apis/rbac/types.go @@ -80,6 +80,16 @@ type Subject struct { Namespace string } +// RoleRef contains information that points to the role being used +type RoleRef struct { + // APIGroup is the group for the resource being referenced + APIGroup string + // Kind is the type of resource being referenced + Kind string + // Name is the name of resource being referenced + Name string +} + // +genclient=true // Role is a namespaced, logical grouping of PolicyRules that can be referenced as a unit by a RoleBinding. @@ -106,7 +116,7 @@ type RoleBinding struct { // RoleRef can reference a Role in the current namespace or a ClusterRole in the global namespace. // If the RoleRef cannot be resolved, the Authorizer must return an error. - RoleRef api.ObjectReference + RoleRef RoleRef } // RoleBindingList is a collection of RoleBindings @@ -157,7 +167,7 @@ type ClusterRoleBinding struct { // RoleRef can only reference a ClusterRole in the global namespace. // If the RoleRef cannot be resolved, the Authorizer must return an error. - RoleRef api.ObjectReference + RoleRef RoleRef } // ClusterRoleBindingList is a collection of ClusterRoleBindings diff --git a/pkg/apis/rbac/v1alpha1/defaults.go b/pkg/apis/rbac/v1alpha1/defaults.go new file mode 100644 index 00000000000..e97f4109c64 --- /dev/null +++ b/pkg/apis/rbac/v1alpha1/defaults.go @@ -0,0 +1,36 @@ +/* +Copyright 2016 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package v1alpha1 + +import ( + "k8s.io/kubernetes/pkg/runtime" +) + +func addDefaultingFuncs(scheme *runtime.Scheme) error { + return scheme.AddDefaultingFuncs( + func(obj *ClusterRoleBinding) { + if len(obj.RoleRef.APIGroup) == 0 { + obj.RoleRef.APIGroup = GroupName + } + }, + func(obj *RoleBinding) { + if len(obj.RoleRef.APIGroup) == 0 { + obj.RoleRef.APIGroup = GroupName + } + }, + ) +} diff --git a/pkg/apis/rbac/v1alpha1/register.go b/pkg/apis/rbac/v1alpha1/register.go index f3a6b5b7624..5b76247d794 100644 --- a/pkg/apis/rbac/v1alpha1/register.go +++ b/pkg/apis/rbac/v1alpha1/register.go @@ -19,16 +19,17 @@ package v1alpha1 import ( "k8s.io/kubernetes/pkg/api/unversioned" "k8s.io/kubernetes/pkg/api/v1" - "k8s.io/kubernetes/pkg/apis/rbac" "k8s.io/kubernetes/pkg/runtime" "k8s.io/kubernetes/pkg/watch/versioned" ) +const GroupName = "rbac.authorization.k8s.io" + // SchemeGroupVersion is group version used to register these objects -var SchemeGroupVersion = unversioned.GroupVersion{Group: rbac.GroupName, Version: "v1alpha1"} +var SchemeGroupVersion = unversioned.GroupVersion{Group: GroupName, Version: "v1alpha1"} var ( - SchemeBuilder = runtime.NewSchemeBuilder(addKnownTypes) + SchemeBuilder = runtime.NewSchemeBuilder(addKnownTypes, addDefaultingFuncs) AddToScheme = SchemeBuilder.AddToScheme ) diff --git a/pkg/apis/rbac/v1alpha1/types.go b/pkg/apis/rbac/v1alpha1/types.go index e8a815ee67c..7223d885534 100644 --- a/pkg/apis/rbac/v1alpha1/types.go +++ b/pkg/apis/rbac/v1alpha1/types.go @@ -66,6 +66,16 @@ type Subject struct { Namespace string `json:"namespace,omitempty" protobuf:"bytes,4,opt,name=namespace"` } +// RoleRef contains information that points to the role being used +type RoleRef struct { + // APIGroup is the group for the resource being referenced + APIGroup string `json:"apiGroup" protobuf:"bytes,1,opt,name=apiGroup"` + // Kind is the type of resource being referenced + Kind string `json:"kind" protobuf:"bytes,2,opt,name=kind"` + // Name is the name of resource being referenced + Name string `json:"name" protobuf:"bytes,3,opt,name=name"` +} + // +genclient=true // Role is a namespaced, logical grouping of PolicyRules that can be referenced as a unit by a RoleBinding. @@ -93,7 +103,7 @@ type RoleBinding struct { // RoleRef can reference a Role in the current namespace or a ClusterRole in the global namespace. // If the RoleRef cannot be resolved, the Authorizer must return an error. - RoleRef v1.ObjectReference `json:"roleRef" protobuf:"bytes,3,opt,name=roleRef"` + RoleRef RoleRef `json:"roleRef" protobuf:"bytes,3,opt,name=roleRef"` } // RoleBindingList is a collection of RoleBindings @@ -144,7 +154,7 @@ type ClusterRoleBinding struct { // RoleRef can only reference a ClusterRole in the global namespace. // If the RoleRef cannot be resolved, the Authorizer must return an error. - RoleRef v1.ObjectReference `json:"roleRef" protobuf:"bytes,3,opt,name=roleRef"` + RoleRef RoleRef `json:"roleRef" protobuf:"bytes,3,opt,name=roleRef"` } // ClusterRoleBindingList is a collection of ClusterRoleBindings diff --git a/pkg/apis/rbac/validation/rulevalidation.go b/pkg/apis/rbac/validation/rulevalidation.go index 60490fee1a1..acf90d1c580 100644 --- a/pkg/apis/rbac/validation/rulevalidation.go +++ b/pkg/apis/rbac/validation/rulevalidation.go @@ -32,7 +32,7 @@ import ( type AuthorizationRuleResolver interface { // GetRoleReferenceRules attempts to resolve the role reference of a RoleBinding or ClusterRoleBinding. The passed namespace should be the namepsace // of the role binding, the empty string if a cluster role binding. - GetRoleReferenceRules(ctx api.Context, roleRef api.ObjectReference, namespace string) ([]rbac.PolicyRule, error) + GetRoleReferenceRules(ctx api.Context, roleRef rbac.RoleRef, namespace string) ([]rbac.PolicyRule, error) // GetEffectivePolicyRules 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 @@ -101,31 +101,24 @@ type ClusterRoleBindingLister interface { } // GetRoleReferenceRules attempts resolve the RoleBinding or ClusterRoleBinding. -func (r *DefaultRuleResolver) GetRoleReferenceRules(ctx api.Context, roleRef api.ObjectReference, bindingNamespace string) ([]rbac.PolicyRule, error) { - switch roleRef.Kind { - case "Role": - // Roles can only be referenced by RoleBindings within the same namespace. - if len(bindingNamespace) == 0 { - return nil, fmt.Errorf("cluster role binding references role %q in namespace %q", roleRef.Name, roleRef.Namespace) - } else { - if bindingNamespace != roleRef.Namespace { - return nil, fmt.Errorf("role binding in namespace %q references role %q in namespace %q", bindingNamespace, roleRef.Name, roleRef.Namespace) - } - } - - role, err := r.roleGetter.GetRole(api.WithNamespace(ctx, roleRef.Namespace), roleRef.Name) +func (r *DefaultRuleResolver) GetRoleReferenceRules(ctx api.Context, roleRef rbac.RoleRef, bindingNamespace string) ([]rbac.PolicyRule, error) { + switch kind := rbac.RoleRefGroupKind(roleRef); kind { + case rbac.Kind("Role"): + role, err := r.roleGetter.GetRole(api.WithNamespace(ctx, bindingNamespace), roleRef.Name) if err != nil { return nil, err } return role.Rules, nil - case "ClusterRole": + + case rbac.Kind("ClusterRole"): clusterRole, err := r.clusterRoleGetter.GetClusterRole(api.WithNamespace(ctx, ""), roleRef.Name) if err != nil { return nil, err } return clusterRole.Rules, nil + default: - return nil, fmt.Errorf("unsupported role reference kind: %q", roleRef.Kind) + return nil, fmt.Errorf("unsupported role reference kind: %q", kind) } } diff --git a/pkg/apis/rbac/validation/rulevalidation_test.go b/pkg/apis/rbac/validation/rulevalidation_test.go index ac0f782b064..34321608059 100644 --- a/pkg/apis/rbac/validation/rulevalidation_test.go +++ b/pkg/apis/rbac/validation/rulevalidation_test.go @@ -96,7 +96,7 @@ func TestDefaultRuleResolver(t *testing.T) { {Kind: rbac.UserKind, Name: "foobar"}, {Kind: rbac.GroupKind, Name: "group1"}, }, - RoleRef: api.ObjectReference{Kind: "Role", Namespace: "namespace1", Name: "readthings"}, + RoleRef: rbac.RoleRef{APIGroup: rbac.GroupName, Kind: "Role", Name: "readthings"}, }, }, clusterRoleBindings: []rbac.ClusterRoleBinding{ @@ -105,7 +105,7 @@ func TestDefaultRuleResolver(t *testing.T) { {Kind: rbac.UserKind, Name: "admin"}, {Kind: rbac.GroupKind, Name: "admin"}, }, - RoleRef: api.ObjectReference{Kind: "ClusterRole", Name: "cluster-admin"}, + RoleRef: rbac.RoleRef{APIGroup: rbac.GroupName, Kind: "ClusterRole", Name: "cluster-admin"}, }, }, } diff --git a/pkg/apis/rbac/validation/validation.go b/pkg/apis/rbac/validation/validation.go index aa94dc7f60b..2dab4759097 100644 --- a/pkg/apis/rbac/validation/validation.go +++ b/pkg/apis/rbac/validation/validation.go @@ -103,11 +103,17 @@ func ValidateRoleBinding(roleBinding *rbac.RoleBinding) field.ErrorList { allErrs := field.ErrorList{} allErrs = append(allErrs, validation.ValidateObjectMeta(&roleBinding.ObjectMeta, true, minimalNameRequirements, field.NewPath("metadata"))...) - // roleRef namespace is empty when referring to global policy. - if len(roleBinding.RoleRef.Namespace) > 0 { - for _, msg := range validation.ValidateNamespaceName(roleBinding.RoleRef.Namespace, false) { - allErrs = append(allErrs, field.Invalid(field.NewPath("roleRef", "namespace"), roleBinding.RoleRef.Namespace, msg)) - } + // TODO allow multiple API groups. For now, restrict to one, but I can envision other experimental roles in other groups taking + // advantage of the binding infrastructure + if roleBinding.RoleRef.APIGroup != rbac.GroupName { + allErrs = append(allErrs, field.NotSupported(field.NewPath("roleRef", "apiGroup"), roleBinding.RoleRef.APIGroup, []string{rbac.GroupName})) + } + + switch roleBinding.RoleRef.Kind { + case "Role", "ClusterRole": + default: + allErrs = append(allErrs, field.NotSupported(field.NewPath("roleRef", "kind"), roleBinding.RoleRef.Kind, []string{"Role", "ClusterRole"})) + } if len(roleBinding.RoleRef.Name) == 0 { @@ -141,11 +147,17 @@ func ValidateClusterRoleBinding(roleBinding *rbac.ClusterRoleBinding) field.Erro allErrs := field.ErrorList{} allErrs = append(allErrs, validation.ValidateObjectMeta(&roleBinding.ObjectMeta, false, minimalNameRequirements, field.NewPath("metadata"))...) - // roleRef namespace is empty when referring to global policy. - if len(roleBinding.RoleRef.Namespace) > 0 { - for _, msg := range validation.ValidateNamespaceName(roleBinding.RoleRef.Namespace, false) { - allErrs = append(allErrs, field.Invalid(field.NewPath("roleRef", "namespace"), roleBinding.RoleRef.Namespace, msg)) - } + // TODO allow multiple API groups. For now, restrict to one, but I can envision other experimental roles in other groups taking + // advantage of the binding infrastructure + if roleBinding.RoleRef.APIGroup != rbac.GroupName { + allErrs = append(allErrs, field.NotSupported(field.NewPath("roleRef", "apiGroup"), roleBinding.RoleRef.APIGroup, []string{rbac.GroupName})) + } + + switch roleBinding.RoleRef.Kind { + case "ClusterRole": + default: + allErrs = append(allErrs, field.NotSupported(field.NewPath("roleRef", "kind"), roleBinding.RoleRef.Kind, []string{"ClusterRole"})) + } if len(roleBinding.RoleRef.Name) == 0 { diff --git a/pkg/apis/rbac/validation/validation_test.go b/pkg/apis/rbac/validation/validation_test.go index c969b21f2d4..b04b1965181 100644 --- a/pkg/apis/rbac/validation/validation_test.go +++ b/pkg/apis/rbac/validation/validation_test.go @@ -24,11 +24,126 @@ import ( "k8s.io/kubernetes/pkg/util/validation/field" ) +func TestValidateClusterRoleBinding(t *testing.T) { + errs := ValidateClusterRoleBinding( + &rbac.ClusterRoleBinding{ + ObjectMeta: api.ObjectMeta{Name: "master"}, + RoleRef: rbac.RoleRef{APIGroup: rbac.GroupName, Kind: "ClusterRole", Name: "valid"}, + Subjects: []rbac.Subject{ + {Name: "validsaname", Namespace: "foo", Kind: rbac.ServiceAccountKind}, + {Name: "valid@username", Kind: rbac.UserKind}, + {Name: "valid@groupname", Kind: rbac.GroupKind}, + }, + }, + ) + if len(errs) != 0 { + t.Errorf("expected success: %v", errs) + } + + errorCases := map[string]struct { + A rbac.ClusterRoleBinding + T field.ErrorType + F string + }{ + "bad group": { + A: rbac.ClusterRoleBinding{ + ObjectMeta: api.ObjectMeta{Name: "default"}, + RoleRef: rbac.RoleRef{APIGroup: "rbac.GroupName", Kind: "ClusterRole", Name: "valid"}, + }, + T: field.ErrorTypeNotSupported, + F: "roleRef.apiGroup", + }, + "bad kind": { + A: rbac.ClusterRoleBinding{ + ObjectMeta: api.ObjectMeta{Name: "default"}, + RoleRef: rbac.RoleRef{APIGroup: rbac.GroupName, Kind: "Type", Name: "valid"}, + }, + T: field.ErrorTypeNotSupported, + F: "roleRef.kind", + }, + "reference role": { + A: rbac.ClusterRoleBinding{ + ObjectMeta: api.ObjectMeta{Name: "default"}, + RoleRef: rbac.RoleRef{APIGroup: rbac.GroupName, Kind: "Role", Name: "valid"}, + }, + T: field.ErrorTypeNotSupported, + F: "roleRef.kind", + }, + "zero-length name": { + A: rbac.ClusterRoleBinding{ + ObjectMeta: api.ObjectMeta{}, + RoleRef: rbac.RoleRef{APIGroup: rbac.GroupName, Kind: "ClusterRole", Name: "valid"}, + }, + T: field.ErrorTypeRequired, + F: "metadata.name", + }, + "bad role": { + A: rbac.ClusterRoleBinding{ + ObjectMeta: api.ObjectMeta{Name: "default"}, + RoleRef: rbac.RoleRef{APIGroup: rbac.GroupName, Kind: "ClusterRole"}, + }, + T: field.ErrorTypeRequired, + F: "roleRef.name", + }, + "bad subject kind": { + A: rbac.ClusterRoleBinding{ + ObjectMeta: api.ObjectMeta{Name: "master"}, + RoleRef: rbac.RoleRef{APIGroup: rbac.GroupName, Kind: "ClusterRole", Name: "valid"}, + Subjects: []rbac.Subject{{Name: "subject"}}, + }, + T: field.ErrorTypeNotSupported, + F: "subjects[0].kind", + }, + "bad subject name": { + A: rbac.ClusterRoleBinding{ + ObjectMeta: api.ObjectMeta{Name: "master"}, + RoleRef: rbac.RoleRef{APIGroup: rbac.GroupName, Kind: "ClusterRole", Name: "valid"}, + Subjects: []rbac.Subject{{Namespace: "foo", Name: "subject:bad", Kind: rbac.ServiceAccountKind}}, + }, + T: field.ErrorTypeInvalid, + F: "subjects[0].name", + }, + "missing SA namespace": { + A: rbac.ClusterRoleBinding{ + ObjectMeta: api.ObjectMeta{Name: "master"}, + RoleRef: rbac.RoleRef{APIGroup: rbac.GroupName, Kind: "ClusterRole", Name: "valid"}, + Subjects: []rbac.Subject{{Name: "good", Kind: rbac.ServiceAccountKind}}, + }, + T: field.ErrorTypeRequired, + F: "subjects[0].namespace", + }, + "missing subject name": { + A: rbac.ClusterRoleBinding{ + ObjectMeta: api.ObjectMeta{Name: "master"}, + RoleRef: rbac.RoleRef{APIGroup: rbac.GroupName, Kind: "ClusterRole", Name: "valid"}, + Subjects: []rbac.Subject{{Namespace: "foo", Kind: rbac.ServiceAccountKind}}, + }, + T: field.ErrorTypeRequired, + F: "subjects[0].name", + }, + } + for k, v := range errorCases { + errs := ValidateClusterRoleBinding(&v.A) + if len(errs) == 0 { + t.Errorf("expected failure %s for %v", k, v.A) + continue + } + for i := range errs { + if errs[i].Type != v.T { + t.Errorf("%s: expected errors to have type %s: %v", k, v.T, errs[i]) + } + if errs[i].Field != v.F { + t.Errorf("%s: expected errors to have field %s: %v", k, v.F, errs[i]) + } + } + } +} + func TestValidateRoleBinding(t *testing.T) { errs := ValidateRoleBinding( &rbac.RoleBinding{ ObjectMeta: api.ObjectMeta{Namespace: api.NamespaceDefault, Name: "master"}, - RoleRef: api.ObjectReference{Namespace: "master", Name: "valid"}, + RoleRef: rbac.RoleRef{APIGroup: rbac.GroupName, Kind: "Role", Name: "valid"}, Subjects: []rbac.Subject{ {Name: "validsaname", Kind: rbac.ServiceAccountKind}, {Name: "valid@username", Kind: rbac.UserKind}, @@ -45,10 +160,26 @@ func TestValidateRoleBinding(t *testing.T) { T field.ErrorType F string }{ + "bad group": { + A: rbac.RoleBinding{ + ObjectMeta: api.ObjectMeta{Namespace: api.NamespaceDefault, Name: "default"}, + RoleRef: rbac.RoleRef{APIGroup: "rbac.GroupName", Kind: "ClusterRole", Name: "valid"}, + }, + T: field.ErrorTypeNotSupported, + F: "roleRef.apiGroup", + }, + "bad kind": { + A: rbac.RoleBinding{ + ObjectMeta: api.ObjectMeta{Namespace: api.NamespaceDefault, Name: "default"}, + RoleRef: rbac.RoleRef{APIGroup: rbac.GroupName, Kind: "Type", Name: "valid"}, + }, + T: field.ErrorTypeNotSupported, + F: "roleRef.kind", + }, "zero-length namespace": { A: rbac.RoleBinding{ ObjectMeta: api.ObjectMeta{Name: "default"}, - RoleRef: api.ObjectReference{Namespace: "master", Name: "valid"}, + RoleRef: rbac.RoleRef{APIGroup: rbac.GroupName, Kind: "Role", Name: "valid"}, }, T: field.ErrorTypeRequired, F: "metadata.namespace", @@ -56,23 +187,15 @@ func TestValidateRoleBinding(t *testing.T) { "zero-length name": { A: rbac.RoleBinding{ ObjectMeta: api.ObjectMeta{Namespace: api.NamespaceDefault}, - RoleRef: api.ObjectReference{Namespace: "master", Name: "valid"}, + RoleRef: rbac.RoleRef{APIGroup: rbac.GroupName, Kind: "Role", Name: "valid"}, }, T: field.ErrorTypeRequired, F: "metadata.name", }, - "invalid ref": { - A: rbac.RoleBinding{ - ObjectMeta: api.ObjectMeta{Namespace: api.NamespaceDefault, Name: "name"}, - RoleRef: api.ObjectReference{Namespace: "-192083", Name: "valid"}, - }, - T: field.ErrorTypeInvalid, - F: "roleRef.namespace", - }, "bad role": { A: rbac.RoleBinding{ ObjectMeta: api.ObjectMeta{Namespace: api.NamespaceDefault, Name: "default"}, - RoleRef: api.ObjectReference{Namespace: "default"}, + RoleRef: rbac.RoleRef{APIGroup: rbac.GroupName, Kind: "Role"}, }, T: field.ErrorTypeRequired, F: "roleRef.name", @@ -80,7 +203,7 @@ func TestValidateRoleBinding(t *testing.T) { "bad subject kind": { A: rbac.RoleBinding{ ObjectMeta: api.ObjectMeta{Namespace: api.NamespaceDefault, Name: "master"}, - RoleRef: api.ObjectReference{Namespace: "master", Name: "valid"}, + RoleRef: rbac.RoleRef{APIGroup: rbac.GroupName, Kind: "Role", Name: "valid"}, Subjects: []rbac.Subject{{Name: "subject"}}, }, T: field.ErrorTypeNotSupported, @@ -89,7 +212,7 @@ func TestValidateRoleBinding(t *testing.T) { "bad subject name": { A: rbac.RoleBinding{ ObjectMeta: api.ObjectMeta{Namespace: api.NamespaceDefault, Name: "master"}, - RoleRef: api.ObjectReference{Namespace: "master", Name: "valid"}, + RoleRef: rbac.RoleRef{APIGroup: rbac.GroupName, Kind: "Role", Name: "valid"}, Subjects: []rbac.Subject{{Name: "subject:bad", Kind: rbac.ServiceAccountKind}}, }, T: field.ErrorTypeInvalid, @@ -98,7 +221,7 @@ func TestValidateRoleBinding(t *testing.T) { "missing subject name": { A: rbac.RoleBinding{ ObjectMeta: api.ObjectMeta{Namespace: api.NamespaceDefault, Name: "master"}, - RoleRef: api.ObjectReference{Namespace: "master", Name: "valid"}, + RoleRef: rbac.RoleRef{APIGroup: rbac.GroupName, Kind: "Role", Name: "valid"}, Subjects: []rbac.Subject{{Kind: rbac.ServiceAccountKind}}, }, T: field.ErrorTypeRequired, @@ -125,13 +248,13 @@ func TestValidateRoleBinding(t *testing.T) { func TestValidateRoleBindingUpdate(t *testing.T) { old := &rbac.RoleBinding{ ObjectMeta: api.ObjectMeta{Namespace: api.NamespaceDefault, Name: "master", ResourceVersion: "1"}, - RoleRef: api.ObjectReference{Namespace: "master", Name: "valid"}, + RoleRef: rbac.RoleRef{APIGroup: rbac.GroupName, Kind: "Role", Name: "valid"}, } errs := ValidateRoleBindingUpdate( &rbac.RoleBinding{ ObjectMeta: api.ObjectMeta{Namespace: api.NamespaceDefault, Name: "master", ResourceVersion: "1"}, - RoleRef: api.ObjectReference{Namespace: "master", Name: "valid"}, + RoleRef: rbac.RoleRef{APIGroup: rbac.GroupName, Kind: "Role", Name: "valid"}, }, old, ) @@ -147,7 +270,7 @@ func TestValidateRoleBindingUpdate(t *testing.T) { "changedRef": { A: rbac.RoleBinding{ ObjectMeta: api.ObjectMeta{Namespace: api.NamespaceDefault, Name: "master", ResourceVersion: "1"}, - RoleRef: api.ObjectReference{Namespace: "master", Name: "changed"}, + RoleRef: rbac.RoleRef{APIGroup: rbac.GroupName, Kind: "Role", Name: "changed"}, }, T: field.ErrorTypeInvalid, F: "roleRef", diff --git a/plugin/pkg/auth/authorizer/rbac/rbac_test.go b/plugin/pkg/auth/authorizer/rbac/rbac_test.go index 892faa81674..adeebac6b33 100644 --- a/plugin/pkg/auth/authorizer/rbac/rbac_test.go +++ b/plugin/pkg/auth/authorizer/rbac/rbac_test.go @@ -53,9 +53,10 @@ const ( func newClusterRoleBinding(roleName string, subjects ...string) rbac.ClusterRoleBinding { r := rbac.ClusterRoleBinding{ ObjectMeta: api.ObjectMeta{}, - RoleRef: api.ObjectReference{ - Kind: "ClusterRole", // ClusterRoleBindings can only refer to ClusterRole - Name: roleName, + RoleRef: rbac.RoleRef{ + APIGroup: rbac.GroupName, + Kind: "ClusterRole", // ClusterRoleBindings can only refer to ClusterRole + Name: roleName, }, } @@ -72,9 +73,9 @@ func newRoleBinding(namespace, roleName string, bindType uint16, subjects ...str switch bindType { case bindToRole: - r.RoleRef = api.ObjectReference{Kind: "Role", Namespace: namespace, Name: roleName} + r.RoleRef = rbac.RoleRef{APIGroup: rbac.GroupName, Kind: "Role", Name: roleName} case bindToClusterRole: - r.RoleRef = api.ObjectReference{Kind: "ClusterRole", Name: roleName} + r.RoleRef = rbac.RoleRef{APIGroup: rbac.GroupName, Kind: "ClusterRole", Name: roleName} } r.Subjects = make([]rbac.Subject, len(subjects)) diff --git a/test/integration/auth/rbac_test.go b/test/integration/auth/rbac_test.go index 17d4c3915c1..6cea15e035a 100644 --- a/test/integration/auth/rbac_test.go +++ b/test/integration/auth/rbac_test.go @@ -303,7 +303,7 @@ func TestRBAC(t *testing.T) { Subjects: []v1alpha1.Subject{ {Kind: "User", Name: "pod-reader"}, }, - RoleRef: v1.ObjectReference{Kind: "ClusterRole", Name: "read-pods"}, + RoleRef: v1alpha1.RoleRef{Kind: "ClusterRole", Name: "read-pods"}, }, }, }, @@ -335,14 +335,14 @@ func TestRBAC(t *testing.T) { { ObjectMeta: v1.ObjectMeta{Name: "write-jobs"}, Subjects: []v1alpha1.Subject{{Kind: "User", Name: "job-writer"}}, - RoleRef: v1.ObjectReference{Kind: "ClusterRole", Name: "write-jobs"}, + RoleRef: v1alpha1.RoleRef{Kind: "ClusterRole", Name: "write-jobs"}, }, }, roleBindings: []v1alpha1.RoleBinding{ { ObjectMeta: v1.ObjectMeta{Name: "write-jobs", Namespace: "job-namespace"}, Subjects: []v1alpha1.Subject{{Kind: "User", Name: "job-writer-namespace"}}, - RoleRef: v1.ObjectReference{Kind: "ClusterRole", Name: "write-jobs"}, + RoleRef: v1alpha1.RoleRef{Kind: "ClusterRole", Name: "write-jobs"}, }, }, },