1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package auditconfig_test
19
20 import (
21 "context"
22 "errors"
23 "reflect"
24 "strings"
25 "testing"
26
27 "github.com/GoogleCloudPlatform/k8s-config-connector/pkg/apis/iam/v1beta1"
28 iamv1beta1 "github.com/GoogleCloudPlatform/k8s-config-connector/pkg/apis/iam/v1beta1"
29 "github.com/GoogleCloudPlatform/k8s-config-connector/pkg/controller/iam/auditconfig"
30 kcciamclient "github.com/GoogleCloudPlatform/k8s-config-connector/pkg/controller/iam/iamclient"
31 "github.com/GoogleCloudPlatform/k8s-config-connector/pkg/k8s"
32 testcontroller "github.com/GoogleCloudPlatform/k8s-config-connector/pkg/test/controller"
33 testreconciler "github.com/GoogleCloudPlatform/k8s-config-connector/pkg/test/controller/reconciler"
34 testgcp "github.com/GoogleCloudPlatform/k8s-config-connector/pkg/test/gcp"
35 testiam "github.com/GoogleCloudPlatform/k8s-config-connector/pkg/test/iam"
36 testk8s "github.com/GoogleCloudPlatform/k8s-config-connector/pkg/test/k8s"
37 testmain "github.com/GoogleCloudPlatform/k8s-config-connector/pkg/test/main"
38 "github.com/GoogleCloudPlatform/k8s-config-connector/pkg/test/resourcefixture"
39 testservicemappingloader "github.com/GoogleCloudPlatform/k8s-config-connector/pkg/test/servicemappingloader"
40 tfprovider "github.com/GoogleCloudPlatform/k8s-config-connector/pkg/tf/provider"
41
42 "github.com/google/go-cmp/cmp"
43 apierrors "k8s.io/apimachinery/pkg/api/errors"
44 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
45 "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
46 "sigs.k8s.io/controller-runtime/pkg/manager"
47 "sigs.k8s.io/controller-runtime/pkg/reconcile"
48 )
49
50 var (
51 mgr manager.Manager
52 expectedReconcileResult = reconcile.Result{RequeueAfter: k8s.MeanReconcileReenqueuePeriod}
53 )
54
55 func TestReconcileIAMAuditConfigResourceLevelCreate(t *testing.T) {
56 testFunc := func(t *testing.T, _ string, mgr manager.Manager, rc testiam.IAMResourceContext, refResource *unstructured.Unstructured, resourceRef v1beta1.ResourceReference) {
57 auditLogConfigs := []iamv1beta1.AuditLogConfig{
58 {
59 LogType: "DATA_WRITE",
60 },
61 {
62 LogType: "DATA_READ",
63 ExemptedMembers: []v1beta1.Member{v1beta1.Member(testgcp.GetIAMPolicyBindingMember(t))},
64 },
65 }
66 k8sAuditConfig := newIAMAuditConfigFixture(t, refResource, resourceRef, "allServices", auditLogConfigs)
67 testReconcileResourceLevelCreate(t, mgr, k8sAuditConfig)
68 }
69 testiam.RunResourceLevelTest(t, mgr, testFunc, testiam.ShouldRunWithAuditConfigs)
70 }
71
72 func TestReconcileIAMAuditConfigResourceLevelCreateWithExternalRef(t *testing.T) {
73 shouldRun := func(fixture resourcefixture.ResourceFixture) bool {
74 return testiam.ShouldRunWithAuditConfigs(fixture) && testiam.ShouldRunWithExternalRef(fixture)
75 }
76 testFunc := func(t *testing.T, _ string, mgr manager.Manager, rc testiam.IAMResourceContext, refResource *unstructured.Unstructured, resourceRef v1beta1.ResourceReference) {
77 auditLogConfigs := []iamv1beta1.AuditLogConfig{
78 {
79 LogType: "DATA_WRITE",
80 },
81 {
82 LogType: "DATA_READ",
83 ExemptedMembers: []v1beta1.Member{v1beta1.Member(testgcp.GetIAMPolicyBindingMember(t))},
84 },
85 }
86 k8sAuditConfig := newIAMAuditConfigFixture(t, refResource, resourceRef, "allServices", auditLogConfigs)
87 testReconcileResourceLevelCreate(t, mgr, k8sAuditConfig)
88 }
89 testiam.RunResourceLevelTestWithExternalRef(t, mgr, testFunc, shouldRun)
90 }
91
92 func testReconcileResourceLevelCreate(t *testing.T, mgr manager.Manager, k8sAuditConfig *iamv1beta1.IAMAuditConfig) {
93 provider := tfprovider.NewOrLogFatal(tfprovider.DefaultConfig)
94 smLoader := testservicemappingloader.New(t)
95 kubeClient := mgr.GetClient()
96 tfIamClient := kcciamclient.New(provider, smLoader, kubeClient, nil, nil).TFIAMClient
97 reconciler := testreconciler.New(t, mgr, provider)
98 if _, err := tfIamClient.GetAuditConfig(context.TODO(), k8sAuditConfig); !errors.Is(err, kcciamclient.NotFoundError) {
99 t.Fatalf("unexpected error value: got '%v', want '%v'", err, kcciamclient.NotFoundError)
100 }
101 if err := kubeClient.Create(context.TODO(), k8sAuditConfig); err != nil {
102 t.Fatalf("error creating k8s resource: %v", err)
103 }
104 preReconcileGeneration := k8sAuditConfig.GetGeneration()
105 resource, err := auditconfig.ToK8sResource(k8sAuditConfig)
106 if err != nil {
107 t.Fatalf("error converting object %v to k8sResource: %v", k8sAuditConfig, err)
108 }
109 u, err := resource.MarshalAsUnstructured()
110 if err != nil {
111 t.Fatalf("error marshalling %v as unstructured: %v", k8sAuditConfig, err)
112 }
113 reconciler.ReconcileObjectMeta(k8sAuditConfig.ObjectMeta, iamv1beta1.IAMAuditConfigGVK.Kind, testreconciler.ExpectedSuccessfulReconcileResultFor(reconciler, u), nil)
114 gcpAuditConfig, err := tfIamClient.GetAuditConfig(context.TODO(), k8sAuditConfig)
115 if err != nil {
116 t.Fatalf("error retrieving GCP audit config: %v", err)
117 }
118 assertSameAuditConfigs(t, k8sAuditConfig, gcpAuditConfig)
119 if err := kubeClient.Get(context.TODO(), k8s.GetNamespacedName(k8sAuditConfig), k8sAuditConfig); err != nil {
120 t.Fatalf("unexpected error getting k8s resource: %v", err)
121 }
122 testcontroller.AssertReadyCondition(t, k8sAuditConfig.Status.Conditions)
123 testcontroller.AssertEventRecordedForObjectMetaAndKind(t, kubeClient, iamv1beta1.IAMAuditConfigGVK.Kind, &k8sAuditConfig.ObjectMeta, k8s.UpToDate)
124 assertObservedGenerationEquals(t, k8sAuditConfig, preReconcileGeneration)
125 }
126
127 func TestReconcileIAMAuditConfigResourceLevelUpdate(t *testing.T) {
128 testFunc := func(t *testing.T, _ string, mgr manager.Manager, rc testiam.IAMResourceContext, refResource *unstructured.Unstructured, resourceRef v1beta1.ResourceReference) {
129 auditLogConfigs := []iamv1beta1.AuditLogConfig{
130 {
131 LogType: "DATA_WRITE",
132 },
133 }
134 newAuditLogConfigs := []iamv1beta1.AuditLogConfig{
135 {
136 LogType: "DATA_WRITE",
137 },
138 {
139 LogType: "DATA_READ",
140 ExemptedMembers: []v1beta1.Member{v1beta1.Member(testgcp.GetIAMPolicyBindingMember(t))},
141 },
142 }
143 k8sAuditConfig := newIAMAuditConfigFixture(t, refResource, resourceRef, "allServices", auditLogConfigs)
144 newK8sAuditConfig := k8sAuditConfig.DeepCopy()
145 newK8sAuditConfig.Spec.AuditLogConfigs = newAuditLogConfigs
146 testReconcileResourceLevelUpdate(t, mgr, k8sAuditConfig, newK8sAuditConfig)
147 }
148 testiam.RunResourceLevelTest(t, mgr, testFunc, testiam.ShouldRunWithAuditConfigs)
149 }
150
151 func TestReconcileIAMAuditConfigResourceLevelUpdateWithExternalRef(t *testing.T) {
152 shouldRun := func(fixture resourcefixture.ResourceFixture) bool {
153 return testiam.ShouldRunWithAuditConfigs(fixture) && testiam.ShouldRunWithExternalRef(fixture)
154 }
155 testFunc := func(t *testing.T, _ string, mgr manager.Manager, rc testiam.IAMResourceContext, refResource *unstructured.Unstructured, resourceRef v1beta1.ResourceReference) {
156 auditLogConfigs := []iamv1beta1.AuditLogConfig{
157 {
158 LogType: "DATA_WRITE",
159 },
160 }
161 newAuditLogConfigs := []iamv1beta1.AuditLogConfig{
162 {
163 LogType: "DATA_WRITE",
164 },
165 {
166 LogType: "DATA_READ",
167 ExemptedMembers: []v1beta1.Member{v1beta1.Member(testgcp.GetIAMPolicyBindingMember(t))},
168 },
169 }
170 k8sAuditConfig := newIAMAuditConfigFixture(t, refResource, resourceRef, "allServices", auditLogConfigs)
171 newK8sAuditConfig := k8sAuditConfig.DeepCopy()
172 newK8sAuditConfig.Spec.AuditLogConfigs = newAuditLogConfigs
173 testReconcileResourceLevelUpdate(t, mgr, k8sAuditConfig, newK8sAuditConfig)
174 }
175 testiam.RunResourceLevelTestWithExternalRef(t, mgr, testFunc, shouldRun)
176 }
177
178 func testReconcileResourceLevelUpdate(t *testing.T, mgr manager.Manager, k8sAuditConfig, newK8sAuditConfig *iamv1beta1.IAMAuditConfig) {
179 provider := tfprovider.NewOrLogFatal(tfprovider.DefaultConfig)
180 smLoader := testservicemappingloader.New(t)
181 kubeClient := mgr.GetClient()
182 tfIamClient := kcciamclient.New(provider, smLoader, kubeClient, nil, nil).TFIAMClient
183 reconciler := testreconciler.New(t, mgr, provider)
184 if _, err := tfIamClient.GetAuditConfig(context.TODO(), k8sAuditConfig); !errors.Is(err, kcciamclient.NotFoundError) {
185 t.Fatalf("unexpected error value: got '%v', want '%v'", err, kcciamclient.NotFoundError)
186 }
187 if err := kubeClient.Create(context.TODO(), k8sAuditConfig); err != nil {
188 t.Fatalf("error creating k8s resource: %v", err)
189 }
190 preReconcileGeneration := k8sAuditConfig.GetGeneration()
191 reconciler.ReconcileObjectMeta(k8sAuditConfig.ObjectMeta, iamv1beta1.IAMAuditConfigGVK.Kind, expectedReconcileResult, nil)
192 gcpAuditConfig, err := tfIamClient.GetAuditConfig(context.TODO(), k8sAuditConfig)
193 if err != nil {
194 t.Fatalf("error retrieving GCP audit config: %v", err)
195 }
196 assertSameAuditConfigs(t, k8sAuditConfig, gcpAuditConfig)
197 if err := kubeClient.Get(context.TODO(), k8s.GetNamespacedName(k8sAuditConfig), k8sAuditConfig); err != nil {
198 t.Fatalf("unexpected error getting k8s resource: %v", err)
199 }
200 assertObservedGenerationEquals(t, k8sAuditConfig, preReconcileGeneration)
201 newK8sAuditConfig.SetResourceVersion(k8sAuditConfig.GetResourceVersion())
202 if err := kubeClient.Update(context.TODO(), newK8sAuditConfig); err != nil {
203 t.Fatalf("error updating k8s resource: %v", err)
204 }
205 preReconcileGeneration = newK8sAuditConfig.GetGeneration()
206 reconciler.ReconcileObjectMeta(newK8sAuditConfig.ObjectMeta, iamv1beta1.IAMAuditConfigGVK.Kind, expectedReconcileResult, nil)
207 if err := kubeClient.Get(context.TODO(), k8s.GetNamespacedName(newK8sAuditConfig), newK8sAuditConfig); err != nil {
208 t.Fatalf("unexpected error getting k8s resource: %v", err)
209 }
210 gcpAuditConfig, err = tfIamClient.GetAuditConfig(context.TODO(), newK8sAuditConfig)
211 if err != nil {
212 t.Fatalf("error retrieving GCP audit config: %v", err)
213 }
214 assertSameAuditConfigs(t, newK8sAuditConfig, gcpAuditConfig)
215 testcontroller.AssertReadyCondition(t, newK8sAuditConfig.Status.Conditions)
216 testcontroller.AssertEventRecordedForObjectMetaAndKind(t, kubeClient, iamv1beta1.IAMAuditConfigGVK.Kind, &newK8sAuditConfig.ObjectMeta, k8s.UpToDate)
217 assertObservedGenerationEquals(t, newK8sAuditConfig, preReconcileGeneration)
218 }
219
220 func TestReconcileIAMAuditConfigResourceLevelNoChanges(t *testing.T) {
221 testFunc := func(t *testing.T, _ string, mgr manager.Manager, rc testiam.IAMResourceContext, refResource *unstructured.Unstructured, resourceRef v1beta1.ResourceReference) {
222 auditLogConfigs := []iamv1beta1.AuditLogConfig{
223 {
224 LogType: "DATA_WRITE",
225 },
226 {
227 LogType: "DATA_READ",
228 ExemptedMembers: []v1beta1.Member{v1beta1.Member(testgcp.GetIAMPolicyBindingMember(t))},
229 },
230 }
231 k8sAuditConfig := newIAMAuditConfigFixture(t, refResource, resourceRef, "allServices", auditLogConfigs)
232 testReconcileResourceLevelNoChanges(t, mgr, k8sAuditConfig)
233 }
234 testiam.RunResourceLevelTest(t, mgr, testFunc, testiam.ShouldRunWithAuditConfigs)
235 }
236
237 func TestReconcileIAMAuditConfigResourceLevelNoChangesWithExternalRef(t *testing.T) {
238 shouldRun := func(fixture resourcefixture.ResourceFixture) bool {
239 return testiam.ShouldRunWithAuditConfigs(fixture) && testiam.ShouldRunWithExternalRef(fixture)
240 }
241 testFunc := func(t *testing.T, _ string, mgr manager.Manager, rc testiam.IAMResourceContext, refResource *unstructured.Unstructured, resourceRef v1beta1.ResourceReference) {
242 auditLogConfigs := []iamv1beta1.AuditLogConfig{
243 {
244 LogType: "DATA_WRITE",
245 },
246 {
247 LogType: "DATA_READ",
248 ExemptedMembers: []v1beta1.Member{v1beta1.Member(testgcp.GetIAMPolicyBindingMember(t))},
249 },
250 }
251 k8sAuditConfig := newIAMAuditConfigFixture(t, refResource, resourceRef, "allServices", auditLogConfigs)
252 testReconcileResourceLevelNoChanges(t, mgr, k8sAuditConfig)
253 }
254 testiam.RunResourceLevelTestWithExternalRef(t, mgr, testFunc, shouldRun)
255 }
256
257 func testReconcileResourceLevelNoChanges(t *testing.T, mgr manager.Manager, k8sAuditConfig *iamv1beta1.IAMAuditConfig) {
258 provider := tfprovider.NewOrLogFatal(tfprovider.DefaultConfig)
259 smLoader := testservicemappingloader.New(t)
260 kubeClient := mgr.GetClient()
261 tfIamClient := kcciamclient.New(provider, smLoader, kubeClient, nil, nil).TFIAMClient
262 reconciler := testreconciler.New(t, mgr, provider)
263 if _, err := tfIamClient.GetAuditConfig(context.TODO(), k8sAuditConfig); !errors.Is(err, kcciamclient.NotFoundError) {
264 t.Fatalf("unexpected error value: got '%v', want '%v'", err, kcciamclient.NotFoundError)
265 }
266 if err := kubeClient.Create(context.TODO(), k8sAuditConfig); err != nil {
267 t.Fatalf("error creating k8s resource: %v", err)
268 }
269 preReconcileGeneration := k8sAuditConfig.GetGeneration()
270 reconciler.ReconcileObjectMeta(k8sAuditConfig.ObjectMeta, iamv1beta1.IAMAuditConfigGVK.Kind, expectedReconcileResult, nil)
271 gcpAuditConfig, err := tfIamClient.GetAuditConfig(context.TODO(), k8sAuditConfig)
272 if err != nil {
273 t.Fatalf("error retrieving GCP audit config: %v", err)
274 }
275 assertSameAuditConfigs(t, k8sAuditConfig, gcpAuditConfig)
276 if err := kubeClient.Get(context.TODO(), k8s.GetNamespacedName(k8sAuditConfig), k8sAuditConfig); err != nil {
277 t.Fatalf("unexpected error getting k8s resource: %v", err)
278 }
279 assertObservedGenerationEquals(t, k8sAuditConfig, preReconcileGeneration)
280 preReconcileGeneration = k8sAuditConfig.GetGeneration()
281 reconciler.ReconcileObjectMeta(k8sAuditConfig.ObjectMeta, iamv1beta1.IAMAuditConfigGVK.Kind, expectedReconcileResult, nil)
282 newK8sAuditConfig := &iamv1beta1.IAMAuditConfig{}
283 if err := kubeClient.Get(context.TODO(), k8s.GetNamespacedName(k8sAuditConfig), newK8sAuditConfig); err != nil {
284 t.Fatalf("unexpected error getting k8s resource: %v", err)
285 }
286 gcpAuditConfig, err = tfIamClient.GetAuditConfig(context.TODO(), k8sAuditConfig)
287 if err != nil {
288 t.Fatalf("error retrieving GCP audit config: %v", err)
289 }
290 assertSameAuditConfigs(t, newK8sAuditConfig, gcpAuditConfig)
291 if k8sAuditConfig.GetResourceVersion() != newK8sAuditConfig.GetResourceVersion() {
292 t.Errorf("reconcile that was expected to be a no-op resulted in a write to the API server")
293 }
294 testcontroller.AssertReadyCondition(t, newK8sAuditConfig.Status.Conditions)
295 testcontroller.AssertEventRecordedForObjectMetaAndKind(t, kubeClient, iamv1beta1.IAMAuditConfigGVK.Kind, &newK8sAuditConfig.ObjectMeta, k8s.UpToDate)
296 assertObservedGenerationEquals(t, newK8sAuditConfig, preReconcileGeneration)
297 }
298
299 func TestReconcileIAMAuditConfigResourceLevelDelete(t *testing.T) {
300 testFunc := func(t *testing.T, _ string, mgr manager.Manager, rc testiam.IAMResourceContext, refResource *unstructured.Unstructured, resourceRef v1beta1.ResourceReference) {
301 auditLogConfigs := []iamv1beta1.AuditLogConfig{
302 {
303 LogType: "DATA_WRITE",
304 },
305 {
306 LogType: "DATA_READ",
307 ExemptedMembers: []v1beta1.Member{v1beta1.Member(testgcp.GetIAMPolicyBindingMember(t))},
308 },
309 }
310 k8sAuditConfig := newIAMAuditConfigFixture(t, refResource, resourceRef, "allServices", auditLogConfigs)
311 testReconcileResourceLevelDelete(t, mgr, k8sAuditConfig)
312 }
313 testiam.RunResourceLevelTest(t, mgr, testFunc, testiam.ShouldRunWithAuditConfigs)
314 }
315
316 func TestReconcileIAMAuditConfigResourceLevelDeleteWithExternalRef(t *testing.T) {
317 shouldRun := func(fixture resourcefixture.ResourceFixture) bool {
318 return testiam.ShouldRunWithAuditConfigs(fixture) && testiam.ShouldRunWithExternalRef(fixture)
319 }
320 testFunc := func(t *testing.T, _ string, mgr manager.Manager, rc testiam.IAMResourceContext, refResource *unstructured.Unstructured, resourceRef v1beta1.ResourceReference) {
321 auditLogConfigs := []iamv1beta1.AuditLogConfig{
322 {
323 LogType: "DATA_WRITE",
324 },
325 {
326 LogType: "DATA_READ",
327 ExemptedMembers: []v1beta1.Member{v1beta1.Member(testgcp.GetIAMPolicyBindingMember(t))},
328 },
329 }
330 k8sAuditConfig := newIAMAuditConfigFixture(t, refResource, resourceRef, "allServices", auditLogConfigs)
331 testReconcileResourceLevelDelete(t, mgr, k8sAuditConfig)
332 }
333 testiam.RunResourceLevelTestWithExternalRef(t, mgr, testFunc, shouldRun)
334 }
335
336 func testReconcileResourceLevelDelete(t *testing.T, mgr manager.Manager, k8sAuditConfig *iamv1beta1.IAMAuditConfig) {
337 provider := tfprovider.NewOrLogFatal(tfprovider.DefaultConfig)
338 smLoader := testservicemappingloader.New(t)
339 kubeClient := mgr.GetClient()
340 tfIamClient := kcciamclient.New(provider, smLoader, kubeClient, nil, nil).TFIAMClient
341 reconciler := testreconciler.New(t, mgr, provider)
342 if _, err := tfIamClient.GetAuditConfig(context.TODO(), k8sAuditConfig); !errors.Is(err, kcciamclient.NotFoundError) {
343 t.Fatalf("unexpected error value: got '%v', want '%v'", err, kcciamclient.NotFoundError)
344 }
345 if err := kubeClient.Create(context.TODO(), k8sAuditConfig); err != nil {
346 t.Fatalf("error creating k8s resource: %v", err)
347 }
348 reconciler.ReconcileObjectMeta(k8sAuditConfig.ObjectMeta, iamv1beta1.IAMAuditConfigGVK.Kind, expectedReconcileResult, nil)
349 gcpAuditConfig, err := tfIamClient.GetAuditConfig(context.TODO(), k8sAuditConfig)
350 if err != nil {
351 t.Fatalf("error retrieving GCP audit config: %v", err)
352 }
353 assertSameAuditConfigs(t, k8sAuditConfig, gcpAuditConfig)
354 if err := kubeClient.Get(context.TODO(), k8s.GetNamespacedName(k8sAuditConfig), k8sAuditConfig); err != nil {
355 t.Fatalf("unexpected error getting k8s resource: %v", err)
356 }
357 testcontroller.AssertReadyCondition(t, k8sAuditConfig.Status.Conditions)
358 testcontroller.AssertEventRecordedForObjectMetaAndKind(t, kubeClient, iamv1beta1.IAMAuditConfigGVK.Kind, &k8sAuditConfig.ObjectMeta, k8s.UpToDate)
359 if err := kubeClient.Delete(context.TODO(), k8sAuditConfig); err != nil {
360 t.Fatalf("error deleting k8s resource: %v", err)
361 }
362 reconciler.ReconcileObjectMeta(k8sAuditConfig.ObjectMeta, iamv1beta1.IAMAuditConfigGVK.Kind, testreconciler.ExpectedRequeueReconcileStruct, nil)
363 _, err = tfIamClient.GetAuditConfig(context.TODO(), k8sAuditConfig)
364 if err != nil {
365 t.Fatalf("expected audit config to exist in GCP, but got error: %v", err)
366 }
367 testk8s.RemoveDeletionDefenderFinalizer(t, k8sAuditConfig, v1beta1.IAMAuditConfigGVK, kubeClient)
368 reconciler.ReconcileObjectMeta(k8sAuditConfig.ObjectMeta, iamv1beta1.IAMAuditConfigGVK.Kind, expectedReconcileResult, nil)
369 if _, err := tfIamClient.GetAuditConfig(context.TODO(), k8sAuditConfig); !errors.Is(err, kcciamclient.NotFoundError) {
370 t.Fatalf("unexpected error value: got '%v', want '%v'", err, kcciamclient.NotFoundError)
371 }
372 if err := kubeClient.Get(context.TODO(), k8s.GetNamespacedName(k8sAuditConfig), k8sAuditConfig); err == nil || !apierrors.IsNotFound(err) {
373 t.Fatalf("unexpected error value: %v", err)
374 }
375 testcontroller.AssertEventRecordedForObjectMetaAndKind(t, kubeClient, v1beta1.IAMAuditConfigGVK.Kind, &k8sAuditConfig.ObjectMeta, k8s.Deleted)
376 }
377
378 func TestReconcileIAMAuditConfigResourceLevelDeleteParentFirst(t *testing.T) {
379 testFunc := func(t *testing.T, _ string, mgr manager.Manager, rc testiam.IAMResourceContext, refResource *unstructured.Unstructured, resourceRef v1beta1.ResourceReference) {
380 auditLogConfigs := []iamv1beta1.AuditLogConfig{
381 {
382 LogType: "DATA_WRITE",
383 },
384 {
385 LogType: "DATA_READ",
386 ExemptedMembers: []v1beta1.Member{v1beta1.Member(testgcp.GetIAMPolicyBindingMember(t))},
387 },
388 }
389 k8sAuditConfig := newIAMAuditConfigFixture(t, refResource, resourceRef, "allServices", auditLogConfigs)
390 testReconcileResourceLevelDeleteParentFirst(t, mgr, k8sAuditConfig, refResource)
391 }
392 testiam.RunResourceLevelTest(t, mgr, testFunc, testiam.ShouldRunWithAuditConfigs)
393 }
394
395 func TestReconcileIAMAuditConfigResourceLevelDeleteParentFirstWithExternalRef(t *testing.T) {
396 shouldRun := func(fixture resourcefixture.ResourceFixture) bool {
397 return testiam.ShouldRunWithAuditConfigs(fixture) && testiam.ShouldRunWithExternalRef(fixture)
398 }
399 testFunc := func(t *testing.T, _ string, mgr manager.Manager, rc testiam.IAMResourceContext, refResource *unstructured.Unstructured, resourceRef v1beta1.ResourceReference) {
400 auditLogConfigs := []iamv1beta1.AuditLogConfig{
401 {
402 LogType: "DATA_WRITE",
403 },
404 {
405 LogType: "DATA_READ",
406 ExemptedMembers: []v1beta1.Member{v1beta1.Member(testgcp.GetIAMPolicyBindingMember(t))},
407 },
408 }
409 k8sAuditConfig := newIAMAuditConfigFixture(t, refResource, resourceRef, "allServices", auditLogConfigs)
410 testReconcileResourceLevelDeleteParentFirst(t, mgr, k8sAuditConfig, refResource)
411 }
412 testiam.RunResourceLevelTestWithExternalRef(t, mgr, testFunc, shouldRun)
413 }
414
415 func testReconcileResourceLevelDeleteParentFirst(t *testing.T, mgr manager.Manager, k8sAuditConfig *iamv1beta1.IAMAuditConfig, refResource *unstructured.Unstructured) {
416 provider := tfprovider.NewOrLogFatal(tfprovider.DefaultConfig)
417 smLoader := testservicemappingloader.New(t)
418 kubeClient := mgr.GetClient()
419 tfIamClient := kcciamclient.New(provider, smLoader, kubeClient, nil, nil).TFIAMClient
420 reconciler := testreconciler.New(t, mgr, provider)
421 if _, err := tfIamClient.GetAuditConfig(context.TODO(), k8sAuditConfig); !errors.Is(err, kcciamclient.NotFoundError) {
422 t.Fatalf("unexpected error value: got '%v', want '%v'", err, kcciamclient.NotFoundError)
423 }
424 if err := kubeClient.Create(context.TODO(), k8sAuditConfig); err != nil {
425 t.Fatalf("error creating k8s resource: %v", err)
426 }
427 reconciler.ReconcileObjectMeta(k8sAuditConfig.ObjectMeta, iamv1beta1.IAMAuditConfigGVK.Kind, expectedReconcileResult, nil)
428 gcpAuditConfig, err := tfIamClient.GetAuditConfig(context.TODO(), k8sAuditConfig)
429 if err != nil {
430 t.Fatalf("error retrieving GCP audit config: %v", err)
431 }
432 assertSameAuditConfigs(t, k8sAuditConfig, gcpAuditConfig)
433 if err := kubeClient.Get(context.TODO(), k8s.GetNamespacedName(k8sAuditConfig), k8sAuditConfig); err != nil {
434 t.Fatalf("unexpected error getting k8s resource: %v", err)
435 }
436 testcontroller.AssertReadyCondition(t, k8sAuditConfig.Status.Conditions)
437 testcontroller.AssertEventRecordedForObjectMetaAndKind(t, kubeClient, iamv1beta1.IAMAuditConfigGVK.Kind, &k8sAuditConfig.ObjectMeta, k8s.UpToDate)
438
439
440 if err := kubeClient.Delete(context.TODO(), refResource); err != nil {
441 t.Fatalf("error deleting parent resource: %v", err)
442 }
443 testk8s.RemoveDeletionDefenderFinalizerForUnstructured(t, refResource, kubeClient)
444 reconciler.Reconcile(refResource, expectedReconcileResult, nil)
445
446
447 if err := kubeClient.Delete(context.TODO(), k8sAuditConfig); err != nil {
448 t.Fatalf("error deleting k8s resource: %v", err)
449 }
450 testk8s.RemoveDeletionDefenderFinalizer(t, k8sAuditConfig, v1beta1.IAMAuditConfigGVK, kubeClient)
451 reconciler.ReconcileObjectMeta(k8sAuditConfig.ObjectMeta, iamv1beta1.IAMAuditConfigGVK.Kind, expectedReconcileResult, nil)
452 if err := kubeClient.Get(context.TODO(), k8s.GetNamespacedName(k8sAuditConfig), k8sAuditConfig); err == nil || !apierrors.IsNotFound(err) {
453 t.Fatalf("unexpected error value: %v", err)
454 }
455 testcontroller.AssertEventRecordedForObjectMetaAndKind(t, kubeClient, v1beta1.IAMAuditConfigGVK.Kind, &k8sAuditConfig.ObjectMeta, k8s.Deleted)
456 }
457
458 func TestReconcileIAMAuditConfigResourceLevelAcquire(t *testing.T) {
459 testFunc := func(t *testing.T, _ string, mgr manager.Manager, rc testiam.IAMResourceContext, refResource *unstructured.Unstructured, resourceRef v1beta1.ResourceReference) {
460 auditLogConfigs := []iamv1beta1.AuditLogConfig{
461 {
462 LogType: "DATA_WRITE",
463 },
464 {
465 LogType: "DATA_READ",
466 ExemptedMembers: []v1beta1.Member{v1beta1.Member(testgcp.GetIAMPolicyBindingMember(t))},
467 },
468 }
469 k8sAuditConfig := newIAMAuditConfigFixture(t, refResource, resourceRef, "allServices", auditLogConfigs)
470 testReconcileResourceLevelAcquire(t, mgr, k8sAuditConfig)
471 }
472 testiam.RunResourceLevelTest(t, mgr, testFunc, testiam.ShouldRunWithAuditConfigs)
473 }
474
475 func TestReconcileIAMAuditConfigResourceLevelAcquireWithExternalRef(t *testing.T) {
476 shouldRun := func(fixture resourcefixture.ResourceFixture) bool {
477 return testiam.ShouldRunWithAuditConfigs(fixture) && testiam.ShouldRunWithExternalRef(fixture)
478 }
479 testFunc := func(t *testing.T, _ string, mgr manager.Manager, rc testiam.IAMResourceContext, refResource *unstructured.Unstructured, resourceRef v1beta1.ResourceReference) {
480 auditLogConfigs := []iamv1beta1.AuditLogConfig{
481 {
482 LogType: "DATA_WRITE",
483 },
484 {
485 LogType: "DATA_READ",
486 ExemptedMembers: []v1beta1.Member{v1beta1.Member(testgcp.GetIAMPolicyBindingMember(t))},
487 },
488 }
489 k8sAuditConfig := newIAMAuditConfigFixture(t, refResource, resourceRef, "allServices", auditLogConfigs)
490 testReconcileResourceLevelAcquire(t, mgr, k8sAuditConfig)
491 }
492 testiam.RunResourceLevelTestWithExternalRef(t, mgr, testFunc, shouldRun)
493 }
494
495 func testReconcileResourceLevelAcquire(t *testing.T, mgr manager.Manager, k8sAuditConfig *iamv1beta1.IAMAuditConfig) {
496 provider := tfprovider.NewOrLogFatal(tfprovider.DefaultConfig)
497 smLoader := testservicemappingloader.New(t)
498 kubeClient := mgr.GetClient()
499 tfIamClient := kcciamclient.New(provider, smLoader, kubeClient, nil, nil).TFIAMClient
500 reconciler := testreconciler.New(t, mgr, provider)
501
502
503 if _, err := tfIamClient.SetAuditConfig(context.TODO(), k8sAuditConfig); err != nil {
504 t.Fatalf("error creating GCP audit config: %v", err)
505 }
506
507
508 if err := kubeClient.Create(context.TODO(), k8sAuditConfig); err != nil {
509 t.Fatalf("error creating k8s resource: %v", err)
510 }
511 preReconcileGeneration := k8sAuditConfig.GetGeneration()
512 reconciler.ReconcileObjectMeta(k8sAuditConfig.ObjectMeta, iamv1beta1.IAMAuditConfigGVK.Kind, expectedReconcileResult, nil)
513 if _, err := tfIamClient.GetAuditConfig(context.TODO(), k8sAuditConfig); err != nil {
514 t.Fatalf("error retrieving GCP audit config: %v", err)
515 }
516 if err := kubeClient.Get(context.TODO(), k8s.GetNamespacedName(k8sAuditConfig), k8sAuditConfig); err != nil {
517 t.Fatalf("unexpected error getting k8s resource: %v", err)
518 }
519 testcontroller.AssertReadyCondition(t, k8sAuditConfig.Status.Conditions)
520 testcontroller.AssertEventRecordedForObjectMetaAndKind(t, kubeClient, v1beta1.IAMAuditConfigGVK.Kind, &k8sAuditConfig.ObjectMeta, k8s.UpToDate)
521 assertObservedGenerationEquals(t, k8sAuditConfig, preReconcileGeneration)
522 }
523
524 func assertSameAuditConfigs(t *testing.T, k8sAuditConfig *iamv1beta1.IAMAuditConfig, gcpAuditConfig *iamv1beta1.IAMAuditConfig) {
525 if k8sAuditConfig.Spec.Service != gcpAuditConfig.Spec.Service {
526 t.Fatalf("GCP audit config has incorrect service: got %v, want %v", gcpAuditConfig.Spec.Service, k8sAuditConfig.Spec.Service)
527 }
528 if !reflect.DeepEqual(k8sAuditConfig.Spec.ResourceReference, gcpAuditConfig.Spec.ResourceReference) {
529 diff := cmp.Diff(k8sAuditConfig.Spec.ResourceReference, gcpAuditConfig.Spec.ResourceReference)
530 t.Fatalf("GCP audit config has incorrect resource reference. Diff (-want, +got):\n%v", diff)
531 }
532 if !testiam.SameAuditLogConfigs(k8sAuditConfig.Spec.AuditLogConfigs, gcpAuditConfig.Spec.AuditLogConfigs) {
533 t.Fatalf("GCP audit config has incorrect set of audit log configs; got: %v, want: %v", gcpAuditConfig.Spec.AuditLogConfigs, k8sAuditConfig.Spec.AuditLogConfigs)
534 }
535 }
536
537 func assertObservedGenerationEquals(t *testing.T, k8sAuditConfig *iamv1beta1.IAMAuditConfig, preReconcileGeneration int64) {
538 if k8sAuditConfig.Status.ObservedGeneration != preReconcileGeneration {
539 t.Errorf("observedGeneration %v doesn't match with the pre-reconcile generation %v", k8sAuditConfig.Status.ObservedGeneration, preReconcileGeneration)
540 }
541 }
542
543 func newIAMAuditConfigFixture(t *testing.T, refResource *unstructured.Unstructured, resourceRef iamv1beta1.ResourceReference, service string, auditLogConfigs []iamv1beta1.AuditLogConfig) *iamv1beta1.IAMAuditConfig {
544 return &iamv1beta1.IAMAuditConfig{
545 TypeMeta: metav1.TypeMeta{
546 APIVersion: iamv1beta1.IAMAuditConfigGVK.GroupKind().String(),
547 Kind: iamv1beta1.IAMAuditConfigGVK.Kind,
548 },
549 ObjectMeta: metav1.ObjectMeta{
550 Name: testcontroller.UniqueName(t, name(t)),
551 Namespace: refResource.GetNamespace(),
552 },
553 Spec: iamv1beta1.IAMAuditConfigSpec{
554 ResourceReference: resourceRef,
555 Service: service,
556 AuditLogConfigs: auditLogConfigs,
557 },
558 }
559 }
560
561 func name(t *testing.T) string {
562
563 name := strings.ToLower(testcontroller.Name(t))
564 return strings.Split(name, "/")[0]
565 }
566
567 func TestMain(m *testing.M) {
568 testmain.TestMainForIntegrationTests(m, &mgr)
569 }
570
View as plain text