diff --git a/.changelog/7376.txt b/.changelog/7376.txt new file mode 100644 index 0000000000..8ec013c069 --- /dev/null +++ b/.changelog/7376.txt @@ -0,0 +1,3 @@ +```release-note:none + +``` diff --git a/google-beta/bootstrap_utils_test.go b/google-beta/bootstrap_utils_test.go index 5ca2570660..5b64718d86 100644 --- a/google-beta/bootstrap_utils_test.go +++ b/google-beta/bootstrap_utils_test.go @@ -516,6 +516,82 @@ func BootstrapProject(t *testing.T, projectID, billingAccount string, services [ return project } +// BootstrapAllPSARoles ensures that the given project's IAM +// policy grants the given service agents the given roles. +// This is important to bootstrap because using iam policy resources means that +// deleting them removes permissions for concurrent tests. +// Return whether the policy changed. +func BootstrapAllPSARoles(t *testing.T, agentNames, roles []string) bool { + config := BootstrapConfig(t) + if config == nil { + t.Fatal("Could not bootstrap a config for BootstrapAllPSARoles.") + return false + } + client := config.NewResourceManagerClient(config.userAgent) + + // Get the project since we need its number, id, and policy. + project, err := client.Projects.Get(getTestProjectFromEnv()).Do() + if err != nil { + t.Fatalf("Error getting project with id %q: %s", project.ProjectId, err) + return false + } + + getPolicyRequest := &cloudresourcemanager.GetIamPolicyRequest{} + policy, err := client.Projects.GetIamPolicy(project.ProjectId, getPolicyRequest).Do() + if err != nil { + t.Fatalf("Error getting project iam policy: %v", err) + return false + } + + var members []string + for _, agentName := range agentNames { + member := fmt.Sprintf("serviceAccount:service-%d@%s.iam.gserviceaccount.com", project.ProjectNumber, agentName) + members = append(members, member) + } + + // Create the bindings we need to add to the policy. + var newBindings []*cloudresourcemanager.Binding + for _, role := range roles { + newBindings = append(newBindings, &cloudresourcemanager.Binding{ + Role: role, + Members: members, + }) + } + + mergedBindings := mergeBindings(append(policy.Bindings, newBindings...)) + + if !compareBindings(policy.Bindings, mergedBindings) { + // The policy must change. + setPolicyRequest := &cloudresourcemanager.SetIamPolicyRequest{Policy: policy} + policy, err = client.Projects.SetIamPolicy(project.ProjectId, setPolicyRequest).Do() + if err != nil { + t.Fatalf("Error setting project iam policy: %v", err) + return false + } + return true + } + + return false +} + +// BootstrapAllPSARole is a version of BootstrapAllPSARoles for granting a +// single role to multiple service agents. +func BootstrapAllPSARole(t *testing.T, agentNames []string, role string) bool { + return BootstrapAllPSARoles(t, agentNames, []string{role}) +} + +// BootstrapPSARoles is a version of BootstrapAllPSARoles for granting roles to +// a single service agent. +func BootstrapPSARoles(t *testing.T, agentName string, roles []string) bool { + return BootstrapAllPSARoles(t, []string{agentName}, roles) +} + +// BootstrapPSARole is a simplified version of BootstrapPSARoles for granting a +// single role to a single service agent. +func BootstrapPSARole(t *testing.T, agentName, role string) bool { + return BootstrapPSARoles(t, agentName, []string{role}) +} + func BootstrapConfig(t *testing.T) *Config { if v := os.Getenv("TF_ACC"); v == "" { t.Skip("Acceptance tests and bootstrapping skipped unless env 'TF_ACC' set") diff --git a/google-beta/resource_healthcare_dicom_store_generated_test.go b/google-beta/resource_healthcare_dicom_store_generated_test.go index a3dcb4444e..379f125dec 100644 --- a/google-beta/resource_healthcare_dicom_store_generated_test.go +++ b/google-beta/resource_healthcare_dicom_store_generated_test.go @@ -78,6 +78,7 @@ func TestAccHealthcareDicomStore_healthcareDicomStoreBqStreamExample(t *testing. t.Parallel() context := map[string]interface{}{ + "policyChanged": BootstrapPSARoles(t, "gsp-sa-healthcare", []string{"roles/bigquery.dataEditor", "roles/bigquery.jobUser"}), "random_suffix": randString(t, 10), } diff --git a/google-beta/resource_healthcare_fhir_store_generated_test.go b/google-beta/resource_healthcare_fhir_store_generated_test.go index 6a083b0aa3..720c4a700e 100644 --- a/google-beta/resource_healthcare_fhir_store_generated_test.go +++ b/google-beta/resource_healthcare_fhir_store_generated_test.go @@ -84,6 +84,7 @@ func TestAccHealthcareFhirStore_healthcareFhirStoreStreamingConfigExample(t *tes t.Parallel() context := map[string]interface{}{ + "policyChanged": BootstrapPSARoles(t, "gsp-sa-healthcare", []string{"roles/bigquery.dataEditor", "roles/bigquery.jobUser"}), "random_suffix": randString(t, 10), } @@ -130,25 +131,6 @@ resource "google_healthcare_fhir_store" "default" { } } } - - depends_on = [ - google_project_iam_member.bigquery_editor, - google_project_iam_member.bigquery_job_user - ] -} - -data "google_project" "project" {} - -resource "google_project_iam_member" "bigquery_editor" { - project = data.google_project.project.project_id - role = "roles/bigquery.dataEditor" - member = "serviceAccount:service-${data.google_project.project.number}@gcp-sa-healthcare.iam.gserviceaccount.com" -} - -resource "google_project_iam_member" "bigquery_job_user" { - project = data.google_project.project.project_id - role = "roles/bigquery.jobUser" - member = "serviceAccount:service-${data.google_project.project.number}@gcp-sa-healthcare.iam.gserviceaccount.com" } resource "google_pubsub_topic" "topic" { diff --git a/website/docs/r/healthcare_fhir_store.html.markdown b/website/docs/r/healthcare_fhir_store.html.markdown index 81d3ef1462..ccf11a73c4 100644 --- a/website/docs/r/healthcare_fhir_store.html.markdown +++ b/website/docs/r/healthcare_fhir_store.html.markdown @@ -98,25 +98,6 @@ resource "google_healthcare_fhir_store" "default" { } } } - - depends_on = [ - google_project_iam_member.bigquery_editor, - google_project_iam_member.bigquery_job_user - ] -} - -data "google_project" "project" {} - -resource "google_project_iam_member" "bigquery_editor" { - project = data.google_project.project.project_id - role = "roles/bigquery.dataEditor" - member = "serviceAccount:service-${data.google_project.project.number}@gcp-sa-healthcare.iam.gserviceaccount.com" -} - -resource "google_project_iam_member" "bigquery_job_user" { - project = data.google_project.project.project_id - role = "roles/bigquery.jobUser" - member = "serviceAccount:service-${data.google_project.project.number}@gcp-sa-healthcare.iam.gserviceaccount.com" } resource "google_pubsub_topic" "topic" {