1
16
17 package set
18
19 import (
20 "reflect"
21 "testing"
22
23 rbacv1 "k8s.io/api/rbac/v1"
24 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
25 "k8s.io/apimachinery/pkg/runtime"
26 "k8s.io/cli-runtime/pkg/resource"
27 cmdtesting "k8s.io/kubectl/pkg/cmd/testing"
28 )
29
30 func TestValidate(t *testing.T) {
31 tf := cmdtesting.NewTestFactory().WithNamespace("test")
32 defer tf.Cleanup()
33
34 tests := map[string]struct {
35 options *SubjectOptions
36 expectErr bool
37 }{
38 "test-missing-subjects": {
39 options: &SubjectOptions{
40 Users: []string{},
41 Groups: []string{},
42 ServiceAccounts: []string{},
43 },
44 expectErr: true,
45 },
46 "test-invalid-serviceaccounts": {
47 options: &SubjectOptions{
48 Users: []string{},
49 Groups: []string{},
50 ServiceAccounts: []string{"foo"},
51 },
52 expectErr: true,
53 },
54 "test-missing-serviceaccounts-name": {
55 options: &SubjectOptions{
56 Users: []string{},
57 Groups: []string{},
58 ServiceAccounts: []string{"foo:"},
59 },
60 expectErr: true,
61 },
62 "test-missing-serviceaccounts-namespace": {
63 options: &SubjectOptions{
64 Infos: []*resource.Info{
65 {
66 Object: &rbacv1.ClusterRoleBinding{
67 ObjectMeta: metav1.ObjectMeta{
68 Name: "clusterrolebinding",
69 },
70 RoleRef: rbacv1.RoleRef{
71 APIGroup: "rbac.authorization.k8s.io",
72 Kind: "ClusterRole",
73 Name: "role",
74 },
75 },
76 },
77 },
78 Users: []string{},
79 Groups: []string{},
80 ServiceAccounts: []string{":foo"},
81 },
82 expectErr: true,
83 },
84 "test-valid-case": {
85 options: &SubjectOptions{
86 Infos: []*resource.Info{
87 {
88 Object: &rbacv1.RoleBinding{
89 ObjectMeta: metav1.ObjectMeta{
90 Name: "rolebinding",
91 Namespace: "one",
92 },
93 RoleRef: rbacv1.RoleRef{
94 APIGroup: "rbac.authorization.k8s.io",
95 Kind: "ClusterRole",
96 Name: "role",
97 },
98 },
99 },
100 },
101 Users: []string{"foo"},
102 Groups: []string{"foo"},
103 ServiceAccounts: []string{"ns:foo"},
104 },
105 expectErr: false,
106 },
107 }
108
109 for name, test := range tests {
110 err := test.options.Validate()
111 if test.expectErr && err != nil {
112 continue
113 }
114 if !test.expectErr && err != nil {
115 t.Errorf("%s: unexpected error: %v", name, err)
116 }
117 }
118 }
119
120 func TestUpdateSubjectForObject(t *testing.T) {
121 tests := []struct {
122 Name string
123 obj runtime.Object
124 subjects []rbacv1.Subject
125 expected []rbacv1.Subject
126 wantErr bool
127 }{
128 {
129 Name: "invalid object type",
130 obj: &rbacv1.Role{
131 ObjectMeta: metav1.ObjectMeta{
132 Name: "role",
133 Namespace: "one",
134 },
135 },
136 wantErr: true,
137 },
138 {
139 Name: "add resource with users in rolebinding",
140 obj: &rbacv1.RoleBinding{
141 ObjectMeta: metav1.ObjectMeta{
142 Name: "rolebinding",
143 Namespace: "one",
144 },
145 Subjects: []rbacv1.Subject{
146 {
147 APIGroup: "rbac.authorization.k8s.io",
148 Kind: "User",
149 Name: "a",
150 },
151 },
152 },
153 subjects: []rbacv1.Subject{
154 {
155 APIGroup: "rbac.authorization.k8s.io",
156 Kind: "User",
157 Name: "a",
158 },
159 {
160 APIGroup: "rbac.authorization.k8s.io",
161 Kind: "User",
162 Name: "b",
163 },
164 },
165 expected: []rbacv1.Subject{
166 {
167 APIGroup: "rbac.authorization.k8s.io",
168 Kind: "User",
169 Name: "a",
170 },
171 {
172 APIGroup: "rbac.authorization.k8s.io",
173 Kind: "User",
174 Name: "b",
175 },
176 },
177 wantErr: false,
178 },
179 {
180 Name: "add resource with groups in rolebinding",
181 obj: &rbacv1.RoleBinding{
182 ObjectMeta: metav1.ObjectMeta{
183 Name: "rolebinding",
184 Namespace: "one",
185 },
186 Subjects: []rbacv1.Subject{
187 {
188 APIGroup: "rbac.authorization.k8s.io",
189 Kind: "Group",
190 Name: "a",
191 },
192 },
193 },
194 subjects: []rbacv1.Subject{
195 {
196 APIGroup: "rbac.authorization.k8s.io",
197 Kind: "Group",
198 Name: "a",
199 },
200 {
201 APIGroup: "rbac.authorization.k8s.io",
202 Kind: "Group",
203 Name: "b",
204 },
205 },
206 expected: []rbacv1.Subject{
207 {
208 APIGroup: "rbac.authorization.k8s.io",
209 Kind: "Group",
210 Name: "a",
211 },
212 {
213 APIGroup: "rbac.authorization.k8s.io",
214 Kind: "Group",
215 Name: "b",
216 },
217 },
218 wantErr: false,
219 },
220 {
221 Name: "add resource with serviceaccounts in rolebinding",
222 obj: &rbacv1.RoleBinding{
223 ObjectMeta: metav1.ObjectMeta{
224 Name: "rolebinding",
225 Namespace: "one",
226 },
227 Subjects: []rbacv1.Subject{
228 {
229 Kind: "ServiceAccount",
230 Namespace: "one",
231 Name: "a",
232 },
233 },
234 },
235 subjects: []rbacv1.Subject{
236 {
237 Kind: "ServiceAccount",
238 Namespace: "one",
239 Name: "a",
240 },
241 {
242 Kind: "ServiceAccount",
243 Namespace: "one",
244 Name: "b",
245 },
246 },
247 expected: []rbacv1.Subject{
248 {
249 Kind: "ServiceAccount",
250 Namespace: "one",
251 Name: "a",
252 },
253 {
254 Kind: "ServiceAccount",
255 Namespace: "one",
256 Name: "b",
257 },
258 },
259 wantErr: false,
260 },
261 {
262 Name: "add resource with serviceaccounts in clusterrolebinding",
263 obj: &rbacv1.ClusterRoleBinding{
264 ObjectMeta: metav1.ObjectMeta{
265 Name: "clusterrolebinding",
266 },
267 Subjects: []rbacv1.Subject{
268 {
269 APIGroup: "rbac.authorization.k8s.io",
270 Kind: "User",
271 Name: "a",
272 },
273 {
274 APIGroup: "rbac.authorization.k8s.io",
275 Kind: "Group",
276 Name: "a",
277 },
278 },
279 },
280 subjects: []rbacv1.Subject{
281 {
282 Kind: "ServiceAccount",
283 Namespace: "one",
284 Name: "a",
285 },
286 },
287 expected: []rbacv1.Subject{
288 {
289 APIGroup: "rbac.authorization.k8s.io",
290 Kind: "User",
291 Name: "a",
292 },
293 {
294 APIGroup: "rbac.authorization.k8s.io",
295 Kind: "Group",
296 Name: "a",
297 },
298 {
299 Kind: "ServiceAccount",
300 Namespace: "one",
301 Name: "a",
302 },
303 },
304 wantErr: false,
305 },
306 }
307 for _, tt := range tests {
308 if _, err := updateSubjectForObject(tt.obj, tt.subjects, addSubjects); (err != nil) != tt.wantErr {
309 t.Errorf("%q. updateSubjectForObject() error = %v, wantErr %v", tt.Name, err, tt.wantErr)
310 }
311
312 want := tt.expected
313 var got []rbacv1.Subject
314 switch t := tt.obj.(type) {
315 case *rbacv1.RoleBinding:
316 got = t.Subjects
317 case *rbacv1.ClusterRoleBinding:
318 got = t.Subjects
319 }
320 if !reflect.DeepEqual(got, want) {
321 t.Errorf("%q. updateSubjectForObject() failed", tt.Name)
322 t.Errorf("Got: %v", got)
323 t.Errorf("Want: %v", want)
324 }
325 }
326 }
327
328 func TestAddSubject(t *testing.T) {
329 tests := []struct {
330 Name string
331 existing []rbacv1.Subject
332 subjects []rbacv1.Subject
333 expected []rbacv1.Subject
334 wantChange bool
335 }{
336 {
337 Name: "add resource with users",
338 existing: []rbacv1.Subject{
339 {
340 APIGroup: "rbac.authorization.k8s.io",
341 Kind: "User",
342 Name: "a",
343 },
344 {
345 APIGroup: "rbac.authorization.k8s.io",
346 Kind: "User",
347 Name: "b",
348 },
349 },
350 subjects: []rbacv1.Subject{
351 {
352 APIGroup: "rbac.authorization.k8s.io",
353 Kind: "User",
354 Name: "a",
355 },
356 },
357 expected: []rbacv1.Subject{
358 {
359 APIGroup: "rbac.authorization.k8s.io",
360 Kind: "User",
361 Name: "a",
362 },
363 {
364 APIGroup: "rbac.authorization.k8s.io",
365 Kind: "User",
366 Name: "b",
367 },
368 },
369 wantChange: false,
370 },
371 {
372 Name: "add resource with serviceaccounts",
373 existing: []rbacv1.Subject{
374 {
375 Kind: "ServiceAccount",
376 Namespace: "one",
377 Name: "a",
378 },
379 {
380 Kind: "ServiceAccount",
381 Namespace: "one",
382 Name: "b",
383 },
384 },
385 subjects: []rbacv1.Subject{
386 {
387 Kind: "ServiceAccount",
388 Namespace: "two",
389 Name: "a",
390 },
391 },
392 expected: []rbacv1.Subject{
393 {
394 Kind: "ServiceAccount",
395 Namespace: "one",
396 Name: "a",
397 },
398 {
399 Kind: "ServiceAccount",
400 Namespace: "one",
401 Name: "b",
402 },
403 {
404 Kind: "ServiceAccount",
405 Namespace: "two",
406 Name: "a",
407 },
408 },
409 wantChange: true,
410 },
411 }
412 for _, tt := range tests {
413 changed := false
414 var got []rbacv1.Subject
415 if changed, got = addSubjects(tt.existing, tt.subjects); (changed != false) != tt.wantChange {
416 t.Errorf("%q. addSubjects() changed = %v, wantChange = %v", tt.Name, changed, tt.wantChange)
417 }
418
419 want := tt.expected
420 if !reflect.DeepEqual(got, want) {
421 t.Errorf("%q. addSubjects() failed", tt.Name)
422 t.Errorf("Got: %v", got)
423 t.Errorf("Want: %v", want)
424 }
425 }
426 }
427
View as plain text