1
16
17 package validation
18
19 import (
20 "reflect"
21 "sort"
22 "testing"
23
24 rbacv1 "k8s.io/api/rbac/v1"
25 "k8s.io/component-helpers/auth/rbac/validation"
26 rbacv1helpers "k8s.io/kubernetes/pkg/apis/rbac/v1"
27 )
28
29 func TestCompactRules(t *testing.T) {
30 testcases := map[string]struct {
31 Rules []rbacv1.PolicyRule
32 Expected []rbacv1.PolicyRule
33 }{
34 "empty": {
35 Rules: []rbacv1.PolicyRule{},
36 Expected: []rbacv1.PolicyRule{},
37 },
38 "simple": {
39 Rules: []rbacv1.PolicyRule{
40 {Verbs: []string{"get"}, APIGroups: []string{""}, Resources: []string{"builds"}},
41 {Verbs: []string{"list"}, APIGroups: []string{""}, Resources: []string{"builds"}},
42 {Verbs: []string{"update", "patch"}, APIGroups: []string{""}, Resources: []string{"builds"}},
43
44 {Verbs: []string{"create"}, APIGroups: []string{"extensions"}, Resources: []string{"daemonsets"}},
45 {Verbs: []string{"delete"}, APIGroups: []string{"extensions"}, Resources: []string{"daemonsets"}},
46 {Verbs: []string{"patch"}, APIGroups: []string{"extensions"}, Resources: []string{"daemonsets"}, ResourceNames: []string{""}},
47 {Verbs: []string{"get"}, APIGroups: []string{"extensions"}, Resources: []string{"daemonsets"}, ResourceNames: []string{"foo"}},
48 {Verbs: []string{"list"}, APIGroups: []string{"extensions"}, Resources: []string{"daemonsets"}, ResourceNames: []string{"foo"}},
49
50 {Verbs: []string{"educate"}, APIGroups: []string{""}, Resources: []string{"dolphins"}},
51
52
53
54 {Verbs: nil, APIGroups: []string{""}, Resources: []string{"pirates"}},
55
56
57 {Verbs: nil, APIGroups: []string{""}, Resources: []string{"pods"}},
58 {Verbs: []string{"create"}, APIGroups: []string{""}, Resources: []string{"pods"}},
59 },
60 Expected: []rbacv1.PolicyRule{
61 {Verbs: []string{"create", "delete"}, APIGroups: []string{"extensions"}, Resources: []string{"daemonsets"}},
62 {Verbs: []string{"patch"}, APIGroups: []string{"extensions"}, Resources: []string{"daemonsets"}, ResourceNames: []string{""}},
63 {Verbs: []string{"get", "list"}, APIGroups: []string{"extensions"}, Resources: []string{"daemonsets"}, ResourceNames: []string{"foo"}},
64 {Verbs: []string{"get", "list", "update", "patch"}, APIGroups: []string{""}, Resources: []string{"builds"}},
65 {Verbs: []string{"educate"}, APIGroups: []string{""}, Resources: []string{"dolphins"}},
66 {Verbs: nil, APIGroups: []string{""}, Resources: []string{"pirates"}},
67 {Verbs: []string{"create"}, APIGroups: []string{""}, Resources: []string{"pods"}},
68 },
69 },
70 "complex multi-group": {
71 Rules: []rbacv1.PolicyRule{
72 {Verbs: []string{"get"}, APIGroups: []string{"", "builds.openshift.io"}, Resources: []string{"builds"}},
73 {Verbs: []string{"list"}, APIGroups: []string{"", "builds.openshift.io"}, Resources: []string{"builds"}},
74 },
75 Expected: []rbacv1.PolicyRule{
76 {Verbs: []string{"get"}, APIGroups: []string{"", "builds.openshift.io"}, Resources: []string{"builds"}},
77 {Verbs: []string{"list"}, APIGroups: []string{"", "builds.openshift.io"}, Resources: []string{"builds"}},
78 },
79 },
80
81 "complex multi-resource": {
82 Rules: []rbacv1.PolicyRule{
83 {Verbs: []string{"get"}, APIGroups: []string{""}, Resources: []string{"builds", "images"}},
84 {Verbs: []string{"list"}, APIGroups: []string{""}, Resources: []string{"builds", "images"}},
85 },
86 Expected: []rbacv1.PolicyRule{
87 {Verbs: []string{"get"}, APIGroups: []string{""}, Resources: []string{"builds", "images"}},
88 {Verbs: []string{"list"}, APIGroups: []string{""}, Resources: []string{"builds", "images"}},
89 },
90 },
91
92 "complex named-resource": {
93 Rules: []rbacv1.PolicyRule{
94 {Verbs: []string{"get"}, APIGroups: []string{""}, Resources: []string{"builds"}, ResourceNames: []string{"mybuild"}},
95 {Verbs: []string{"list"}, APIGroups: []string{""}, Resources: []string{"builds"}, ResourceNames: []string{"mybuild2"}},
96 },
97 Expected: []rbacv1.PolicyRule{
98 {Verbs: []string{"get"}, APIGroups: []string{""}, Resources: []string{"builds"}, ResourceNames: []string{"mybuild"}},
99 {Verbs: []string{"list"}, APIGroups: []string{""}, Resources: []string{"builds"}, ResourceNames: []string{"mybuild2"}},
100 },
101 },
102
103 "complex non-resource": {
104 Rules: []rbacv1.PolicyRule{
105 {Verbs: []string{"get"}, APIGroups: []string{""}, Resources: []string{"builds"}, NonResourceURLs: []string{"/"}},
106 {Verbs: []string{"get"}, APIGroups: []string{""}, Resources: []string{"builds"}, NonResourceURLs: []string{"/foo"}},
107 },
108 Expected: []rbacv1.PolicyRule{
109 {Verbs: []string{"get"}, APIGroups: []string{""}, Resources: []string{"builds"}, NonResourceURLs: []string{"/"}},
110 {Verbs: []string{"get"}, APIGroups: []string{""}, Resources: []string{"builds"}, NonResourceURLs: []string{"/foo"}},
111 },
112 },
113 }
114
115 for k, tc := range testcases {
116 rules := tc.Rules
117 originalRules := make([]rbacv1.PolicyRule, len(tc.Rules))
118 for i := range tc.Rules {
119 originalRules[i] = *tc.Rules[i].DeepCopy()
120 }
121 compacted, err := CompactRules(tc.Rules)
122 if err != nil {
123 t.Errorf("%s: unexpected error: %v", k, err)
124 continue
125 }
126 if !reflect.DeepEqual(rules, originalRules) {
127 t.Errorf("%s: CompactRules mutated rules. Expected\n%#v\ngot\n%#v", k, originalRules, rules)
128 continue
129 }
130 if covers, missing := validation.Covers(compacted, rules); !covers {
131 t.Errorf("%s: compacted rules did not cover original rules. missing: %#v", k, missing)
132 continue
133 }
134 if covers, missing := validation.Covers(rules, compacted); !covers {
135 t.Errorf("%s: original rules did not cover compacted rules. missing: %#v", k, missing)
136 continue
137 }
138
139 sort.Stable(rbacv1helpers.SortableRuleSlice(compacted))
140 sort.Stable(rbacv1helpers.SortableRuleSlice(tc.Expected))
141 if !reflect.DeepEqual(compacted, tc.Expected) {
142 t.Errorf("%s: Expected\n%#v\ngot\n%#v", k, tc.Expected, compacted)
143 continue
144 }
145 }
146 }
147
148 func TestIsSimpleResourceRule(t *testing.T) {
149 testcases := map[string]struct {
150 Rule rbacv1.PolicyRule
151 Simple bool
152 Resource simpleResource
153 }{
154 "simple, no verbs": {
155 Rule: rbacv1.PolicyRule{Verbs: []string{}, APIGroups: []string{""}, Resources: []string{"builds"}},
156 Simple: true,
157 Resource: simpleResource{Group: "", Resource: "builds"},
158 },
159 "simple, one verb": {
160 Rule: rbacv1.PolicyRule{Verbs: []string{"get"}, APIGroups: []string{""}, Resources: []string{"builds"}},
161 Simple: true,
162 Resource: simpleResource{Group: "", Resource: "builds"},
163 },
164 "simple, one empty resource name": {
165 Rule: rbacv1.PolicyRule{Verbs: []string{"get"}, APIGroups: []string{""}, Resources: []string{"builds"}, ResourceNames: []string{""}},
166 Simple: true,
167 Resource: simpleResource{Group: "", Resource: "builds", ResourceNameExist: true, ResourceName: ""},
168 },
169 "simple, one resource name": {
170 Rule: rbacv1.PolicyRule{Verbs: []string{"get"}, APIGroups: []string{""}, Resources: []string{"builds"}, ResourceNames: []string{"foo"}},
171 Simple: true,
172 Resource: simpleResource{Group: "", Resource: "builds", ResourceNameExist: true, ResourceName: "foo"},
173 },
174 "simple, multi verb": {
175 Rule: rbacv1.PolicyRule{Verbs: []string{"get", "list"}, APIGroups: []string{""}, Resources: []string{"builds"}},
176 Simple: true,
177 Resource: simpleResource{Group: "", Resource: "builds"},
178 },
179
180 "complex, empty": {
181 Rule: rbacv1.PolicyRule{},
182 Simple: false,
183 Resource: simpleResource{},
184 },
185 "complex, no group": {
186 Rule: rbacv1.PolicyRule{Verbs: []string{"get"}, APIGroups: []string{}, Resources: []string{"builds"}},
187 Simple: false,
188 Resource: simpleResource{},
189 },
190 "complex, multi group": {
191 Rule: rbacv1.PolicyRule{Verbs: []string{"get"}, APIGroups: []string{"a", "b"}, Resources: []string{"builds"}},
192 Simple: false,
193 Resource: simpleResource{},
194 },
195 "complex, no resource": {
196 Rule: rbacv1.PolicyRule{Verbs: []string{"get"}, APIGroups: []string{""}, Resources: []string{}},
197 Simple: false,
198 Resource: simpleResource{},
199 },
200 "complex, multi resource": {
201 Rule: rbacv1.PolicyRule{Verbs: []string{"get"}, APIGroups: []string{""}, Resources: []string{"builds", "images"}},
202 Simple: false,
203 Resource: simpleResource{},
204 },
205 "complex, resource names": {
206 Rule: rbacv1.PolicyRule{Verbs: []string{"get"}, APIGroups: []string{""}, Resources: []string{"builds"}, ResourceNames: []string{"foo", "bar"}},
207 Simple: false,
208 Resource: simpleResource{},
209 },
210 "complex, non-resource urls": {
211 Rule: rbacv1.PolicyRule{Verbs: []string{"get"}, APIGroups: []string{""}, Resources: []string{"builds"}, NonResourceURLs: []string{"/"}},
212 Simple: false,
213 Resource: simpleResource{},
214 },
215 }
216
217 for k, tc := range testcases {
218 resource, simple := isSimpleResourceRule(&tc.Rule)
219 if simple != tc.Simple {
220 t.Errorf("%s: expected simple=%v, got simple=%v", k, tc.Simple, simple)
221 continue
222 }
223 if resource != tc.Resource {
224 t.Errorf("%s: expected resource=%v, got resource=%v", k, tc.Resource, resource)
225 continue
226 }
227 }
228 }
229
View as plain text