Skip to content

Commit fc46920

Browse files
kunalkg11Kunal Kumar Gupta
andauthored
feat: Add helper for assigning members to custom roles (#102)
* Added bindings for custom roles * Added org policy role in project setup * Added org admin role for setup * Changed from iam_binding to iam_member * Fixed service account domain * Added members to custom role module Co-authored-by: Kunal Kumar Gupta <kunalkgupta@kunalkgupta-macbookpro3.roam.corp.google.com>
1 parent 64722cd commit fc46920

File tree

7 files changed

+95
-3
lines changed

7 files changed

+95
-3
lines changed

examples/custom_role_org/main.tf

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,4 +40,5 @@ module "custom-roles-org" {
4040
role_id = "iamDeleter_${random_id.rand_custom_id.hex}"
4141
permissions = ["iam.roles.list", "iam.roles.delete"]
4242
description = "This is an organization level custom role."
43+
members = ["group:test-gcp-org-admins@test.infra.cft.tips", "group:test-gcp-billing-admins@test.infra.cft.tips"]
4344
}

examples/custom_role_project/main.tf

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,4 +36,18 @@ module "custom-role-project" {
3636
role_id = "iamDeleter"
3737
permissions = ["iam.roles.list", "iam.roles.delete"]
3838
description = "This is a project level custom role."
39+
members = ["serviceAccount:custom-role-account-01@${var.project_id}.iam.gserviceaccount.com", "serviceAccount:custom-role-account-02@${var.project_id}.iam.gserviceaccount.com"]
40+
}
41+
42+
/******************************************
43+
Create service accounts to use as members
44+
*****************************************/
45+
resource "google_service_account" "custom_role_account_01" {
46+
account_id = "custom-role-account-01"
47+
project = var.project_id
48+
}
49+
50+
resource "google_service_account" "custom_role_account_02" {
51+
account_id = "custom-role-account-02"
52+
project = var.project_id
3953
}

modules/custom_role_iam/README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ module "custom-roles" {
1414
title = "Custom Role Unique Title"
1515
description = "Custom Role Description"
1616
permissions = ["iam.roles.list", "iam.roles.create", "iam.roles.delete"]
17+
members = ["user:user01@domain.com", "group:group01@domain.com"]
1718
}
1819
```
1920

@@ -38,6 +39,7 @@ module "custom-roles" {
3839
| Name | Description | Type | Default | Required |
3940
|------|-------------|:----:|:-----:|:-----:|
4041
| description | Description of Custom role. | string | `""` | no |
42+
| members | List of members to be added to custom role. | list(string) | n/a | yes |
4143
| permissions | IAM permissions assigned to Custom Role. | list(string) | n/a | yes |
4244
| role\_id | ID of the Custom Role. | string | n/a | yes |
4345
| stage | The current launch stage of the role. Defaults to GA. | string | `"GA"` | no |

modules/custom_role_iam/main.tf

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,17 @@ resource "google_organization_iam_custom_role" "org-custom-role" {
3131
permissions = var.permissions
3232
}
3333

34+
/******************************************
35+
Assigning custom_role to member
36+
*****************************************/
37+
resource "google_organization_iam_member" "custom_role_member" {
38+
39+
for_each = var.target_level == "org" ? toset(var.members) : []
40+
org_id = var.target_id
41+
role = "organizations/${var.target_id}/roles/${local.custom-role-output}"
42+
member = each.key
43+
}
44+
3445
/******************************************
3546
Custom IAM Project Role
3647
*****************************************/
@@ -43,3 +54,14 @@ resource "google_project_iam_custom_role" "project-custom-role" {
4354
description = var.description
4455
permissions = var.permissions
4556
}
57+
58+
/******************************************
59+
Assigning custom_role to member
60+
*****************************************/
61+
resource "google_project_iam_member" "custom_role_member" {
62+
63+
for_each = var.target_level == "project" ? toset(var.members) : []
64+
project = var.target_id
65+
role = "projects/${var.target_id}/roles/${local.custom-role-output}"
66+
member = each.key
67+
}

modules/custom_role_iam/variables.tf

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,3 +52,8 @@ variable "target_level" {
5252
description = "String variable to denote if custom role being created is at project or organization level."
5353
default = "project"
5454
}
55+
56+
variable "members" {
57+
description = "List of members to be added to custom role."
58+
type = list(string)
59+
}

test/integration/custom-role/controls/custom-role.rb

Lines changed: 48 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@
3434
end
3535
end
3636

37-
describe "custom_role" do
37+
describe "project_custom_role" do
3838
it "have role" do
3939
expect(data["description"]).to include("This is a project level custom role.")
4040
expect(data["includedPermissions"]).to include("iam.roles.list")
@@ -55,12 +55,58 @@
5555
end
5656
end
5757

58-
describe "custom_role" do
58+
describe "organization_custom_role" do
5959
it "have role" do
6060
expect(data["description"]).to include("This is an organization level custom role.")
6161
expect(data["includedPermissions"]).to include("iam.roles.list")
6262
expect(data["includedPermissions"]).to include("iam.roles.delete")
6363
end
6464
end
6565
end
66+
67+
describe command ("gcloud projects get-iam-policy #{project_id} --format=json") do
68+
its(:exit_status) { should eq 0 }
69+
its(:stderr) { should eq '' }
70+
71+
let!(:data) do
72+
if subject.exit_status == 0
73+
JSON.parse(subject.stdout)
74+
else
75+
{}
76+
end
77+
end
78+
79+
describe "project_custom_role" do
80+
it "is bound to" do
81+
transformed_data={}
82+
data['bindings'].each do |binding|
83+
transformed_data.store(binding["role"],binding["members"])
84+
end
85+
expect(transformed_data["projects/#{project_id}/roles/#{custom_role_id_project}"]).to include("serviceAccount:custom-role-account-01@#{project_id}.iam.gserviceaccount.com")
86+
end
87+
end
88+
end
89+
90+
describe command ("gcloud organizations get-iam-policy #{org_id} --format=json") do
91+
its(:exit_status) { should eq 0 }
92+
its(:stderr) { should eq '' }
93+
94+
let!(:data) do
95+
if subject.exit_status == 0
96+
JSON.parse(subject.stdout)
97+
else
98+
{}
99+
end
100+
end
101+
102+
describe "organization_custom_role" do
103+
it "is bound to" do
104+
transformed_data={}
105+
data['bindings'].each do |binding|
106+
transformed_data.store(binding["role"],binding["members"])
107+
end
108+
expect(transformed_data["organizations/#{org_id}/roles/#{custom_role_id_org}"]).to include("group:test-gcp-org-admins@test.infra.cft.tips")
109+
end
110+
end
111+
end
66112
end

test/setup/iam.tf

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,9 @@
1616

1717
locals {
1818
int_required_org_roles = [
19-
"roles/iam.organizationRoleAdmin"
19+
"roles/iam.organizationRoleAdmin",
20+
"roles/orgpolicy.policyAdmin",
21+
"roles/resourcemanager.organizationAdmin",
2022
]
2123

2224
int_required_proj_roles = [

0 commit comments

Comments
 (0)