1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 package partialpolicy_test
16
17 import (
18 "fmt"
19 "reflect"
20 "testing"
21
22 iamv1beta1 "github.com/GoogleCloudPlatform/k8s-config-connector/pkg/apis/iam/v1beta1"
23 "github.com/GoogleCloudPlatform/k8s-config-connector/pkg/controller/iam/partialpolicy"
24
25 "github.com/google/go-cmp/cmp"
26 )
27
28
29 type mockIdentityResolver struct{}
30
31 func (t *mockIdentityResolver) Resolve(member iamv1beta1.Member, memberFrom *iamv1beta1.MemberSource, defaultNamespace string) (string, error) {
32 if member != "" {
33 return string(member), nil
34 }
35
36 if memberFrom.ServiceAccountRef != nil {
37 if memberFrom.ServiceAccountRef.Namespace == "cnrm-foo" && memberFrom.ServiceAccountRef.Name == "cnrm-sa" {
38 return "serviceAccount:foo@domain.com", nil
39 }
40 }
41 panic(fmt.Errorf("memberFrom is not mocked"))
42 }
43
44 func TestComputePartialPolicyWithMergedBindings(t *testing.T) {
45 condition1 := newIAMCondition("test-iam-condition1")
46 condition2 := newIAMCondition("test-iam-condition2")
47 tests := []struct {
48 name string
49 partialPolicy *iamv1beta1.IAMPartialPolicy
50 livePolicy *iamv1beta1.IAMPolicy
51 mergedPolicy *iamv1beta1.IAMPartialPolicy
52 }{
53 {
54 name: "empty partial policy with empty live policy",
55 partialPolicy: &iamv1beta1.IAMPartialPolicy{
56 Spec: iamv1beta1.IAMPartialPolicySpec{},
57 },
58 livePolicy: &iamv1beta1.IAMPolicy{
59 Spec: iamv1beta1.IAMPolicySpec{},
60 },
61 mergedPolicy: &iamv1beta1.IAMPartialPolicy{
62 Spec: iamv1beta1.IAMPartialPolicySpec{},
63 Status: iamv1beta1.IAMPartialPolicyStatus{
64 LastAppliedBindings: []iamv1beta1.IAMPolicyBinding{},
65 AllBindings: []iamv1beta1.IAMPolicyBinding{},
66 },
67 },
68 },
69 {
70 name: "empty partial policy with non-empty live policy",
71 partialPolicy: &iamv1beta1.IAMPartialPolicy{
72 Spec: iamv1beta1.IAMPartialPolicySpec{},
73 },
74 livePolicy: &iamv1beta1.IAMPolicy{
75 Spec: iamv1beta1.IAMPolicySpec{
76 Bindings: []iamv1beta1.IAMPolicyBinding{
77 {
78 Role: "roles/owner",
79 Members: []iamv1beta1.Member{
80 "user:foo@example.com",
81 "serviceAccount:foo@domain.com",
82 },
83 },
84 },
85 },
86 },
87 mergedPolicy: &iamv1beta1.IAMPartialPolicy{
88 Spec: iamv1beta1.IAMPartialPolicySpec{},
89 Status: iamv1beta1.IAMPartialPolicyStatus{
90 LastAppliedBindings: []iamv1beta1.IAMPolicyBinding{},
91 AllBindings: []iamv1beta1.IAMPolicyBinding{
92 {
93 Role: "roles/owner",
94 Members: []iamv1beta1.Member{
95 "user:foo@example.com",
96 "serviceAccount:foo@domain.com",
97 },
98 },
99 },
100 },
101 },
102 },
103 {
104 name: "no existing bindings from live policy",
105 partialPolicy: &iamv1beta1.IAMPartialPolicy{
106 Spec: iamv1beta1.IAMPartialPolicySpec{
107 Bindings: []iamv1beta1.IAMPartialPolicyBinding{
108 {
109 Role: "roles/owner",
110 Members: []iamv1beta1.IAMPartialPolicyMember{
111 {
112 Member: "user:foo@example.com",
113 },
114 {
115 Member: "serviceAccount:foo@domain.com",
116 },
117 },
118 },
119 },
120 },
121 },
122 livePolicy: &iamv1beta1.IAMPolicy{
123 Spec: iamv1beta1.IAMPolicySpec{
124 Bindings: []iamv1beta1.IAMPolicyBinding{},
125 },
126 },
127 mergedPolicy: &iamv1beta1.IAMPartialPolicy{
128 Spec: iamv1beta1.IAMPartialPolicySpec{
129 Bindings: []iamv1beta1.IAMPartialPolicyBinding{
130 {
131 Role: "roles/owner",
132 Members: []iamv1beta1.IAMPartialPolicyMember{
133 {
134 Member: "user:foo@example.com",
135 },
136 {
137 Member: "serviceAccount:foo@domain.com",
138 },
139 },
140 },
141 },
142 },
143 Status: iamv1beta1.IAMPartialPolicyStatus{
144 LastAppliedBindings: []iamv1beta1.IAMPolicyBinding{
145 {
146 Role: "roles/owner",
147 Members: []iamv1beta1.Member{
148 "user:foo@example.com",
149 "serviceAccount:foo@domain.com",
150 },
151 },
152 },
153 AllBindings: []iamv1beta1.IAMPolicyBinding{
154 {
155 Role: "roles/owner",
156 Members: []iamv1beta1.Member{
157 "user:foo@example.com",
158 "serviceAccount:foo@domain.com",
159 },
160 },
161 },
162 },
163 },
164 },
165 {
166 name: "merge bindings with different {role, condition} tuples",
167 partialPolicy: &iamv1beta1.IAMPartialPolicy{
168 Spec: iamv1beta1.IAMPartialPolicySpec{
169 Bindings: []iamv1beta1.IAMPartialPolicyBinding{
170 {
171 Role: "roles/owner",
172 Members: []iamv1beta1.IAMPartialPolicyMember{
173 {
174 Member: "user:user1@example.com",
175 },
176 {
177
178 MemberFrom: &iamv1beta1.MemberSource{
179 ServiceAccountRef: &iamv1beta1.MemberReference{
180 Namespace: "cnrm-foo",
181 Name: "cnrm-sa",
182 },
183 },
184 },
185 },
186 },
187 {
188 Role: "roles/editor",
189 Condition: condition1,
190 Members: []iamv1beta1.IAMPartialPolicyMember{
191 {
192 Member: "user:user1@example.com",
193 },
194 },
195 },
196 },
197 },
198 },
199 livePolicy: &iamv1beta1.IAMPolicy{
200 Spec: iamv1beta1.IAMPolicySpec{
201 Bindings: []iamv1beta1.IAMPolicyBinding{
202 {
203 Role: "roles/editor",
204 Members: []iamv1beta1.Member{
205 "user:user2@example.com",
206 },
207 },
208 },
209 },
210 },
211 mergedPolicy: &iamv1beta1.IAMPartialPolicy{
212 Spec: iamv1beta1.IAMPartialPolicySpec{
213 Bindings: []iamv1beta1.IAMPartialPolicyBinding{
214 {
215 Role: "roles/owner",
216 Members: []iamv1beta1.IAMPartialPolicyMember{
217 {
218 Member: "user:user1@example.com",
219 },
220 {
221
222 MemberFrom: &iamv1beta1.MemberSource{
223 ServiceAccountRef: &iamv1beta1.MemberReference{
224 Namespace: "cnrm-foo",
225 Name: "cnrm-sa",
226 },
227 },
228 },
229 },
230 },
231 {
232 Role: "roles/editor",
233 Condition: condition1,
234 Members: []iamv1beta1.IAMPartialPolicyMember{
235 {
236 Member: "user:user1@example.com",
237 },
238 },
239 },
240 },
241 },
242 Status: iamv1beta1.IAMPartialPolicyStatus{
243 LastAppliedBindings: []iamv1beta1.IAMPolicyBinding{
244 {
245 Role: "roles/editor",
246 Condition: condition1,
247 Members: []iamv1beta1.Member{
248 "user:user1@example.com",
249 },
250 },
251 {
252 Role: "roles/owner",
253 Members: []iamv1beta1.Member{
254 "user:user1@example.com",
255 "serviceAccount:foo@domain.com",
256 },
257 },
258 },
259 AllBindings: []iamv1beta1.IAMPolicyBinding{
260 {
261 Role: "roles/editor",
262 Members: []iamv1beta1.Member{
263 "user:user2@example.com",
264 },
265 },
266 {
267 Role: "roles/editor",
268 Condition: condition1,
269 Members: []iamv1beta1.Member{
270 "user:user1@example.com",
271 },
272 },
273 {
274 Role: "roles/owner",
275 Members: []iamv1beta1.Member{
276 "user:user1@example.com",
277 "serviceAccount:foo@domain.com",
278 },
279 },
280 },
281 },
282 },
283 },
284 {
285 name: "merge members with same {role, condition} tuples",
286 partialPolicy: &iamv1beta1.IAMPartialPolicy{
287 Spec: iamv1beta1.IAMPartialPolicySpec{
288 Bindings: []iamv1beta1.IAMPartialPolicyBinding{
289 {
290 Role: "roles/editor",
291 Members: []iamv1beta1.IAMPartialPolicyMember{
292 {
293 Member: "user:user1@example.com",
294 },
295 {
296 Member: "serviceAccount:foo@domain.com",
297 },
298 },
299 },
300 {
301 Role: "roles/editor",
302 Condition: condition1,
303 Members: []iamv1beta1.IAMPartialPolicyMember{
304 {
305 Member: "user:user2@example.com",
306 },
307 },
308 },
309 },
310 },
311 },
312 livePolicy: &iamv1beta1.IAMPolicy{
313 Spec: iamv1beta1.IAMPolicySpec{
314 Bindings: []iamv1beta1.IAMPolicyBinding{
315 {
316 Role: "roles/editor",
317 Members: []iamv1beta1.Member{
318 "user:foo@example.com",
319 },
320 },
321 {
322 Role: "roles/editor",
323 Condition: condition1,
324 Members: []iamv1beta1.Member{
325 "user:bar@example.com",
326 },
327 },
328 },
329 },
330 },
331 mergedPolicy: &iamv1beta1.IAMPartialPolicy{
332 Spec: iamv1beta1.IAMPartialPolicySpec{
333 Bindings: []iamv1beta1.IAMPartialPolicyBinding{
334 {
335 Role: "roles/editor",
336 Members: []iamv1beta1.IAMPartialPolicyMember{
337 {
338 Member: "user:user1@example.com",
339 },
340 {
341 Member: "serviceAccount:foo@domain.com",
342 },
343 },
344 },
345 {
346 Role: "roles/editor",
347 Condition: condition1,
348 Members: []iamv1beta1.IAMPartialPolicyMember{
349 {
350 Member: "user:user2@example.com",
351 },
352 },
353 },
354 },
355 },
356 Status: iamv1beta1.IAMPartialPolicyStatus{
357 LastAppliedBindings: []iamv1beta1.IAMPolicyBinding{
358 {
359 Role: "roles/editor",
360 Members: []iamv1beta1.Member{
361 "user:user1@example.com",
362 "serviceAccount:foo@domain.com",
363 },
364 },
365 {
366 Role: "roles/editor",
367 Condition: condition1,
368 Members: []iamv1beta1.Member{
369 "user:user2@example.com",
370 },
371 },
372 },
373 AllBindings: []iamv1beta1.IAMPolicyBinding{
374 {
375 Role: "roles/editor",
376 Members: []iamv1beta1.Member{
377 "serviceAccount:foo@domain.com",
378 "user:foo@example.com",
379 "user:user1@example.com",
380 },
381 },
382 {
383 Role: "roles/editor",
384 Condition: condition1,
385 Members: []iamv1beta1.Member{
386 "user:bar@example.com",
387 "user:user2@example.com",
388 },
389 },
390 },
391 },
392 },
393 },
394 {
395 name: "merge members from multiple entries with same {role, condition} tuples in the same binding slice",
396 partialPolicy: &iamv1beta1.IAMPartialPolicy{
397 Spec: iamv1beta1.IAMPartialPolicySpec{
398 Bindings: []iamv1beta1.IAMPartialPolicyBinding{
399 {
400 Role: "roles/editor",
401 Condition: condition1,
402 Members: []iamv1beta1.IAMPartialPolicyMember{
403 {
404 Member: "user:user1@example.com",
405 },
406 {
407 Member: "serviceAccount:foo@domain.com",
408 },
409 },
410 },
411 {
412 Role: "roles/editor",
413 Condition: condition1,
414 Members: []iamv1beta1.IAMPartialPolicyMember{
415 {
416 Member: "user:user3@example.com",
417 },
418 },
419 },
420 {
421 Role: "roles/editor",
422 Condition: condition1,
423 Members: []iamv1beta1.IAMPartialPolicyMember{
424 {
425 Member: "user:user2@example.com",
426 },
427 },
428 },
429 {
430 Role: "roles/editor",
431 Condition: condition2,
432 Members: []iamv1beta1.IAMPartialPolicyMember{
433 {
434 Member: "user:user1@example.com",
435 },
436 },
437 },
438 {
439 Role: "roles/editor",
440 Condition: condition2,
441 Members: []iamv1beta1.IAMPartialPolicyMember{
442 {
443 Member: "user:user2@example.com",
444 },
445 },
446 },
447 },
448 },
449 },
450 livePolicy: &iamv1beta1.IAMPolicy{
451 Spec: iamv1beta1.IAMPolicySpec{
452 Bindings: []iamv1beta1.IAMPolicyBinding{
453 {
454 Role: "roles/editor",
455 Condition: condition1,
456 Members: []iamv1beta1.Member{
457 "user:foo@example.com",
458 },
459 },
460 {
461 Role: "roles/editor",
462 Condition: condition2,
463 Members: []iamv1beta1.Member{
464 "user:bar@example.com",
465 },
466 },
467 },
468 },
469 },
470 mergedPolicy: &iamv1beta1.IAMPartialPolicy{
471 Spec: iamv1beta1.IAMPartialPolicySpec{
472 Bindings: []iamv1beta1.IAMPartialPolicyBinding{
473 {
474 Role: "roles/editor",
475 Condition: condition1,
476 Members: []iamv1beta1.IAMPartialPolicyMember{
477 {
478 Member: "user:user1@example.com",
479 },
480 {
481 Member: "serviceAccount:foo@domain.com",
482 },
483 },
484 },
485 {
486 Role: "roles/editor",
487 Condition: condition1,
488 Members: []iamv1beta1.IAMPartialPolicyMember{
489 {
490 Member: "user:user3@example.com",
491 },
492 },
493 },
494 {
495 Role: "roles/editor",
496 Condition: condition1,
497 Members: []iamv1beta1.IAMPartialPolicyMember{
498 {
499 Member: "user:user2@example.com",
500 },
501 },
502 },
503 {
504 Role: "roles/editor",
505 Condition: condition2,
506 Members: []iamv1beta1.IAMPartialPolicyMember{
507 {
508 Member: "user:user1@example.com",
509 },
510 },
511 },
512 {
513 Role: "roles/editor",
514 Condition: condition2,
515 Members: []iamv1beta1.IAMPartialPolicyMember{
516 {
517 Member: "user:user2@example.com",
518 },
519 },
520 },
521 },
522 },
523 Status: iamv1beta1.IAMPartialPolicyStatus{
524 LastAppliedBindings: []iamv1beta1.IAMPolicyBinding{
525 {
526 Role: "roles/editor",
527 Condition: condition1,
528 Members: []iamv1beta1.Member{
529 "serviceAccount:foo@domain.com",
530 "user:user1@example.com",
531 "user:user2@example.com",
532 "user:user3@example.com",
533 },
534 },
535 {
536 Role: "roles/editor",
537 Condition: condition2,
538 Members: []iamv1beta1.Member{
539 "user:user1@example.com",
540 "user:user2@example.com",
541 },
542 },
543 },
544 AllBindings: []iamv1beta1.IAMPolicyBinding{
545 {
546 Role: "roles/editor",
547 Condition: condition1,
548 Members: []iamv1beta1.Member{
549 "serviceAccount:foo@domain.com",
550 "user:foo@example.com",
551 "user:user1@example.com",
552 "user:user2@example.com",
553 "user:user3@example.com",
554 },
555 },
556 {
557 Role: "roles/editor",
558 Condition: condition2,
559 Members: []iamv1beta1.Member{
560 "user:bar@example.com",
561 "user:user1@example.com",
562 "user:user2@example.com",
563 },
564 },
565 },
566 },
567 },
568 },
569 {
570 name: "empty member arrays",
571 partialPolicy: &iamv1beta1.IAMPartialPolicy{
572 Spec: iamv1beta1.IAMPartialPolicySpec{
573 Bindings: []iamv1beta1.IAMPartialPolicyBinding{
574 {
575 Role: "roles/owner",
576 Members: []iamv1beta1.IAMPartialPolicyMember{
577 {
578 Member: "user:foo@example.com",
579 },
580 {
581 Member: "serviceAccount:foo@domain.com",
582 },
583 },
584 },
585 {
586 Role: "roles/viewer",
587 Members: []iamv1beta1.IAMPartialPolicyMember{},
588 },
589 },
590 },
591 },
592 livePolicy: &iamv1beta1.IAMPolicy{
593 Spec: iamv1beta1.IAMPolicySpec{
594 Bindings: []iamv1beta1.IAMPolicyBinding{},
595 },
596 },
597 mergedPolicy: &iamv1beta1.IAMPartialPolicy{
598 Spec: iamv1beta1.IAMPartialPolicySpec{
599 Bindings: []iamv1beta1.IAMPartialPolicyBinding{
600 {
601 Role: "roles/owner",
602 Members: []iamv1beta1.IAMPartialPolicyMember{
603 {
604 Member: "user:foo@example.com",
605 },
606 {
607 Member: "serviceAccount:foo@domain.com",
608 },
609 },
610 },
611 {
612 Role: "roles/viewer",
613 Members: []iamv1beta1.IAMPartialPolicyMember{},
614 },
615 },
616 },
617 Status: iamv1beta1.IAMPartialPolicyStatus{
618 LastAppliedBindings: []iamv1beta1.IAMPolicyBinding{
619 {
620 Role: "roles/owner",
621 Members: []iamv1beta1.Member{
622 "user:foo@example.com",
623 "serviceAccount:foo@domain.com",
624 },
625 },
626 },
627 AllBindings: []iamv1beta1.IAMPolicyBinding{
628 {
629 Role: "roles/owner",
630 Members: []iamv1beta1.Member{
631 "user:foo@example.com",
632 "serviceAccount:foo@domain.com",
633 },
634 },
635 },
636 },
637 },
638 },
639 {
640 name: "remove partial managed bindings from spec compared to lastAppliedBindings",
641 partialPolicy: &iamv1beta1.IAMPartialPolicy{
642 Spec: iamv1beta1.IAMPartialPolicySpec{
643 Bindings: []iamv1beta1.IAMPartialPolicyBinding{
644 {
645 Role: "roles/editor",
646 Members: []iamv1beta1.IAMPartialPolicyMember{
647 {
648 Member: "user:foo@example.com",
649 },
650 },
651 },
652 },
653 },
654 Status: iamv1beta1.IAMPartialPolicyStatus{
655 LastAppliedBindings: []iamv1beta1.IAMPolicyBinding{
656 {
657 Role: "roles/editor",
658 Members: []iamv1beta1.Member{
659 "user:foo@example.com",
660 "serviceAccount:foo@domain.com",
661 },
662 },
663 {
664 Role: "roles/editor",
665 Condition: condition1,
666 Members: []iamv1beta1.Member{
667 "user:bar@example.com",
668 },
669 },
670 {
671 Role: "roles/owner",
672 Members: []iamv1beta1.Member{
673 "user:user1@example.com",
674 "serviceAccount:foo@domain.com",
675 },
676 },
677 },
678 },
679 },
680 livePolicy: &iamv1beta1.IAMPolicy{
681 Spec: iamv1beta1.IAMPolicySpec{
682 Bindings: []iamv1beta1.IAMPolicyBinding{
683 {
684 Role: "roles/editor",
685 Members: []iamv1beta1.Member{
686 "user:foo@example.com",
687 "serviceAccount:foo@domain.com",
688 },
689 },
690 {
691 Role: "roles/editor",
692 Condition: condition1,
693 Members: []iamv1beta1.Member{
694 "user:bar@example.com",
695 "user:user1@example.com",
696 },
697 },
698 {
699 Role: "roles/owner",
700 Members: []iamv1beta1.Member{
701 "user:user1@example.com",
702 "serviceAccount:foo@domain.com",
703 },
704 },
705 },
706 },
707 },
708 mergedPolicy: &iamv1beta1.IAMPartialPolicy{
709 Spec: iamv1beta1.IAMPartialPolicySpec{
710 Bindings: []iamv1beta1.IAMPartialPolicyBinding{
711 {
712 Role: "roles/editor",
713 Members: []iamv1beta1.IAMPartialPolicyMember{
714 {
715 Member: "user:foo@example.com",
716 },
717 },
718 },
719 },
720 },
721 Status: iamv1beta1.IAMPartialPolicyStatus{
722 LastAppliedBindings: []iamv1beta1.IAMPolicyBinding{
723 {
724 Role: "roles/editor",
725 Members: []iamv1beta1.Member{
726 "user:foo@example.com",
727 },
728 },
729 },
730 AllBindings: []iamv1beta1.IAMPolicyBinding{
731 {
732 Role: "roles/editor",
733 Members: []iamv1beta1.Member{
734 "user:foo@example.com",
735 },
736 },
737 {
738 Role: "roles/editor",
739 Condition: condition1,
740 Members: []iamv1beta1.Member{
741 "user:user1@example.com",
742 },
743 },
744 },
745 },
746 },
747 },
748 {
749 name: "remove all managed bindings from spec compared to lastAppliedBindings",
750 partialPolicy: &iamv1beta1.IAMPartialPolicy{
751 Spec: iamv1beta1.IAMPartialPolicySpec{},
752 Status: iamv1beta1.IAMPartialPolicyStatus{
753 LastAppliedBindings: []iamv1beta1.IAMPolicyBinding{
754 {
755 Role: "roles/editor",
756 Members: []iamv1beta1.Member{
757 "user:foo@example.com",
758 "serviceAccount:foo@domain.com",
759 },
760 },
761 {
762 Role: "roles/editor",
763 Condition: condition1,
764 Members: []iamv1beta1.Member{
765 "user:bar@example.com",
766 },
767 },
768 {
769 Role: "roles/viewer",
770 Members: []iamv1beta1.Member{
771 "user:foo@example.com",
772 },
773 },
774 },
775 },
776 },
777 livePolicy: &iamv1beta1.IAMPolicy{
778 Spec: iamv1beta1.IAMPolicySpec{
779 Bindings: []iamv1beta1.IAMPolicyBinding{
780 {
781 Role: "roles/editor",
782 Members: []iamv1beta1.Member{
783 "user:foo@example.com",
784 "serviceAccount:foo@domain.com",
785 },
786 },
787 {
788 Role: "roles/editor",
789 Condition: condition1,
790 Members: []iamv1beta1.Member{
791 "user:bar@example.com",
792 "user:user1@example.com",
793 },
794 },
795 {
796 Role: "roles/owner",
797 Members: []iamv1beta1.Member{
798 "user:bar@example.com",
799 },
800 },
801 },
802 },
803 },
804 mergedPolicy: &iamv1beta1.IAMPartialPolicy{
805 Spec: iamv1beta1.IAMPartialPolicySpec{},
806 Status: iamv1beta1.IAMPartialPolicyStatus{
807 LastAppliedBindings: []iamv1beta1.IAMPolicyBinding{},
808 AllBindings: []iamv1beta1.IAMPolicyBinding{
809 {
810 Role: "roles/editor",
811 Condition: condition1,
812 Members: []iamv1beta1.Member{
813 "user:user1@example.com",
814 },
815 },
816 {
817 Role: "roles/owner",
818 Members: []iamv1beta1.Member{
819 "user:bar@example.com",
820 },
821 },
822 },
823 },
824 },
825 },
826 {
827 name: "remove all bindings",
828 partialPolicy: &iamv1beta1.IAMPartialPolicy{
829 Spec: iamv1beta1.IAMPartialPolicySpec{},
830 Status: iamv1beta1.IAMPartialPolicyStatus{
831 LastAppliedBindings: []iamv1beta1.IAMPolicyBinding{
832 {
833 Role: "roles/editor",
834 Members: []iamv1beta1.Member{
835 "user:foo@example.com",
836 "serviceAccount:foo@domain.com",
837 },
838 },
839 {
840 Role: "roles/editor",
841 Condition: condition1,
842 Members: []iamv1beta1.Member{
843 "user:bar@example.com",
844 },
845 },
846 },
847 },
848 },
849 livePolicy: &iamv1beta1.IAMPolicy{
850 Spec: iamv1beta1.IAMPolicySpec{
851 Bindings: []iamv1beta1.IAMPolicyBinding{
852 {
853 Role: "roles/editor",
854 Members: []iamv1beta1.Member{
855 "user:foo@example.com",
856 "serviceAccount:foo@domain.com",
857 },
858 },
859 {
860 Role: "roles/editor",
861 Condition: condition1,
862 Members: []iamv1beta1.Member{
863 "user:bar@example.com",
864 },
865 },
866 },
867 },
868 },
869 mergedPolicy: &iamv1beta1.IAMPartialPolicy{
870 Spec: iamv1beta1.IAMPartialPolicySpec{},
871 Status: iamv1beta1.IAMPartialPolicyStatus{
872 LastAppliedBindings: []iamv1beta1.IAMPolicyBinding{},
873 AllBindings: []iamv1beta1.IAMPolicyBinding{},
874 },
875 },
876 },
877 }
878 for _, tc := range tests {
879 tc := tc
880 t.Run(tc.name, func(t *testing.T) {
881 t.Parallel()
882 resolver := mockIdentityResolver{}
883 res, err := partialpolicy.ComputePartialPolicyWithMergedBindings(tc.partialPolicy, tc.livePolicy, &resolver)
884 if err != nil {
885 t.Fatalf("error when computing partial policy with merged bindings: %v", err)
886 }
887 if !reflect.DeepEqual(res, tc.mergedPolicy) {
888 t.Fatalf("unexpected merged policy diff (-want +got): \n%v", cmp.Diff(tc.mergedPolicy, res))
889 }
890 })
891 }
892 }
893
894 func TestComputePartialPolicyWithRemainingBindings(t *testing.T) {
895 condition1 := newIAMCondition("test-iam-condition1")
896 tests := []struct {
897 name string
898 partialPolicy *iamv1beta1.IAMPartialPolicy
899 livePolicy *iamv1beta1.IAMPolicy
900 remaining *iamv1beta1.IAMPartialPolicy
901 }{
902 {
903 name: "remove previously managed bindings",
904 partialPolicy: &iamv1beta1.IAMPartialPolicy{
905 Status: iamv1beta1.IAMPartialPolicyStatus{
906 LastAppliedBindings: []iamv1beta1.IAMPolicyBinding{
907 {
908 Role: "roles/editor",
909 Condition: condition1,
910 Members: []iamv1beta1.Member{
911 "user:user1@example.com",
912 },
913 },
914 {
915 Role: "roles/owner",
916 Members: []iamv1beta1.Member{
917 "user:user1@example.com",
918 },
919 },
920 },
921 },
922 },
923 livePolicy: &iamv1beta1.IAMPolicy{
924 Spec: iamv1beta1.IAMPolicySpec{
925 Bindings: []iamv1beta1.IAMPolicyBinding{
926 {
927 Role: "roles/editor",
928 Members: []iamv1beta1.Member{
929 "user:user2@example.com",
930 },
931 },
932 {
933 Role: "roles/editor",
934 Condition: condition1,
935 Members: []iamv1beta1.Member{
936 "user:user1@example.com",
937 },
938 },
939 {
940 Role: "roles/owner",
941 Members: []iamv1beta1.Member{
942 "user:user1@example.com",
943 "serviceAccount:foo@domain.com",
944 },
945 },
946 },
947 },
948 },
949 remaining: &iamv1beta1.IAMPartialPolicy{
950 Status: iamv1beta1.IAMPartialPolicyStatus{
951 LastAppliedBindings: []iamv1beta1.IAMPolicyBinding{},
952 AllBindings: []iamv1beta1.IAMPolicyBinding{
953 {
954 Role: "roles/editor",
955 Members: []iamv1beta1.Member{
956 "user:user2@example.com",
957 },
958 },
959 {
960 Role: "roles/owner",
961 Members: []iamv1beta1.Member{
962 "serviceAccount:foo@domain.com",
963 },
964 },
965 },
966 },
967 },
968 },
969 {
970 name: "no previously managed bindings to remove",
971 partialPolicy: &iamv1beta1.IAMPartialPolicy{
972 Status: iamv1beta1.IAMPartialPolicyStatus{
973 LastAppliedBindings: []iamv1beta1.IAMPolicyBinding{},
974 },
975 },
976 livePolicy: &iamv1beta1.IAMPolicy{
977 Spec: iamv1beta1.IAMPolicySpec{
978 Bindings: []iamv1beta1.IAMPolicyBinding{
979 {
980 Role: "roles/editor",
981 Members: []iamv1beta1.Member{
982 "user:user2@example.com",
983 },
984 },
985 {
986 Role: "roles/editor",
987 Condition: condition1,
988 Members: []iamv1beta1.Member{
989 "user:user1@example.com",
990 },
991 },
992 {
993 Role: "roles/owner",
994 Members: []iamv1beta1.Member{
995 "user:user1@example.com",
996 "serviceAccount:foo@domain.com",
997 },
998 },
999 },
1000 },
1001 },
1002 remaining: &iamv1beta1.IAMPartialPolicy{
1003 Status: iamv1beta1.IAMPartialPolicyStatus{
1004 LastAppliedBindings: []iamv1beta1.IAMPolicyBinding{},
1005 AllBindings: []iamv1beta1.IAMPolicyBinding{
1006 {
1007 Role: "roles/editor",
1008 Members: []iamv1beta1.Member{
1009 "user:user2@example.com",
1010 },
1011 },
1012 {
1013 Role: "roles/editor",
1014 Condition: condition1,
1015 Members: []iamv1beta1.Member{
1016 "user:user1@example.com",
1017 },
1018 },
1019 {
1020 Role: "roles/owner",
1021 Members: []iamv1beta1.Member{
1022 "user:user1@example.com",
1023 "serviceAccount:foo@domain.com",
1024 },
1025 },
1026 },
1027 },
1028 },
1029 },
1030 {
1031 name: "all bindings are removed",
1032 partialPolicy: &iamv1beta1.IAMPartialPolicy{
1033 Status: iamv1beta1.IAMPartialPolicyStatus{
1034 LastAppliedBindings: []iamv1beta1.IAMPolicyBinding{
1035 {
1036 Role: "roles/editor",
1037 Condition: condition1,
1038 Members: []iamv1beta1.Member{
1039 "user:user1@example.com",
1040 },
1041 },
1042 {
1043 Role: "roles/editor",
1044 Members: []iamv1beta1.Member{
1045 "user:user2@example.com",
1046 },
1047 },
1048 {
1049 Role: "roles/owner",
1050 Members: []iamv1beta1.Member{
1051 "user:user1@example.com",
1052 },
1053 },
1054
1055
1056 {
1057 Role: "roles/viewer",
1058 Members: []iamv1beta1.Member{
1059 "user:user2@example.com",
1060 },
1061 },
1062 },
1063 },
1064 },
1065 livePolicy: &iamv1beta1.IAMPolicy{
1066 Spec: iamv1beta1.IAMPolicySpec{
1067 Bindings: []iamv1beta1.IAMPolicyBinding{
1068 {
1069 Role: "roles/editor",
1070 Members: []iamv1beta1.Member{
1071 "user:user2@example.com",
1072 },
1073 },
1074 {
1075 Role: "roles/editor",
1076 Condition: condition1,
1077 Members: []iamv1beta1.Member{
1078 "user:user1@example.com",
1079 },
1080 },
1081 {
1082 Role: "roles/owner",
1083 Members: []iamv1beta1.Member{
1084 "user:user1@example.com",
1085 },
1086 },
1087 },
1088 },
1089 },
1090 remaining: &iamv1beta1.IAMPartialPolicy{
1091 Status: iamv1beta1.IAMPartialPolicyStatus{
1092 LastAppliedBindings: []iamv1beta1.IAMPolicyBinding{},
1093 AllBindings: []iamv1beta1.IAMPolicyBinding{},
1094 },
1095 },
1096 },
1097 }
1098 for _, tc := range tests {
1099 tc := tc
1100 t.Run(tc.name, func(t *testing.T) {
1101 t.Parallel()
1102 res := partialpolicy.ComputePartialPolicyWithRemainingBindings(tc.partialPolicy, tc.livePolicy)
1103 if !reflect.DeepEqual(res, tc.remaining) {
1104 t.Fatalf("unexpected merged policy diff (-want +got): \n%v", cmp.Diff(tc.remaining, res))
1105 }
1106 })
1107 }
1108 }
1109
1110 func newIAMCondition(title string) *iamv1beta1.IAMCondition {
1111 return &iamv1beta1.IAMCondition{
1112 Title: title,
1113 Description: "Test IAM Condition",
1114 Expression: "request.time < timestamp(\"2020-01-01T00:00:00Z\")",
1115 }
1116 }
1117
View as plain text