mirror of
https://github.com/k3s-io/kubernetes.git
synced 2026-01-13 11:25:19 +00:00
change rbac roleref type
This commit is contained in:
@@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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"},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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",
|
||||
|
||||
Reference in New Issue
Block a user