1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package iamclient_test
19
20 import (
21 "context"
22 "errors"
23 "flag"
24 "fmt"
25 "reflect"
26 "regexp"
27 "runtime"
28 "testing"
29
30 iamv1beta1 "github.com/GoogleCloudPlatform/k8s-config-connector/pkg/apis/iam/v1beta1"
31 kcciamclient "github.com/GoogleCloudPlatform/k8s-config-connector/pkg/controller/iam/iamclient"
32 dclmetadata "github.com/GoogleCloudPlatform/k8s-config-connector/pkg/dcl/metadata"
33 "github.com/GoogleCloudPlatform/k8s-config-connector/pkg/dcl/schema/dclschemaloader"
34 "github.com/GoogleCloudPlatform/k8s-config-connector/pkg/k8s"
35 testcontroller "github.com/GoogleCloudPlatform/k8s-config-connector/pkg/test/controller"
36 testreconciler "github.com/GoogleCloudPlatform/k8s-config-connector/pkg/test/controller/reconciler"
37 testgcp "github.com/GoogleCloudPlatform/k8s-config-connector/pkg/test/gcp"
38 testiam "github.com/GoogleCloudPlatform/k8s-config-connector/pkg/test/iam"
39 testmain "github.com/GoogleCloudPlatform/k8s-config-connector/pkg/test/main"
40 "github.com/GoogleCloudPlatform/k8s-config-connector/pkg/test/resourcefixture"
41 testrunner "github.com/GoogleCloudPlatform/k8s-config-connector/pkg/test/runner"
42 testservicemappingloader "github.com/GoogleCloudPlatform/k8s-config-connector/pkg/test/servicemappingloader"
43 "github.com/GoogleCloudPlatform/k8s-config-connector/pkg/util"
44
45 "github.com/GoogleCloudPlatform/declarative-resource-client-library/dcl"
46 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
47 "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
48 "sigs.k8s.io/controller-runtime/pkg/manager"
49 "sigs.k8s.io/controller-runtime/pkg/reconcile"
50 )
51
52 func init() {
53
54
55
56 flag.StringVar(&runTestsRegex, "run-tests", "", "run only the tests whose names match the given regex")
57 flag.StringVar(&skipTestsRegex, "skip-tests", "", "skip the tests whose names match the given regex, even those that match the run-tests regex")
58 }
59
60 var (
61 mgr manager.Manager
62 runTestsRegex string
63 skipTestsRegex string
64 )
65
66 func shouldRunBasedOnRunAndSkipRegexes(parentTestName string, fixture resourcefixture.ResourceFixture) bool {
67 testName := fmt.Sprintf("%v/%v", parentTestName, resourcefixture.FormatTestName(fixture))
68
69
70 if skipTestsRegex != "" {
71 if regexp.MustCompile(skipTestsRegex).MatchString(testName) {
72 return false
73 }
74 }
75
76
77 if runTestsRegex != "" {
78 if !regexp.MustCompile(runTestsRegex).MatchString(testName) {
79 return false
80 }
81 }
82
83 return true
84 }
85
86 func TestAllGetSetDeletePolicy(t *testing.T) {
87 smLoader := testservicemappingloader.New(t)
88 serviceMetadataLoader := dclmetadata.New()
89 dclSchemaLoader, err := dclschemaloader.New()
90 if err != nil {
91 t.Fatalf("error creating a new DCL schema loader: %v", err)
92 }
93 testName := getCurrentFuncName()
94 shouldRun := func(fixture resourcefixture.ResourceFixture, mgr manager.Manager) bool {
95 return shouldRunBasedOnRunAndSkipRegexes(testName, fixture) && fixture.Type == resourcefixture.Basic && testiam.FixtureSupportsIAMPolicy(t, smLoader, serviceMetadataLoader, dclSchemaLoader, fixture)
96 }
97 testCaseFunc := func(t *testing.T, testContext testrunner.TestContext, sysContext testrunner.SystemContext) {
98 iamClient := testiam.NewIAMClient(sysContext)
99 refResource := testContext.CreateUnstruct
100 resourceRef := testiam.NewResourceRef(refResource)
101 iamPolicy := newPolicy(t, refResource, resourceRef, testContext.UniqueId)
102 testGetSetDeletePolicy(t, iamClient, iamPolicy, refResource.GetKind())
103 }
104 testrunner.RunAllWithObjectCreated(t, mgr, shouldRun, testCaseFunc)
105 }
106
107 func TestAllGetSetDeletePolicyWithExternalRef(t *testing.T) {
108 smLoader := testservicemappingloader.New(t)
109 serviceMetadataLoader := dclmetadata.New()
110 dclSchemaLoader, err := dclschemaloader.New()
111 if err != nil {
112 t.Fatalf("error creating a new DCL schema loader: %v", err)
113 }
114 testName := getCurrentFuncName()
115 shouldRun := func(fixture resourcefixture.ResourceFixture, mgr manager.Manager) bool {
116 return shouldRunBasedOnRunAndSkipRegexes(testName, fixture) && fixture.Type == resourcefixture.Basic && testiam.ShouldRunWithExternalRef(fixture) && testiam.FixtureSupportsIAMPolicy(t, smLoader, serviceMetadataLoader, dclSchemaLoader, fixture)
117 }
118 testCaseFunc := func(t *testing.T, testContext testrunner.TestContext, sysContext testrunner.SystemContext) {
119 iamClient := testiam.NewIAMClient(sysContext)
120 refResource := testContext.CreateUnstruct
121 resourceRef, err := testiam.NewExternalRef(refResource, sysContext.TFProvider, sysContext.SMLoader)
122 if err != nil {
123 t.Fatal(err)
124 }
125 iamPolicy := newPolicy(t, refResource, resourceRef, testContext.UniqueId)
126 testGetSetDeletePolicy(t, iamClient, iamPolicy, refResource.GetKind())
127 }
128 testrunner.RunAllWithObjectCreated(t, mgr, shouldRun, testCaseFunc)
129 }
130
131 func TestAllGetSetDeletePolicyWithExternalOnlyRef(t *testing.T) {
132 testName := getCurrentFuncName()
133 shouldRun := func(fixture resourcefixture.ResourceFixture, mgr manager.Manager) bool {
134 return shouldRunBasedOnRunAndSkipRegexes(testName, fixture) && fixture.Type == resourcefixture.IAMExternalOnlyRef && fixture.GVK.Kind == "IAMPolicy"
135 }
136 testCaseFunc := func(t *testing.T, testContext testrunner.TestContext, sysContext testrunner.SystemContext) {
137 iamClient := testiam.NewIAMClient(sysContext)
138 iamPolicy := &iamv1beta1.IAMPolicy{}
139 if err := util.Marshal(testContext.CreateUnstruct, iamPolicy); err != nil {
140 t.Fatalf("error marshaling create unstruct into IAMPolicy object: %v", err)
141 }
142
143 testGetSetDeletePolicy(t, iamClient, iamPolicy, iamPolicy.Spec.ResourceReference.Kind)
144 }
145 testrunner.RunAllWithObjectCreated(t, mgr, shouldRun, testCaseFunc)
146 }
147
148 func TestAllGetSetDeletePolicyWithIAMCondition(t *testing.T) {
149 smLoader := testservicemappingloader.New(t)
150 serviceMetadataLoader := dclmetadata.New()
151 dclSchemaLoader, err := dclschemaloader.New()
152 if err != nil {
153 t.Fatalf("error creating a new DCL schema loader: %v", err)
154 }
155 testName := getCurrentFuncName()
156 shouldRun := func(fixture resourcefixture.ResourceFixture, mgr manager.Manager) bool {
157 return shouldRunBasedOnRunAndSkipRegexes(testName, fixture) && fixture.Type == resourcefixture.Basic && testiam.ShouldRunWithIAMConditions(fixture) && testiam.FixtureSupportsIAMPolicy(t, smLoader, serviceMetadataLoader, dclSchemaLoader, fixture)
158 }
159 testCaseFunc := func(t *testing.T, testContext testrunner.TestContext, sysContext testrunner.SystemContext) {
160 iamClient := testiam.NewIAMClient(sysContext)
161 refResource := testContext.CreateUnstruct
162 resourceRef := testiam.NewResourceRef(refResource)
163 iamPolicy := newPolicyWithIAMConditions(t, refResource, resourceRef, testContext.UniqueId)
164 testGetSetDeletePolicy(t, iamClient, iamPolicy, refResource.GetKind())
165 }
166 testrunner.RunAllWithObjectCreated(t, mgr, shouldRun, testCaseFunc)
167 }
168
169 func TestAllGetSetPolicyWithAuditConfigs(t *testing.T) {
170 smLoader := testservicemappingloader.New(t)
171 serviceMetadataLoader := dclmetadata.New()
172 testName := getCurrentFuncName()
173 shouldRun := func(fixture resourcefixture.ResourceFixture, mgr manager.Manager) bool {
174 return shouldRunBasedOnRunAndSkipRegexes(testName, fixture) && fixture.Type == resourcefixture.Basic && testiam.FixtureSupportsIAMAuditConfigs(t, smLoader, serviceMetadataLoader, fixture)
175 }
176 testCaseFunc := func(t *testing.T, testContext testrunner.TestContext, sysContext testrunner.SystemContext) {
177 iamClient := testiam.NewIAMClient(sysContext)
178 refResource := testContext.CreateUnstruct
179 resourceRef := testiam.NewResourceRef(refResource)
180 iamPolicy := newPolicyWithAuditConfigs(t, refResource, resourceRef, testContext.UniqueId)
181 testGetSetDeletePolicy(t, iamClient, iamPolicy, refResource.GetKind())
182 }
183 testrunner.RunAllWithObjectCreated(t, mgr, shouldRun, testCaseFunc)
184 }
185
186 func testGetSetDeletePolicy(t *testing.T, iamClient *kcciamclient.IAMClient, newPolicy *iamv1beta1.IAMPolicy, refResourceKind string) {
187 gcpPolicy, err := iamClient.GetPolicy(context.TODO(), newPolicy)
188 if err != nil {
189 t.Fatalf("error getting iam policy: %v", err)
190 }
191
192
193 defaultNumBindings := 0
194 switch refResourceKind {
195 case "StorageBucket":
196 defaultNumBindings = 2
197 case "Project":
198 defaultNumBindings = 1
199 case "Folder":
200 defaultNumBindings = 2
201 case "Organization":
202 defaultNumBindings = 3
203 case "BillingAccount":
204 defaultNumBindings = 1
205 }
206 if len(gcpPolicy.Spec.Bindings) != defaultNumBindings {
207 t.Errorf("unexpected length of bindings: got '%v', want '%v'", len(gcpPolicy.Spec.Bindings), defaultNumBindings)
208 }
209 if len(gcpPolicy.Spec.AuditConfigs) != 0 {
210 t.Errorf("unexpected length of audit configs: got '%v', want '%v'", len(gcpPolicy.Spec.AuditConfigs), 0)
211 }
212 if !reflect.DeepEqual(gcpPolicy.Spec.ResourceReference, newPolicy.Spec.ResourceReference) {
213 t.Errorf("resource reference mismatch: got '%v', want '%v'", gcpPolicy.Spec.ResourceReference, newPolicy.Spec.ResourceReference)
214 }
215 resultPolicy, err := iamClient.SetPolicy(context.TODO(), newPolicy)
216 if err != nil {
217 t.Errorf("error setting iam policy: %v", err)
218 }
219 if resultPolicy == nil {
220 t.Fatalf("unexpected nil value for resultPolicy")
221 }
222 if !reflect.DeepEqual(resultPolicy.Spec.Bindings, newPolicy.Spec.Bindings) {
223 t.Errorf("mismatched bindings: got '%v', want '%v'", resultPolicy.Spec.Bindings, newPolicy.Spec.Bindings)
224 }
225 if !reflect.DeepEqual(resultPolicy.Spec.AuditConfigs, newPolicy.Spec.AuditConfigs) {
226 t.Errorf("mismatched audit configs: got '%v', want '%v'", resultPolicy.Spec.AuditConfigs, newPolicy.Spec.AuditConfigs)
227 }
228 gcpPolicy, err = iamClient.GetPolicy(context.TODO(), newPolicy)
229 if err != nil {
230 t.Fatalf("error getting iam policy: %v", err)
231 }
232
233
234
235
236 if !testiam.SameBindings(newPolicy.Spec.Bindings, gcpPolicy.Spec.Bindings) {
237 t.Errorf("mismatched bindings: got '%v', want '%v'", gcpPolicy.Spec.Bindings, newPolicy.Spec.Bindings)
238 }
239 if !testiam.SameAuditConfigs(newPolicy.Spec.AuditConfigs, gcpPolicy.Spec.AuditConfigs) {
240 t.Errorf("mismatched auditConfigs: got '%v', want '%v'", gcpPolicy.Spec.AuditConfigs, newPolicy.Spec.AuditConfigs)
241 }
242
243
244
245 switch refResourceKind {
246 case "StorageBucket", "Organization", "BillingAccount":
247 return
248 }
249 if err := iamClient.DeletePolicy(context.TODO(), newPolicy); err != nil {
250 t.Fatalf("error deleting: %v", err)
251 }
252
253
254 gcpPolicy, err = iamClient.GetPolicy(context.TODO(), newPolicy)
255 if err != nil {
256 t.Fatalf("error getting iam policy: %v", err)
257 }
258 if len(gcpPolicy.Spec.Bindings) > 0 {
259 t.Errorf("expected there to be no bindings but there were %v", len(gcpPolicy.Spec.Bindings))
260 }
261 }
262
263 func TestResolveMemberIdentity(t *testing.T) {
264 testName := getCurrentFuncName()
265 shouldRun := func(fixture resourcefixture.ResourceFixture, _ manager.Manager) bool {
266 return shouldRunBasedOnRunAndSkipRegexes(testName, fixture) && fixture.Type == resourcefixture.Basic && fixture.GVK.Kind == "IAMServiceAccount"
267 }
268 testCaseFunc := func(t *testing.T, testContext testrunner.TestContext, sysContext testrunner.SystemContext) {
269 iamClient := testiam.NewIAMClient(sysContext)
270 testResolveMemberIdentity(t, iamClient, testContext)
271 }
272 testrunner.RunAllWithObjectCreated(t, mgr, shouldRun, testCaseFunc)
273 }
274
275 func testResolveMemberIdentity(t *testing.T, iamClient *kcciamclient.IAMClient, testContext testrunner.TestContext) {
276 member := iamv1beta1.Member("user:user2@example.com")
277
278 resolvedId, err := kcciamclient.ResolveMemberIdentity(context.TODO(), member, nil, testContext.NamespacedName.Namespace, iamClient.TFIAMClient)
279 if err != nil {
280 t.Fatalf("error resolving member identity with member")
281 }
282
283 if resolvedId != string(member) {
284 t.Fatalf("error resolving member identity with member, expect: %v, received: %v", string(member), resolvedId)
285 }
286
287 memberFrom := &iamv1beta1.MemberSource{
288 ServiceAccountRef: &iamv1beta1.MemberReference{
289 Namespace: "cnrm-foo",
290 Name: "cnrm-sa",
291 },
292 }
293 _, err = kcciamclient.ResolveMemberIdentity(context.TODO(), "", memberFrom, testContext.NamespacedName.Namespace, iamClient.TFIAMClient)
294 if err == nil || !k8s.IsReferenceNotFoundError(err) {
295 t.Fatalf("resolving member identity with non-existent memberFrom reference: got error: %v, want ReferenceNotFoundError", err)
296 }
297
298 memberFrom.ServiceAccountRef.Name = testContext.NamespacedName.Name
299 memberFrom.ServiceAccountRef.Namespace = testContext.NamespacedName.Namespace
300
301
302 _, err = kcciamclient.ResolveMemberIdentity(context.TODO(), "", memberFrom, testContext.NamespacedName.Namespace, iamClient.TFIAMClient)
303 if err != nil {
304 t.Fatalf("error resolving member identity with valid memberFrom")
305 }
306
307 _, err = kcciamclient.ResolveMemberIdentity(context.TODO(), member, memberFrom, testContext.NamespacedName.Namespace, iamClient.TFIAMClient)
308 if err == nil {
309 t.Fatalf("got no error when ResolveMemberIdentity() was given both a valid member and memberFrom; want error")
310 }
311 }
312
313 func TestGetSetDeletePolicyReferenceNotFound(t *testing.T) {
314 testName := getCurrentFuncName()
315 shouldRun := func(fixture resourcefixture.ResourceFixture, _ manager.Manager) bool {
316 return shouldRunBasedOnRunAndSkipRegexes(testName, fixture) && fixture.Type == resourcefixture.Basic && fixture.GVK.Kind == "PubSubTopic"
317 }
318 testCaseFunc := func(t *testing.T, testContext testrunner.TestContext, sysContext testrunner.SystemContext) {
319 iamClient := testiam.NewIAMClient(sysContext)
320 refResource := testContext.CreateUnstruct
321 resourceRef := testiam.NewResourceRef(refResource)
322 newPolicy := newPolicy(t, refResource, resourceRef, testContext.UniqueId)
323 testGetSetDeletePolicyReferenceNotFound(t, iamClient, newPolicy)
324 }
325 testrunner.RunAllWithDependenciesCreatedButNotObject(t, mgr, shouldRun, testCaseFunc)
326 }
327
328 func testGetSetDeletePolicyReferenceNotFound(t *testing.T, iamClient *kcciamclient.IAMClient, newPolicy *iamv1beta1.IAMPolicy) {
329 _, err := iamClient.GetPolicy(context.TODO(), newPolicy)
330 if !k8s.IsReferenceNotFoundError(err) {
331 t.Errorf("getting policy when referenced resource not found: got error: %v, want ReferenceNotFoundError", err)
332 }
333 _, err = iamClient.SetPolicy(context.TODO(), newPolicy)
334 if !k8s.IsReferenceNotFoundError(err) {
335 t.Errorf("setting policy when referenced resource not found: got error: %v, want ReferenceNotFoundError", err)
336 }
337 err = iamClient.DeletePolicy(context.TODO(), newPolicy)
338 if !k8s.IsReferenceNotFoundError(err) {
339 t.Errorf("deleting policy when referenced resource not found: got error: %v, want ReferenceNotFoundError", err)
340 }
341 }
342
343 func TestProjectIdAsNamespace(t *testing.T) {
344 testName := getCurrentFuncName()
345 shouldRun := func(fixture resourcefixture.ResourceFixture, mgr manager.Manager) bool {
346
347
348 return shouldRunBasedOnRunAndSkipRegexes(testName, fixture) && fixture.Type == resourcefixture.Basic && fixture.GVK.Kind == "IAMServiceAccount"
349 }
350 testCaseFunc := func(t *testing.T, tstCtx testrunner.TestContext, sysCtx testrunner.SystemContext) {
351 projectId := testgcp.GetDefaultProjectID(t)
352 testcontroller.SetupNamespaceForDefaultProject(t, sysCtx.Manager.GetClient(), projectId)
353 refResource := tstCtx.CreateUnstruct
354 refResource.SetNamespace(projectId)
355 if err := sysCtx.Manager.GetClient().Create(context.TODO(), refResource); err != nil {
356 t.Fatalf("error creating resource: %v", err)
357 }
358 resourceCleanup := sysCtx.Reconciler.BuildCleanupFunc(refResource, testreconciler.CleanupPolicyAlways)
359 defer resourceCleanup()
360 sysCtx.Reconciler.Reconcile(refResource, reconcile.Result{RequeueAfter: k8s.MeanReconcileReenqueuePeriod}, nil)
361 iamClient := testiam.NewIAMClient(sysCtx)
362 resourceRef := testiam.NewResourceRef(refResource)
363 newPolicy := newPolicy(t, refResource, resourceRef, tstCtx.UniqueId)
364 policy, err := iamClient.GetPolicy(context.TODO(), newPolicy)
365 if err != nil {
366 t.Fatalf("error getting iam policy: %v", err)
367 }
368 if policy.Spec.Bindings != nil {
369 t.Errorf("unexpected value for bindings: got '%v' want 'nil'", policy.Spec.Bindings)
370 }
371 resultPolicy, err := iamClient.SetPolicy(context.TODO(), newPolicy)
372 if err != nil {
373 t.Errorf("error setting iam policy: %v", err)
374 }
375 if resultPolicy == nil {
376 t.Fatalf("unexpected nil value for resultPolicy")
377 }
378 if !reflect.DeepEqual(resultPolicy.Spec.Bindings, newPolicy.Spec.Bindings) {
379 t.Errorf("mismatched bindings: got '%v', want '%v'", resultPolicy.Spec.Bindings, newPolicy.Spec.Bindings)
380 }
381 }
382 testrunner.RunAllWithDependenciesCreatedButNotObject(t, mgr, shouldRun, testCaseFunc)
383 }
384
385 func TestAllGetSetDeletePolicyMember(t *testing.T) {
386 smLoader := testservicemappingloader.New(t)
387 serviceMetadataLoader := dclmetadata.New()
388 dclSchemaLoader, err := dclschemaloader.New()
389 if err != nil {
390 t.Fatalf("error creating a new DCL schema loader: %v", err)
391 }
392 testName := getCurrentFuncName()
393 shouldRun := func(fixture resourcefixture.ResourceFixture, mgr manager.Manager) bool {
394 return shouldRunBasedOnRunAndSkipRegexes(testName, fixture) && fixture.Type == resourcefixture.Basic && testiam.FixtureSupportsIAMPolicy(t, smLoader, serviceMetadataLoader, dclSchemaLoader, fixture)
395 }
396 testCaseFunc := func(t *testing.T, testContext testrunner.TestContext, sysContext testrunner.SystemContext) {
397 iamClient := testiam.NewIAMClient(sysContext)
398 refResource := testContext.CreateUnstruct
399 resourceRef := testiam.NewResourceRef(refResource)
400 iamPolicyMember := newPolicyMember(t, refResource, resourceRef, testContext.UniqueId)
401 testGetSetDeleteIamPolicyMember(t, iamClient, iamPolicyMember, refResource)
402 }
403 testrunner.RunAllWithObjectCreated(t, mgr, shouldRun, testCaseFunc)
404 }
405
406 func TestAllGetSetDeletePolicyMemberWithExternalRef(t *testing.T) {
407 smLoader := testservicemappingloader.New(t)
408 serviceMetadataLoader := dclmetadata.New()
409 dclSchemaLoader, err := dclschemaloader.New()
410 if err != nil {
411 t.Fatalf("error creating a new DCL schema loader: %v", err)
412 }
413 testName := getCurrentFuncName()
414 shouldRun := func(fixture resourcefixture.ResourceFixture, mgr manager.Manager) bool {
415 return shouldRunBasedOnRunAndSkipRegexes(testName, fixture) && fixture.Type == resourcefixture.Basic && testiam.ShouldRunWithExternalRef(fixture) && testiam.FixtureSupportsIAMPolicy(t, smLoader, serviceMetadataLoader, dclSchemaLoader, fixture)
416 }
417 testCaseFunc := func(t *testing.T, testContext testrunner.TestContext, sysContext testrunner.SystemContext) {
418 iamClient := testiam.NewIAMClient(sysContext)
419 refResource := testContext.CreateUnstruct
420 resourceRef, err := testiam.NewExternalRef(refResource, sysContext.TFProvider, sysContext.SMLoader)
421 if err != nil {
422 t.Fatal(err)
423 }
424 iamPolicyMember := newPolicyMember(t, refResource, resourceRef, testContext.UniqueId)
425 testGetSetDeleteIamPolicyMember(t, iamClient, iamPolicyMember, refResource)
426 }
427 testrunner.RunAllWithObjectCreated(t, mgr, shouldRun, testCaseFunc)
428 }
429
430 func TestAllGetSetDeletePolicyMemberWithIAMCondition(t *testing.T) {
431 smLoader := testservicemappingloader.New(t)
432 serviceMetadataLoader := dclmetadata.New()
433 dclSchemaLoader, err := dclschemaloader.New()
434 if err != nil {
435 t.Fatalf("error creating a new DCL schema loader: %v", err)
436 }
437 testName := getCurrentFuncName()
438 shouldRun := func(fixture resourcefixture.ResourceFixture, mgr manager.Manager) bool {
439 return shouldRunBasedOnRunAndSkipRegexes(testName, fixture) && fixture.Type == resourcefixture.Basic && testiam.ShouldRunWithIAMConditions(fixture) && testiam.FixtureSupportsIAMPolicy(t, smLoader, serviceMetadataLoader, dclSchemaLoader, fixture)
440 }
441 testCaseFunc := func(t *testing.T, testContext testrunner.TestContext, sysContext testrunner.SystemContext) {
442 iamClient := testiam.NewIAMClient(sysContext)
443 refResource := testContext.CreateUnstruct
444 resourceRef := testiam.NewResourceRef(refResource)
445 iamPolicyMember := newPolicyMemberWithIAMCondition(t, refResource, resourceRef, testContext.UniqueId)
446 testGetSetDeleteIamPolicyMember(t, iamClient, iamPolicyMember, refResource)
447 }
448 testrunner.RunAllWithObjectCreated(t, mgr, shouldRun, testCaseFunc)
449 }
450
451 func TestAllGetSetDeletePolicyMemberWithExternalOnlyRef(t *testing.T) {
452 testName := getCurrentFuncName()
453 shouldRun := func(fixture resourcefixture.ResourceFixture, mgr manager.Manager) bool {
454 return shouldRunBasedOnRunAndSkipRegexes(testName, fixture) && fixture.Type == resourcefixture.IAMExternalOnlyRef && fixture.GVK.Kind == "IAMPolicyMember"
455 }
456 testCaseFunc := func(t *testing.T, testContext testrunner.TestContext, sysContext testrunner.SystemContext) {
457 iamClient := testiam.NewIAMClient(sysContext)
458 iamPolicyMember := &iamv1beta1.IAMPolicyMember{}
459 if err := util.Marshal(testContext.CreateUnstruct, iamPolicyMember); err != nil {
460 t.Fatalf("error marshaling create unstruct into IAMPolicyMember object: %v", err)
461 }
462 testGetSetDeleteIamPolicyMember(t, iamClient, iamPolicyMember, nil)
463 }
464 testrunner.RunAllWithDependenciesCreatedButNotObject(t, mgr, shouldRun, testCaseFunc)
465 }
466
467 func TestAllGetSetDeletePolicyMemberWithMemberReference(t *testing.T) {
468 testName := getCurrentFuncName()
469 shouldRun := func(fixture resourcefixture.ResourceFixture, mgr manager.Manager) bool {
470 return shouldRunBasedOnRunAndSkipRegexes(testName, fixture) && fixture.Type == resourcefixture.IAMMemberReferences
471 }
472 testCaseFunc := func(t *testing.T, testContext testrunner.TestContext, sysContext testrunner.SystemContext) {
473 iamClient := testiam.NewIAMClient(sysContext)
474 iamPolicyMember := &iamv1beta1.IAMPolicyMember{}
475 if err := util.Marshal(testContext.CreateUnstruct, iamPolicyMember); err != nil {
476 t.Fatalf("error marshaling create unstruct into IAMPolicyMember object: %v", err)
477 }
478 testGetSetDeleteIamPolicyMember(t, iamClient, iamPolicyMember, nil)
479 }
480 testrunner.RunAllWithDependenciesCreatedButNotObject(t, mgr, shouldRun, testCaseFunc)
481 }
482
483 func testGetSetDeleteIamPolicyMember(t *testing.T, iamClient *kcciamclient.IAMClient, policyMember *iamv1beta1.IAMPolicyMember, refResource *unstructured.Unstructured) {
484 _, err := iamClient.GetPolicyMember(context.TODO(), policyMember)
485 if err == nil {
486 t.Fatalf("expected an error when retrieving IAMPolicyMember, instead got 'nil'")
487 }
488 if !isNotFoundError(err) {
489 t.Fatalf("unexpected error when retrieving IAMPolicyMember: got '%v', want '%v'", err, kcciamclient.NotFoundError)
490 }
491 gcpPolicyMember, err := iamClient.SetPolicyMember(context.TODO(), policyMember)
492 if err != nil {
493 t.Fatalf("unexpected error: %v", err)
494 }
495 if gcpPolicyMember.Spec.Member != policyMember.Spec.Member {
496 t.Errorf("unexpected member value: got '%v', want '%v'",
497 gcpPolicyMember.Spec.Member, policyMember.Spec.Member)
498 }
499 if !reflect.DeepEqual(gcpPolicyMember.Spec.MemberFrom, policyMember.Spec.MemberFrom) {
500 t.Errorf("memberFrom mismatch: got '%v', want '%v'",
501 gcpPolicyMember.Spec.MemberFrom, policyMember.Spec.MemberFrom)
502 }
503 if gcpPolicyMember.Spec.Role != policyMember.Spec.Role {
504 t.Errorf("unexpected role value: got '%v', want '%v'",
505 gcpPolicyMember.Spec.Role, policyMember.Spec.Role)
506 }
507 if !reflect.DeepEqual(gcpPolicyMember.Spec.ResourceReference, policyMember.Spec.ResourceReference) {
508 t.Errorf("resource reference mismatch: got '%v', want '%v'",
509 gcpPolicyMember.Spec.ResourceReference, policyMember.Spec.ResourceReference)
510 }
511 _, err = iamClient.GetPolicyMember(context.TODO(), policyMember)
512 if err != nil {
513 t.Fatalf("unexpected error: %v", err)
514 }
515 if err := iamClient.DeletePolicyMember(context.TODO(), gcpPolicyMember); err != nil {
516 t.Fatalf("error deleting: %v", err)
517 }
518 _, err = iamClient.GetPolicyMember(context.TODO(), policyMember)
519 if err == nil {
520 t.Fatalf("expected an error when retrieving IAMPolicyMember, instead got 'nil'")
521 }
522 if !isNotFoundError(err) {
523 t.Fatalf("unexpected error when retrieving IAMPolicyMember: got '%v', want '%v'", err, kcciamclient.NotFoundError)
524 }
525 }
526
527 func TestGetSetDeletePolicyMemberReferenceNotFound(t *testing.T) {
528 testName := getCurrentFuncName()
529 shouldRun := func(fixture resourcefixture.ResourceFixture, _ manager.Manager) bool {
530 return shouldRunBasedOnRunAndSkipRegexes(testName, fixture) && fixture.Type == resourcefixture.Basic && fixture.GVK.Kind == "PubSubTopic"
531 }
532 testCaseFunc := func(t *testing.T, testContext testrunner.TestContext, sysContext testrunner.SystemContext) {
533 iamClient := testiam.NewIAMClient(sysContext)
534 refResource := testContext.CreateUnstruct
535 resourceRef := testiam.NewResourceRef(refResource)
536 iamPolicyMember := newPolicyMemberWithIAMCondition(t, refResource, resourceRef, testContext.UniqueId)
537 testGetSetDeletePolicyMemberReferenceNotFound(t, iamClient, iamPolicyMember)
538 }
539 testrunner.RunAllWithDependenciesCreatedButNotObject(t, mgr, shouldRun, testCaseFunc)
540 }
541
542 func testGetSetDeletePolicyMemberReferenceNotFound(t *testing.T, iamClient *kcciamclient.IAMClient, policyMember *iamv1beta1.IAMPolicyMember) {
543 _, err := iamClient.GetPolicyMember(context.TODO(), policyMember)
544 if !k8s.IsReferenceNotFoundError(err) {
545 t.Errorf("getting policy member when referenced resource not found: got error: %v, want ReferenceNotFoundError", err)
546 }
547 _, err = iamClient.SetPolicyMember(context.TODO(), policyMember)
548 if !k8s.IsReferenceNotFoundError(err) {
549 t.Errorf("setting policy member when referenced resource not found: got error: %v, want ReferenceNotFoundError", err)
550 }
551 err = iamClient.DeletePolicyMember(context.TODO(), policyMember)
552 if !k8s.IsReferenceNotFoundError(err) {
553 t.Errorf("deleting policy member when referenced resource not found: got error: %v, want ReferenceNotFoundError", err)
554 }
555 }
556
557 func TestAllGetSetDeleteAuditConfig(t *testing.T) {
558 smLoader := testservicemappingloader.New(t)
559 serviceMetadataLoader := dclmetadata.New()
560 testName := getCurrentFuncName()
561 shouldRun := func(fixture resourcefixture.ResourceFixture, mgr manager.Manager) bool {
562 return shouldRunBasedOnRunAndSkipRegexes(testName, fixture) && fixture.Type == resourcefixture.Basic && testiam.FixtureSupportsIAMAuditConfigs(t, smLoader, serviceMetadataLoader, fixture)
563 }
564 testCaseFunc := func(t *testing.T, testContext testrunner.TestContext, sysContext testrunner.SystemContext) {
565 iamClient := testiam.NewIAMClient(sysContext)
566 refResource := testContext.CreateUnstruct
567 resourceRef := testiam.NewResourceRef(refResource)
568 iamAuditConfig := newAuditConfig(t, refResource, resourceRef, testContext.UniqueId)
569 testGetSetDeleteIamAuditConfig(t, iamClient.TFIAMClient, iamAuditConfig, refResource)
570 }
571 testrunner.RunAllWithObjectCreated(t, mgr, shouldRun, testCaseFunc)
572 }
573
574 func TestAllGetSetDeleteAuditConfigWithExternalRef(t *testing.T) {
575 smLoader := testservicemappingloader.New(t)
576 serviceMetadataLoader := dclmetadata.New()
577 testName := getCurrentFuncName()
578 shouldRun := func(fixture resourcefixture.ResourceFixture, mgr manager.Manager) bool {
579 return shouldRunBasedOnRunAndSkipRegexes(testName, fixture) && fixture.Type == resourcefixture.Basic && testiam.ShouldRunWithExternalRef(fixture) && testiam.FixtureSupportsIAMAuditConfigs(t, smLoader, serviceMetadataLoader, fixture)
580 }
581 testCaseFunc := func(t *testing.T, testContext testrunner.TestContext, sysContext testrunner.SystemContext) {
582 iamClient := testiam.NewIAMClient(sysContext)
583 refResource := testContext.CreateUnstruct
584 resourceRef, err := testiam.NewExternalRef(refResource, sysContext.TFProvider, sysContext.SMLoader)
585 if err != nil {
586 t.Fatal(err)
587 }
588 iamAuditConfig := newAuditConfig(t, refResource, resourceRef, testContext.UniqueId)
589 testGetSetDeleteIamAuditConfig(t, iamClient.TFIAMClient, iamAuditConfig, refResource)
590 }
591 testrunner.RunAllWithObjectCreated(t, mgr, shouldRun, testCaseFunc)
592 }
593
594 func testGetSetDeleteIamAuditConfig(t *testing.T, iamClient *kcciamclient.TFIAMClient, auditConfig *iamv1beta1.IAMAuditConfig, refResource *unstructured.Unstructured) {
595 _, err := iamClient.GetAuditConfig(context.TODO(), auditConfig)
596 if err == nil {
597 t.Fatalf("expected an error when retrieving IAMAuditConfig, instead got 'nil'")
598 }
599 if !errors.Is(err, kcciamclient.NotFoundError) {
600 t.Fatalf("unexpected error when retrieving IAMAuditConfig: got '%v', want '%v'", err, kcciamclient.NotFoundError)
601 }
602 gcpAuditConfig, err := iamClient.SetAuditConfig(context.TODO(), auditConfig)
603 if err != nil {
604 t.Fatalf("unexpected error: %v", err)
605 }
606 if auditConfig == gcpAuditConfig {
607 t.Fatalf("expected auditConfig pointer values to not be equal")
608 }
609 if gcpAuditConfig.Spec.Service != auditConfig.Spec.Service {
610 t.Errorf("service value mismatch: got '%v', want '%v'", gcpAuditConfig.Spec.Service, auditConfig.Spec.Service)
611 }
612 if !reflect.DeepEqual(auditConfig.Spec.AuditLogConfigs, gcpAuditConfig.Spec.AuditLogConfigs) {
613 t.Errorf("audit log config mismatch: got '%v', want '%v'", gcpAuditConfig.Spec.AuditLogConfigs, auditConfig.Spec.AuditLogConfigs)
614 }
615 if !reflect.DeepEqual(auditConfig.Spec.ResourceReference, gcpAuditConfig.Spec.ResourceReference) {
616 t.Errorf("resource reference mismatch: got '%v', want '%v'", gcpAuditConfig.Spec.ResourceReference, auditConfig.Spec.ResourceReference)
617 }
618 _, err = iamClient.GetAuditConfig(context.TODO(), auditConfig)
619 if err != nil {
620 t.Fatalf("unexpected error: %v", err)
621 }
622 if err := iamClient.DeleteAuditConfig(context.TODO(), gcpAuditConfig); err != nil {
623 t.Fatalf("error deleting: %v", err)
624 }
625 _, err = iamClient.GetAuditConfig(context.TODO(), auditConfig)
626 if err == nil {
627 t.Fatalf("expected an error when retrieving IAMAuditConfig, instead got 'nil'")
628 }
629 if !errors.Is(err, kcciamclient.NotFoundError) {
630 t.Fatalf("unexpected error when retrieving IAMAuditConfig: got '%v', want '%v'", err, kcciamclient.NotFoundError)
631 }
632 }
633
634 func TestGetSetDeleteAuditConfigReferenceNotFound(t *testing.T) {
635 testName := getCurrentFuncName()
636 shouldRun := func(fixture resourcefixture.ResourceFixture, _ manager.Manager) bool {
637 return shouldRunBasedOnRunAndSkipRegexes(testName, fixture) && fixture.Type == resourcefixture.Basic && fixture.GVK.Kind == "Project"
638 }
639 testCaseFunc := func(t *testing.T, testContext testrunner.TestContext, sysContext testrunner.SystemContext) {
640 iamClient := testiam.NewIAMClient(sysContext)
641 refResource := testContext.CreateUnstruct
642 resourceRef := testiam.NewResourceRef(refResource)
643 iamAuditConfig := newAuditConfig(t, refResource, resourceRef, testContext.UniqueId)
644 testGetSetDeleteAuditConfigReferenceNotFound(t, iamClient.TFIAMClient, iamAuditConfig)
645 }
646 testrunner.RunAllWithDependenciesCreatedButNotObject(t, mgr, shouldRun, testCaseFunc)
647 }
648
649 func testGetSetDeleteAuditConfigReferenceNotFound(t *testing.T, iamClient *kcciamclient.TFIAMClient, auditConfig *iamv1beta1.IAMAuditConfig) {
650 _, err := iamClient.GetAuditConfig(context.TODO(), auditConfig)
651 if !k8s.IsReferenceNotFoundError(err) {
652 t.Errorf("getting audit config when referenced resource not found: got error: %v, want ReferenceNotFoundError", err)
653 }
654 _, err = iamClient.SetAuditConfig(context.TODO(), auditConfig)
655 if !k8s.IsReferenceNotFoundError(err) {
656 t.Errorf("setting audit config when referenced resource not found: got error: %v, want ReferenceNotFoundError", err)
657 }
658 err = iamClient.DeleteAuditConfig(context.TODO(), auditConfig)
659 if !k8s.IsReferenceNotFoundError(err) {
660 t.Errorf("deleting audit config when referenced resource not found: got error: %v, want ReferenceNotFoundError", err)
661 }
662 }
663
664 func TestConflictPreventionWithEtags(t *testing.T) {
665 testName := getCurrentFuncName()
666 shouldRun := func(fixture resourcefixture.ResourceFixture, mgr manager.Manager) bool {
667 return shouldRunBasedOnRunAndSkipRegexes(testName, fixture) &&
668 fixture.Type == resourcefixture.Basic &&
669 (fixture.GVK.Kind == "PubSubTopic" || fixture.GVK.Kind == "Project" || fixture.GVK.Kind == "DataprocCluster")
670 }
671
672 testCaseFunc := func(t *testing.T, testContext testrunner.TestContext, sysContext testrunner.SystemContext) {
673 iamClient := testiam.NewIAMClient(sysContext)
674 refResource := testContext.CreateUnstruct
675 resourceRef := testiam.NewResourceRef(refResource)
676 iamPolicy := newPolicy(t, refResource, resourceRef, testContext.UniqueId)
677 testConflictPreventionWithEtags(t, iamClient, iamPolicy, refResource)
678 }
679 testrunner.RunAllWithObjectCreated(t, mgr, shouldRun, testCaseFunc)
680 }
681
682 func testConflictPreventionWithEtags(t *testing.T, iamClient *kcciamclient.IAMClient, policy *iamv1beta1.IAMPolicy, refResource *unstructured.Unstructured) {
683 gcpPolicy, err := iamClient.GetPolicy(context.TODO(), policy)
684 if err != nil {
685 t.Fatalf("error getting iam policy: %v", err)
686 }
687 etag := gcpPolicy.Spec.Etag
688 if etag == "" {
689 t.Fatalf("returned etag should not be empty")
690 }
691
692
693 noChangePolicy, err := iamClient.SetPolicy(context.TODO(), gcpPolicy)
694 if err != nil {
695 t.Fatalf("error setting iam policy: %v", err)
696 }
697 if noChangePolicy.Spec.Etag != etag {
698 t.Fatalf("expect no change of etag since there is no realy IAM policy change")
699 }
700
701
702 rc := testiam.GetResourceContext(t, refResource.GetKind())
703 newBinding := iamv1beta1.IAMPolicyBinding{
704 Role: rc.CreateBindingRole,
705 Members: []iamv1beta1.Member{"group:configconnector-test@google.com"},
706 }
707 newPolicy := gcpPolicy.DeepCopy()
708 newPolicy.Spec.Bindings = append(newPolicy.Spec.Bindings, newBinding)
709 changedPolicy, err := iamClient.SetPolicy(context.TODO(), newPolicy)
710 if err != nil {
711 t.Fatalf("error setting iam policy: %v", err)
712 }
713 if changedPolicy.Spec.Etag == etag {
714 t.Fatalf("expect the returned etag changed")
715 }
716
717
718 _, err = iamClient.SetPolicy(context.TODO(), gcpPolicy)
719 if err == nil {
720 t.Fatalf("got no error, want an error related to concurrent policy changes")
721 }
722 }
723
724 func newPolicyMemberWithIAMCondition(t *testing.T, refResource *unstructured.Unstructured, resourceRef iamv1beta1.ResourceReference, testId string) *iamv1beta1.IAMPolicyMember {
725 iamPolicyMember := newPolicyMember(t, refResource, resourceRef, testId)
726 iamPolicyMember.Spec.Condition = newIAMCondition()
727 return iamPolicyMember
728 }
729
730 func newPolicyWithIAMConditions(t *testing.T, refResource *unstructured.Unstructured, resourceRef iamv1beta1.ResourceReference, testId string) *iamv1beta1.IAMPolicy {
731 iamPolicy := newPolicy(t, refResource, resourceRef, testId)
732 bindings := make([]iamv1beta1.IAMPolicyBinding, 0)
733 for _, binding := range iamPolicy.Spec.Bindings {
734 binding.Condition = newIAMCondition()
735 bindings = append(bindings, binding)
736 }
737 iamPolicy.Spec.Bindings = bindings
738 return iamPolicy
739 }
740
741 func newPolicyWithAuditConfigs(t *testing.T, refResource *unstructured.Unstructured, resourceRef iamv1beta1.ResourceReference, testId string) *iamv1beta1.IAMPolicy {
742 iamPolicy := newPolicy(t, refResource, resourceRef, testId)
743 iamPolicy.Spec.AuditConfigs = []iamv1beta1.IAMPolicyAuditConfig{
744 {
745 Service: "allServices",
746 AuditLogConfigs: []iamv1beta1.AuditLogConfig{
747 {
748 LogType: "DATA_WRITE",
749 },
750 {
751 LogType: "DATA_READ",
752 ExemptedMembers: []iamv1beta1.Member{iamv1beta1.Member(testgcp.GetIAMPolicyBindingMember(t))},
753 },
754 },
755 },
756 }
757 return iamPolicy
758 }
759
760 func newPolicyMember(t *testing.T, refResource *unstructured.Unstructured, resourceRef iamv1beta1.ResourceReference, testId string) *iamv1beta1.IAMPolicyMember {
761 rc := testiam.GetResourceContext(t, refResource.GetKind())
762 return &iamv1beta1.IAMPolicyMember{
763 TypeMeta: metav1.TypeMeta{
764 APIVersion: iamv1beta1.IAMPolicyMemberGVK.GroupVersion().String(),
765 Kind: iamv1beta1.IAMPolicyMemberGVK.Kind,
766 },
767 ObjectMeta: metav1.ObjectMeta{
768 Name: fmt.Sprintf("iam-policy-member-%v", testId),
769 Namespace: refResource.GetNamespace(),
770 },
771 Spec: iamv1beta1.IAMPolicyMemberSpec{
772 ResourceReference: resourceRef,
773 Member: iamv1beta1.Member(testgcp.GetIAMPolicyBindingMember(t)),
774 Role: rc.CreateBindingRole,
775 },
776 }
777 }
778
779 func newPolicy(t *testing.T, refResource *unstructured.Unstructured, resourceRef iamv1beta1.ResourceReference, testId string) *iamv1beta1.IAMPolicy {
780 rc := testiam.GetResourceContext(t, refResource.GetKind())
781 return &iamv1beta1.IAMPolicy{
782 TypeMeta: metav1.TypeMeta{
783 APIVersion: iamv1beta1.IAMPolicyGVK.GroupVersion().String(),
784 Kind: iamv1beta1.IAMPolicyGVK.Kind,
785 },
786 ObjectMeta: metav1.ObjectMeta{
787 Name: fmt.Sprintf("iam-policy-%v", testId),
788 Namespace: refResource.GetNamespace(),
789 },
790 Spec: iamv1beta1.IAMPolicySpec{
791 ResourceReference: resourceRef,
792 Bindings: []iamv1beta1.IAMPolicyBinding{
793 {
794 Members: []iamv1beta1.Member{
795 iamv1beta1.Member(testgcp.GetIAMPolicyBindingMember(t)),
796 },
797 Role: rc.CreateBindingRole,
798 },
799 },
800 },
801 Status: iamv1beta1.IAMPolicyStatus{},
802 }
803 }
804
805 func newIAMCondition() *iamv1beta1.IAMCondition {
806 return &iamv1beta1.IAMCondition{
807 Title: "test-iam-condition",
808 Description: "Test IAM Condition",
809 Expression: "request.time < timestamp(\"2020-01-01T00:00:00Z\")",
810 }
811 }
812
813 func newAuditConfig(t *testing.T, refResource *unstructured.Unstructured, resourceRef iamv1beta1.ResourceReference, testId string) *iamv1beta1.IAMAuditConfig {
814 return &iamv1beta1.IAMAuditConfig{
815 TypeMeta: metav1.TypeMeta{
816 APIVersion: iamv1beta1.IAMAuditConfigGVK.GroupKind().String(),
817 Kind: iamv1beta1.IAMPolicyGVK.Kind,
818 },
819 ObjectMeta: metav1.ObjectMeta{
820 Name: fmt.Sprintf("iam-audit-config-%v", testId),
821 Namespace: refResource.GetNamespace(),
822 },
823 Spec: iamv1beta1.IAMAuditConfigSpec{
824 ResourceReference: resourceRef,
825 Service: "allServices",
826 AuditLogConfigs: []iamv1beta1.AuditLogConfig{
827 {
828 LogType: "DATA_WRITE",
829 },
830 {
831 LogType: "DATA_READ",
832 ExemptedMembers: []iamv1beta1.Member{iamv1beta1.Member(testgcp.GetIAMPolicyBindingMember(t))},
833 },
834 },
835 },
836 }
837 }
838
839 func getCurrentFuncName() string {
840 pc, _, _, _ := runtime.Caller(1)
841 return fmt.Sprintf("%s", runtime.FuncForPC(pc).Name())
842 }
843
844
845
846
847 func isNotFoundError(err error) bool {
848 return errors.Is(err, kcciamclient.NotFoundError) || dcl.IsNotFound(errors.Unwrap(err))
849 }
850
851 func TestMain(m *testing.M) {
852 testmain.TestMainForIntegrationTests(m, &mgr)
853 }
854
View as plain text