1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 package webhook
16
17 import (
18 "fmt"
19 "testing"
20
21 "github.com/GoogleCloudPlatform/k8s-config-connector/pkg/apis/iam/v1beta1"
22 dclmetadata "github.com/GoogleCloudPlatform/k8s-config-connector/pkg/dcl/metadata"
23 "github.com/GoogleCloudPlatform/k8s-config-connector/pkg/deepcopy"
24 testutil "github.com/GoogleCloudPlatform/k8s-config-connector/pkg/test"
25 testservicemappingloader "github.com/GoogleCloudPlatform/k8s-config-connector/pkg/test/servicemappingloader"
26
27 "github.com/google/go-cmp/cmp"
28 "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
29 )
30
31 func TestDefaultAPIVersionForIAMResourceRef(t *testing.T) {
32 tests := []struct {
33 name string
34 resourceRef map[string]interface{}
35 resourceRefNew map[string]interface{}
36 denied bool
37 }{
38 {
39 name: "spec.resourceRef is not set",
40 denied: true,
41 },
42 {
43 name: "spec.resourceRef.kind is not set",
44 resourceRef: map[string]interface{}{
45 "name": "resource-name",
46 },
47 denied: true,
48 },
49 {
50 name: "spec.resourceRef.kind is set to unsupported kind",
51 resourceRef: map[string]interface{}{
52 "kind": "UnsupportedKind",
53 "name": "resource-name",
54 },
55 denied: true,
56 },
57 {
58 name: "spec.resourceRef.apiVersion is already set",
59 resourceRef: map[string]interface{}{
60 "apiVersion": "pubsub.cnrm.cloud.google.com/v1beta1",
61 "kind": "PubSubTopic",
62 "name": "resource-name",
63 },
64 resourceRefNew: map[string]interface{}{
65 "apiVersion": "pubsub.cnrm.cloud.google.com/v1beta1",
66 "kind": "PubSubTopic",
67 "name": "resource-name",
68 },
69 },
70 {
71 name: "spec.resourceRef.apiVersion is not set",
72 resourceRef: map[string]interface{}{
73 "kind": "PubSubTopic",
74 "name": "resource-name",
75 },
76 resourceRefNew: map[string]interface{}{
77 "apiVersion": "pubsub.cnrm.cloud.google.com/v1beta1",
78 "kind": "PubSubTopic",
79 "name": "resource-name",
80 },
81 },
82 {
83 name: "spec.resourceRef.apiVersion is not set, and spec.resourceRef.kind is set to an external-only kind Organization",
84 resourceRef: map[string]interface{}{
85 "kind": "Organization",
86 "name": "resource-name",
87 },
88 resourceRefNew: map[string]interface{}{
89 "apiVersion": "resourcemanager.cnrm.cloud.google.com/v1beta1",
90 "kind": "Organization",
91 "name": "resource-name",
92 },
93 },
94 {
95 name: "spec.resourceRef.apiVersion is not set, and spec.resourceRef.kind is set to an external-only kind BillingAccount",
96 resourceRef: map[string]interface{}{
97 "kind": "BillingAccount",
98 "name": "resource-name",
99 },
100 resourceRefNew: map[string]interface{}{
101 "apiVersion": "billing.cnrm.cloud.google.com/v1beta1",
102 "kind": "BillingAccount",
103 "name": "resource-name",
104 },
105 },
106 }
107
108 iamTemplates := map[string]map[string]interface{}{
109 "IAMPolicy": map[string]interface{}{
110 "apiVersion": v1beta1.IAMPolicyGVK.GroupVersion().String(),
111 "kind": v1beta1.IAMPolicyGVK.Kind,
112 "metadata": map[string]interface{}{
113 "name": "policy",
114 },
115 "spec": map[string]interface{}{
116 "bindings": []interface{}{
117 map[string]interface{}{
118 "role": "role",
119 "members": []interface{}{
120 "member",
121 },
122 },
123 },
124 },
125 },
126 "IAMPartialPolicy": map[string]interface{}{
127 "apiVersion": v1beta1.IAMPartialPolicyGVK.GroupVersion().String(),
128 "kind": v1beta1.IAMPartialPolicyGVK.Kind,
129 "metadata": map[string]interface{}{
130 "name": "policy",
131 },
132 "spec": map[string]interface{}{
133 "bindings": []interface{}{
134 map[string]interface{}{
135 "role": "role",
136 "members": []interface{}{
137 map[string]interface{}{
138 "member": "member",
139 },
140 },
141 },
142 },
143 },
144 },
145 "IAMPolicyMember": map[string]interface{}{
146 "apiVersion": v1beta1.IAMPolicyMemberGVK.GroupVersion().String(),
147 "kind": v1beta1.IAMPolicyMemberGVK.Kind,
148 "metadata": map[string]interface{}{
149 "name": "policy",
150 },
151 "spec": map[string]interface{}{
152 "member": "member",
153 "role": "role",
154 },
155 },
156 "IAMAuditConfig": map[string]interface{}{
157 "apiVersion": v1beta1.IAMAuditConfigGVK.GroupVersion().String(),
158 "kind": v1beta1.IAMAuditConfigGVK.Kind,
159 "metadata": map[string]interface{}{
160 "name": "policy",
161 },
162 "spec": map[string]interface{}{
163 "service": "service",
164 "auditLogConfigs": []interface{}{
165 map[string]interface{}{
166 "logType": "log-type",
167 "exemptedMembers": []interface{}{
168 "member",
169 },
170 },
171 },
172 },
173 },
174 }
175
176 for iamKind, iamTemplate := range iamTemplates {
177 for _, tc := range tests {
178 iamKind := iamKind
179 iamTemplate := iamTemplate
180 tc := tc
181 t.Run(fmt.Sprintf("%v (%v)", tc.name, iamKind), func(t *testing.T) {
182 t.Parallel()
183
184
185 iamObj := &unstructured.Unstructured{
186 Object: deepcopy.MapStringInterface(iamTemplate),
187 }
188 if tc.resourceRef != nil {
189 if err := unstructured.SetNestedField(iamObj.Object, tc.resourceRef, iamResourceRefPath...); err != nil {
190 t.Fatalf("error setting '%v' on IAM resource meant to be passed into webhook: %v", iamResourceRefField, err)
191 }
192 }
193
194
195 iamObjExpected := &unstructured.Unstructured{
196 Object: deepcopy.MapStringInterface(iamTemplate),
197 }
198 if tc.resourceRefNew != nil {
199 if err := unstructured.SetNestedField(iamObjExpected.Object, tc.resourceRefNew, iamResourceRefPath...); err != nil {
200 t.Fatalf("error setting '%v' on IAM resource meant for testing webhook response: %v", iamResourceRefField, err)
201 }
202 }
203
204 response := defaultAPIVersionForIAMResourceRef(iamObj, testservicemappingloader.New(t), dclmetadata.New())
205 if tc.denied {
206 if response.Allowed {
207 t.Fatalf("expected request to be denied, but was allowed. Response:\n%v", response)
208 }
209 return
210 }
211 if !response.Allowed {
212 t.Fatalf("request was unexpectedly denied. Response:\n%v", response)
213 }
214 expectedResponse := constructPatchResponse(iamObj, iamObjExpected)
215 if !testutil.Equals(t, response, expectedResponse) {
216 diff := cmp.Diff(expectedResponse, response)
217 t.Fatalf("unexpected diff in the response (-want +got):\n%v", diff)
218 }
219 })
220 }
221 }
222 }
223
View as plain text