123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228 |
- /*
- Copyright 2017 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 (
- "reflect"
- "sort"
- "testing"
- rbacv1 "k8s.io/api/rbac/v1"
- rbacv1helpers "k8s.io/kubernetes/pkg/apis/rbac/v1"
- )
- func TestCompactRules(t *testing.T) {
- testcases := map[string]struct {
- Rules []rbacv1.PolicyRule
- Expected []rbacv1.PolicyRule
- }{
- "empty": {
- Rules: []rbacv1.PolicyRule{},
- Expected: []rbacv1.PolicyRule{},
- },
- "simple": {
- 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"}},
- {Verbs: []string{"create"}, APIGroups: []string{"extensions"}, Resources: []string{"daemonsets"}},
- {Verbs: []string{"delete"}, APIGroups: []string{"extensions"}, Resources: []string{"daemonsets"}},
- {Verbs: []string{"patch"}, APIGroups: []string{"extensions"}, Resources: []string{"daemonsets"}, ResourceNames: []string{""}},
- {Verbs: []string{"get"}, APIGroups: []string{"extensions"}, Resources: []string{"daemonsets"}, ResourceNames: []string{"foo"}},
- {Verbs: []string{"list"}, APIGroups: []string{"extensions"}, Resources: []string{"daemonsets"}, ResourceNames: []string{"foo"}},
- {Verbs: []string{"educate"}, APIGroups: []string{""}, Resources: []string{"dolphins"}},
- // nil verbs are preserved in non-merge cases.
- // these are the pirates who don't do anything.
- {Verbs: nil, APIGroups: []string{""}, Resources: []string{"pirates"}},
- // Test merging into a nil Verbs string set
- {Verbs: nil, APIGroups: []string{""}, Resources: []string{"pods"}},
- {Verbs: []string{"create"}, APIGroups: []string{""}, Resources: []string{"pods"}},
- },
- 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"}},
- {Verbs: []string{"get", "list", "update", "patch"}, APIGroups: []string{""}, Resources: []string{"builds"}},
- {Verbs: []string{"educate"}, APIGroups: []string{""}, Resources: []string{"dolphins"}},
- {Verbs: nil, APIGroups: []string{""}, Resources: []string{"pirates"}},
- {Verbs: []string{"create"}, APIGroups: []string{""}, Resources: []string{"pods"}},
- },
- },
- "complex multi-group": {
- 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: []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: []rbacv1.PolicyRule{
- {Verbs: []string{"get"}, APIGroups: []string{""}, Resources: []string{"builds", "images"}},
- {Verbs: []string{"list"}, APIGroups: []string{""}, Resources: []string{"builds", "images"}},
- },
- 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: []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: []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: []rbacv1.PolicyRule{
- {Verbs: []string{"get"}, APIGroups: []string{""}, Resources: []string{"builds"}, NonResourceURLs: []string{"/"}},
- {Verbs: []string{"get"}, APIGroups: []string{""}, Resources: []string{"builds"}, NonResourceURLs: []string{"/foo"}},
- },
- Expected: []rbacv1.PolicyRule{
- {Verbs: []string{"get"}, APIGroups: []string{""}, Resources: []string{"builds"}, NonResourceURLs: []string{"/"}},
- {Verbs: []string{"get"}, APIGroups: []string{""}, Resources: []string{"builds"}, NonResourceURLs: []string{"/foo"}},
- },
- },
- }
- for k, tc := range testcases {
- rules := tc.Rules
- originalRules := make([]rbacv1.PolicyRule, len(tc.Rules))
- for i := range tc.Rules {
- originalRules[i] = *tc.Rules[i].DeepCopy()
- }
- compacted, err := CompactRules(tc.Rules)
- if err != nil {
- t.Errorf("%s: unexpected error: %v", k, err)
- continue
- }
- if !reflect.DeepEqual(rules, originalRules) {
- t.Errorf("%s: CompactRules mutated rules. Expected\n%#v\ngot\n%#v", k, originalRules, rules)
- continue
- }
- if covers, missing := Covers(compacted, rules); !covers {
- t.Errorf("%s: compacted rules did not cover original rules. missing: %#v", k, missing)
- continue
- }
- if covers, missing := Covers(rules, compacted); !covers {
- t.Errorf("%s: original rules did not cover compacted rules. missing: %#v", k, missing)
- continue
- }
- 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
- }
- }
- }
- func TestIsSimpleResourceRule(t *testing.T) {
- testcases := map[string]struct {
- Rule rbacv1.PolicyRule
- Simple bool
- Resource simpleResource
- }{
- "simple, no verbs": {
- Rule: rbacv1.PolicyRule{Verbs: []string{}, APIGroups: []string{""}, Resources: []string{"builds"}},
- Simple: true,
- Resource: simpleResource{Group: "", Resource: "builds"},
- },
- "simple, one verb": {
- Rule: rbacv1.PolicyRule{Verbs: []string{"get"}, APIGroups: []string{""}, Resources: []string{"builds"}},
- Simple: true,
- Resource: simpleResource{Group: "", Resource: "builds"},
- },
- "simple, one empty resource name": {
- 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: 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: rbacv1.PolicyRule{Verbs: []string{"get", "list"}, APIGroups: []string{""}, Resources: []string{"builds"}},
- Simple: true,
- Resource: simpleResource{Group: "", Resource: "builds"},
- },
- "complex, empty": {
- Rule: rbacv1.PolicyRule{},
- Simple: false,
- Resource: simpleResource{},
- },
- "complex, no group": {
- Rule: rbacv1.PolicyRule{Verbs: []string{"get"}, APIGroups: []string{}, Resources: []string{"builds"}},
- Simple: false,
- Resource: simpleResource{},
- },
- "complex, multi group": {
- Rule: rbacv1.PolicyRule{Verbs: []string{"get"}, APIGroups: []string{"a", "b"}, Resources: []string{"builds"}},
- Simple: false,
- Resource: simpleResource{},
- },
- "complex, no resource": {
- Rule: rbacv1.PolicyRule{Verbs: []string{"get"}, APIGroups: []string{""}, Resources: []string{}},
- Simple: false,
- Resource: simpleResource{},
- },
- "complex, multi resource": {
- Rule: rbacv1.PolicyRule{Verbs: []string{"get"}, APIGroups: []string{""}, Resources: []string{"builds", "images"}},
- Simple: false,
- Resource: simpleResource{},
- },
- "complex, resource names": {
- Rule: rbacv1.PolicyRule{Verbs: []string{"get"}, APIGroups: []string{""}, Resources: []string{"builds"}, ResourceNames: []string{"foo", "bar"}},
- Simple: false,
- Resource: simpleResource{},
- },
- "complex, non-resource urls": {
- Rule: rbacv1.PolicyRule{Verbs: []string{"get"}, APIGroups: []string{""}, Resources: []string{"builds"}, NonResourceURLs: []string{"/"}},
- Simple: false,
- Resource: simpleResource{},
- },
- }
- for k, tc := range testcases {
- resource, simple := isSimpleResourceRule(&tc.Rule)
- if simple != tc.Simple {
- t.Errorf("%s: expected simple=%v, got simple=%v", k, tc.Simple, simple)
- continue
- }
- if resource != tc.Resource {
- t.Errorf("%s: expected resource=%v, got resource=%v", k, tc.Resource, resource)
- continue
- }
- }
- }
|