diff --git a/fast/stages/0-bootstrap/IAM.md b/fast/stages/0-bootstrap/IAM.md
index b938c44f18..b2d6d277a5 100644
--- a/fast/stages/0-bootstrap/IAM.md
+++ b/fast/stages/0-bootstrap/IAM.md
@@ -7,24 +7,24 @@ Legend: +
additive, •
conditional.
| members | roles |
|---|---|
|GCP organization domain
domain|[roles/browser](https://cloud.google.com/iam/docs/understanding-roles#browser) |
-|gcp-billing-admins
group|[roles/billing.admin](https://cloud.google.com/iam/docs/understanding-roles#billing.admin) +
[roles/billing.costsManager](https://cloud.google.com/iam/docs/understanding-roles#billing.costsManager) +
|
+|cloud-gong-hierarchy_management-hm_tool-latchkey-presubmits
group|[roles/browser](https://cloud.google.com/iam/docs/understanding-roles#browser) |
|gcp-devops
group|[roles/cloudsupport.techSupportEditor](https://cloud.google.com/iam/docs/understanding-roles#cloudsupport.techSupportEditor)
[roles/logging.viewer](https://cloud.google.com/iam/docs/understanding-roles#logging.viewer)
[roles/monitoring.viewer](https://cloud.google.com/iam/docs/understanding-roles#monitoring.viewer) |
|gcp-network-admins
group|[roles/cloudasset.owner](https://cloud.google.com/iam/docs/understanding-roles#cloudasset.owner)
[roles/cloudsupport.techSupportEditor](https://cloud.google.com/iam/docs/understanding-roles#cloudsupport.techSupportEditor)
[roles/compute.orgFirewallPolicyAdmin](https://cloud.google.com/iam/docs/understanding-roles#compute.orgFirewallPolicyAdmin) +
[roles/compute.xpnAdmin](https://cloud.google.com/iam/docs/understanding-roles#compute.xpnAdmin) +
|
-|gcp-organization-admins
group|[roles/cloudasset.owner](https://cloud.google.com/iam/docs/understanding-roles#cloudasset.owner)
[roles/cloudsupport.admin](https://cloud.google.com/iam/docs/understanding-roles#cloudsupport.admin)
[roles/compute.osAdminLogin](https://cloud.google.com/iam/docs/understanding-roles#compute.osAdminLogin)
[roles/compute.osLoginExternalUser](https://cloud.google.com/iam/docs/understanding-roles#compute.osLoginExternalUser)
[roles/owner](https://cloud.google.com/iam/docs/understanding-roles#owner)
[roles/resourcemanager.folderAdmin](https://cloud.google.com/iam/docs/understanding-roles#resourcemanager.folderAdmin)
[roles/resourcemanager.organizationAdmin](https://cloud.google.com/iam/docs/understanding-roles#resourcemanager.organizationAdmin)
[roles/resourcemanager.projectCreator](https://cloud.google.com/iam/docs/understanding-roles#resourcemanager.projectCreator)
[roles/billing.admin](https://cloud.google.com/iam/docs/understanding-roles#billing.admin) +
[roles/billing.costsManager](https://cloud.google.com/iam/docs/understanding-roles#billing.costsManager) +
[roles/orgpolicy.policyAdmin](https://cloud.google.com/iam/docs/understanding-roles#orgpolicy.policyAdmin) +
|
+|gcp-organization-admins
group|[roles/cloudasset.owner](https://cloud.google.com/iam/docs/understanding-roles#cloudasset.owner)
[roles/cloudsupport.admin](https://cloud.google.com/iam/docs/understanding-roles#cloudsupport.admin)
[roles/compute.osAdminLogin](https://cloud.google.com/iam/docs/understanding-roles#compute.osAdminLogin)
[roles/compute.osLoginExternalUser](https://cloud.google.com/iam/docs/understanding-roles#compute.osLoginExternalUser)
[roles/owner](https://cloud.google.com/iam/docs/understanding-roles#owner)
[roles/resourcemanager.folderAdmin](https://cloud.google.com/iam/docs/understanding-roles#resourcemanager.folderAdmin)
[roles/resourcemanager.organizationAdmin](https://cloud.google.com/iam/docs/understanding-roles#resourcemanager.organizationAdmin)
[roles/resourcemanager.projectCreator](https://cloud.google.com/iam/docs/understanding-roles#resourcemanager.projectCreator)
[roles/resourcemanager.tagAdmin](https://cloud.google.com/iam/docs/understanding-roles#resourcemanager.tagAdmin)
[roles/orgpolicy.policyAdmin](https://cloud.google.com/iam/docs/understanding-roles#orgpolicy.policyAdmin) +
[roles/compute.xpnAdmin](https://cloud.google.com/iam/docs/understanding-roles#compute.xpnAdmin) +
|
|gcp-security-admins
group|[roles/cloudasset.owner](https://cloud.google.com/iam/docs/understanding-roles#cloudasset.owner)
[roles/cloudsupport.techSupportEditor](https://cloud.google.com/iam/docs/understanding-roles#cloudsupport.techSupportEditor)
[roles/iam.securityReviewer](https://cloud.google.com/iam/docs/understanding-roles#iam.securityReviewer)
[roles/logging.admin](https://cloud.google.com/iam/docs/understanding-roles#logging.admin)
[roles/securitycenter.admin](https://cloud.google.com/iam/docs/understanding-roles#securitycenter.admin)
[roles/accesscontextmanager.policyAdmin](https://cloud.google.com/iam/docs/understanding-roles#accesscontextmanager.policyAdmin) +
[roles/iam.organizationRoleAdmin](https://cloud.google.com/iam/docs/understanding-roles#iam.organizationRoleAdmin) +
[roles/orgpolicy.policyAdmin](https://cloud.google.com/iam/docs/understanding-roles#orgpolicy.policyAdmin) +
|
-|prod-bootstrap-0
serviceAccount|[roles/logging.admin](https://cloud.google.com/iam/docs/understanding-roles#logging.admin)
[roles/resourcemanager.organizationAdmin](https://cloud.google.com/iam/docs/understanding-roles#resourcemanager.organizationAdmin)
[roles/resourcemanager.projectCreator](https://cloud.google.com/iam/docs/understanding-roles#resourcemanager.projectCreator)
[roles/resourcemanager.projectMover](https://cloud.google.com/iam/docs/understanding-roles#resourcemanager.projectMover)
[roles/billing.admin](https://cloud.google.com/iam/docs/understanding-roles#billing.admin) +
[roles/billing.costsManager](https://cloud.google.com/iam/docs/understanding-roles#billing.costsManager) +
[roles/iam.organizationRoleAdmin](https://cloud.google.com/iam/docs/understanding-roles#iam.organizationRoleAdmin) +
|
-|prod-resman-0
serviceAccount|organizations/[org_id #0]/roles/organizationIamAdmin •
[roles/resourcemanager.folderAdmin](https://cloud.google.com/iam/docs/understanding-roles#resourcemanager.folderAdmin)
[roles/resourcemanager.tagAdmin](https://cloud.google.com/iam/docs/understanding-roles#resourcemanager.tagAdmin)
[roles/resourcemanager.tagUser](https://cloud.google.com/iam/docs/understanding-roles#resourcemanager.tagUser)
[roles/billing.admin](https://cloud.google.com/iam/docs/understanding-roles#billing.admin) +
[roles/billing.costsManager](https://cloud.google.com/iam/docs/understanding-roles#billing.costsManager) +
[roles/orgpolicy.policyAdmin](https://cloud.google.com/iam/docs/understanding-roles#orgpolicy.policyAdmin) +
|
+|latchkey-multiorg-ephemeral-custom-automation
serviceAccount|[roles/iam.organizationRoleAdmin](https://cloud.google.com/iam/docs/understanding-roles#iam.organizationRoleAdmin) +
|
+|latchkey-multiorg-ephemeral-iam-automation
serviceAccount|[roles/resourcemanager.organizationAdmin](https://cloud.google.com/iam/docs/understanding-roles#resourcemanager.organizationAdmin) |
+|latchkey-multiorg-ephemeral-organization-automation
serviceAccount|[roles/browser](https://cloud.google.com/iam/docs/understanding-roles#browser) |
+|prod-bootstrap-0
serviceAccount|[roles/logging.admin](https://cloud.google.com/iam/docs/understanding-roles#logging.admin)
[roles/resourcemanager.organizationAdmin](https://cloud.google.com/iam/docs/understanding-roles#resourcemanager.organizationAdmin)
[roles/resourcemanager.projectCreator](https://cloud.google.com/iam/docs/understanding-roles#resourcemanager.projectCreator)
[roles/resourcemanager.projectMover](https://cloud.google.com/iam/docs/understanding-roles#resourcemanager.projectMover)
[roles/resourcemanager.tagAdmin](https://cloud.google.com/iam/docs/understanding-roles#resourcemanager.tagAdmin)
[roles/iam.organizationRoleAdmin](https://cloud.google.com/iam/docs/understanding-roles#iam.organizationRoleAdmin) +
[roles/orgpolicy.policyAdmin](https://cloud.google.com/iam/docs/understanding-roles#orgpolicy.policyAdmin) +
|
+|prod-resman-0
serviceAccount|[roles/logging.admin](https://cloud.google.com/iam/docs/understanding-roles#logging.admin)
[roles/resourcemanager.folderAdmin](https://cloud.google.com/iam/docs/understanding-roles#resourcemanager.folderAdmin)
[roles/resourcemanager.projectCreator](https://cloud.google.com/iam/docs/understanding-roles#resourcemanager.projectCreator)
[roles/resourcemanager.tagAdmin](https://cloud.google.com/iam/docs/understanding-roles#resourcemanager.tagAdmin)
[roles/resourcemanager.tagUser](https://cloud.google.com/iam/docs/understanding-roles#resourcemanager.tagUser)
organizations/[org_id #0]/roles/organizationIamAdmin •
[roles/orgpolicy.policyAdmin](https://cloud.google.com/iam/docs/understanding-roles#orgpolicy.policyAdmin) +
|
+|tf-cf-quota-monitor
serviceAccount|[roles/compute.viewer](https://cloud.google.com/iam/docs/understanding-roles#compute.viewer) |
## Project prod-audit-logs-0
| members | roles |
|---|---|
-|prod-bootstrap-0
serviceAccount|[roles/owner](https://cloud.google.com/iam/docs/understanding-roles#owner) |
-
-## Project prod-billing-exp-0
-
-| members | roles |
-|---|---|
+|o366118655033-148933
serviceAccount|[roles/logging.bucketWriter](https://cloud.google.com/iam/docs/understanding-roles#logging.bucketWriter) +
•
|
+|o366118655033-468879
serviceAccount|[roles/logging.bucketWriter](https://cloud.google.com/iam/docs/understanding-roles#logging.bucketWriter) +
•
|
|prod-bootstrap-0
serviceAccount|[roles/owner](https://cloud.google.com/iam/docs/understanding-roles#owner) |
## Project prod-iac-core-0
@@ -36,5 +36,5 @@ Legend: +
additive, •
conditional.
|SERVICE_IDENTITY_service-networking
serviceAccount|[roles/servicenetworking.serviceAgent](https://cloud.google.com/iam/docs/understanding-roles#servicenetworking.serviceAgent) +
|
|prod-bootstrap-0
serviceAccount|[roles/owner](https://cloud.google.com/iam/docs/understanding-roles#owner) |
|prod-bootstrap-1
serviceAccount|[roles/logging.logWriter](https://cloud.google.com/iam/docs/understanding-roles#logging.logWriter) +
|
-|prod-resman-0
serviceAccount|[roles/cloudbuild.builds.editor](https://cloud.google.com/iam/docs/understanding-roles#cloudbuild.builds.editor)
[roles/iam.serviceAccountAdmin](https://cloud.google.com/iam/docs/understanding-roles#iam.serviceAccountAdmin)
[roles/iam.workloadIdentityPoolAdmin](https://cloud.google.com/iam/docs/understanding-roles#iam.workloadIdentityPoolAdmin)
[roles/source.admin](https://cloud.google.com/iam/docs/understanding-roles#source.admin)
[roles/storage.admin](https://cloud.google.com/iam/docs/understanding-roles#storage.admin) |
+|prod-resman-0
serviceAccount|[roles/cloudbuild.builds.editor](https://cloud.google.com/iam/docs/understanding-roles#cloudbuild.builds.editor)
[roles/iam.serviceAccountAdmin](https://cloud.google.com/iam/docs/understanding-roles#iam.serviceAccountAdmin)
[roles/iam.workloadIdentityPoolAdmin](https://cloud.google.com/iam/docs/understanding-roles#iam.workloadIdentityPoolAdmin)
[roles/source.admin](https://cloud.google.com/iam/docs/understanding-roles#source.admin)
[roles/storage.admin](https://cloud.google.com/iam/docs/understanding-roles#storage.admin)
[roles/resourcemanager.projectIamAdmin](https://cloud.google.com/iam/docs/understanding-roles#resourcemanager.projectIamAdmin) •
[roles/serviceusage.serviceUsageConsumer](https://cloud.google.com/iam/docs/understanding-roles#serviceusage.serviceUsageConsumer) +
|
|prod-resman-1
serviceAccount|[roles/logging.logWriter](https://cloud.google.com/iam/docs/understanding-roles#logging.logWriter) +
|
diff --git a/fast/stages/0-bootstrap/automation.tf b/fast/stages/0-bootstrap/automation.tf
index d74e9efbf5..55ec56198b 100644
--- a/fast/stages/0-bootstrap/automation.tf
+++ b/fast/stages/0-bootstrap/automation.tf
@@ -60,6 +60,26 @@ module "automation-project" {
module.automation-tf-resman-sa.iam_email
]
}
+ iam_bindings = {
+ delegated_grants_resman = {
+ members = [module.automation-tf-resman-sa.iam_email]
+ role = "roles/resourcemanager.projectIamAdmin"
+ condition = {
+ title = "resman_delegated_grant"
+ description = "Resource manager service account delegated grant."
+ expression = format(
+ "api.getAttribute('iam.googleapis.com/modifiedGrantsByRole', []).hasOnly(['%s'])",
+ "roles/serviceusage.serviceUsageConsumer"
+ )
+ }
+ }
+ }
+ iam_bindings_additive = {
+ serviceusage_resman = {
+ member = module.automation-tf-resman-sa.iam_email
+ role = "roles/serviceusage.serviceUsageConsumer"
+ }
+ }
services = [
"accesscontextmanager.googleapis.com",
"bigquery.googleapis.com",
diff --git a/fast/stages/1-resman/IAM.md b/fast/stages/1-resman/IAM.md
index 403bd96cce..fd94019cdc 100644
--- a/fast/stages/1-resman/IAM.md
+++ b/fast/stages/1-resman/IAM.md
@@ -6,14 +6,11 @@ Legend: +
additive, •
conditional.
| members | roles |
|---|---|
-|dev-resman-dp-0
serviceAccount|[roles/orgpolicy.policyAdmin](https://cloud.google.com/iam/docs/understanding-roles#orgpolicy.policyAdmin) +
•
[roles/billing.user](https://cloud.google.com/iam/docs/understanding-roles#billing.user) +
|
-|dev-resman-gke-0
serviceAccount|[roles/billing.user](https://cloud.google.com/iam/docs/understanding-roles#billing.user) +
|
-|dev-resman-pf-0
serviceAccount|[roles/orgpolicy.policyAdmin](https://cloud.google.com/iam/docs/understanding-roles#orgpolicy.policyAdmin) +
•
[roles/billing.costsManager](https://cloud.google.com/iam/docs/understanding-roles#billing.costsManager) +
[roles/billing.user](https://cloud.google.com/iam/docs/understanding-roles#billing.user) +
|
-|prod-resman-dp-0
serviceAccount|[roles/orgpolicy.policyAdmin](https://cloud.google.com/iam/docs/understanding-roles#orgpolicy.policyAdmin) +
•
[roles/billing.user](https://cloud.google.com/iam/docs/understanding-roles#billing.user) +
|
-|prod-resman-gke-0
serviceAccount|[roles/billing.user](https://cloud.google.com/iam/docs/understanding-roles#billing.user) +
|
-|prod-resman-net-0
serviceAccount|[roles/billing.user](https://cloud.google.com/iam/docs/understanding-roles#billing.user) +
[roles/compute.orgFirewallPolicyAdmin](https://cloud.google.com/iam/docs/understanding-roles#compute.orgFirewallPolicyAdmin) +
[roles/compute.xpnAdmin](https://cloud.google.com/iam/docs/understanding-roles#compute.xpnAdmin) +
|
-|prod-resman-pf-0
serviceAccount|[roles/orgpolicy.policyAdmin](https://cloud.google.com/iam/docs/understanding-roles#orgpolicy.policyAdmin) +
•
[roles/billing.costsManager](https://cloud.google.com/iam/docs/understanding-roles#billing.costsManager) +
[roles/billing.user](https://cloud.google.com/iam/docs/understanding-roles#billing.user) +
|
-|prod-resman-sec-0
serviceAccount|[roles/accesscontextmanager.policyAdmin](https://cloud.google.com/iam/docs/understanding-roles#accesscontextmanager.policyAdmin) +
[roles/billing.user](https://cloud.google.com/iam/docs/understanding-roles#billing.user) +
|
+|egov-test-0
group|[roles/resourcemanager.organizationViewer](https://cloud.google.com/iam/docs/understanding-roles#resourcemanager.organizationViewer) +
|
+|dev-resman-pf-0
serviceAccount|[roles/orgpolicy.policyAdmin](https://cloud.google.com/iam/docs/understanding-roles#orgpolicy.policyAdmin) +
•
|
+|prod-resman-net-0
serviceAccount|[roles/compute.orgFirewallPolicyAdmin](https://cloud.google.com/iam/docs/understanding-roles#compute.orgFirewallPolicyAdmin) +
[roles/compute.xpnAdmin](https://cloud.google.com/iam/docs/understanding-roles#compute.xpnAdmin) +
|
+|prod-resman-pf-0
serviceAccount|[roles/orgpolicy.policyAdmin](https://cloud.google.com/iam/docs/understanding-roles#orgpolicy.policyAdmin) +
•
|
+|security-0
serviceAccount|[roles/accesscontextmanager.policyAdmin](https://cloud.google.com/iam/docs/understanding-roles#accesscontextmanager.policyAdmin) +
|
## Folder development [#0]
@@ -41,6 +38,29 @@ Legend: +
additive, •
conditional.
|---|---|
|dev-resman-pf-0
serviceAccount|organizations/[org_id #0]/roles/serviceProjectNetworkAdmin
[roles/logging.admin](https://cloud.google.com/iam/docs/understanding-roles#logging.admin)
[roles/owner](https://cloud.google.com/iam/docs/understanding-roles#owner)
[roles/resourcemanager.folderAdmin](https://cloud.google.com/iam/docs/understanding-roles#resourcemanager.folderAdmin)
[roles/resourcemanager.projectCreator](https://cloud.google.com/iam/docs/understanding-roles#resourcemanager.projectCreator) |
+## Folder egov test 0 - core [#1]
+
+| members | roles |
+|---|---|
+|egov-test-0
group|organizations/[org_id #0]/roles/tenantLoadBalancerAdmin
[roles/compute.instanceAdmin.v1](https://cloud.google.com/iam/docs/understanding-roles#compute.instanceAdmin.v1)
[roles/viewer](https://cloud.google.com/iam/docs/understanding-roles#viewer) |
+|egov-t0-iac-0
serviceAccount|organizations/[org_id #0]/roles/tenantLoadBalancerAdmin
[roles/compute.instanceAdmin.v1](https://cloud.google.com/iam/docs/understanding-roles#compute.instanceAdmin.v1)
[roles/viewer](https://cloud.google.com/iam/docs/understanding-roles#viewer) |
+|tn-egov-t0-0
serviceAccount|[roles/owner](https://cloud.google.com/iam/docs/understanding-roles#owner) |
+
+## Folder egov test 0 - tenant [#1]
+
+| members | roles |
+|---|---|
+|egov-test-0
group|[roles/cloudasset.owner](https://cloud.google.com/iam/docs/understanding-roles#cloudasset.owner)
[roles/compute.xpnAdmin](https://cloud.google.com/iam/docs/understanding-roles#compute.xpnAdmin)
[roles/owner](https://cloud.google.com/iam/docs/understanding-roles#owner)
[roles/resourcemanager.folderAdmin](https://cloud.google.com/iam/docs/understanding-roles#resourcemanager.folderAdmin)
[roles/resourcemanager.projectCreator](https://cloud.google.com/iam/docs/understanding-roles#resourcemanager.projectCreator)
[roles/resourcemanager.tagUser](https://cloud.google.com/iam/docs/understanding-roles#resourcemanager.tagUser) |
+|egov-t0-iac-0
serviceAccount|[roles/cloudasset.owner](https://cloud.google.com/iam/docs/understanding-roles#cloudasset.owner)
[roles/compute.xpnAdmin](https://cloud.google.com/iam/docs/understanding-roles#compute.xpnAdmin)
[roles/owner](https://cloud.google.com/iam/docs/understanding-roles#owner)
[roles/resourcemanager.folderAdmin](https://cloud.google.com/iam/docs/understanding-roles#resourcemanager.folderAdmin)
[roles/resourcemanager.projectCreator](https://cloud.google.com/iam/docs/understanding-roles#resourcemanager.projectCreator)
[roles/resourcemanager.tagUser](https://cloud.google.com/iam/docs/understanding-roles#resourcemanager.tagUser) |
+
+## Folder egov test 0 [#1]
+
+| members | roles |
+|---|---|
+|egov-test-0
group|[roles/logging.admin](https://cloud.google.com/iam/docs/understanding-roles#logging.admin)
[roles/monitoring.admin](https://cloud.google.com/iam/docs/understanding-roles#monitoring.admin)
[roles/resourcemanager.folderViewer](https://cloud.google.com/iam/docs/understanding-roles#resourcemanager.folderViewer)
[roles/browser](https://cloud.google.com/iam/docs/understanding-roles#browser) |
+|egov-t0-iac-0
serviceAccount|[roles/logging.admin](https://cloud.google.com/iam/docs/understanding-roles#logging.admin)
[roles/monitoring.admin](https://cloud.google.com/iam/docs/understanding-roles#monitoring.admin)
[roles/resourcemanager.folderViewer](https://cloud.google.com/iam/docs/understanding-roles#resourcemanager.folderViewer) |
+|tn-egov-t0-0
serviceAccount|[roles/cloudasset.owner](https://cloud.google.com/iam/docs/understanding-roles#cloudasset.owner)
[roles/compute.xpnAdmin](https://cloud.google.com/iam/docs/understanding-roles#compute.xpnAdmin)
[roles/resourcemanager.folderAdmin](https://cloud.google.com/iam/docs/understanding-roles#resourcemanager.folderAdmin)
[roles/resourcemanager.projectCreator](https://cloud.google.com/iam/docs/understanding-roles#resourcemanager.projectCreator)
[roles/resourcemanager.tagUser](https://cloud.google.com/iam/docs/understanding-roles#resourcemanager.tagUser) |
+
## Folder networking
| members | roles |
@@ -85,7 +105,13 @@ Legend: +
additive, •
conditional.
| members | roles |
|---|---|
|gcp-security-admins
group|[roles/viewer](https://cloud.google.com/iam/docs/understanding-roles#viewer) |
-|prod-resman-sec-0
serviceAccount|[roles/logging.admin](https://cloud.google.com/iam/docs/understanding-roles#logging.admin)
[roles/owner](https://cloud.google.com/iam/docs/understanding-roles#owner)
[roles/resourcemanager.folderAdmin](https://cloud.google.com/iam/docs/understanding-roles#resourcemanager.folderAdmin)
[roles/resourcemanager.projectCreator](https://cloud.google.com/iam/docs/understanding-roles#resourcemanager.projectCreator) |
+|security-0
serviceAccount|[roles/logging.admin](https://cloud.google.com/iam/docs/understanding-roles#logging.admin)
[roles/owner](https://cloud.google.com/iam/docs/understanding-roles#owner)
[roles/resourcemanager.folderAdmin](https://cloud.google.com/iam/docs/understanding-roles#resourcemanager.folderAdmin)
[roles/resourcemanager.projectCreator](https://cloud.google.com/iam/docs/understanding-roles#resourcemanager.projectCreator) |
+
+## Folder team 0
+
+| members | roles |
+|---|---|
+|prod-teams-team-0-0
serviceAccount|[roles/compute.xpnAdmin](https://cloud.google.com/iam/docs/understanding-roles#compute.xpnAdmin)
[roles/logging.admin](https://cloud.google.com/iam/docs/understanding-roles#logging.admin)
[roles/owner](https://cloud.google.com/iam/docs/understanding-roles#owner)
[roles/resourcemanager.folderAdmin](https://cloud.google.com/iam/docs/understanding-roles#resourcemanager.folderAdmin)
[roles/resourcemanager.projectCreator](https://cloud.google.com/iam/docs/understanding-roles#resourcemanager.projectCreator) |
## Folder teams
@@ -93,21 +119,26 @@ Legend: +
additive, •
conditional.
|---|---|
|prod-resman-teams-0
serviceAccount|[roles/compute.xpnAdmin](https://cloud.google.com/iam/docs/understanding-roles#compute.xpnAdmin)
[roles/logging.admin](https://cloud.google.com/iam/docs/understanding-roles#logging.admin)
[roles/owner](https://cloud.google.com/iam/docs/understanding-roles#owner)
[roles/resourcemanager.folderAdmin](https://cloud.google.com/iam/docs/understanding-roles#resourcemanager.folderAdmin)
[roles/resourcemanager.projectCreator](https://cloud.google.com/iam/docs/understanding-roles#resourcemanager.projectCreator) |
-## Folder teams test
+## Project egov-t0-iac-core-0
| members | roles |
|---|---|
-|prod-teams-teams-test-0
serviceAccount|[roles/compute.xpnAdmin](https://cloud.google.com/iam/docs/understanding-roles#compute.xpnAdmin)
[roles/logging.admin](https://cloud.google.com/iam/docs/understanding-roles#logging.admin)
[roles/owner](https://cloud.google.com/iam/docs/understanding-roles#owner)
[roles/resourcemanager.folderAdmin](https://cloud.google.com/iam/docs/understanding-roles#resourcemanager.folderAdmin)
[roles/resourcemanager.projectCreator](https://cloud.google.com/iam/docs/understanding-roles#resourcemanager.projectCreator) |
+|egov-test-0
group|[roles/iam.serviceAccountAdmin](https://cloud.google.com/iam/docs/understanding-roles#iam.serviceAccountAdmin)
[roles/iam.serviceAccountTokenCreator](https://cloud.google.com/iam/docs/understanding-roles#iam.serviceAccountTokenCreator)
[roles/iam.workloadIdentityPoolAdmin](https://cloud.google.com/iam/docs/understanding-roles#iam.workloadIdentityPoolAdmin) |
+|SERVICE_IDENTITY_service-networking
serviceAccount|[roles/servicenetworking.serviceAgent](https://cloud.google.com/iam/docs/understanding-roles#servicenetworking.serviceAgent) +
|
## Project prod-iac-core-0
| members | roles |
|---|---|
-|dev-pf-resman-pf-1
serviceAccount|[roles/logging.logWriter](https://cloud.google.com/iam/docs/understanding-roles#logging.logWriter) +
|
-|dev-resman-dp-1
serviceAccount|[roles/logging.logWriter](https://cloud.google.com/iam/docs/understanding-roles#logging.logWriter) +
|
-|dev-resman-gke-1
serviceAccount|[roles/logging.logWriter](https://cloud.google.com/iam/docs/understanding-roles#logging.logWriter) +
|
-|prod-pf-resman-pf-1
serviceAccount|[roles/logging.logWriter](https://cloud.google.com/iam/docs/understanding-roles#logging.logWriter) +
|
-|prod-resman-dp-1
serviceAccount|[roles/logging.logWriter](https://cloud.google.com/iam/docs/understanding-roles#logging.logWriter) +
|
-|prod-resman-gke-1
serviceAccount|[roles/logging.logWriter](https://cloud.google.com/iam/docs/understanding-roles#logging.logWriter) +
|
+|dev-resman-dp-0
serviceAccount|[roles/serviceusage.serviceUsageConsumer](https://cloud.google.com/iam/docs/understanding-roles#serviceusage.serviceUsageConsumer) +
|
+|dev-resman-gke-0
serviceAccount|[roles/serviceusage.serviceUsageConsumer](https://cloud.google.com/iam/docs/understanding-roles#serviceusage.serviceUsageConsumer) +
|
+|dev-resman-pf-0
serviceAccount|[roles/serviceusage.serviceUsageConsumer](https://cloud.google.com/iam/docs/understanding-roles#serviceusage.serviceUsageConsumer) +
|
+|dev-resman-sbox-0
serviceAccount|[roles/serviceusage.serviceUsageConsumer](https://cloud.google.com/iam/docs/understanding-roles#serviceusage.serviceUsageConsumer) +
|
+|prod-resman-gke-0
serviceAccount|[roles/serviceusage.serviceUsageConsumer](https://cloud.google.com/iam/docs/understanding-roles#serviceusage.serviceUsageConsumer) +
|
+|prod-resman-net-0
serviceAccount|[roles/serviceusage.serviceUsageConsumer](https://cloud.google.com/iam/docs/understanding-roles#serviceusage.serviceUsageConsumer) +
|
|prod-resman-net-1
serviceAccount|[roles/logging.logWriter](https://cloud.google.com/iam/docs/understanding-roles#logging.logWriter) +
|
+|prod-resman-pf-0
serviceAccount|[roles/serviceusage.serviceUsageConsumer](https://cloud.google.com/iam/docs/understanding-roles#serviceusage.serviceUsageConsumer) +
|
|prod-resman-sec-1
serviceAccount|[roles/logging.logWriter](https://cloud.google.com/iam/docs/understanding-roles#logging.logWriter) +
|
+|prod-resman-teams-0
serviceAccount|[roles/serviceusage.serviceUsageConsumer](https://cloud.google.com/iam/docs/understanding-roles#serviceusage.serviceUsageConsumer) +
|
+|security-0
serviceAccount|[roles/serviceusage.serviceUsageConsumer](https://cloud.google.com/iam/docs/understanding-roles#serviceusage.serviceUsageConsumer) +
|
+|tn-egov-t0-0
serviceAccount|[roles/serviceusage.serviceUsageConsumer](https://cloud.google.com/iam/docs/understanding-roles#serviceusage.serviceUsageConsumer) +
|
diff --git a/fast/stages/1-resman/branch-data-platform.tf b/fast/stages/1-resman/branch-data-platform.tf
index 219c3c655b..635522cff1 100644
--- a/fast/stages/1-resman/branch-data-platform.tf
+++ b/fast/stages/1-resman/branch-data-platform.tf
@@ -88,6 +88,9 @@ module "branch-dp-dev-sa" {
try(module.branch-dp-dev-sa-cicd.0.iam_email, null)
])
}
+ iam_project_roles = {
+ (var.automation.project_id) = ["roles/serviceusage.serviceUsageConsumer"]
+ }
iam_storage_roles = {
(var.automation.outputs_bucket) = ["roles/storage.objectAdmin"]
}
diff --git a/fast/stages/1-resman/branch-gke.tf b/fast/stages/1-resman/branch-gke.tf
index 791305f22a..3d46fec9d1 100644
--- a/fast/stages/1-resman/branch-gke.tf
+++ b/fast/stages/1-resman/branch-gke.tf
@@ -87,6 +87,9 @@ module "branch-gke-dev-sa" {
])
)
}
+ iam_project_roles = {
+ (var.automation.project_id) = ["roles/serviceusage.serviceUsageConsumer"]
+ }
iam_storage_roles = {
(var.automation.outputs_bucket) = ["roles/storage.objectAdmin"]
}
@@ -111,6 +114,9 @@ module "branch-gke-prod-sa" {
])
)
}
+ iam_project_roles = {
+ (var.automation.project_id) = ["roles/serviceusage.serviceUsageConsumer"]
+ }
iam_storage_roles = {
(var.automation.outputs_bucket) = ["roles/storage.objectAdmin"]
}
diff --git a/fast/stages/1-resman/branch-networking.tf b/fast/stages/1-resman/branch-networking.tf
index fe457569ab..e1379906e2 100644
--- a/fast/stages/1-resman/branch-networking.tf
+++ b/fast/stages/1-resman/branch-networking.tf
@@ -96,6 +96,9 @@ module "branch-network-sa" {
try(module.branch-network-sa-cicd.0.iam_email, null)
])
}
+ iam_project_roles = {
+ (var.automation.project_id) = ["roles/serviceusage.serviceUsageConsumer"]
+ }
iam_storage_roles = {
(var.automation.outputs_bucket) = ["roles/storage.objectAdmin"]
}
diff --git a/fast/stages/1-resman/branch-project-factory.tf b/fast/stages/1-resman/branch-project-factory.tf
index 7f2fbf28bd..6b708b27e1 100644
--- a/fast/stages/1-resman/branch-project-factory.tf
+++ b/fast/stages/1-resman/branch-project-factory.tf
@@ -29,6 +29,9 @@ module "branch-pf-dev-sa" {
try(module.branch-pf-dev-sa-cicd.0.iam_email, null)
])
}
+ iam_project_roles = {
+ (var.automation.project_id) = ["roles/serviceusage.serviceUsageConsumer"]
+ }
iam_storage_roles = {
(var.automation.outputs_bucket) = ["roles/storage.objectAdmin"]
}
@@ -47,6 +50,9 @@ module "branch-pf-prod-sa" {
try(module.branch-pf-prod-sa-cicd.0.iam_email, null)
])
}
+ iam_project_roles = {
+ (var.automation.project_id) = ["roles/serviceusage.serviceUsageConsumer"]
+ }
iam_storage_roles = {
(var.automation.outputs_bucket) = ["roles/storage.objectAdmin"]
}
diff --git a/fast/stages/1-resman/branch-sandbox.tf b/fast/stages/1-resman/branch-sandbox.tf
index 33eae4f001..3628df76b6 100644
--- a/fast/stages/1-resman/branch-sandbox.tf
+++ b/fast/stages/1-resman/branch-sandbox.tf
@@ -59,4 +59,7 @@ module "branch-sandbox-sa" {
name = "dev-resman-sbox-0"
display_name = "Terraform resman sandbox service account."
prefix = var.prefix
+ iam_project_roles = {
+ (var.automation.project_id) = ["roles/serviceusage.serviceUsageConsumer"]
+ }
}
diff --git a/fast/stages/1-resman/branch-security.tf b/fast/stages/1-resman/branch-security.tf
index 31a833dc5e..78c98aa076 100644
--- a/fast/stages/1-resman/branch-security.tf
+++ b/fast/stages/1-resman/branch-security.tf
@@ -60,9 +60,7 @@ module "branch-security-sa" {
])
}
iam_project_roles = {
- (var.automation.project_id) = [
- "roles/serviceusage.serviceUsageConsumer",
- ]
+ (var.automation.project_id) = ["roles/serviceusage.serviceUsageConsumer"]
}
iam_storage_roles = {
(var.automation.outputs_bucket) = ["roles/storage.objectAdmin"]
diff --git a/fast/stages/1-resman/branch-teams.tf b/fast/stages/1-resman/branch-teams.tf
index 9c9f539905..33026c8e02 100644
--- a/fast/stages/1-resman/branch-teams.tf
+++ b/fast/stages/1-resman/branch-teams.tf
@@ -46,6 +46,9 @@ module "branch-teams-sa" {
name = "prod-resman-teams-0"
display_name = "Terraform resman teams service account."
prefix = var.prefix
+ iam_project_roles = {
+ (var.automation.project_id) = ["roles/serviceusage.serviceUsageConsumer"]
+ }
iam_storage_roles = {
(var.automation.outputs_bucket) = ["roles/storage.objectAdmin"]
}
@@ -82,6 +85,8 @@ module "branch-teams-team-folder" {
group_iam = each.value.group_iam == null ? {} : each.value.group_iam
}
+# TODO: move into team's own IaC project
+
module "branch-teams-team-sa" {
source = "../../../modules/iam-service-account"
for_each = var.fast_features.teams ? coalesce(var.team_folders, {}) : {}
diff --git a/fast/stages/1-resman/branch-tenants.tf b/fast/stages/1-resman/branch-tenants.tf
index 2bbafd7d1b..251c63c8ef 100644
--- a/fast/stages/1-resman/branch-tenants.tf
+++ b/fast/stages/1-resman/branch-tenants.tf
@@ -135,6 +135,9 @@ module "tenant-core-sa" {
name = "tn-${each.key}-0"
description = "Terraform service account for tenant ${each.key}."
prefix = var.prefix
+ iam_project_roles = {
+ (var.automation.project_id) = ["roles/serviceusage.serviceUsageConsumer"]
+ }
}
module "tenant-core-gcs" {
diff --git a/fast/stages/2-networking-a-peering/README.md b/fast/stages/2-networking-a-peering/README.md
index 05478d79c7..e0c9f9b254 100644
--- a/fast/stages/2-networking-a-peering/README.md
+++ b/fast/stages/2-networking-a-peering/README.md
@@ -376,8 +376,8 @@ DNS configurations are centralised in the `dns-*.tf` files. Spokes delegate DNS
| [outputs.tf](./outputs.tf) | Module outputs. | | google_storage_bucket_object
· local_file
|
| [peerings.tf](./peerings.tf) | None | net-vpc-peering
| |
| [regions.tf](./regions.tf) | Compute short names for regions. | | |
-| [spoke-dev.tf](./spoke-dev.tf) | Dev spoke VPC and related resources. | net-cloudnat
· net-vpc
· net-vpc-firewall
· project
| google_project_iam_binding
|
-| [spoke-prod.tf](./spoke-prod.tf) | Production spoke VPC and related resources. | net-cloudnat
· net-vpc
· net-vpc-firewall
· project
| google_project_iam_binding
|
+| [spoke-dev.tf](./spoke-dev.tf) | Dev spoke VPC and related resources. | net-cloudnat
· net-vpc
· net-vpc-firewall
· project
| |
+| [spoke-prod.tf](./spoke-prod.tf) | Production spoke VPC and related resources. | net-cloudnat
· net-vpc
· net-vpc-firewall
· project
| |
| [test-resources.tf](./test-resources.tf) | temporary instances for testing | compute-vm
| |
| [variables-peerings.tf](./variables-peerings.tf) | Peering related variables. | | |
| [variables.tf](./variables.tf) | Module variables. | | |
diff --git a/fast/stages/2-networking-a-peering/spoke-dev.tf b/fast/stages/2-networking-a-peering/spoke-dev.tf
index bfff002b41..898bb8506f 100644
--- a/fast/stages/2-networking-a-peering/spoke-dev.tf
+++ b/fast/stages/2-networking-a-peering/spoke-dev.tf
@@ -43,6 +43,26 @@ module "dev-spoke-project" {
try(local.service_accounts.project-factory-prod, null),
])
}
+ # allow specific service accounts to assign a set of roles
+ iam_bindings = {
+ sa_delegated_grants = {
+ role = "roles/resourcemanager.projectIamAdmin"
+ members = compact([
+ try(local.service_accounts.data-platform-dev, null),
+ try(local.service_accounts.project-factory-dev, null),
+ try(local.service_accounts.project-factory-prod, null),
+ try(local.service_accounts.gke-dev, null),
+ ])
+ condition = {
+ title = "dev_stage3_sa_delegated_grants"
+ description = "Development host project delegated grants."
+ expression = format(
+ "api.getAttribute('iam.googleapis.com/modifiedGrantsByRole', []).hasOnly([%s])",
+ join(",", formatlist("'%s'", local.stage3_sas_delegated_grants))
+ )
+ }
+ }
+ }
}
module "dev-spoke-vpc" {
@@ -84,23 +104,3 @@ module "dev-spoke-cloudnat" {
router_network = module.dev-spoke-vpc.name
logging_filter = "ERRORS_ONLY"
}
-
-# Create delegated grants for stage3 service accounts
-resource "google_project_iam_binding" "dev_spoke_project_iam_delegated" {
- project = module.dev-spoke-project.project_id
- role = "roles/resourcemanager.projectIamAdmin"
- members = compact([
- try(local.service_accounts.data-platform-dev, null),
- try(local.service_accounts.project-factory-dev, null),
- try(local.service_accounts.project-factory-prod, null),
- try(local.service_accounts.gke-dev, null),
- ])
- condition {
- title = "dev_stage3_sa_delegated_grants"
- description = "Development host project delegated grants."
- expression = format(
- "api.getAttribute('iam.googleapis.com/modifiedGrantsByRole', []).hasOnly([%s])",
- join(",", formatlist("'%s'", local.stage3_sas_delegated_grants))
- )
- }
-}
diff --git a/fast/stages/2-networking-a-peering/spoke-prod.tf b/fast/stages/2-networking-a-peering/spoke-prod.tf
index 505005bdb1..3226af61d8 100644
--- a/fast/stages/2-networking-a-peering/spoke-prod.tf
+++ b/fast/stages/2-networking-a-peering/spoke-prod.tf
@@ -42,6 +42,25 @@ module "prod-spoke-project" {
try(local.service_accounts.project-factory-prod, null),
])
}
+ # allow specific service accounts to assign a set of roles
+ iam_bindings = {
+ sa_delegated_grants = {
+ role = "roles/resourcemanager.projectIamAdmin"
+ members = compact([
+ try(local.service_accounts.data-platform-prod, null),
+ try(local.service_accounts.project-factory-prod, null),
+ try(local.service_accounts.gke-prod, null),
+ ])
+ condition = {
+ title = "prod_stage3_sa_delegated_grants"
+ description = "Production host project delegated grants."
+ expression = format(
+ "api.getAttribute('iam.googleapis.com/modifiedGrantsByRole', []).hasOnly([%s])",
+ join(",", formatlist("'%s'", local.stage3_sas_delegated_grants))
+ )
+ }
+ }
+ }
}
module "prod-spoke-vpc" {
@@ -83,22 +102,3 @@ module "prod-spoke-cloudnat" {
router_network = module.prod-spoke-vpc.name
logging_filter = "ERRORS_ONLY"
}
-
-# Create delegated grants for stage3 service accounts
-resource "google_project_iam_binding" "prod_spoke_project_iam_delegated" {
- project = module.prod-spoke-project.project_id
- role = "roles/resourcemanager.projectIamAdmin"
- members = compact([
- try(local.service_accounts.data-platform-prod, null),
- try(local.service_accounts.project-factory-prod, null),
- try(local.service_accounts.gke-prod, null),
- ])
- condition {
- title = "prod_stage3_sa_delegated_grants"
- description = "Production host project delegated grants."
- expression = format(
- "api.getAttribute('iam.googleapis.com/modifiedGrantsByRole', []).hasOnly([%s])",
- join(",", formatlist("'%s'", local.stage3_sas_delegated_grants))
- )
- }
-}
diff --git a/fast/stages/2-networking-b-vpn/README.md b/fast/stages/2-networking-b-vpn/README.md
index 4de2666eeb..68e9a2793b 100644
--- a/fast/stages/2-networking-b-vpn/README.md
+++ b/fast/stages/2-networking-b-vpn/README.md
@@ -397,8 +397,8 @@ DNS configurations are centralised in the `dns-*.tf` files. Spokes delegate DNS
| [monitoring.tf](./monitoring.tf) | Network monitoring dashboards. | | google_monitoring_dashboard
|
| [outputs.tf](./outputs.tf) | Module outputs. | | google_storage_bucket_object
· local_file
|
| [regions.tf](./regions.tf) | Compute short names for regions. | | |
-| [spoke-dev.tf](./spoke-dev.tf) | Dev spoke VPC and related resources. | net-cloudnat
· net-vpc
· net-vpc-firewall
· project
| google_project_iam_binding
|
-| [spoke-prod.tf](./spoke-prod.tf) | Production spoke VPC and related resources. | net-cloudnat
· net-vpc
· net-vpc-firewall
· project
| google_project_iam_binding
|
+| [spoke-dev.tf](./spoke-dev.tf) | Dev spoke VPC and related resources. | net-cloudnat
· net-vpc
· net-vpc-firewall
· project
| |
+| [spoke-prod.tf](./spoke-prod.tf) | Production spoke VPC and related resources. | net-cloudnat
· net-vpc
· net-vpc-firewall
· project
| |
| [test-resources.tf](./test-resources.tf) | temporary instances for testing | compute-vm
| |
| [variables-vpn.tf](./variables-vpn.tf) | None | | |
| [variables.tf](./variables.tf) | Module variables. | | |
diff --git a/fast/stages/2-networking-b-vpn/spoke-dev.tf b/fast/stages/2-networking-b-vpn/spoke-dev.tf
index bfff002b41..898bb8506f 100644
--- a/fast/stages/2-networking-b-vpn/spoke-dev.tf
+++ b/fast/stages/2-networking-b-vpn/spoke-dev.tf
@@ -43,6 +43,26 @@ module "dev-spoke-project" {
try(local.service_accounts.project-factory-prod, null),
])
}
+ # allow specific service accounts to assign a set of roles
+ iam_bindings = {
+ sa_delegated_grants = {
+ role = "roles/resourcemanager.projectIamAdmin"
+ members = compact([
+ try(local.service_accounts.data-platform-dev, null),
+ try(local.service_accounts.project-factory-dev, null),
+ try(local.service_accounts.project-factory-prod, null),
+ try(local.service_accounts.gke-dev, null),
+ ])
+ condition = {
+ title = "dev_stage3_sa_delegated_grants"
+ description = "Development host project delegated grants."
+ expression = format(
+ "api.getAttribute('iam.googleapis.com/modifiedGrantsByRole', []).hasOnly([%s])",
+ join(",", formatlist("'%s'", local.stage3_sas_delegated_grants))
+ )
+ }
+ }
+ }
}
module "dev-spoke-vpc" {
@@ -84,23 +104,3 @@ module "dev-spoke-cloudnat" {
router_network = module.dev-spoke-vpc.name
logging_filter = "ERRORS_ONLY"
}
-
-# Create delegated grants for stage3 service accounts
-resource "google_project_iam_binding" "dev_spoke_project_iam_delegated" {
- project = module.dev-spoke-project.project_id
- role = "roles/resourcemanager.projectIamAdmin"
- members = compact([
- try(local.service_accounts.data-platform-dev, null),
- try(local.service_accounts.project-factory-dev, null),
- try(local.service_accounts.project-factory-prod, null),
- try(local.service_accounts.gke-dev, null),
- ])
- condition {
- title = "dev_stage3_sa_delegated_grants"
- description = "Development host project delegated grants."
- expression = format(
- "api.getAttribute('iam.googleapis.com/modifiedGrantsByRole', []).hasOnly([%s])",
- join(",", formatlist("'%s'", local.stage3_sas_delegated_grants))
- )
- }
-}
diff --git a/fast/stages/2-networking-b-vpn/spoke-prod.tf b/fast/stages/2-networking-b-vpn/spoke-prod.tf
index 505005bdb1..3226af61d8 100644
--- a/fast/stages/2-networking-b-vpn/spoke-prod.tf
+++ b/fast/stages/2-networking-b-vpn/spoke-prod.tf
@@ -42,6 +42,25 @@ module "prod-spoke-project" {
try(local.service_accounts.project-factory-prod, null),
])
}
+ # allow specific service accounts to assign a set of roles
+ iam_bindings = {
+ sa_delegated_grants = {
+ role = "roles/resourcemanager.projectIamAdmin"
+ members = compact([
+ try(local.service_accounts.data-platform-prod, null),
+ try(local.service_accounts.project-factory-prod, null),
+ try(local.service_accounts.gke-prod, null),
+ ])
+ condition = {
+ title = "prod_stage3_sa_delegated_grants"
+ description = "Production host project delegated grants."
+ expression = format(
+ "api.getAttribute('iam.googleapis.com/modifiedGrantsByRole', []).hasOnly([%s])",
+ join(",", formatlist("'%s'", local.stage3_sas_delegated_grants))
+ )
+ }
+ }
+ }
}
module "prod-spoke-vpc" {
@@ -83,22 +102,3 @@ module "prod-spoke-cloudnat" {
router_network = module.prod-spoke-vpc.name
logging_filter = "ERRORS_ONLY"
}
-
-# Create delegated grants for stage3 service accounts
-resource "google_project_iam_binding" "prod_spoke_project_iam_delegated" {
- project = module.prod-spoke-project.project_id
- role = "roles/resourcemanager.projectIamAdmin"
- members = compact([
- try(local.service_accounts.data-platform-prod, null),
- try(local.service_accounts.project-factory-prod, null),
- try(local.service_accounts.gke-prod, null),
- ])
- condition {
- title = "prod_stage3_sa_delegated_grants"
- description = "Production host project delegated grants."
- expression = format(
- "api.getAttribute('iam.googleapis.com/modifiedGrantsByRole', []).hasOnly([%s])",
- join(",", formatlist("'%s'", local.stage3_sas_delegated_grants))
- )
- }
-}
diff --git a/fast/stages/2-networking-c-nva/README.md b/fast/stages/2-networking-c-nva/README.md
index d61baf5713..daee38fc5f 100644
--- a/fast/stages/2-networking-c-nva/README.md
+++ b/fast/stages/2-networking-c-nva/README.md
@@ -446,8 +446,8 @@ DNS configurations are centralised in the `dns-*.tf` files. Spokes delegate DNS
| [nva.tf](./nva.tf) | None | compute-mig
· compute-vm
· simple-nva
| |
| [outputs.tf](./outputs.tf) | Module outputs. | | google_storage_bucket_object
· local_file
|
| [regions.tf](./regions.tf) | Compute short names for regions. | | |
-| [spoke-dev.tf](./spoke-dev.tf) | Dev spoke VPC and related resources. | net-vpc
· net-vpc-firewall
· net-vpc-peering
· project
| google_project_iam_binding
|
-| [spoke-prod.tf](./spoke-prod.tf) | Production spoke VPC and related resources. | net-vpc
· net-vpc-firewall
· net-vpc-peering
· project
| google_project_iam_binding
|
+| [spoke-dev.tf](./spoke-dev.tf) | Dev spoke VPC and related resources. | net-vpc
· net-vpc-firewall
· net-vpc-peering
· project
| |
+| [spoke-prod.tf](./spoke-prod.tf) | Production spoke VPC and related resources. | net-vpc
· net-vpc-firewall
· net-vpc-peering
· project
| |
| [test-resources.tf](./test-resources.tf) | temporary instances for testing | compute-vm
| |
| [variables.tf](./variables.tf) | Module variables. | | |
| [vpn-onprem.tf](./vpn-onprem.tf) | VPN between landing and onprem. | net-vpn-ha
| |
diff --git a/fast/stages/2-networking-c-nva/spoke-dev.tf b/fast/stages/2-networking-c-nva/spoke-dev.tf
index b90ed4dca7..98c4038b7c 100644
--- a/fast/stages/2-networking-c-nva/spoke-dev.tf
+++ b/fast/stages/2-networking-c-nva/spoke-dev.tf
@@ -42,6 +42,26 @@ module "dev-spoke-project" {
try(local.service_accounts.project-factory-prod, null),
])
}
+ # allow specific service accounts to assign a set of roles
+ iam_bindings = {
+ sa_delegated_grants = {
+ role = "roles/resourcemanager.projectIamAdmin"
+ members = compact([
+ try(local.service_accounts.data-platform-dev, null),
+ try(local.service_accounts.project-factory-dev, null),
+ try(local.service_accounts.project-factory-prod, null),
+ try(local.service_accounts.gke-dev, null),
+ ])
+ condition = {
+ title = "dev_stage3_sa_delegated_grants"
+ description = "Development host project delegated grants."
+ expression = format(
+ "api.getAttribute('iam.googleapis.com/modifiedGrantsByRole', []).hasOnly([%s])",
+ join(",", formatlist("'%s'", local.stage3_sas_delegated_grants))
+ )
+ }
+ }
+ }
}
module "dev-spoke-vpc" {
@@ -110,23 +130,3 @@ module "peering-dev" {
local_network = module.dev-spoke-vpc.self_link
peer_network = module.landing-trusted-vpc.self_link
}
-
-# Create delegated grants for stage3 service accounts
-resource "google_project_iam_binding" "dev_spoke_project_iam_delegated" {
- project = module.dev-spoke-project.project_id
- role = "roles/resourcemanager.projectIamAdmin"
- members = compact([
- try(local.service_accounts.data-platform-dev, null),
- try(local.service_accounts.project-factory-dev, null),
- try(local.service_accounts.project-factory-prod, null),
- try(local.service_accounts.gke-dev, null),
- ])
- condition {
- title = "dev_stage3_sa_delegated_grants"
- description = "Development host project delegated grants."
- expression = format(
- "api.getAttribute('iam.googleapis.com/modifiedGrantsByRole', []).hasOnly([%s])",
- join(",", formatlist("'%s'", local.stage3_sas_delegated_grants))
- )
- }
-}
diff --git a/fast/stages/2-networking-c-nva/spoke-prod.tf b/fast/stages/2-networking-c-nva/spoke-prod.tf
index a4bdb1d23c..91353c970f 100644
--- a/fast/stages/2-networking-c-nva/spoke-prod.tf
+++ b/fast/stages/2-networking-c-nva/spoke-prod.tf
@@ -41,6 +41,25 @@ module "prod-spoke-project" {
try(local.service_accounts.project-factory-prod, null),
])
}
+ # allow specific service accounts to assign a set of roles
+ iam_bindings = {
+ sa_delegated_grants = {
+ role = "roles/resourcemanager.projectIamAdmin"
+ members = compact([
+ try(local.service_accounts.data-platform-prod, null),
+ try(local.service_accounts.project-factory-prod, null),
+ try(local.service_accounts.gke-prod, null),
+ ])
+ condition = {
+ title = "prod_stage3_sa_delegated_grants"
+ description = "Production host project delegated grants."
+ expression = format(
+ "api.getAttribute('iam.googleapis.com/modifiedGrantsByRole', []).hasOnly([%s])",
+ join(",", formatlist("'%s'", local.stage3_sas_delegated_grants))
+ )
+ }
+ }
+ }
}
module "prod-spoke-vpc" {
@@ -109,22 +128,3 @@ module "peering-prod" {
local_network = module.prod-spoke-vpc.self_link
peer_network = module.landing-trusted-vpc.self_link
}
-
-# Create delegated grants for stage3 service accounts
-resource "google_project_iam_binding" "prod_spoke_project_iam_delegated" {
- project = module.prod-spoke-project.project_id
- role = "roles/resourcemanager.projectIamAdmin"
- members = compact([
- try(local.service_accounts.data-platform-prod, null),
- try(local.service_accounts.project-factory-prod, null),
- try(local.service_accounts.gke-prod, null),
- ])
- condition {
- title = "prod_stage3_sa_delegated_grants"
- description = "Production host project delegated grants."
- expression = format(
- "api.getAttribute('iam.googleapis.com/modifiedGrantsByRole', []).hasOnly([%s])",
- join(",", formatlist("'%s'", local.stage3_sas_delegated_grants))
- )
- }
-}
diff --git a/fast/stages/2-networking-d-separate-envs/README.md b/fast/stages/2-networking-d-separate-envs/README.md
index e84530e8cb..88f68846bb 100644
--- a/fast/stages/2-networking-d-separate-envs/README.md
+++ b/fast/stages/2-networking-d-separate-envs/README.md
@@ -320,8 +320,8 @@ Regions are defined via the `regions` variable which sets up a mapping between t
| [monitoring.tf](./monitoring.tf) | Network monitoring dashboards. | | google_monitoring_dashboard
|
| [outputs.tf](./outputs.tf) | Module outputs. | | google_storage_bucket_object
· local_file
|
| [regions.tf](./regions.tf) | Compute short names for regions. | | |
-| [spoke-dev.tf](./spoke-dev.tf) | Dev spoke VPC and related resources. | net-cloudnat
· net-vpc
· net-vpc-firewall
· project
| google_project_iam_binding
|
-| [spoke-prod.tf](./spoke-prod.tf) | Production spoke VPC and related resources. | net-cloudnat
· net-vpc
· net-vpc-firewall
· project
| google_project_iam_binding
|
+| [spoke-dev.tf](./spoke-dev.tf) | Dev spoke VPC and related resources. | net-cloudnat
· net-vpc
· net-vpc-firewall
· project
| |
+| [spoke-prod.tf](./spoke-prod.tf) | Production spoke VPC and related resources. | net-cloudnat
· net-vpc
· net-vpc-firewall
· project
| |
| [test-resources.tf](./test-resources.tf) | Temporary instances for testing | compute-vm
| |
| [variables.tf](./variables.tf) | Module variables. | | |
| [vpn-onprem.tf](./vpn-onprem.tf) | VPN between landing and onprem. | net-vpn-ha
| |
diff --git a/fast/stages/2-networking-d-separate-envs/spoke-dev.tf b/fast/stages/2-networking-d-separate-envs/spoke-dev.tf
index 61562f4483..5cd8c3552e 100644
--- a/fast/stages/2-networking-d-separate-envs/spoke-dev.tf
+++ b/fast/stages/2-networking-d-separate-envs/spoke-dev.tf
@@ -43,6 +43,26 @@ module "dev-spoke-project" {
try(local.service_accounts.project-factory-prod, null),
])
}
+ # allow specific service accounts to assign a set of roles
+ iam_bindings = {
+ sa_delegated_grants = {
+ role = "roles/resourcemanager.projectIamAdmin"
+ members = compact([
+ try(local.service_accounts.data-platform-dev, null),
+ try(local.service_accounts.project-factory-dev, null),
+ try(local.service_accounts.project-factory-prod, null),
+ try(local.service_accounts.gke-dev, null),
+ ])
+ condition = {
+ title = "dev_stage3_sa_delegated_grants"
+ description = "Development host project delegated grants."
+ expression = format(
+ "api.getAttribute('iam.googleapis.com/modifiedGrantsByRole', []).hasOnly([%s])",
+ join(",", formatlist("'%s'", local.stage3_sas_delegated_grants))
+ )
+ }
+ }
+ }
}
module "dev-spoke-vpc" {
@@ -84,23 +104,3 @@ module "dev-spoke-cloudnat" {
router_network = module.dev-spoke-vpc.name
logging_filter = "ERRORS_ONLY"
}
-
-# Create delegated grants for stage3 service accounts
-resource "google_project_iam_binding" "dev_spoke_project_iam_delegated" {
- project = module.dev-spoke-project.project_id
- role = "roles/resourcemanager.projectIamAdmin"
- members = compact([
- try(local.service_accounts.data-platform-dev, null),
- try(local.service_accounts.gke-dev, null),
- try(local.service_accounts.project-factory-dev, null),
- try(local.service_accounts.project-factory-prod, null),
- ])
- condition {
- title = "dev_stage3_sa_delegated_grants"
- description = "Development host project delegated grants."
- expression = format(
- "api.getAttribute('iam.googleapis.com/modifiedGrantsByRole', []).hasOnly([%s])",
- join(",", formatlist("'%s'", local.stage3_sas_delegated_grants))
- )
- }
-}
diff --git a/fast/stages/2-networking-d-separate-envs/spoke-prod.tf b/fast/stages/2-networking-d-separate-envs/spoke-prod.tf
index 7b42f54682..6889bb96d2 100644
--- a/fast/stages/2-networking-d-separate-envs/spoke-prod.tf
+++ b/fast/stages/2-networking-d-separate-envs/spoke-prod.tf
@@ -42,6 +42,25 @@ module "prod-spoke-project" {
try(local.service_accounts.project-factory-prod, null)
])
}
+ # allow specific service accounts to assign a set of roles
+ iam_bindings = {
+ sa_delegated_grants = {
+ role = "roles/resourcemanager.projectIamAdmin"
+ members = compact([
+ try(local.service_accounts.data-platform-prod, null),
+ try(local.service_accounts.project-factory-prod, null),
+ try(local.service_accounts.gke-prod, null),
+ ])
+ condition = {
+ title = "prod_stage3_sa_delegated_grants"
+ description = "Production host project delegated grants."
+ expression = format(
+ "api.getAttribute('iam.googleapis.com/modifiedGrantsByRole', []).hasOnly([%s])",
+ join(",", formatlist("'%s'", local.stage3_sas_delegated_grants))
+ )
+ }
+ }
+ }
}
module "prod-spoke-vpc" {
@@ -83,22 +102,3 @@ module "prod-spoke-cloudnat" {
router_network = module.prod-spoke-vpc.name
logging_filter = "ERRORS_ONLY"
}
-
-# Create delegated grants for stage3 service accounts
-resource "google_project_iam_binding" "prod_spoke_project_iam_delegated" {
- project = module.prod-spoke-project.project_id
- role = "roles/resourcemanager.projectIamAdmin"
- members = compact([
- try(local.service_accounts.data-platform-prod, null),
- try(local.service_accounts.gke-platform-prod, null),
- try(local.service_accounts.project-factory-prod, null),
- ])
- condition {
- title = "prod_stage3_sa_delegated_grants"
- description = "Production host project delegated grants."
- expression = format(
- "api.getAttribute('iam.googleapis.com/modifiedGrantsByRole', []).hasOnly([%s])",
- join(",", formatlist("'%s'", local.stage3_sas_delegated_grants))
- )
- }
-}
diff --git a/fast/stages/2-networking-e-nva-bgp/README.md b/fast/stages/2-networking-e-nva-bgp/README.md
index 4b3d6fad53..e9bf8c1026 100644
--- a/fast/stages/2-networking-e-nva-bgp/README.md
+++ b/fast/stages/2-networking-e-nva-bgp/README.md
@@ -472,8 +472,8 @@ DNS configurations are centralised in the `dns-*.tf` files. Spokes delegate DNS
| [nva.tf](./nva.tf) | None | compute-vm
· simple-nva
| google_compute_address
|
| [outputs.tf](./outputs.tf) | Module outputs. | | google_storage_bucket_object
· local_file
|
| [regions.tf](./regions.tf) | Compute short names for regions. | | |
-| [spoke-dev.tf](./spoke-dev.tf) | Dev spoke VPC and related resources. | net-vpc
· net-vpc-firewall
· net-vpc-peering
· project
| google_project_iam_binding
|
-| [spoke-prod.tf](./spoke-prod.tf) | Production spoke VPC and related resources. | net-vpc
· net-vpc-firewall
· net-vpc-peering
· project
| google_project_iam_binding
|
+| [spoke-dev.tf](./spoke-dev.tf) | Dev spoke VPC and related resources. | net-vpc
· net-vpc-firewall
· net-vpc-peering
· project
| |
+| [spoke-prod.tf](./spoke-prod.tf) | Production spoke VPC and related resources. | net-vpc
· net-vpc-firewall
· net-vpc-peering
· project
| |
| [test-resources.tf](./test-resources.tf) | temporary instances for testing | compute-vm
| |
| [variables.tf](./variables.tf) | Module variables. | | |
| [vpn-onprem.tf](./vpn-onprem.tf) | VPN between landing and onprem. | net-vpn-ha
| |
diff --git a/fast/stages/2-networking-e-nva-bgp/spoke-dev.tf b/fast/stages/2-networking-e-nva-bgp/spoke-dev.tf
index 56b65e3999..92a4a21f7a 100644
--- a/fast/stages/2-networking-e-nva-bgp/spoke-dev.tf
+++ b/fast/stages/2-networking-e-nva-bgp/spoke-dev.tf
@@ -42,6 +42,26 @@ module "dev-spoke-project" {
try(local.service_accounts.project-factory-prod, null),
])
}
+ # allow specific service accounts to assign a set of roles
+ iam_bindings = {
+ sa_delegated_grants = {
+ role = "roles/resourcemanager.projectIamAdmin"
+ members = compact([
+ try(local.service_accounts.data-platform-dev, null),
+ try(local.service_accounts.project-factory-dev, null),
+ try(local.service_accounts.project-factory-prod, null),
+ try(local.service_accounts.gke-dev, null),
+ ])
+ condition = {
+ title = "dev_stage3_sa_delegated_grants"
+ description = "Development host project delegated grants."
+ expression = format(
+ "api.getAttribute('iam.googleapis.com/modifiedGrantsByRole', []).hasOnly([%s])",
+ join(",", formatlist("'%s'", local.stage3_sas_delegated_grants))
+ )
+ }
+ }
+ }
}
module "dev-spoke-vpc" {
@@ -80,23 +100,3 @@ module "peering-dev" {
local_network = module.dev-spoke-vpc.self_link
peer_network = module.landing-trusted-vpc.self_link
}
-
-# Create delegated grants for stage3 service accounts
-resource "google_project_iam_binding" "dev_spoke_project_iam_delegated" {
- project = module.dev-spoke-project.project_id
- role = "roles/resourcemanager.projectIamAdmin"
- members = compact([
- try(local.service_accounts.data-platform-dev, null),
- try(local.service_accounts.project-factory-dev, null),
- try(local.service_accounts.project-factory-prod, null),
- try(local.service_accounts.gke-dev, null),
- ])
- condition {
- title = "dev_stage3_sa_delegated_grants"
- description = "Development host project delegated grants."
- expression = format(
- "api.getAttribute('iam.googleapis.com/modifiedGrantsByRole', []).hasOnly([%s])",
- join(",", formatlist("'%s'", local.stage3_sas_delegated_grants))
- )
- }
-}
diff --git a/fast/stages/2-networking-e-nva-bgp/spoke-prod.tf b/fast/stages/2-networking-e-nva-bgp/spoke-prod.tf
index 6ae49dee98..b5bff393f8 100644
--- a/fast/stages/2-networking-e-nva-bgp/spoke-prod.tf
+++ b/fast/stages/2-networking-e-nva-bgp/spoke-prod.tf
@@ -41,6 +41,25 @@ module "prod-spoke-project" {
try(local.service_accounts.project-factory-prod, null),
])
}
+ # allow specific service accounts to assign a set of roles
+ iam_bindings = {
+ sa_delegated_grants = {
+ role = "roles/resourcemanager.projectIamAdmin"
+ members = compact([
+ try(local.service_accounts.data-platform-prod, null),
+ try(local.service_accounts.project-factory-prod, null),
+ try(local.service_accounts.gke-prod, null),
+ ])
+ condition = {
+ title = "prod_stage3_sa_delegated_grants"
+ description = "Production host project delegated grants."
+ expression = format(
+ "api.getAttribute('iam.googleapis.com/modifiedGrantsByRole', []).hasOnly([%s])",
+ join(",", formatlist("'%s'", local.stage3_sas_delegated_grants))
+ )
+ }
+ }
+ }
}
module "prod-spoke-vpc" {
@@ -79,22 +98,3 @@ module "peering-prod" {
local_network = module.prod-spoke-vpc.self_link
peer_network = module.landing-trusted-vpc.self_link
}
-
-# Create delegated grants for stage3 service accounts
-resource "google_project_iam_binding" "prod_spoke_project_iam_delegated" {
- project = module.prod-spoke-project.project_id
- role = "roles/resourcemanager.projectIamAdmin"
- members = compact([
- try(local.service_accounts.data-platform-prod, null),
- try(local.service_accounts.project-factory-prod, null),
- try(local.service_accounts.gke-prod, null),
- ])
- condition {
- title = "prod_stage3_sa_delegated_grants"
- description = "Production host project delegated grants."
- expression = format(
- "api.getAttribute('iam.googleapis.com/modifiedGrantsByRole', []).hasOnly([%s])",
- join(",", formatlist("'%s'", local.stage3_sas_delegated_grants))
- )
- }
-}
diff --git a/tests/fast/stages/s0_bootstrap/simple.yaml b/tests/fast/stages/s0_bootstrap/simple.yaml
index 0afb9d02c6..70ad130a43 100644
--- a/tests/fast/stages/s0_bootstrap/simple.yaml
+++ b/tests/fast/stages/s0_bootstrap/simple.yaml
@@ -20,8 +20,8 @@ counts:
google_organization_iam_custom_role: 3
google_organization_iam_member: 13
google_project: 3
- google_project_iam_binding: 9
- google_project_iam_member: 3
+ google_project_iam_binding: 10
+ google_project_iam_member: 4
google_project_service: 29
google_project_service_identity: 3
google_service_account: 2