Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Bootstrapping PSA Roles for Healthcare #5277

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .changelog/7376.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
```release-note:none

```
76 changes: 76 additions & 0 deletions google-beta/bootstrap_utils_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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),
}

Expand Down
20 changes: 1 addition & 19 deletions google-beta/resource_healthcare_fhir_store_generated_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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),
}

Expand Down Expand Up @@ -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" {
Expand Down
19 changes: 0 additions & 19 deletions website/docs/r/healthcare_fhir_store.html.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -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" {
Expand Down