add field and label selectors to authorization attributes
Co-authored-by: Jordan Liggitt <liggitt@google.com>
This commit is contained in:
committed by
Jordan Liggitt
parent
f5e5bef2e0
commit
92e3445e9d
@@ -24,6 +24,8 @@ import (
|
||||
|
||||
rbacv1 "k8s.io/api/rbac/v1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/fields"
|
||||
"k8s.io/apimachinery/pkg/labels"
|
||||
"k8s.io/apiserver/pkg/authentication/user"
|
||||
"k8s.io/apiserver/pkg/authorization/authorizer"
|
||||
rbacv1helpers "k8s.io/kubernetes/pkg/apis/rbac/v1"
|
||||
@@ -135,6 +137,12 @@ func (d *defaultAttributes) GetAPIGroup() string { return d.apiGroup }
|
||||
func (d *defaultAttributes) GetAPIVersion() string { return "" }
|
||||
func (d *defaultAttributes) IsResourceRequest() bool { return true }
|
||||
func (d *defaultAttributes) GetPath() string { return "" }
|
||||
func (d *defaultAttributes) GetFieldSelector() (fields.Requirements, error) {
|
||||
panic("not supported for RBAC")
|
||||
}
|
||||
func (d *defaultAttributes) GetLabelSelector() (labels.Requirements, error) {
|
||||
panic("not supported for RBAC")
|
||||
}
|
||||
|
||||
func TestAuthorizer(t *testing.T) {
|
||||
tests := []struct {
|
||||
@@ -263,135 +271,139 @@ func TestAuthorizer(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestRuleMatches(t *testing.T) {
|
||||
type requestToTest struct {
|
||||
request authorizer.AttributesRecord
|
||||
expected bool
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
rule rbacv1.PolicyRule
|
||||
|
||||
requestsToExpected map[authorizer.AttributesRecord]bool
|
||||
requestsToExpected []*requestToTest
|
||||
}{
|
||||
{
|
||||
name: "star verb, exact match other",
|
||||
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,
|
||||
resourceRequest("verb1").Group("group1").Resource("resource2").New(): false,
|
||||
resourceRequest("verb1").Group("group2").Resource("resource2").New(): false,
|
||||
resourceRequest("verb2").Group("group1").Resource("resource1").New(): true,
|
||||
resourceRequest("verb2").Group("group2").Resource("resource1").New(): false,
|
||||
resourceRequest("verb2").Group("group1").Resource("resource2").New(): false,
|
||||
resourceRequest("verb2").Group("group2").Resource("resource2").New(): false,
|
||||
requestsToExpected: []*requestToTest{
|
||||
{resourceRequest("verb1").Group("group1").Resource("resource1").New(), true},
|
||||
{resourceRequest("verb1").Group("group2").Resource("resource1").New(), false},
|
||||
{resourceRequest("verb1").Group("group1").Resource("resource2").New(), false},
|
||||
{resourceRequest("verb1").Group("group2").Resource("resource2").New(), false},
|
||||
{resourceRequest("verb2").Group("group1").Resource("resource1").New(), true},
|
||||
{resourceRequest("verb2").Group("group2").Resource("resource1").New(), false},
|
||||
{resourceRequest("verb2").Group("group1").Resource("resource2").New(), false},
|
||||
{resourceRequest("verb2").Group("group2").Resource("resource2").New(), false},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "star group, exact match other",
|
||||
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,
|
||||
resourceRequest("verb1").Group("group1").Resource("resource2").New(): false,
|
||||
resourceRequest("verb1").Group("group2").Resource("resource2").New(): false,
|
||||
resourceRequest("verb2").Group("group1").Resource("resource1").New(): false,
|
||||
resourceRequest("verb2").Group("group2").Resource("resource1").New(): false,
|
||||
resourceRequest("verb2").Group("group1").Resource("resource2").New(): false,
|
||||
resourceRequest("verb2").Group("group2").Resource("resource2").New(): false,
|
||||
requestsToExpected: []*requestToTest{
|
||||
{resourceRequest("verb1").Group("group1").Resource("resource1").New(), true},
|
||||
{resourceRequest("verb1").Group("group2").Resource("resource1").New(), true},
|
||||
{resourceRequest("verb1").Group("group1").Resource("resource2").New(), false},
|
||||
{resourceRequest("verb1").Group("group2").Resource("resource2").New(), false},
|
||||
{resourceRequest("verb2").Group("group1").Resource("resource1").New(), false},
|
||||
{resourceRequest("verb2").Group("group2").Resource("resource1").New(), false},
|
||||
{resourceRequest("verb2").Group("group1").Resource("resource2").New(), false},
|
||||
{resourceRequest("verb2").Group("group2").Resource("resource2").New(), false},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "star resource, exact match other",
|
||||
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,
|
||||
resourceRequest("verb1").Group("group1").Resource("resource2").New(): true,
|
||||
resourceRequest("verb1").Group("group2").Resource("resource2").New(): false,
|
||||
resourceRequest("verb2").Group("group1").Resource("resource1").New(): false,
|
||||
resourceRequest("verb2").Group("group2").Resource("resource1").New(): false,
|
||||
resourceRequest("verb2").Group("group1").Resource("resource2").New(): false,
|
||||
resourceRequest("verb2").Group("group2").Resource("resource2").New(): false,
|
||||
requestsToExpected: []*requestToTest{
|
||||
{resourceRequest("verb1").Group("group1").Resource("resource1").New(), true},
|
||||
{resourceRequest("verb1").Group("group2").Resource("resource1").New(), false},
|
||||
{resourceRequest("verb1").Group("group1").Resource("resource2").New(), true},
|
||||
{resourceRequest("verb1").Group("group2").Resource("resource2").New(), false},
|
||||
{resourceRequest("verb2").Group("group1").Resource("resource1").New(), false},
|
||||
{resourceRequest("verb2").Group("group2").Resource("resource1").New(), false},
|
||||
{resourceRequest("verb2").Group("group1").Resource("resource2").New(), false},
|
||||
{resourceRequest("verb2").Group("group2").Resource("resource2").New(), false},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "tuple expansion",
|
||||
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,
|
||||
resourceRequest("verb1").Group("group1").Resource("resource2").New(): true,
|
||||
resourceRequest("verb1").Group("group2").Resource("resource2").New(): true,
|
||||
resourceRequest("verb2").Group("group1").Resource("resource1").New(): true,
|
||||
resourceRequest("verb2").Group("group2").Resource("resource1").New(): true,
|
||||
resourceRequest("verb2").Group("group1").Resource("resource2").New(): true,
|
||||
resourceRequest("verb2").Group("group2").Resource("resource2").New(): true,
|
||||
requestsToExpected: []*requestToTest{
|
||||
{resourceRequest("verb1").Group("group1").Resource("resource1").New(), true},
|
||||
{resourceRequest("verb1").Group("group2").Resource("resource1").New(), true},
|
||||
{resourceRequest("verb1").Group("group1").Resource("resource2").New(), true},
|
||||
{resourceRequest("verb1").Group("group2").Resource("resource2").New(), true},
|
||||
{resourceRequest("verb2").Group("group1").Resource("resource1").New(), true},
|
||||
{resourceRequest("verb2").Group("group2").Resource("resource1").New(), true},
|
||||
{resourceRequest("verb2").Group("group1").Resource("resource2").New(), true},
|
||||
{resourceRequest("verb2").Group("group2").Resource("resource2").New(), true},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "subresource expansion",
|
||||
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,
|
||||
resourceRequest("verb1").Group("group1").Resource("resource2").Subresource("subresource1").New(): false,
|
||||
resourceRequest("verb1").Group("group2").Resource("resource2").Subresource("subresource1").New(): false,
|
||||
resourceRequest("verb2").Group("group1").Resource("resource1").Subresource("subresource1").New(): true,
|
||||
resourceRequest("verb2").Group("group2").Resource("resource1").Subresource("subresource2").New(): false,
|
||||
resourceRequest("verb2").Group("group1").Resource("resource2").Subresource("subresource1").New(): false,
|
||||
resourceRequest("verb2").Group("group2").Resource("resource2").Subresource("subresource1").New(): false,
|
||||
requestsToExpected: []*requestToTest{
|
||||
{resourceRequest("verb1").Group("group1").Resource("resource1").Subresource("subresource1").New(), true},
|
||||
{resourceRequest("verb1").Group("group2").Resource("resource1").Subresource("subresource2").New(), false},
|
||||
{resourceRequest("verb1").Group("group1").Resource("resource2").Subresource("subresource1").New(), false},
|
||||
{resourceRequest("verb1").Group("group2").Resource("resource2").Subresource("subresource1").New(), false},
|
||||
{resourceRequest("verb2").Group("group1").Resource("resource1").Subresource("subresource1").New(), true},
|
||||
{resourceRequest("verb2").Group("group2").Resource("resource1").Subresource("subresource2").New(), false},
|
||||
{resourceRequest("verb2").Group("group1").Resource("resource2").Subresource("subresource1").New(), false},
|
||||
{resourceRequest("verb2").Group("group2").Resource("resource2").Subresource("subresource1").New(), false},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "star nonresource, exact match other",
|
||||
rule: rbacv1helpers.NewRule("verb1").URLs("*").RuleOrDie(),
|
||||
requestsToExpected: map[authorizer.AttributesRecord]bool{
|
||||
nonresourceRequest("verb1").URL("/foo").New(): true,
|
||||
nonresourceRequest("verb1").URL("/foo/bar").New(): true,
|
||||
nonresourceRequest("verb1").URL("/foo/baz").New(): true,
|
||||
nonresourceRequest("verb1").URL("/foo/bar/one").New(): true,
|
||||
nonresourceRequest("verb1").URL("/foo/baz/one").New(): true,
|
||||
nonresourceRequest("verb2").URL("/foo").New(): false,
|
||||
nonresourceRequest("verb2").URL("/foo/bar").New(): false,
|
||||
nonresourceRequest("verb2").URL("/foo/baz").New(): false,
|
||||
nonresourceRequest("verb2").URL("/foo/bar/one").New(): false,
|
||||
nonresourceRequest("verb2").URL("/foo/baz/one").New(): false,
|
||||
requestsToExpected: []*requestToTest{
|
||||
{nonresourceRequest("verb1").URL("/foo").New(), true},
|
||||
{nonresourceRequest("verb1").URL("/foo/bar").New(), true},
|
||||
{nonresourceRequest("verb1").URL("/foo/baz").New(), true},
|
||||
{nonresourceRequest("verb1").URL("/foo/bar/one").New(), true},
|
||||
{nonresourceRequest("verb1").URL("/foo/baz/one").New(), true},
|
||||
{nonresourceRequest("verb2").URL("/foo").New(), false},
|
||||
{nonresourceRequest("verb2").URL("/foo/bar").New(), false},
|
||||
{nonresourceRequest("verb2").URL("/foo/baz").New(), false},
|
||||
{nonresourceRequest("verb2").URL("/foo/bar/one").New(), false},
|
||||
{nonresourceRequest("verb2").URL("/foo/baz/one").New(), false},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "star nonresource subpath",
|
||||
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,
|
||||
nonresourceRequest("verb1").URL("/foo/baz").New(): true,
|
||||
nonresourceRequest("verb1").URL("/foo/bar/one").New(): true,
|
||||
nonresourceRequest("verb1").URL("/foo/baz/one").New(): true,
|
||||
nonresourceRequest("verb1").URL("/notfoo").New(): false,
|
||||
nonresourceRequest("verb1").URL("/notfoo/bar").New(): false,
|
||||
nonresourceRequest("verb1").URL("/notfoo/baz").New(): false,
|
||||
nonresourceRequest("verb1").URL("/notfoo/bar/one").New(): false,
|
||||
nonresourceRequest("verb1").URL("/notfoo/baz/one").New(): false,
|
||||
requestsToExpected: []*requestToTest{
|
||||
{nonresourceRequest("verb1").URL("/foo").New(), false},
|
||||
{nonresourceRequest("verb1").URL("/foo/bar").New(), true},
|
||||
{nonresourceRequest("verb1").URL("/foo/baz").New(), true},
|
||||
{nonresourceRequest("verb1").URL("/foo/bar/one").New(), true},
|
||||
{nonresourceRequest("verb1").URL("/foo/baz/one").New(), true},
|
||||
{nonresourceRequest("verb1").URL("/notfoo").New(), false},
|
||||
{nonresourceRequest("verb1").URL("/notfoo/bar").New(), false},
|
||||
{nonresourceRequest("verb1").URL("/notfoo/baz").New(), false},
|
||||
{nonresourceRequest("verb1").URL("/notfoo/bar/one").New(), false},
|
||||
{nonresourceRequest("verb1").URL("/notfoo/baz/one").New(), false},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "star verb, exact nonresource",
|
||||
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,
|
||||
nonresourceRequest("verb1").URL("/foo/baz").New(): false,
|
||||
nonresourceRequest("verb1").URL("/foo/bar/one").New(): true,
|
||||
nonresourceRequest("verb1").URL("/foo/baz/one").New(): false,
|
||||
nonresourceRequest("verb2").URL("/foo").New(): true,
|
||||
nonresourceRequest("verb2").URL("/foo/bar").New(): false,
|
||||
nonresourceRequest("verb2").URL("/foo/baz").New(): false,
|
||||
nonresourceRequest("verb2").URL("/foo/bar/one").New(): true,
|
||||
nonresourceRequest("verb2").URL("/foo/baz/one").New(): false,
|
||||
requestsToExpected: []*requestToTest{
|
||||
{nonresourceRequest("verb1").URL("/foo").New(), true},
|
||||
{nonresourceRequest("verb1").URL("/foo/bar").New(), false},
|
||||
{nonresourceRequest("verb1").URL("/foo/baz").New(), false},
|
||||
{nonresourceRequest("verb1").URL("/foo/bar/one").New(), true},
|
||||
{nonresourceRequest("verb1").URL("/foo/baz/one").New(), false},
|
||||
{nonresourceRequest("verb2").URL("/foo").New(), true},
|
||||
{nonresourceRequest("verb2").URL("/foo/bar").New(), false},
|
||||
{nonresourceRequest("verb2").URL("/foo/baz").New(), false},
|
||||
{nonresourceRequest("verb2").URL("/foo/bar/one").New(), true},
|
||||
{nonresourceRequest("verb2").URL("/foo/baz/one").New(), false},
|
||||
},
|
||||
},
|
||||
}
|
||||
for _, tc := range tests {
|
||||
for request, expected := range tc.requestsToExpected {
|
||||
if e, a := expected, RuleAllows(request, &tc.rule); e != a {
|
||||
t.Errorf("%q: expected %v, got %v for %v", tc.name, e, a, request)
|
||||
for _, requestToTest := range tc.requestsToExpected {
|
||||
if e, a := requestToTest.expected, RuleAllows(requestToTest.request, &tc.rule); e != a {
|
||||
t.Errorf("%q: expected %v, got %v for %v", tc.name, e, a, requestToTest.request)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user