...

Source file src/github.com/GoogleCloudPlatform/k8s-config-connector/pkg/controller/iam/policy/iampolicy_controller_integration_test.go

Documentation: github.com/GoogleCloudPlatform/k8s-config-connector/pkg/controller/iam/policy

     1  // Copyright 2022 Google LLC
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //      http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  //go:build integration
    16  // +build integration
    17  
    18  package policy_test
    19  
    20  import (
    21  	"context"
    22  	"log"
    23  	"strings"
    24  	"testing"
    25  	"time"
    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  	kcciamclient "github.com/GoogleCloudPlatform/k8s-config-connector/pkg/controller/iam/iamclient"
    30  	"github.com/GoogleCloudPlatform/k8s-config-connector/pkg/dcl/clientconfig"
    31  	"github.com/GoogleCloudPlatform/k8s-config-connector/pkg/dcl/conversion"
    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  	testk8s "github.com/GoogleCloudPlatform/k8s-config-connector/pkg/test/k8s"
    40  	testmain "github.com/GoogleCloudPlatform/k8s-config-connector/pkg/test/main"
    41  	testservicemappingloader "github.com/GoogleCloudPlatform/k8s-config-connector/pkg/test/servicemappingloader"
    42  	tfprovider "github.com/GoogleCloudPlatform/k8s-config-connector/pkg/tf/provider"
    43  
    44  	"k8s.io/apimachinery/pkg/api/errors"
    45  	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    46  	"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
    47  	"sigs.k8s.io/controller-runtime/pkg/client"
    48  	"sigs.k8s.io/controller-runtime/pkg/manager"
    49  	"sigs.k8s.io/controller-runtime/pkg/reconcile"
    50  )
    51  
    52  var (
    53  	mgr                     manager.Manager
    54  	expectedReconcileResult = reconcile.Result{RequeueAfter: k8s.MeanReconcileReenqueuePeriod}
    55  )
    56  
    57  var resourceLevelIAMPolicyTestFunc = func(t *testing.T, _ string, mgr manager.Manager, rc testiam.IAMResourceContext, refResource *unstructured.Unstructured, resourceRef v1beta1.ResourceReference) {
    58  	bindings := []iamv1beta1.IAMPolicyBinding{
    59  		{
    60  			Role:    rc.CreateBindingRole,
    61  			Members: []v1beta1.Member{v1beta1.Member(testgcp.GetIAMPolicyBindingMember(t))},
    62  		},
    63  	}
    64  	newBindings := []iamv1beta1.IAMPolicyBinding{
    65  		{
    66  			Role:    rc.CreateBindingRole,
    67  			Members: []v1beta1.Member{v1beta1.Member(testgcp.GetIAMPolicyBindingMember(t))},
    68  		},
    69  		{
    70  			Role:    rc.UpdateBindingRole,
    71  			Members: []v1beta1.Member{v1beta1.Member(testgcp.GetIAMPolicyBindingMember(t))},
    72  		},
    73  	}
    74  	k8sPolicy := newIAMPolicyFixture(t, refResource, resourceRef, bindings, nil)
    75  	newK8sPolicy := k8sPolicy.DeepCopy()
    76  	newK8sPolicy.Spec.Bindings = newBindings
    77  	provider := tfprovider.NewOrLogFatal(tfprovider.DefaultConfig)
    78  	smLoader := testservicemappingloader.New(t)
    79  	kubeClient := mgr.GetClient()
    80  	dclConfig := clientconfig.NewForIntegrationTest()
    81  	dclSchemaLoader, err := dclschemaloader.New()
    82  	if err != nil {
    83  		t.Fatalf("error creating a new DCL schema loader: %v", err)
    84  	}
    85  	serviceMetaLoader := dclmetadata.New()
    86  	converter := conversion.New(dclSchemaLoader, serviceMetaLoader)
    87  	iamClient := kcciamclient.New(provider, smLoader, kubeClient, converter, dclConfig)
    88  	reconciler := testreconciler.NewForDCLAndTFTestReconciler(t, mgr, provider, dclConfig)
    89  
    90  	testReconcileResourceLevelCreateNoChangesUpdateDelete(t, kubeClient, k8sPolicy, newK8sPolicy, iamClient, reconciler)
    91  }
    92  
    93  func TestReconcileIAMPolicyResourceLevelCreateNoChangesUpdateDelete(t *testing.T) {
    94  	testiam.RunResourceLevelTest(t, mgr, resourceLevelIAMPolicyTestFunc, testiam.ShouldRunWithNoProjectKind)
    95  }
    96  
    97  func TestReconcileIAMPolicyResourceLevelCreateNoChangesUpdateDeleteWithExternalRef(t *testing.T) {
    98  	testiam.RunResourceLevelTestWithExternalRef(t, mgr, resourceLevelIAMPolicyTestFunc, testiam.ShouldRunWithExternalRef)
    99  }
   100  
   101  func TestReconcileIAMPolicyResourceLevelCreateNoChangesUpdateDeleteWithAuditConfigs(t *testing.T) {
   102  	testFunc := func(t *testing.T, _ string, mgr manager.Manager, rc testiam.IAMResourceContext, refResource *unstructured.Unstructured, resourceRef v1beta1.ResourceReference) {
   103  		bindings := []iamv1beta1.IAMPolicyBinding{
   104  			{
   105  				Role:    rc.CreateBindingRole,
   106  				Members: []v1beta1.Member{v1beta1.Member(testgcp.GetIAMPolicyBindingMember(t))},
   107  			},
   108  		}
   109  		auditConfigs := []iamv1beta1.IAMPolicyAuditConfig{
   110  			{
   111  				Service: "allServices",
   112  				AuditLogConfigs: []iamv1beta1.AuditLogConfig{
   113  					{
   114  						LogType:         "ADMIN_READ",
   115  						ExemptedMembers: []v1beta1.Member{v1beta1.Member(testgcp.GetIAMPolicyBindingMember(t))},
   116  					},
   117  				},
   118  			},
   119  		}
   120  		newAuditConfigs := []iamv1beta1.IAMPolicyAuditConfig{
   121  			{
   122  				Service: "allServices",
   123  				AuditLogConfigs: []iamv1beta1.AuditLogConfig{
   124  					{
   125  						LogType: "DATA_READ",
   126  					},
   127  					{
   128  						LogType:         "ADMIN_READ",
   129  						ExemptedMembers: []v1beta1.Member{v1beta1.Member(testgcp.GetIAMPolicyBindingMember(t))},
   130  					},
   131  				},
   132  			},
   133  			{
   134  				Service: "compute.googleapis.com",
   135  				AuditLogConfigs: []iamv1beta1.AuditLogConfig{
   136  					{
   137  						LogType: "DATA_WRITE",
   138  					},
   139  				},
   140  			},
   141  		}
   142  		k8sPolicy := newIAMPolicyFixture(t, refResource, resourceRef, bindings, auditConfigs)
   143  		newK8sPolicy := k8sPolicy.DeepCopy()
   144  		newK8sPolicy.Spec.AuditConfigs = newAuditConfigs
   145  		provider := tfprovider.NewOrLogFatal(tfprovider.DefaultConfig)
   146  		smLoader := testservicemappingloader.New(t)
   147  		kubeClient := mgr.GetClient()
   148  		dclConfig := clientconfig.NewForIntegrationTest()
   149  		dclSchemaLoader, err := dclschemaloader.New()
   150  		if err != nil {
   151  			t.Fatalf("error creating a new DCL schema loader: %v", err)
   152  		}
   153  		serviceMetaLoader := dclmetadata.New()
   154  		converter := conversion.New(dclSchemaLoader, serviceMetaLoader)
   155  		iamClient := kcciamclient.New(provider, smLoader, kubeClient, converter, dclConfig)
   156  		reconciler := testreconciler.New(t, mgr, provider)
   157  
   158  		testReconcileResourceLevelCreateNoChangesUpdateDelete(t, kubeClient, k8sPolicy, newK8sPolicy, iamClient, reconciler)
   159  	}
   160  	testiam.RunResourceLevelTest(t, mgr, testFunc, testiam.ShouldRunWithAuditConfigs)
   161  }
   162  
   163  func testReconcileResourceLevelCreateNoChangesUpdateDelete(t *testing.T, kubeClient client.Client, k8sPolicy, newK8sPolicy *iamv1beta1.IAMPolicy, iamClient *kcciamclient.IAMClient, reconciler *testreconciler.TestReconciler) {
   164  	testReconcileResourceLevelCreate(t, kubeClient, k8sPolicy, iamClient, reconciler)
   165  	testReconcileResourceLevelNoChanges(t, kubeClient, k8sPolicy, iamClient, reconciler)
   166  	testReconcileResourceLevelUpdate(t, kubeClient, k8sPolicy, newK8sPolicy, iamClient, reconciler)
   167  	testReconcileResourceLevelDelete(t, kubeClient, newK8sPolicy, iamClient, reconciler)
   168  }
   169  
   170  func testReconcileResourceLevelCreate(t *testing.T, kubeClient client.Client, k8sPolicy *iamv1beta1.IAMPolicy, iamClient *kcciamclient.IAMClient, reconciler *testreconciler.TestReconciler) {
   171  	if err := kubeClient.Create(context.TODO(), k8sPolicy); err != nil {
   172  		t.Fatalf("error creating k8sPolicy: %v", err)
   173  	}
   174  	preReconcileGeneration := k8sPolicy.GetGeneration()
   175  	reconciler.ReconcileObjectMeta(k8sPolicy.ObjectMeta, iamv1beta1.IAMPolicyGVK.Kind, expectedReconcileResult, nil)
   176  	gcpPolicy, err := iamClient.GetPolicy(context.TODO(), k8sPolicy)
   177  	if err != nil {
   178  		t.Fatalf("error retrieving GCP policy: %v", err)
   179  	}
   180  	testiam.AssertSamePolicy(t, k8sPolicy, gcpPolicy)
   181  	if err := kubeClient.Get(context.TODO(), k8s.GetNamespacedName(k8sPolicy), k8sPolicy); err != nil {
   182  		t.Fatalf("unexpected error getting k8s resource: %v", err)
   183  	}
   184  	testcontroller.AssertReadyCondition(t, k8sPolicy.Status.Conditions)
   185  	testcontroller.AssertEventRecordedForObjectMetaAndKind(t, kubeClient, iamv1beta1.IAMPolicyGVK.Kind, &k8sPolicy.ObjectMeta, k8s.UpToDate)
   186  	assertObservedGenerationEquals(t, k8sPolicy, preReconcileGeneration)
   187  }
   188  
   189  func testReconcileResourceLevelUpdate(t *testing.T, kubeClient client.Client, k8sPolicy, newK8sPolicy *iamv1beta1.IAMPolicy, iamClient *kcciamclient.IAMClient, reconciler *testreconciler.TestReconciler) {
   190  	if err := kubeClient.Get(context.TODO(), k8s.GetNamespacedName(k8sPolicy), k8sPolicy); err != nil {
   191  		t.Fatalf("unexpected error getting k8s resource: %v", err)
   192  	}
   193  	newK8sPolicy.SetResourceVersion(k8sPolicy.GetResourceVersion())
   194  	if err := kubeClient.Update(context.TODO(), newK8sPolicy); err != nil {
   195  		t.Fatalf("error updating k8sPolicy: %v", err)
   196  	}
   197  	preReconcileGeneration := newK8sPolicy.GetGeneration()
   198  	reconciler.ReconcileObjectMeta(newK8sPolicy.ObjectMeta, iamv1beta1.IAMPolicyGVK.Kind, expectedReconcileResult, nil)
   199  	if err := kubeClient.Get(context.TODO(), k8s.GetNamespacedName(newK8sPolicy), newK8sPolicy); err != nil {
   200  		t.Fatalf("unexpected error getting k8s resource: %v", err)
   201  	}
   202  	gcpPolicy, err := iamClient.GetPolicy(context.TODO(), newK8sPolicy)
   203  	if err != nil {
   204  		t.Fatalf("error retrieving GCP policy: %v", err)
   205  	}
   206  	testiam.AssertSamePolicy(t, newK8sPolicy, gcpPolicy)
   207  	testcontroller.AssertReadyCondition(t, newK8sPolicy.Status.Conditions)
   208  	testcontroller.AssertEventRecordedForObjectMetaAndKind(t, kubeClient, iamv1beta1.IAMPolicyGVK.Kind, &newK8sPolicy.ObjectMeta, k8s.UpToDate)
   209  	assertObservedGenerationEquals(t, newK8sPolicy, preReconcileGeneration)
   210  }
   211  
   212  func testReconcileResourceLevelNoChanges(t *testing.T, kubeClient client.Client, k8sPolicy *iamv1beta1.IAMPolicy, iamClient *kcciamclient.IAMClient, reconciler *testreconciler.TestReconciler) {
   213  	if err := kubeClient.Get(context.TODO(), k8s.GetNamespacedName(k8sPolicy), k8sPolicy); err != nil {
   214  		t.Fatalf("unexpected error getting k8s resource: %v", err)
   215  	}
   216  	preReconcileGeneration := k8sPolicy.GetGeneration()
   217  	reconciler.ReconcileObjectMeta(k8sPolicy.ObjectMeta, iamv1beta1.IAMPolicyGVK.Kind, expectedReconcileResult, nil)
   218  	newK8sPolicy := &iamv1beta1.IAMPolicy{}
   219  	if err := kubeClient.Get(context.TODO(), k8s.GetNamespacedName(k8sPolicy), newK8sPolicy); err != nil {
   220  		t.Fatalf("unexpected error getting k8s resource: %v", err)
   221  	}
   222  	if k8sPolicy.GetResourceVersion() != newK8sPolicy.GetResourceVersion() {
   223  		t.Errorf("reconcile that was expected to be a no-op resulted in a write to the API server")
   224  	}
   225  	assertObservedGenerationEquals(t, newK8sPolicy, preReconcileGeneration)
   226  }
   227  
   228  func TestReconcileIAMPolicyResourceLevelDeleteParentFirst(t *testing.T) {
   229  	testFunc := func(t *testing.T, _ string, mgr manager.Manager, rc testiam.IAMResourceContext, refResource *unstructured.Unstructured, resourceRef v1beta1.ResourceReference) {
   230  		bindings := []iamv1beta1.IAMPolicyBinding{
   231  			{
   232  				Role:    rc.CreateBindingRole,
   233  				Members: []v1beta1.Member{v1beta1.Member(testgcp.GetIAMPolicyBindingMember(t))},
   234  			},
   235  		}
   236  		k8sPolicy := newIAMPolicyFixture(t, refResource, resourceRef, bindings, nil)
   237  		testReconcileResourceLevelDeleteParentFirst(t, mgr, k8sPolicy, refResource)
   238  	}
   239  	testiam.RunResourceLevelTest(t, mgr, testFunc, testiam.ShouldRunDeleteParentFirst)
   240  }
   241  
   242  func TestReconcileIAMPolicyResourceLevelDeleteParentFirstWithExternalRef(t *testing.T) {
   243  	testFunc := func(t *testing.T, _ string, mgr manager.Manager, rc testiam.IAMResourceContext, refResource *unstructured.Unstructured, resourceRef v1beta1.ResourceReference) {
   244  		bindings := []iamv1beta1.IAMPolicyBinding{
   245  			{
   246  				Role:    rc.CreateBindingRole,
   247  				Members: []v1beta1.Member{v1beta1.Member(testgcp.GetIAMPolicyBindingMember(t))},
   248  			},
   249  		}
   250  		k8sPolicy := newIAMPolicyFixture(t, refResource, resourceRef, bindings, nil)
   251  		testReconcileResourceLevelDeleteParentFirst(t, mgr, k8sPolicy, refResource)
   252  	}
   253  	testiam.RunResourceLevelTestWithExternalRef(t, mgr, testFunc, testiam.ShouldRunDeleteParentFirst)
   254  }
   255  
   256  func testReconcileResourceLevelDelete(t *testing.T, kubeClient client.Client, k8sPolicy *iamv1beta1.IAMPolicy, iamClient *kcciamclient.IAMClient, reconciler *testreconciler.TestReconciler) {
   257  	if k8sPolicy.Spec.ResourceReference.Kind == "StorageBucket" {
   258  		// Once removing roles/storage.admin role, the caller cannot get access to the storage bucket
   259  		// even if it's the owner of the project.
   260  		return
   261  	}
   262  	if err := kubeClient.Delete(context.TODO(), k8sPolicy); err != nil {
   263  		t.Fatalf("error deleting k8sPolicy: %v", err)
   264  	}
   265  	reconciler.ReconcileObjectMeta(k8sPolicy.ObjectMeta, iamv1beta1.IAMPolicyGVK.Kind, testreconciler.ExpectedRequeueReconcileStruct, nil)
   266  	gcpPolicy, err := iamClient.GetPolicy(context.TODO(), k8sPolicy)
   267  	if err != nil {
   268  		t.Fatalf("error retrieving GCP policy: %v", err)
   269  	}
   270  	testiam.AssertSamePolicy(t, k8sPolicy, gcpPolicy)
   271  	testk8s.RemoveDeletionDefenderFinalizer(t, k8sPolicy, iamv1beta1.IAMPolicyGVK, kubeClient)
   272  	reconciler.ReconcileObjectMeta(k8sPolicy.ObjectMeta, iamv1beta1.IAMPolicyGVK.Kind, expectedReconcileResult, nil)
   273  	gcpPolicy, err = iamClient.GetPolicy(context.TODO(), k8sPolicy)
   274  	if err != nil {
   275  		t.Fatalf("error retrieving GCP policy: %v", err)
   276  	}
   277  	if len(gcpPolicy.Spec.Bindings) > 0 {
   278  		t.Fatalf("expected there to be no bindings but there were %v", len(gcpPolicy.Spec.Bindings))
   279  	}
   280  	if err := kubeClient.Get(context.TODO(), k8s.GetNamespacedName(k8sPolicy), k8sPolicy); err == nil || !errors.IsNotFound(err) {
   281  		t.Fatalf("unexpected error value: %v", err)
   282  	}
   283  	testcontroller.AssertEventRecordedForObjectMetaAndKind(t, kubeClient, iamv1beta1.IAMPolicyGVK.Kind, &k8sPolicy.ObjectMeta, k8s.Deleted)
   284  }
   285  
   286  func testReconcileResourceLevelDeleteParentFirst(t *testing.T, mgr manager.Manager, k8sPolicy *iamv1beta1.IAMPolicy, refResource *unstructured.Unstructured) {
   287  	kubeClient := mgr.GetClient()
   288  	if err := kubeClient.Create(context.TODO(), k8sPolicy); err != nil {
   289  		t.Fatalf("error creating k8sPolicy: %v", err)
   290  	}
   291  	reconciler := testreconciler.New(t, mgr, tfprovider.NewOrLogFatal(tfprovider.DefaultConfig))
   292  	reconciler.ReconcileObjectMeta(k8sPolicy.ObjectMeta, iamv1beta1.IAMPolicyGVK.Kind, expectedReconcileResult, nil)
   293  
   294  	// First, delete the parent resource of the IAM Policy.
   295  	log.Printf("Deleting the parent of the IAM Policy first %v: %v/%v\n", refResource.GetKind(), refResource.GetNamespace(), refResource.GetName())
   296  	testk8s.RemoveDeletionDefenderFinalizerForUnstructured(t, refResource, kubeClient)
   297  	err := kubeClient.Delete(context.TODO(), refResource)
   298  	if err != nil {
   299  		t.Errorf("error deleting %v: %v", refResource, err)
   300  	}
   301  	reconciler.Reconcile(refResource, expectedReconcileResult, nil)
   302  
   303  	// Then, delete the IAM Policy.
   304  	testk8s.RemoveDeletionDefenderFinalizer(t, k8sPolicy, iamv1beta1.IAMPolicyGVK, kubeClient)
   305  	if err := kubeClient.Delete(context.TODO(), k8sPolicy); err != nil {
   306  		t.Fatalf("error deleting k8sPolicy: %v", err)
   307  	}
   308  	reconciler.ReconcileObjectMeta(k8sPolicy.ObjectMeta, iamv1beta1.IAMPolicyGVK.Kind, expectedReconcileResult, nil)
   309  	if err := kubeClient.Get(context.TODO(), k8s.GetNamespacedName(k8sPolicy), k8sPolicy); err == nil || !errors.IsNotFound(err) {
   310  		t.Fatalf("unexpected error value: %v", err)
   311  	}
   312  	// Wait till all the events are properly cached.
   313  	testcontroller.CollectEvents(t, mgr.GetConfig(), k8sPolicy.Namespace, 6, 5*time.Second)
   314  	testcontroller.AssertEventRecordedForObjectMetaAndKind(t, kubeClient, iamv1beta1.IAMPolicyGVK.Kind, &k8sPolicy.ObjectMeta, k8s.Deleted)
   315  }
   316  
   317  func TestReconcileIAMPolicyResourceLevelAcquire(t *testing.T) {
   318  	testFunc := func(t *testing.T, _ string, mgr manager.Manager, rc testiam.IAMResourceContext, refResource *unstructured.Unstructured, resourceRef v1beta1.ResourceReference) {
   319  		bindings := []iamv1beta1.IAMPolicyBinding{
   320  			{
   321  				Role:    rc.CreateBindingRole,
   322  				Members: []v1beta1.Member{v1beta1.Member(testgcp.GetIAMPolicyBindingMember(t))},
   323  			},
   324  		}
   325  		k8sPolicy := newIAMPolicyFixture(t, refResource, resourceRef, bindings, nil)
   326  		testReconcileResourceLevelAcquire(t, mgr, k8sPolicy)
   327  	}
   328  	testiam.RunResourceLevelTest(t, mgr, testFunc, testiam.ShouldRunAcquire)
   329  }
   330  
   331  func TestReconcileIAMPolicyResourceLevelAcquireWithExternalRef(t *testing.T) {
   332  	testFunc := func(t *testing.T, _ string, mgr manager.Manager, rc testiam.IAMResourceContext, refResource *unstructured.Unstructured, resourceRef v1beta1.ResourceReference) {
   333  		bindings := []iamv1beta1.IAMPolicyBinding{
   334  			{
   335  				Role:    rc.CreateBindingRole,
   336  				Members: []v1beta1.Member{v1beta1.Member(testgcp.GetIAMPolicyBindingMember(t))},
   337  			},
   338  		}
   339  		k8sPolicy := newIAMPolicyFixture(t, refResource, resourceRef, bindings, nil)
   340  		testReconcileResourceLevelAcquire(t, mgr, k8sPolicy)
   341  	}
   342  	testiam.RunResourceLevelTestWithExternalRef(t, mgr, testFunc, testiam.ShouldRunAcquire)
   343  }
   344  
   345  func TestReconcileIAMPolicyResourceLevelAcquireWithAuditConfigs(t *testing.T) {
   346  	testFunc := func(t *testing.T, _ string, mgr manager.Manager, rc testiam.IAMResourceContext, refResource *unstructured.Unstructured, resourceRef v1beta1.ResourceReference) {
   347  		bindings := []iamv1beta1.IAMPolicyBinding{
   348  			{
   349  				Role:    rc.CreateBindingRole,
   350  				Members: []v1beta1.Member{v1beta1.Member(testgcp.GetIAMPolicyBindingMember(t))},
   351  			},
   352  		}
   353  		auditConfigs := []iamv1beta1.IAMPolicyAuditConfig{
   354  			{
   355  				Service: "allServices",
   356  				AuditLogConfigs: []iamv1beta1.AuditLogConfig{
   357  					{
   358  						LogType:         "ADMIN_READ",
   359  						ExemptedMembers: []v1beta1.Member{v1beta1.Member(testgcp.GetIAMPolicyBindingMember(t))},
   360  					},
   361  				},
   362  			},
   363  		}
   364  		k8sPolicy := newIAMPolicyFixture(t, refResource, resourceRef, bindings, auditConfigs)
   365  		testReconcileResourceLevelAcquire(t, mgr, k8sPolicy)
   366  	}
   367  	testiam.RunResourceLevelTest(t, mgr, testFunc, testiam.ShouldRunWithAuditConfigs)
   368  }
   369  
   370  func testReconcileResourceLevelAcquire(t *testing.T, mgr manager.Manager, k8sPolicy *iamv1beta1.IAMPolicy) {
   371  	kubeClient := mgr.GetClient()
   372  	provider := tfprovider.NewOrLogFatal(tfprovider.DefaultConfig)
   373  	smLoader := testservicemappingloader.New(t)
   374  	dclConfig := clientconfig.NewForIntegrationTest()
   375  	dclSchemaLoader, err := dclschemaloader.New()
   376  	if err != nil {
   377  		t.Fatalf("error creating a new DCL schema loader: %v", err)
   378  	}
   379  	serviceMetaLoader := dclmetadata.New()
   380  	converter := conversion.New(dclSchemaLoader, serviceMetaLoader)
   381  	iamClient := kcciamclient.New(provider, smLoader, kubeClient, converter, dclConfig)
   382  	reconciler := testreconciler.New(t, mgr, provider)
   383  
   384  	// Create resource in GCP
   385  	if _, err := iamClient.SetPolicy(context.TODO(), k8sPolicy); err != nil {
   386  		t.Fatalf("error creating GCP policy: %v", err)
   387  	}
   388  
   389  	// Acquire IAM Policy
   390  	if err := kubeClient.Create(context.TODO(), k8sPolicy); err != nil {
   391  		t.Fatalf("error creating k8sPolicy: %v", err)
   392  	}
   393  	preReconcileGeneration := k8sPolicy.GetGeneration()
   394  	reconciler.ReconcileObjectMeta(k8sPolicy.ObjectMeta, iamv1beta1.IAMPolicyGVK.Kind, expectedReconcileResult, nil)
   395  	gcpPolicy, err := iamClient.GetPolicy(context.TODO(), k8sPolicy)
   396  	if err != nil {
   397  		t.Fatalf("error retrieving GCP policy: %v", err)
   398  	}
   399  	testiam.AssertSamePolicy(t, k8sPolicy, gcpPolicy)
   400  	if err := kubeClient.Get(context.TODO(), k8s.GetNamespacedName(k8sPolicy), k8sPolicy); err != nil {
   401  		t.Fatalf("unexpected error getting k8s resource: %v", err)
   402  	}
   403  	testcontroller.AssertReadyCondition(t, k8sPolicy.Status.Conditions)
   404  	testcontroller.AssertEventRecordedForObjectMetaAndKind(t, kubeClient, iamv1beta1.IAMPolicyGVK.Kind, &k8sPolicy.ObjectMeta, k8s.UpToDate)
   405  	assertObservedGenerationEquals(t, k8sPolicy, preReconcileGeneration)
   406  }
   407  
   408  func newIAMPolicyFixture(t *testing.T, refResource *unstructured.Unstructured, resourceRef iamv1beta1.ResourceReference, bindings []iamv1beta1.IAMPolicyBinding, auditConfigs []iamv1beta1.IAMPolicyAuditConfig) *iamv1beta1.IAMPolicy {
   409  	t.Helper()
   410  	if !strings.HasPrefix(t.Name(), "TestReconcile") {
   411  		t.Fatalf("Unexpected test name prefix, all tests are expected to start with TestReconcile")
   412  	}
   413  	return &iamv1beta1.IAMPolicy{
   414  		TypeMeta: metav1.TypeMeta{
   415  			APIVersion: iamv1beta1.IAMPolicyGVK.GroupVersion().String(),
   416  			Kind:       iamv1beta1.IAMPolicyGVK.Kind,
   417  		},
   418  		ObjectMeta: metav1.ObjectMeta{
   419  			Name:      testcontroller.UniqueName(t, name(t)),
   420  			Namespace: refResource.GetNamespace(),
   421  		},
   422  		Spec: iamv1beta1.IAMPolicySpec{
   423  			ResourceReference: resourceRef,
   424  			Bindings:          bindings,
   425  			AuditConfigs:      auditConfigs,
   426  		},
   427  	}
   428  }
   429  
   430  func assertObservedGenerationEquals(t *testing.T, gcpPolicy *iamv1beta1.IAMPolicy, preReconcileGeneration int64) {
   431  	if gcpPolicy.Status.ObservedGeneration != preReconcileGeneration {
   432  		t.Errorf("observedGeneration %v doesn't match with the pre-reconcile generation %v", gcpPolicy.Status.ObservedGeneration, preReconcileGeneration)
   433  	}
   434  }
   435  
   436  func name(t *testing.T) string {
   437  	// Necessary to remove the "/$KIND" portion of the subtest name
   438  	name := strings.ToLower(testcontroller.Name(t))
   439  	return strings.Split(name, "/")[0]
   440  }
   441  
   442  func TestMain(m *testing.M) {
   443  	testmain.TestMainForIntegrationTests(m, &mgr)
   444  }
   445  

View as plain text