diff --git a/fast/addons/1-resman-tenants/README.md b/fast/addons/1-resman-tenants/README.md index d40422072..4a16731da 100644 --- a/fast/addons/1-resman-tenants/README.md +++ b/fast/addons/1-resman-tenants/README.md @@ -328,14 +328,14 @@ gcloud storage cp gs://{prefix}-{tenant-shortname}-prod-iac-core-0/tfvars/0-boot |---|---|:---:|:---:|:---:|:---:| | [automation](variables-fast.tf#L19) | Automation resources created by the bootstrap stage. | object({…}) | ✓ | | 0-bootstrap | | [billing_account](variables-fast.tf#L42) | Billing account id. If billing account is not part of the same org set `is_org_level` to `false`. To disable handling of billing IAM roles set `no_iam` to `true`. | object({…}) | ✓ | | 0-bootstrap | -| [environments](variables-fast.tf#L69) | Environment names. | map(object({…})) | ✓ | | 0-globals | -| [logging](variables-fast.tf#L115) | Logging resources created by the bootstrap stage. | object({…}) | ✓ | | 0-bootstrap | -| [org_policy_tags](variables-fast.tf#L134) | Organization policy tags. | object({…}) | ✓ | | 0-bootstrap | -| [organization](variables-fast.tf#L124) | Organization details. | object({…}) | ✓ | | 0-bootstrap | -| [prefix](variables-fast.tf#L151) | Prefix used for resources that need unique names. Use 9 characters or less. | string | ✓ | | 0-bootstrap | -| [custom_roles](variables-fast.tf#L53) | Custom roles defined at the org level, in key => id format. | object({…}) | | null | 0-bootstrap | -| [groups](variables-fast.tf#L87) | Group names or IAM-format principals to grant organization-level permissions. If just the name is provided, the 'group:' principal and organization domain are interpolated. | object({…}) | | {} | 0-bootstrap | -| [locations](variables-fast.tf#L102) | Optional locations for GCS, BigQuery, and logging buckets created here. | object({…}) | | {} | 0-bootstrap | +| [environments](variables-fast.tf#L75) | Environment names. | map(object({…})) | ✓ | | 0-globals | +| [logging](variables-fast.tf#L121) | Logging resources created by the bootstrap stage. | object({…}) | ✓ | | 0-bootstrap | +| [org_policy_tags](variables-fast.tf#L140) | Organization policy tags. | object({…}) | ✓ | | 0-bootstrap | +| [organization](variables-fast.tf#L130) | Organization details. | object({…}) | ✓ | | 0-bootstrap | +| [prefix](variables-fast.tf#L157) | Prefix used for resources that need unique names. Use 9 characters or less. | string | ✓ | | 0-bootstrap | +| [custom_roles](variables-fast.tf#L53) | Custom roles defined at the org level, in key => id format. | object({…}) | | null | 0-bootstrap | +| [groups](variables-fast.tf#L93) | Group names or IAM-format principals to grant organization-level permissions. If just the name is provided, the 'group:' principal and organization domain are interpolated. | object({…}) | | {} | 0-bootstrap | +| [locations](variables-fast.tf#L108) | Optional locations for GCS, BigQuery, and logging buckets created here. | object({…}) | | {} | 0-bootstrap | | [names](variables.tf#L18) | Configuration for names used for resources and output files. | object({…}) | | {} | | | [outputs_location](variables.tf#L28) | Path where providers and tfvars files for the following stages are written. Leave empty to disable. | string | | null | | | [root_node](variables.tf#L34) | Root folder under which tenants are created, in folders/nnnn format. Defaults to the organization if null. | string | | null | | @@ -346,5 +346,5 @@ gcloud storage cp gs://{prefix}-{tenant-shortname}-prod-iac-core-0/tfvars/0-boot | name | description | sensitive | consumers | |---|---|:---:|---| -| [tenants](outputs.tf#L130) | Tenant base configuration. | | | +| [tenants](outputs.tf#L139) | Tenant base configuration. | | | diff --git a/fast/addons/1-resman-tenants/outputs.tf b/fast/addons/1-resman-tenants/outputs.tf index 71ec64f67..bb0c75d7b 100644 --- a/fast/addons/1-resman-tenants/outputs.tf +++ b/fast/addons/1-resman-tenants/outputs.tf @@ -71,9 +71,18 @@ locals { for k, v in local.fast_tenants : k => { billing_account = v.billing_account groups = v.principals - locations = v.locations - organization = v.organization - prefix = v.prefix + environments = { + for k, v in var.environments : k => { + is_default = v.is_default + key = k + name = v.name + short_name = v.short_name != null ? v.short_name : k + tag_name = v.tag_name != null ? v.tag_name : lower(v.name) + } + } + locations = v.locations + organization = v.organization + prefix = v.prefix } } tenant_tfvars = { diff --git a/fast/addons/1-resman-tenants/variables-fast.tf b/fast/addons/1-resman-tenants/variables-fast.tf index ed246957f..81c68ef2b 100644 --- a/fast/addons/1-resman-tenants/variables-fast.tf +++ b/fast/addons/1-resman-tenants/variables-fast.tf @@ -54,13 +54,19 @@ variable "custom_roles" { # tfdoc:variable:source 0-bootstrap description = "Custom roles defined at the org level, in key => id format." type = object({ - gcve_network_admin = string - network_firewall_policies_admin = string - ngfw_enterprise_admin = optional(string) - ngfw_enterprise_viewer = optional(string) + billing_viewer = string + dns_zone_binder = string + kms_key_encryption_admin = string + kms_key_viewer = string organization_admin_viewer = string + project_iam_viewer = string service_project_network_admin = string storage_viewer = string + gcve_network_admin = optional(string) + gcve_network_viewer = optional(string) + network_firewall_policies_admin = optional(string) + ngfw_enterprise_admin = optional(string) + ngfw_enterprise_viewer = optional(string) tenant_network_admin = string }) default = null diff --git a/fast/stages/1-resman/tenant-root.tf b/fast/stages/1-resman/tenant-root.tf index 38403ff54..bbb30a16a 100644 --- a/fast/stages/1-resman/tenant-root.tf +++ b/fast/stages/1-resman/tenant-root.tf @@ -20,7 +20,13 @@ module "root-folder" { id = var.root_node folder_create = false # additive bindings via delegated IAM grant set in stage 0 - iam_bindings_additive = local.iam_bindings_additive + iam_bindings_additive = { + for k, v in local.iam_bindings_additive : k => { + role = lookup(var.custom_roles, v.role, v.role) + member = lookup(local.principals_iam, v.member, v.member) + condition = lookup(v, "condition", null) + } + } logging_sinks = { for name, attrs in local.log_sinks : name => { bq_partitioned_table = attrs.type == "bigquery" diff --git a/tests/fast/addons/a1_resman_tenants/simple.tfvars b/tests/fast/addons/a1_resman_tenants/simple.tfvars index a1a588c70..4ccc1e002 100644 --- a/tests/fast/addons/a1_resman_tenants/simple.tfvars +++ b/tests/fast/addons/a1_resman_tenants/simple.tfvars @@ -15,10 +15,17 @@ billing_account = { } custom_roles = { # organization_iam_admin = "organizations/123456789012/roles/organizationIamAdmin", + billing_viewer = "organizations/123456789012/roles/billingViewer" + dns_zone_binder = "organizations/123456789012/roles/dnsZoneBinder" gcve_network_admin = "organizations/123456789012/roles/gcveNetworkAdmin" + gcve_network_viewer = "organizations/123456789012/roles/gcveNetworkViewer" + kms_key_encryption_admin = "organizations/123456789012/roles/kmsKeyEncryptionAdmin" + kms_key_viewer = "organizations/123456789012/roles/kmsKeyViewer" network_firewall_policies_admin = "organizations/123456789012/roles/networkFirewallPoliciesAdmin" ngfw_enterprise_admin = "organizations/123456789012/roles/ngfwEnterpriseAdmin" + ngfw_enterprise_viewer = "organizations/123456789012/roles/ngfwEnterpriseViewer" organization_admin_viewer = "organizations/123456789012/roles/organizationAdminViewer" + project_iam_viewer = "organizations/123456789012/roles/projectIamViewer" service_project_network_admin = "organizations/123456789012/roles/xpnServiceAdmin" storage_viewer = "organizations/123456789012/roles/storageViewer" tenant_network_admin = "organizations/123456789012/roles/tenantNetworkAdmin"