Skip to content

Commit

Permalink
feat: allow more than 1 cross project IAM binding per service account (
Browse files Browse the repository at this point in the history
  • Loading branch information
MXfive authored Aug 15, 2022
1 parent 6840f84 commit cde8d4a
Show file tree
Hide file tree
Showing 8 changed files with 16 additions and 24 deletions.
4 changes: 0 additions & 4 deletions examples/google_service_account_cross_project_test/inputs.tf
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,4 @@ variable "cross_project_iam_role_memberships" {
default = {}
description = "A map of GCP project IDs and an associated list of IAM roles to add a membership to."
type = map(list(string))
validation {
condition = length(var.cross_project_iam_role_memberships) < 2
error_message = "To maintain a cleaner security model, only one project is currently supported for cross-project role memberships."
}
}
8 changes: 0 additions & 8 deletions modules/google_service_account/inputs.tf
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,6 @@ variable "cross_project_iam_role_memberships" {
default = {}
description = "A map of GCP project IDs and an associated list of IAM roles to add a membership to."
type = map(list(string))
validation {
condition = length(var.cross_project_iam_role_memberships) < 2
error_message = "To maintain a cleaner security model, only one project is currently supported for cross-project role memberships."
}
}

variable "description" {
Expand All @@ -27,10 +23,6 @@ variable "folder_iam_role_memberships" {
default = {}
description = "A map of GCP folder IDs and an associated list of IAM roles to add a membership to."
type = map(list(string))
validation {
condition = length(var.folder_iam_role_memberships) < 2
error_message = "To maintain a cleaner security model, only one folder is currently supported for folder role memberships."
}
}

variable "iam_role_membership_type" {
Expand Down
2 changes: 1 addition & 1 deletion test/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ module github.com/honestbank/terraform-gcp-iam/v2
go 1.17

require (
cloud.google.com/go/storage v1.22.1
github.com/gruntwork-io/terratest v0.40.6
github.com/stretchr/testify v1.7.0
)
Expand All @@ -12,6 +11,7 @@ require (
cloud.google.com/go v0.102.0 // indirect
cloud.google.com/go/compute v1.6.1 // indirect
cloud.google.com/go/iam v0.3.0 // indirect
cloud.google.com/go/storage v1.22.1 // indirect
github.com/agext/levenshtein v1.2.3 // indirect
github.com/apparentlymart/go-textseg/v13 v13.0.0 // indirect
github.com/aws/aws-sdk-go v1.40.56 // indirect
Expand Down
2 changes: 1 addition & 1 deletion test/google_service_account_cross_project_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,6 @@ func TestGoogleServiceAccountCrossProjectMultipleProjects(t *testing.T) {

test_structure.RunTestStage(t, testCaseName+"_terraform_plan", func() {
_, planErr := terraform.PlanE(t, terraformOptions)
assert.NotNil(t, planErr, "plan should error when 2 external projects are specified")
assert.Nil(t, planErr, "plan should not error when 2 external projects are specified")
})
}
Original file line number Diff line number Diff line change
Expand Up @@ -104,10 +104,11 @@ func TestGoogleServiceAccountCrossProjectMultipleProjectsWithCondition(t *testin
run := strings.ToLower(random.UniqueId())

// [roles/iam.serviceAccountAdmin, roles/iam.serviceAccountKeyAdmin] required in this project
gcpServiceAccountHostProject := "test-terraform-project-01"
gcpServiceAccountHostProject := os.Getenv("GOOGLE_PROJECT")

// [roles/iam.securityAdmin] required in this project
gcpCrossProjectIamRoleMembershipProjectId := "storage-0994"
gcpCrossProjectIamRoleMembershipProjectId2 := "tf-shared-vpc-host-78a3"
gcpIndonesiaRegion := "asia-southeast2"

// GCP credentials will be sourced from this var. Do not use `GOOGLE_CREDENTIALS`
Expand Down Expand Up @@ -149,8 +150,8 @@ func TestGoogleServiceAccountCrossProjectMultipleProjectsWithCondition(t *testin
"iam_role_membership_type": "CROSS_PROJECT",
// Two projects should cause an error
"cross_project_iam_role_memberships": map[string][]string{
gcpCrossProjectIamRoleMembershipProjectId: {"roles/storage.objectViewer"},
"some-other-project": {"roles/storage.objectViewer"},
gcpCrossProjectIamRoleMembershipProjectId: {"roles/storage.objectViewer"},
gcpCrossProjectIamRoleMembershipProjectId2: {"roles/storage.objectViewer"},
},
"conditions": []map[string]string{
{
Expand All @@ -169,6 +170,6 @@ func TestGoogleServiceAccountCrossProjectMultipleProjectsWithCondition(t *testin

test_structure.RunTestStage(t, testCaseName+"_terraform_plan", func() {
_, planErr := terraform.PlanE(t, terraformOptions)
assert.NotNil(t, planErr, "plan should error when 2 external projects are specified")
assert.Nil(t, planErr, "plan should not error when 2 external projects are specified")
})
}
7 changes: 4 additions & 3 deletions test/google_service_account_folder_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,7 @@ func TestGoogleServiceAccountCrossProjectMultipleFolders(t *testing.T) {
// [roles/iam.securityAdmin] required on this folder
// 502911218937 is the folder titled `terraform automated testing`
folderIamRoleMembershipFolderId := "502911218937"
folderIamRoleMembershipFolderId2 := "1004506453476"
gcpIndonesiaRegion := "asia-southeast2"

// GCP credentials will be sourced from this var. Do not use `GOOGLE_CREDENTIALS`
Expand Down Expand Up @@ -145,8 +146,8 @@ func TestGoogleServiceAccountCrossProjectMultipleFolders(t *testing.T) {
"iam_role_membership_type": "FOLDER",
// Two folders should cause an error
"folder_iam_role_memberships": map[string][]string{
folderIamRoleMembershipFolderId: {"roles/viewer"},
"1234567890": {"roles/viewer"},
folderIamRoleMembershipFolderId: {"roles/viewer"},
folderIamRoleMembershipFolderId2: {"roles/viewer"},
},
},
})
Expand All @@ -158,6 +159,6 @@ func TestGoogleServiceAccountCrossProjectMultipleFolders(t *testing.T) {

test_structure.RunTestStage(t, testCaseName+"_terraform_plan", func() {
_, planErr := terraform.PlanE(t, terraformOptions)
assert.NotNil(t, planErr, "plan should error when 2 external projects are specified")
assert.Nil(t, planErr, "plan should not error when 2 external projects are specified")
})
}
7 changes: 4 additions & 3 deletions test/google_service_account_folder_with_condition_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,7 @@ func TestGoogleServiceAccountCrossProjectMultipleFoldersWithCondition(t *testing
// [roles/iam.securityAdmin] required on this folder
// 502911218937 is the folder titled `terraform automated testing`
folderIamRoleMembershipFolderId := "502911218937"
folderIamRoleMembershipFolderId2 := "1004506453476"
gcpIndonesiaRegion := "asia-southeast2"

// GCP credentials will be sourced from this var. Do not use `GOOGLE_CREDENTIALS`
Expand Down Expand Up @@ -152,8 +153,8 @@ func TestGoogleServiceAccountCrossProjectMultipleFoldersWithCondition(t *testing
"iam_role_membership_type": "FOLDER",
// Two folders should cause an error
"folder_iam_role_memberships": map[string][]string{
folderIamRoleMembershipFolderId: {"roles/storage.objectViewer"},
"1234567890": {"roles/storage.objectViewer"},
folderIamRoleMembershipFolderId: {"roles/storage.objectViewer"},
folderIamRoleMembershipFolderId2: {"roles/storage.objectViewer"},
},
"conditions": []map[string]string{
{
Expand All @@ -173,6 +174,6 @@ func TestGoogleServiceAccountCrossProjectMultipleFoldersWithCondition(t *testing

test_structure.RunTestStage(t, testCaseName+"_terraform_plan", func() {
_, planErr := terraform.PlanE(t, terraformOptions)
assert.NotNil(t, planErr, "plan should error when 2 external projects are specified")
assert.Nil(t, planErr, "plan should not error when 2 external projects are specified")
})
}
1 change: 1 addition & 0 deletions test/google_service_account_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ func TestGoogleServiceAccountInProject(t *testing.T) {
// Can be any project and region, need to source from env var
gcpProject := os.Getenv("GOOGLE_PROJECT")
gcpIndonesiaRegion := "asia-southeast2"
logger.Log(t, gcpProject)

// GCP credentials will be sourced from this var. Do not use `GOOGLE_CREDENTIALS`
// since we will be using that for validating Terraform-created credentials.
Expand Down

0 comments on commit cde8d4a

Please sign in to comment.