diff --git a/fast/stages/0-bootstrap/organization.tf b/fast/stages/0-bootstrap/organization.tf
index 946e3d7bb5..d9f622211b 100644
--- a/fast/stages/0-bootstrap/organization.tf
+++ b/fast/stages/0-bootstrap/organization.tf
@@ -88,8 +88,9 @@ module "organization" {
)
# delegated role grant for resource manager service account
iam_bindings = {
- (module.organization.custom_role_id[var.custom_role_names.organization_iam_admin]) = {
+ organization_iam_admin_conditional = {
members = [module.automation-tf-resman-sa.iam_email]
+ role = module.organization.custom_role_id[var.custom_role_names.organization_iam_admin]
condition = {
expression = format(
"api.getAttribute('iam.googleapis.com/modifiedGrantsByRole', []).hasOnly([%s])",
diff --git a/modules/__docs/20230816-iam-refactor.md b/modules/__docs/20230816-iam-refactor.md
index 438252ac18..a5ad33799b 100644
--- a/modules/__docs/20230816-iam-refactor.md
+++ b/modules/__docs/20230816-iam-refactor.md
@@ -6,6 +6,7 @@
## Status
Implemented in [#1595](https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/pull/1595).
+Authoritative bindings type changed as per [#1622](https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/issues/1622).
## Context
@@ -39,15 +40,18 @@ The new `iam_bindings` variable will look like this:
```hcl
variable "iam_bindings" {
- description = "Authoritative IAM bindings with support for conditions, in {ROLE => { members = [], condition = {}}} format."
+ description = "Authoritative IAM bindings in {KEY => {role = ROLE, members = [], condition = {}}}. Keys are arbitrary."
type = map(object({
- members = list(string)
+ members = list(string)
+ role = string
condition = optional(object({
expression = string
title = string
description = optional(string)
}))
}))
+ nullable = false
+ default = {}
}
```
diff --git a/modules/data-catalog-policy-tag/README.md b/modules/data-catalog-policy-tag/README.md
index b08a9feb64..8a46478426 100644
--- a/modules/data-catalog-policy-tag/README.md
+++ b/modules/data-catalog-policy-tag/README.md
@@ -79,17 +79,17 @@ module "cmn-dc" {
| name | description | type | required | default |
|---|---|:---:|:---:|:---:|
-| [name](variables.tf#L76) | Name of this taxonomy. | string
| ✓ | |
-| [project_id](variables.tf#L91) | GCP project id. |
| ✓ | |
+| [name](variables.tf#L77) | Name of this taxonomy. | string
| ✓ | |
+| [project_id](variables.tf#L92) | GCP project id. |
| ✓ | |
| [activated_policy_types](variables.tf#L17) | A list of policy types that are activated for this taxonomy. | list(string)
| | ["FINE_GRAINED_ACCESS_CONTROL"]
|
| [description](variables.tf#L23) | Description of this taxonomy. | string
| | "Taxonomy - Terraform managed"
|
| [group_iam](variables.tf#L29) | Authoritative IAM binding for organization groups, in {GROUP_EMAIL => [ROLES]} format. Group emails need to be static. Can be used in combination with the `iam` variable. | map(list(string))
| | {}
|
| [iam](variables.tf#L35) | IAM bindings in {ROLE => [MEMBERS]} format. | map(list(string))
| | {}
|
-| [iam_bindings](variables.tf#L41) | Authoritative IAM bindings in {ROLE => {members = [], condition = {}}}. | map(object({…}))
| | {}
|
-| [iam_bindings_additive](variables.tf#L55) | Individual additive IAM bindings. Keys are arbitrary. | map(object({…}))
| | {}
|
-| [location](variables.tf#L70) | Data Catalog Taxonomy location. | string
| | "eu"
|
-| [prefix](variables.tf#L81) | Optional prefix used to generate project id and name. | string
| | null
|
-| [tags](variables.tf#L95) | List of Data Catalog Policy tags to be created with optional IAM binging configuration in {tag => {ROLE => [MEMBERS]}} format. | map(object({…}))
| | {}
|
+| [iam_bindings](variables.tf#L41) | Authoritative IAM bindings in {KEY => {role = ROLE, members = [], condition = {}}}. Keys are arbitrary. | map(object({…}))
| | {}
|
+| [iam_bindings_additive](variables.tf#L56) | Individual additive IAM bindings. Keys are arbitrary. | map(object({…}))
| | {}
|
+| [location](variables.tf#L71) | Data Catalog Taxonomy location. | string
| | "eu"
|
+| [prefix](variables.tf#L82) | Optional prefix used to generate project id and name. | string
| | null
|
+| [tags](variables.tf#L96) | List of Data Catalog Policy tags to be created with optional IAM binging configuration in {tag => {ROLE => [MEMBERS]}} format. | map(object({…}))
| | {}
|
## Outputs
diff --git a/modules/data-catalog-policy-tag/iam.tf b/modules/data-catalog-policy-tag/iam.tf
index 268c0c58a9..06c307631e 100644
--- a/modules/data-catalog-policy-tag/iam.tf
+++ b/modules/data-catalog-policy-tag/iam.tf
@@ -53,7 +53,7 @@ resource "google_data_catalog_taxonomy_iam_binding" "bindings" {
provider = google-beta
for_each = var.iam_bindings
taxonomy = google_data_catalog_taxonomy.default.id
- role = each.key
+ role = each.value.role
members = each.value.members
dynamic "condition" {
for_each = each.value.condition == null ? [] : [""]
diff --git a/modules/data-catalog-policy-tag/variables.tf b/modules/data-catalog-policy-tag/variables.tf
index b0df313d82..0fef9e7bd7 100644
--- a/modules/data-catalog-policy-tag/variables.tf
+++ b/modules/data-catalog-policy-tag/variables.tf
@@ -39,9 +39,10 @@ variable "iam" {
}
variable "iam_bindings" {
- description = "Authoritative IAM bindings in {ROLE => {members = [], condition = {}}}."
+ description = "Authoritative IAM bindings in {KEY => {role = ROLE, members = [], condition = {}}}. Keys are arbitrary."
type = map(object({
members = list(string)
+ role = string
condition = optional(object({
expression = string
title = string
diff --git a/modules/dataplex-datascan/README.md b/modules/dataplex-datascan/README.md
index 1c950184e8..4116732f3d 100644
--- a/modules/dataplex-datascan/README.md
+++ b/modules/dataplex-datascan/README.md
@@ -431,9 +431,9 @@ module "dataplex-datascan" {
| name | description | type | required | default |
|---|---|:---:|:---:|:---:|
| [data](variables.tf#L17) | The data source for DataScan. The source can be either a Dataplex `entity` or a BigQuery `resource`. | object({…})
| ✓ | |
-| [name](variables.tf#L156) | Name of Dataplex Scan. | string
| ✓ | |
-| [project_id](variables.tf#L167) | The ID of the project where the Dataplex DataScan will be created. | string
| ✓ | |
-| [region](variables.tf#L172) | Region for the Dataplex DataScan. | string
| ✓ | |
+| [name](variables.tf#L157) | Name of Dataplex Scan. | string
| ✓ | |
+| [project_id](variables.tf#L168) | The ID of the project where the Dataplex DataScan will be created. | string
| ✓ | |
+| [region](variables.tf#L173) | Region for the Dataplex DataScan. | string
| ✓ | |
| [data_profile_spec](variables.tf#L29) | DataProfileScan related setting. Variable descriptions are provided in https://cloud.google.com/dataplex/docs/reference/rest/v1/DataProfileSpec. | object({…})
| | null
|
| [data_quality_spec](variables.tf#L38) | DataQualityScan related setting. Variable descriptions are provided in https://cloud.google.com/dataplex/docs/reference/rest/v1/DataQualitySpec. | object({…})
| | null
|
| [data_quality_spec_file](variables.tf#L80) | Path to a YAML file containing DataQualityScan related setting. Input content can use either camelCase or snake_case. Variables description are provided in https://cloud.google.com/dataplex/docs/reference/rest/v1/DataQualitySpec. | object({…})
| | null
|
@@ -441,11 +441,11 @@ module "dataplex-datascan" {
| [execution_schedule](variables.tf#L94) | Schedule DataScan to run periodically based on a cron schedule expression. If not specified, the DataScan is created with `on_demand` schedule, which means it will not run until the user calls `dataScans.run` API. | string
| | null
|
| [group_iam](variables.tf#L100) | Authoritative IAM binding for organization groups, in {GROUP_EMAIL => [ROLES]} format. Group emails need to be static. Can be used in combination with the `iam` variable. | map(list(string))
| | {}
|
| [iam](variables.tf#L107) | Dataplex DataScan IAM bindings in {ROLE => [MEMBERS]} format. | map(list(string))
| | {}
|
-| [iam_bindings](variables.tf#L114) | Authoritative IAM bindings in {ROLE => {members = [], condition = {}}}. | map(object({…}))
| | {}
|
-| [iam_bindings_additive](variables.tf#L128) | Individual additive IAM bindings. Keys are arbitrary. | map(object({…}))
| | {}
|
-| [incremental_field](variables.tf#L143) | The unnested field (of type Date or Timestamp) that contains values which monotonically increase over time. If not specified, a data scan will run for all data in the table. | string
| | null
|
-| [labels](variables.tf#L149) | Resource labels. | map(string)
| | {}
|
-| [prefix](variables.tf#L161) | Optional prefix used to generate Dataplex DataScan ID. | string
| | null
|
+| [iam_bindings](variables.tf#L114) | Authoritative IAM bindings in {KEY => {role = ROLE, members = [], condition = {}}}. Keys are arbitrary. | map(object({…}))
| | {}
|
+| [iam_bindings_additive](variables.tf#L129) | Individual additive IAM bindings. Keys are arbitrary. | map(object({…}))
| | {}
|
+| [incremental_field](variables.tf#L144) | The unnested field (of type Date or Timestamp) that contains values which monotonically increase over time. If not specified, a data scan will run for all data in the table. | string
| | null
|
+| [labels](variables.tf#L150) | Resource labels. | map(string)
| | {}
|
+| [prefix](variables.tf#L162) | Optional prefix used to generate Dataplex DataScan ID. | string
| | null
|
## Outputs
diff --git a/modules/dataplex-datascan/iam.tf b/modules/dataplex-datascan/iam.tf
index 9a496ff182..9ed5914446 100644
--- a/modules/dataplex-datascan/iam.tf
+++ b/modules/dataplex-datascan/iam.tf
@@ -44,7 +44,7 @@ resource "google_dataplex_datascan_iam_binding" "bindings" {
project = google_dataplex_datascan.datascan.project
location = google_dataplex_datascan.datascan.location
data_scan_id = google_dataplex_datascan.datascan.data_scan_id
- role = each.key
+ role = each.value.role
members = each.value.members
dynamic "condition" {
for_each = each.value.condition == null ? [] : [""]
diff --git a/modules/dataplex-datascan/variables.tf b/modules/dataplex-datascan/variables.tf
index 4e6b2bb133..a13cdc55e3 100644
--- a/modules/dataplex-datascan/variables.tf
+++ b/modules/dataplex-datascan/variables.tf
@@ -112,9 +112,10 @@ variable "iam" {
}
variable "iam_bindings" {
- description = "Authoritative IAM bindings in {ROLE => {members = [], condition = {}}}."
+ description = "Authoritative IAM bindings in {KEY => {role = ROLE, members = [], condition = {}}}. Keys are arbitrary."
type = map(object({
members = list(string)
+ role = string
condition = optional(object({
expression = string
title = string
diff --git a/modules/dataproc/README.md b/modules/dataproc/README.md
index aa5326718e..5cd220cbaa 100644
--- a/modules/dataproc/README.md
+++ b/modules/dataproc/README.md
@@ -146,17 +146,17 @@ module "processing-dp-cluster" {
| name | description | type | required | default |
|---|---|:---:|:---:|:---:|
-| [name](variables.tf#L234) | Cluster name. | string
| ✓ | |
-| [project_id](variables.tf#L249) | Project ID. | string
| ✓ | |
-| [region](variables.tf#L254) | Dataproc region. | string
| ✓ | |
+| [name](variables.tf#L235) | Cluster name. | string
| ✓ | |
+| [project_id](variables.tf#L250) | Project ID. | string
| ✓ | |
+| [region](variables.tf#L255) | Dataproc region. | string
| ✓ | |
| [dataproc_config](variables.tf#L17) | Dataproc cluster config. | object({…})
| | {}
|
| [group_iam](variables.tf#L185) | Authoritative IAM binding for organization groups, in {GROUP_EMAIL => [ROLES]} format. Group emails need to be static. Can be used in combination with the `iam` variable. | map(list(string))
| | {}
|
| [iam](variables.tf#L192) | IAM bindings in {ROLE => [MEMBERS]} format. | map(list(string))
| | {}
|
-| [iam_bindings](variables.tf#L199) | Authoritative IAM bindings in {ROLE => {members = [], condition = {}}}. | map(object({…}))
| | {}
|
-| [iam_bindings_additive](variables.tf#L213) | Individual additive IAM bindings. Keys are arbitrary. | map(object({…}))
| | {}
|
-| [labels](variables.tf#L228) | The resource labels for instance to use to annotate any related underlying resources, such as Compute Engine VMs. | map(string)
| | {}
|
-| [prefix](variables.tf#L239) | Optional prefix used to generate project id and name. | string
| | null
|
-| [service_account](variables.tf#L259) | Service account to set on the Dataproc cluster. | string
| | null
|
+| [iam_bindings](variables.tf#L199) | Authoritative IAM bindings in {KEY => {role = ROLE, members = [], condition = {}}}. Keys are arbitrary. | map(object({…}))
| | {}
|
+| [iam_bindings_additive](variables.tf#L214) | Individual additive IAM bindings. Keys are arbitrary. | map(object({…}))
| | {}
|
+| [labels](variables.tf#L229) | The resource labels for instance to use to annotate any related underlying resources, such as Compute Engine VMs. | map(string)
| | {}
|
+| [prefix](variables.tf#L240) | Optional prefix used to generate project id and name. | string
| | null
|
+| [service_account](variables.tf#L260) | Service account to set on the Dataproc cluster. | string
| | null
|
## Outputs
diff --git a/modules/dataproc/iam.tf b/modules/dataproc/iam.tf
index fba2eca9a7..ef0428d13c 100644
--- a/modules/dataproc/iam.tf
+++ b/modules/dataproc/iam.tf
@@ -46,7 +46,7 @@ resource "google_dataproc_cluster_iam_binding" "bindings" {
project = var.project_id
cluster = google_dataproc_cluster.cluster.name
region = var.region
- role = each.key
+ role = each.value.role
members = each.value.members
dynamic "condition" {
for_each = each.value.condition == null ? [] : [""]
diff --git a/modules/dataproc/variables.tf b/modules/dataproc/variables.tf
index 49f4fa908b..8b77c5b96b 100644
--- a/modules/dataproc/variables.tf
+++ b/modules/dataproc/variables.tf
@@ -197,9 +197,10 @@ variable "iam" {
}
variable "iam_bindings" {
- description = "Authoritative IAM bindings in {ROLE => {members = [], condition = {}}}."
+ description = "Authoritative IAM bindings in {KEY => {role = ROLE, members = [], condition = {}}}. Keys are arbitrary."
type = map(object({
members = list(string)
+ role = string
condition = optional(object({
expression = string
title = string
diff --git a/modules/dns/README.md b/modules/dns/README.md
index cdfff0e300..5b293768ea 100644
--- a/modules/dns/README.md
+++ b/modules/dns/README.md
@@ -140,17 +140,16 @@ module "public-dns" {
# tftest modules=1 resources=4 inventory=public-zone.yaml
```
-
## Variables
| name | description | type | required | default |
|---|---|:---:|:---:|:---:|
-| [name](variables.tf#L33) | Zone name, must be unique within the project. | string
| ✓ | |
-| [project_id](variables.tf#L38) | Project id for the zone. | string
| ✓ | |
-| [description](variables.tf#L21) | Domain description. | string
| | "Terraform managed."
|
-| [iam](variables.tf#L27) | IAM bindings in {ROLE => [MEMBERS]} format. | map(list(string))
| | null
|
-| [recordsets](variables.tf#L43) | Map of DNS recordsets in \"type name\" => {ttl, [records]} format. | map(object({…}))
| | {}
|
-| [zone_config](variables.tf#L78) | DNS zone configuration. | object({…})
| | null
|
+| [name](variables.tf#L29) | Zone name, must be unique within the project. | string
| ✓ | |
+| [project_id](variables.tf#L34) | Project id for the zone. | string
| ✓ | |
+| [description](variables.tf#L17) | Domain description. | string
| | "Terraform managed."
|
+| [iam](variables.tf#L23) | IAM bindings in {ROLE => [MEMBERS]} format. | map(list(string))
| | null
|
+| [recordsets](variables.tf#L39) | Map of DNS recordsets in \"type name\" => {ttl, [records]} format. | map(object({…}))
| | {}
|
+| [zone_config](variables.tf#L74) | DNS zone configuration. | object({…})
| | null
|
## Outputs
@@ -162,5 +161,4 @@ module "public-dns" {
| [name](outputs.tf#L32) | The DNS zone name. | |
| [name_servers](outputs.tf#L37) | The DNS zone name servers. | |
| [zone](outputs.tf#L42) | DNS zone resource. | |
-
diff --git a/modules/dns/variables.tf b/modules/dns/variables.tf
index 9c2bf54517..08395ba039 100644
--- a/modules/dns/variables.tf
+++ b/modules/dns/variables.tf
@@ -14,10 +14,6 @@
* limitations under the License.
*/
-###############################################################################
-# zone variables #
-###############################################################################
-
variable "description" {
description = "Domain description."
type = string
diff --git a/modules/folder/README.md b/modules/folder/README.md
index b4f4160182..65661210dc 100644
--- a/modules/folder/README.md
+++ b/modules/folder/README.md
@@ -290,17 +290,17 @@ module "folder" {
| [folder_create](variables.tf#L33) | Create folder. When set to false, uses id to reference an existing folder. | bool
| | true
|
| [group_iam](variables.tf#L39) | Authoritative IAM binding for organization groups, in {GROUP_EMAIL => [ROLES]} format. Group emails need to be static. Can be used in combination with the `iam` variable. | map(list(string))
| | {}
|
| [iam](variables.tf#L46) | IAM bindings in {ROLE => [MEMBERS]} format. | map(list(string))
| | {}
|
-| [iam_bindings](variables.tf#L53) | Authoritative IAM bindings in {ROLE => {members = [], condition = {}}}. | map(object({…}))
| | {}
|
-| [iam_bindings_additive](variables.tf#L67) | Individual additive IAM bindings. Keys are arbitrary. | map(object({…}))
| | {}
|
-| [id](variables.tf#L82) | Folder ID in case you use folder_create=false. | string
| | null
|
-| [logging_data_access](variables.tf#L88) | Control activation of data access logs. Format is service => { log type => [exempted members]}. The special 'allServices' key denotes configuration for all services. | map(map(list(string)))
| | {}
|
-| [logging_exclusions](variables.tf#L103) | Logging exclusions for this folder in the form {NAME -> FILTER}. | map(string)
| | {}
|
-| [logging_sinks](variables.tf#L110) | Logging sinks to create for the organization. | map(object({…}))
| | {}
|
-| [name](variables.tf#L140) | Folder name. | string
| | null
|
-| [org_policies](variables.tf#L146) | Organization policies applied to this folder keyed by policy name. | map(object({…}))
| | {}
|
-| [org_policies_data_path](variables.tf#L173) | Path containing org policies in YAML format. | string
| | null
|
-| [parent](variables.tf#L179) | Parent in folders/folder_id or organizations/org_id format. | string
| | null
|
-| [tag_bindings](variables.tf#L189) | Tag bindings for this folder, in key => tag value id format. | map(string)
| | null
|
+| [iam_bindings](variables.tf#L53) | Authoritative IAM bindings in {KEY => {role = ROLE, members = [], condition = {}}}. Keys are arbitrary. | map(object({…}))
| | {}
|
+| [iam_bindings_additive](variables.tf#L68) | Individual additive IAM bindings. Keys are arbitrary. | map(object({…}))
| | {}
|
+| [id](variables.tf#L83) | Folder ID in case you use folder_create=false. | string
| | null
|
+| [logging_data_access](variables.tf#L89) | Control activation of data access logs. Format is service => { log type => [exempted members]}. The special 'allServices' key denotes configuration for all services. | map(map(list(string)))
| | {}
|
+| [logging_exclusions](variables.tf#L104) | Logging exclusions for this folder in the form {NAME -> FILTER}. | map(string)
| | {}
|
+| [logging_sinks](variables.tf#L111) | Logging sinks to create for the organization. | map(object({…}))
| | {}
|
+| [name](variables.tf#L141) | Folder name. | string
| | null
|
+| [org_policies](variables.tf#L147) | Organization policies applied to this folder keyed by policy name. | map(object({…}))
| | {}
|
+| [org_policies_data_path](variables.tf#L174) | Path containing org policies in YAML format. | string
| | null
|
+| [parent](variables.tf#L180) | Parent in folders/folder_id or organizations/org_id format. | string
| | null
|
+| [tag_bindings](variables.tf#L190) | Tag bindings for this folder, in key => tag value id format. | map(string)
| | null
|
## Outputs
diff --git a/modules/folder/iam.tf b/modules/folder/iam.tf
index 976e312c71..20025b2831 100644
--- a/modules/folder/iam.tf
+++ b/modules/folder/iam.tf
@@ -42,7 +42,7 @@ resource "google_folder_iam_binding" "authoritative" {
resource "google_folder_iam_binding" "bindings" {
for_each = var.iam_bindings
folder = local.folder.name
- role = each.key
+ role = each.value.role
members = each.value.members
dynamic "condition" {
for_each = each.value.condition == null ? [] : [""]
diff --git a/modules/folder/variables.tf b/modules/folder/variables.tf
index 619ee9c376..86efc21546 100644
--- a/modules/folder/variables.tf
+++ b/modules/folder/variables.tf
@@ -51,9 +51,10 @@ variable "iam" {
}
variable "iam_bindings" {
- description = "Authoritative IAM bindings in {ROLE => {members = [], condition = {}}}."
+ description = "Authoritative IAM bindings in {KEY => {role = ROLE, members = [], condition = {}}}. Keys are arbitrary."
type = map(object({
members = list(string)
+ role = string
condition = optional(object({
expression = string
title = string
diff --git a/modules/iam-service-account/README.md b/modules/iam-service-account/README.md
index 9fd6cba01b..ea3362c73a 100644
--- a/modules/iam-service-account/README.md
+++ b/modules/iam-service-account/README.md
@@ -45,23 +45,23 @@ module "myproject-default-service-accounts" {
| name | description | type | required | default |
|---|---|:---:|:---:|:---:|
-| [name](variables.tf#L113) | Name of the service account to create. | string
| ✓ | |
-| [project_id](variables.tf#L128) | Project id where service account will be created. | string
| ✓ | |
+| [name](variables.tf#L114) | Name of the service account to create. | string
| ✓ | |
+| [project_id](variables.tf#L129) | Project id where service account will be created. | string
| ✓ | |
| [description](variables.tf#L17) | Optional description. | string
| | null
|
| [display_name](variables.tf#L23) | Display name of the service account to create. | string
| | "Terraform-managed."
|
| [generate_key](variables.tf#L29) | Generate a key for service account. | bool
| | false
|
| [iam](variables.tf#L35) | IAM bindings on the service account in {ROLE => [MEMBERS]} format. | map(list(string))
| | {}
|
| [iam_billing_roles](variables.tf#L42) | Billing account roles granted to this service account, by billing account id. Non-authoritative. | map(list(string))
| | {}
|
-| [iam_bindings](variables.tf#L49) | Authoritative IAM bindings on the service account in {ROLE => {members = [], condition = {}}}. | map(object({…}))
| | {}
|
-| [iam_bindings_additive](variables.tf#L63) | Individual additive IAM bindings on the service account. Keys are arbitrary. | map(object({…}))
| | {}
|
-| [iam_folder_roles](variables.tf#L78) | Folder roles granted to this service account, by folder id. Non-authoritative. | map(list(string))
| | {}
|
-| [iam_organization_roles](variables.tf#L85) | Organization roles granted to this service account, by organization id. Non-authoritative. | map(list(string))
| | {}
|
-| [iam_project_roles](variables.tf#L92) | Project roles granted to this service account, by project id. | map(list(string))
| | {}
|
-| [iam_sa_roles](variables.tf#L99) | Service account roles granted to this service account, by service account name. | map(list(string))
| | {}
|
-| [iam_storage_roles](variables.tf#L106) | Storage roles granted to this service account, by bucket name. | map(list(string))
| | {}
|
-| [prefix](variables.tf#L118) | Prefix applied to service account names. | string
| | null
|
-| [public_keys_directory](variables.tf#L133) | Path to public keys data files to upload to the service account (should have `.pem` extension). | string
| | ""
|
-| [service_account_create](variables.tf#L139) | Create service account. When set to false, uses a data source to reference an existing service account. | bool
| | true
|
+| [iam_bindings](variables.tf#L49) | Authoritative IAM bindings in {KEY => {role = ROLE, members = [], condition = {}}}. Keys are arbitrary. | map(object({…}))
| | {}
|
+| [iam_bindings_additive](variables.tf#L64) | Individual additive IAM bindings on the service account. Keys are arbitrary. | map(object({…}))
| | {}
|
+| [iam_folder_roles](variables.tf#L79) | Folder roles granted to this service account, by folder id. Non-authoritative. | map(list(string))
| | {}
|
+| [iam_organization_roles](variables.tf#L86) | Organization roles granted to this service account, by organization id. Non-authoritative. | map(list(string))
| | {}
|
+| [iam_project_roles](variables.tf#L93) | Project roles granted to this service account, by project id. | map(list(string))
| | {}
|
+| [iam_sa_roles](variables.tf#L100) | Service account roles granted to this service account, by service account name. | map(list(string))
| | {}
|
+| [iam_storage_roles](variables.tf#L107) | Storage roles granted to this service account, by bucket name. | map(list(string))
| | {}
|
+| [prefix](variables.tf#L119) | Prefix applied to service account names. | string
| | null
|
+| [public_keys_directory](variables.tf#L134) | Path to public keys data files to upload to the service account (should have `.pem` extension). | string
| | ""
|
+| [service_account_create](variables.tf#L140) | Create service account. When set to false, uses a data source to reference an existing service account. | bool
| | true
|
## Outputs
diff --git a/modules/iam-service-account/iam.tf b/modules/iam-service-account/iam.tf
index a9423fb0c5..15ae1acca7 100644
--- a/modules/iam-service-account/iam.tf
+++ b/modules/iam-service-account/iam.tf
@@ -71,7 +71,7 @@ resource "google_service_account_iam_binding" "authoritative" {
resource "google_service_account_iam_binding" "bindings" {
for_each = var.iam_bindings
service_account_id = local.service_account.name
- role = each.key
+ role = each.value.role
members = each.value.members
dynamic "condition" {
for_each = each.value.condition == null ? [] : [""]
diff --git a/modules/iam-service-account/variables.tf b/modules/iam-service-account/variables.tf
index c9ca7069dd..4a75af462f 100644
--- a/modules/iam-service-account/variables.tf
+++ b/modules/iam-service-account/variables.tf
@@ -47,9 +47,10 @@ variable "iam_billing_roles" {
}
variable "iam_bindings" {
- description = "Authoritative IAM bindings on the service account in {ROLE => {members = [], condition = {}}}."
+ description = "Authoritative IAM bindings in {KEY => {role = ROLE, members = [], condition = {}}}. Keys are arbitrary."
type = map(object({
members = list(string)
+ role = string
condition = optional(object({
expression = string
title = string
diff --git a/modules/kms/README.md b/modules/kms/README.md
index 56acff46e8..a3b2c902f9 100644
--- a/modules/kms/README.md
+++ b/modules/kms/README.md
@@ -89,19 +89,19 @@ module "kms" {
| name | description | type | required | default |
|---|---|:---:|:---:|:---:|
-| [keyring](variables.tf#L117) | Keyring attributes. | object({…})
| ✓ | |
-| [project_id](variables.tf#L140) | Project id where the keyring will be created. | string
| ✓ | |
+| [keyring](variables.tf#L119) | Keyring attributes. | object({…})
| ✓ | |
+| [project_id](variables.tf#L142) | Project id where the keyring will be created. | string
| ✓ | |
| [iam](variables.tf#L17) | Keyring IAM bindings in {ROLE => [MEMBERS]} format. | map(list(string))
| | {}
|
-| [iam_bindings](variables.tf#L23) | Keyring authoritative IAM bindings in {ROLE => {members = [], condition = {}}}. | map(object({…}))
| | {}
|
-| [iam_bindings_additive](variables.tf#L37) | Keyring individual additive IAM bindings. Keys are arbitrary. | map(object({…}))
| | {}
|
-| [key_iam](variables.tf#L52) | Key IAM bindings in {KEY => {ROLE => [MEMBERS]}} format. | map(map(list(string)))
| | {}
|
-| [key_iam_bindings](variables.tf#L58) | Key authoritative IAM bindings in {KEY => {ROLE => {members = [], condition = {}}}}. | map(object({…}))
| | {}
|
-| [key_iam_bindings_additive](variables.tf#L72) | Key individual additive IAM bindings. Keys are arbitrary. | map(object({…}))
| | {}
|
-| [key_purpose](variables.tf#L88) | Per-key purpose, if not set defaults will be used. If purpose is not `ENCRYPT_DECRYPT` (the default), `version_template.algorithm` is required. | map(object({…}))
| | {}
|
-| [key_purpose_defaults](variables.tf#L100) | Defaults used for key purpose when not defined at the key level. If purpose is not `ENCRYPT_DECRYPT` (the default), `version_template.algorithm` is required. | object({…})
| | {…}
|
-| [keyring_create](variables.tf#L125) | Set to false to manage keys and IAM bindings in an existing keyring. | bool
| | true
|
-| [keys](variables.tf#L131) | Key names and base attributes. Set attributes to null if not needed. | map(object({…}))
| | {}
|
-| [tag_bindings](variables.tf#L145) | Tag bindings for this keyring, in key => tag value id format. | map(string)
| | null
|
+| [iam_bindings](variables.tf#L23) | Authoritative IAM bindings in {KEY => {role = ROLE, members = [], condition = {}}}. Keys are arbitrary. | map(object({…}))
| | {}
|
+| [iam_bindings_additive](variables.tf#L38) | Keyring individual additive IAM bindings. Keys are arbitrary. | map(object({…}))
| | {}
|
+| [key_iam](variables.tf#L53) | Key IAM bindings in {KEY => {ROLE => [MEMBERS]}} format. | map(map(list(string)))
| | {}
|
+| [key_iam_bindings](variables.tf#L59) | Key authoritative IAM bindings in {KEY => {BINDING_KEY => {role = ROLE, members = [], condition = {}}}}. | map(object({…}))
| | {}
|
+| [key_iam_bindings_additive](variables.tf#L74) | Key individual additive IAM bindings. Keys are arbitrary. | map(object({…}))
| | {}
|
+| [key_purpose](variables.tf#L90) | Per-key purpose, if not set defaults will be used. If purpose is not `ENCRYPT_DECRYPT` (the default), `version_template.algorithm` is required. | map(object({…}))
| | {}
|
+| [key_purpose_defaults](variables.tf#L102) | Defaults used for key purpose when not defined at the key level. If purpose is not `ENCRYPT_DECRYPT` (the default), `version_template.algorithm` is required. | object({…})
| | {…}
|
+| [keyring_create](variables.tf#L127) | Set to false to manage keys and IAM bindings in an existing keyring. | bool
| | true
|
+| [keys](variables.tf#L133) | Key names and base attributes. Set attributes to null if not needed. | map(object({…}))
| | {}
|
+| [tag_bindings](variables.tf#L147) | Tag bindings for this keyring, in key => tag value id format. | map(string)
| | null
|
## Outputs
diff --git a/modules/kms/iam.tf b/modules/kms/iam.tf
index 9a78c2cfe4..ff8279a254 100644
--- a/modules/kms/iam.tf
+++ b/modules/kms/iam.tf
@@ -25,12 +25,13 @@ locals {
]
])
key_iam_bindings = flatten([
- for key, roles in var.key_iam_bindings : [
- for role, data in roles : {
- key = key
- role = role
- members = data.members
- condition = data.condition
+ for key, bindings in var.key_iam_bindings : [
+ for binding_key, binding_data in bindings : {
+ key = key
+ binding_key = "${key}.${binding_key}"
+ role = binding_data.role
+ members = binding_data.members
+ condition = binding_data.condition
}
]
])
@@ -46,7 +47,7 @@ resource "google_kms_key_ring_iam_binding" "authoritative" {
resource "google_kms_key_ring_iam_binding" "bindings" {
for_each = var.iam_bindings
key_ring_id = local.keyring.id
- role = each.key
+ role = each.value.role
members = each.value.members
dynamic "condition" {
for_each = each.value.condition == null ? [] : [""]
@@ -85,8 +86,7 @@ resource "google_kms_crypto_key_iam_binding" "authoritative" {
resource "google_kms_crypto_key_iam_binding" "bindings" {
for_each = {
- for binding in local.key_iam_bindings :
- "${binding.key}.${binding.role}" => binding
+ for binding in local.key_iam_bindings : binding.binding_key => binding
}
role = each.value.role
crypto_key_id = google_kms_crypto_key.default[each.value.key].id
diff --git a/modules/kms/variables.tf b/modules/kms/variables.tf
index 44c980364c..93e42dc462 100644
--- a/modules/kms/variables.tf
+++ b/modules/kms/variables.tf
@@ -21,9 +21,10 @@ variable "iam" {
}
variable "iam_bindings" {
- description = "Keyring authoritative IAM bindings in {ROLE => {members = [], condition = {}}}."
+ description = "Authoritative IAM bindings in {KEY => {role = ROLE, members = [], condition = {}}}. Keys are arbitrary."
type = map(object({
members = list(string)
+ role = string
condition = optional(object({
expression = string
title = string
@@ -56,9 +57,10 @@ variable "key_iam" {
}
variable "key_iam_bindings" {
- description = "Key authoritative IAM bindings in {KEY => {ROLE => {members = [], condition = {}}}}."
+ description = "Key authoritative IAM bindings in {KEY => {BINDING_KEY => {role = ROLE, members = [], condition = {}}}}."
type = map(object({
members = list(string)
+ role = string
condition = optional(object({
expression = string
title = string
diff --git a/modules/organization/README.md b/modules/organization/README.md
index eb228dcf6b..fd9ca09435 100644
--- a/modules/organization/README.md
+++ b/modules/organization/README.md
@@ -446,24 +446,24 @@ module "org" {
| name | description | type | required | default |
|---|---|:---:|:---:|:---:|
-| [organization_id](variables.tf#L210) | Organization id in organizations/nnnnnn format. | string
| ✓ | |
+| [organization_id](variables.tf#L211) | Organization id in organizations/nnnnnn format. | string
| ✓ | |
| [contacts](variables.tf#L17) | List of essential contacts for this resource. Must be in the form EMAIL -> [NOTIFICATION_TYPES]. Valid notification types are ALL, SUSPENSION, SECURITY, TECHNICAL, BILLING, LEGAL, PRODUCT_UPDATES. | map(list(string))
| | {}
|
| [custom_roles](variables.tf#L24) | Map of role name => list of permissions to create in this project. | map(list(string))
| | {}
|
| [firewall_policy](variables.tf#L31) | Hierarchical firewall policies to associate to the organization. | object({…})
| | null
|
| [group_iam](variables.tf#L40) | Authoritative IAM binding for organization groups, in {GROUP_EMAIL => [ROLES]} format. Group emails need to be static. Can be used in combination with the `iam` variable. | map(list(string))
| | {}
|
| [iam](variables.tf#L47) | IAM bindings, in {ROLE => [MEMBERS]} format. | map(list(string))
| | {}
|
-| [iam_bindings](variables.tf#L54) | Authoritative IAM bindings in {ROLE => {members = [], condition = {}}}. | map(object({…}))
| | {}
|
-| [iam_bindings_additive](variables.tf#L68) | Individual additive IAM bindings. Keys are arbitrary. | map(object({…}))
| | {}
|
-| [logging_data_access](variables.tf#L83) | Control activation of data access logs. Format is service => { log type => [exempted members]}. The special 'allServices' key denotes configuration for all services. | map(map(list(string)))
| | {}
|
-| [logging_exclusions](variables.tf#L98) | Logging exclusions for this organization in the form {NAME -> FILTER}. | map(string)
| | {}
|
-| [logging_sinks](variables.tf#L105) | Logging sinks to create for the organization. | map(object({…}))
| | {}
|
-| [network_tags](variables.tf#L135) | Network tags by key name. If `id` is provided, key creation is skipped. The `iam` attribute behaves like the similarly named one at module level. | map(object({…}))
| | {}
|
-| [org_policies](variables.tf#L157) | Organization policies applied to this organization keyed by policy name. | map(object({…}))
| | {}
|
-| [org_policies_data_path](variables.tf#L184) | Path containing org policies in YAML format. | string
| | null
|
-| [org_policy_custom_constraints](variables.tf#L190) | Organization policy custom constraints keyed by constraint name. | map(object({…}))
| | {}
|
-| [org_policy_custom_constraints_data_path](variables.tf#L204) | Path containing org policy custom constraints in YAML format. | string
| | null
|
-| [tag_bindings](variables.tf#L219) | Tag bindings for this organization, in key => tag value id format. | map(string)
| | null
|
-| [tags](variables.tf#L225) | Tags by key name. If `id` is provided, key or value creation is skipped. The `iam` attribute behaves like the similarly named one at module level. | map(object({…}))
| | {}
|
+| [iam_bindings](variables.tf#L54) | Authoritative IAM bindings in {KEY => {role = ROLE, members = [], condition = {}}}. Keys are arbitrary. | map(object({…}))
| | {}
|
+| [iam_bindings_additive](variables.tf#L69) | Individual additive IAM bindings. Keys are arbitrary. | map(object({…}))
| | {}
|
+| [logging_data_access](variables.tf#L84) | Control activation of data access logs. Format is service => { log type => [exempted members]}. The special 'allServices' key denotes configuration for all services. | map(map(list(string)))
| | {}
|
+| [logging_exclusions](variables.tf#L99) | Logging exclusions for this organization in the form {NAME -> FILTER}. | map(string)
| | {}
|
+| [logging_sinks](variables.tf#L106) | Logging sinks to create for the organization. | map(object({…}))
| | {}
|
+| [network_tags](variables.tf#L136) | Network tags by key name. If `id` is provided, key creation is skipped. The `iam` attribute behaves like the similarly named one at module level. | map(object({…}))
| | {}
|
+| [org_policies](variables.tf#L158) | Organization policies applied to this organization keyed by policy name. | map(object({…}))
| | {}
|
+| [org_policies_data_path](variables.tf#L185) | Path containing org policies in YAML format. | string
| | null
|
+| [org_policy_custom_constraints](variables.tf#L191) | Organization policy custom constraints keyed by constraint name. | map(object({…}))
| | {}
|
+| [org_policy_custom_constraints_data_path](variables.tf#L205) | Path containing org policy custom constraints in YAML format. | string
| | null
|
+| [tag_bindings](variables.tf#L220) | Tag bindings for this organization, in key => tag value id format. | map(string)
| | null
|
+| [tags](variables.tf#L226) | Tags by key name. If `id` is provided, key or value creation is skipped. The `iam` attribute behaves like the similarly named one at module level. | map(object({…}))
| | {}
|
## Outputs
diff --git a/modules/organization/iam.tf b/modules/organization/iam.tf
index 2882d02a07..81a8d2b0ed 100644
--- a/modules/organization/iam.tf
+++ b/modules/organization/iam.tf
@@ -51,7 +51,7 @@ resource "google_organization_iam_binding" "authoritative" {
resource "google_organization_iam_binding" "bindings" {
for_each = var.iam_bindings
org_id = local.organization_id_numeric
- role = each.key
+ role = each.value.role
members = each.value.members
dynamic "condition" {
for_each = each.value.condition == null ? [] : [""]
diff --git a/modules/organization/variables.tf b/modules/organization/variables.tf
index 99fe49c697..c9899e2e1d 100644
--- a/modules/organization/variables.tf
+++ b/modules/organization/variables.tf
@@ -52,9 +52,10 @@ variable "iam" {
}
variable "iam_bindings" {
- description = "Authoritative IAM bindings in {ROLE => {members = [], condition = {}}}."
+ description = "Authoritative IAM bindings in {KEY => {role = ROLE, members = [], condition = {}}}. Keys are arbitrary."
type = map(object({
members = list(string)
+ role = string
condition = optional(object({
expression = string
title = string
diff --git a/modules/project/README.md b/modules/project/README.md
index 7479eca8cf..3fddf95f97 100644
--- a/modules/project/README.md
+++ b/modules/project/README.md
@@ -117,10 +117,11 @@ module "project" {
"stackdriver.googleapis.com"
]
iam_bindings = {
- "roles/resourcemanager.projectIamAdmin" = {
+ iam_admin_conditional = {
members = [
"group:test-admins@example.org"
]
+ role = "roles/resourcemanager.projectIamAdmin"
condition = {
title = "delegated_network_user_one"
expression = <<-END
@@ -589,7 +590,7 @@ output "compute_robot" {
| name | description | type | required | default |
|---|---|:---:|:---:|:---:|
-| [name](variables.tf#L185) | Project name and id suffix. | string
| ✓ | |
+| [name](variables.tf#L186) | Project name and id suffix. | string
| ✓ | |
| [auto_create_network](variables.tf#L17) | Whether to create the default network for the project. | bool
| | false
|
| [billing_account](variables.tf#L23) | Billing account id. | string
| | null
|
| [compute_metadata](variables.tf#L29) | Optional compute metadata key/values. Only usable if compute API has been enabled. | map(string)
| | {}
|
@@ -599,28 +600,28 @@ output "compute_robot" {
| [descriptive_name](variables.tf#L63) | Name of the project name. Used for project name instead of `name` variable. | string
| | null
|
| [group_iam](variables.tf#L69) | Authoritative IAM binding for organization groups, in {GROUP_EMAIL => [ROLES]} format. Group emails need to be static. Can be used in combination with the `iam` variable. | map(list(string))
| | {}
|
| [iam](variables.tf#L76) | Authoritative IAM bindings in {ROLE => [MEMBERS]} format. | map(list(string))
| | {}
|
-| [iam_bindings](variables.tf#L83) | Authoritative IAM bindings in {ROLE => {members = [], condition = {}}}. | map(object({…}))
| | {}
|
-| [iam_bindings_additive](variables.tf#L97) | Individual additive IAM bindings. Keys are arbitrary. | map(object({…}))
| | {}
|
-| [labels](variables.tf#L112) | Resource labels. | map(string)
| | {}
|
-| [lien_reason](variables.tf#L119) | If non-empty, creates a project lien with this description. | string
| | null
|
-| [logging_data_access](variables.tf#L125) | Control activation of data access logs. Format is service => { log type => [exempted members]}. The special 'allServices' key denotes configuration for all services. | map(map(list(string)))
| | {}
|
-| [logging_exclusions](variables.tf#L140) | Logging exclusions for this project in the form {NAME -> FILTER}. | map(string)
| | {}
|
-| [logging_sinks](variables.tf#L147) | Logging sinks to create for this project. | map(object({…}))
| | {}
|
-| [metric_scopes](variables.tf#L178) | List of projects that will act as metric scopes for this project. | list(string)
| | []
|
-| [org_policies](variables.tf#L190) | Organization policies applied to this project keyed by policy name. | map(object({…}))
| | {}
|
-| [org_policies_data_path](variables.tf#L217) | Path containing org policies in YAML format. | string
| | null
|
-| [parent](variables.tf#L223) | Parent folder or organization in 'folders/folder_id' or 'organizations/org_id' format. | string
| | null
|
-| [prefix](variables.tf#L233) | Optional prefix used to generate project id and name. | string
| | null
|
-| [project_create](variables.tf#L243) | Create project. When set to false, uses a data source to reference existing project. | bool
| | true
|
-| [service_config](variables.tf#L249) | Configure service API activation. | object({…})
| | {…}
|
-| [service_encryption_key_ids](variables.tf#L261) | Cloud KMS encryption key in {SERVICE => [KEY_URL]} format. | map(list(string))
| | {}
|
-| [service_perimeter_bridges](variables.tf#L268) | Name of VPC-SC Bridge perimeters to add project into. See comment in the variables file for format. | list(string)
| | null
|
-| [service_perimeter_standard](variables.tf#L275) | Name of VPC-SC Standard perimeter to add project into. See comment in the variables file for format. | string
| | null
|
-| [services](variables.tf#L281) | Service APIs to enable. | list(string)
| | []
|
-| [shared_vpc_host_config](variables.tf#L287) | Configures this project as a Shared VPC host project (mutually exclusive with shared_vpc_service_project). | object({…})
| | null
|
-| [shared_vpc_service_config](variables.tf#L296) | Configures this project as a Shared VPC service project (mutually exclusive with shared_vpc_host_config). | object({…})
| | {…}
|
-| [skip_delete](variables.tf#L318) | Allows the underlying resources to be destroyed without destroying the project itself. | bool
| | false
|
-| [tag_bindings](variables.tf#L324) | Tag bindings for this project, in key => tag value id format. | map(string)
| | null
|
+| [iam_bindings](variables.tf#L83) | Authoritative IAM bindings in {KEY => {role = ROLE, members = [], condition = {}}}. Keys are arbitrary. | map(object({…}))
| | {}
|
+| [iam_bindings_additive](variables.tf#L98) | Individual additive IAM bindings. Keys are arbitrary. | map(object({…}))
| | {}
|
+| [labels](variables.tf#L113) | Resource labels. | map(string)
| | {}
|
+| [lien_reason](variables.tf#L120) | If non-empty, creates a project lien with this description. | string
| | null
|
+| [logging_data_access](variables.tf#L126) | Control activation of data access logs. Format is service => { log type => [exempted members]}. The special 'allServices' key denotes configuration for all services. | map(map(list(string)))
| | {}
|
+| [logging_exclusions](variables.tf#L141) | Logging exclusions for this project in the form {NAME -> FILTER}. | map(string)
| | {}
|
+| [logging_sinks](variables.tf#L148) | Logging sinks to create for this project. | map(object({…}))
| | {}
|
+| [metric_scopes](variables.tf#L179) | List of projects that will act as metric scopes for this project. | list(string)
| | []
|
+| [org_policies](variables.tf#L191) | Organization policies applied to this project keyed by policy name. | map(object({…}))
| | {}
|
+| [org_policies_data_path](variables.tf#L218) | Path containing org policies in YAML format. | string
| | null
|
+| [parent](variables.tf#L224) | Parent folder or organization in 'folders/folder_id' or 'organizations/org_id' format. | string
| | null
|
+| [prefix](variables.tf#L234) | Optional prefix used to generate project id and name. | string
| | null
|
+| [project_create](variables.tf#L244) | Create project. When set to false, uses a data source to reference existing project. | bool
| | true
|
+| [service_config](variables.tf#L250) | Configure service API activation. | object({…})
| | {…}
|
+| [service_encryption_key_ids](variables.tf#L262) | Cloud KMS encryption key in {SERVICE => [KEY_URL]} format. | map(list(string))
| | {}
|
+| [service_perimeter_bridges](variables.tf#L269) | Name of VPC-SC Bridge perimeters to add project into. See comment in the variables file for format. | list(string)
| | null
|
+| [service_perimeter_standard](variables.tf#L276) | Name of VPC-SC Standard perimeter to add project into. See comment in the variables file for format. | string
| | null
|
+| [services](variables.tf#L282) | Service APIs to enable. | list(string)
| | []
|
+| [shared_vpc_host_config](variables.tf#L288) | Configures this project as a Shared VPC host project (mutually exclusive with shared_vpc_service_project). | object({…})
| | null
|
+| [shared_vpc_service_config](variables.tf#L297) | Configures this project as a Shared VPC service project (mutually exclusive with shared_vpc_host_config). | object({…})
| | {…}
|
+| [skip_delete](variables.tf#L319) | Allows the underlying resources to be destroyed without destroying the project itself. | bool
| | false
|
+| [tag_bindings](variables.tf#L325) | Tag bindings for this project, in key => tag value id format. | map(string)
| | null
|
## Outputs
diff --git a/modules/project/iam.tf b/modules/project/iam.tf
index 16f187d6c9..0f00f2861a 100644
--- a/modules/project/iam.tf
+++ b/modules/project/iam.tf
@@ -58,7 +58,7 @@ resource "google_project_iam_binding" "authoritative" {
resource "google_project_iam_binding" "bindings" {
for_each = var.iam_bindings
project = local.project.project_id
- role = each.key
+ role = each.value.role
members = each.value.members
dynamic "condition" {
for_each = each.value.condition == null ? [] : [""]
diff --git a/modules/project/variables.tf b/modules/project/variables.tf
index 2824fcf38d..68f8b6c027 100644
--- a/modules/project/variables.tf
+++ b/modules/project/variables.tf
@@ -81,9 +81,10 @@ variable "iam" {
}
variable "iam_bindings" {
- description = "Authoritative IAM bindings in {ROLE => {members = [], condition = {}}}."
+ description = "Authoritative IAM bindings in {KEY => {role = ROLE, members = [], condition = {}}}. Keys are arbitrary."
type = map(object({
members = list(string)
+ role = string
condition = optional(object({
expression = string
title = string
diff --git a/modules/source-repository/README.md b/modules/source-repository/README.md
index a62013fa98..c60ba7e46f 100644
--- a/modules/source-repository/README.md
+++ b/modules/source-repository/README.md
@@ -75,13 +75,13 @@ module "repo" {
| name | description | type | required | default |
|---|---|:---:|:---:|:---:|
-| [name](variables.tf#L60) | Repository name. | string
| ✓ | |
-| [project_id](variables.tf#L65) | Project used for resources. | string
| ✓ | |
+| [name](variables.tf#L61) | Repository name. | string
| ✓ | |
+| [project_id](variables.tf#L66) | Project used for resources. | string
| ✓ | |
| [group_iam](variables.tf#L17) | Authoritative IAM binding for organization groups, in {GROUP_EMAIL => [ROLES]} format. Group emails need to be static. Can be used in combination with the `iam` variable. | map(list(string))
| | {}
|
| [iam](variables.tf#L24) | IAM bindings in {ROLE => [MEMBERS]} format. | map(list(string))
| | {}
|
-| [iam_bindings](variables.tf#L31) | Authoritative IAM bindings in {ROLE => {members = [], condition = {}}}. | map(object({…}))
| | {}
|
-| [iam_bindings_additive](variables.tf#L45) | Individual additive IAM bindings. Keys are arbitrary. | map(object({…}))
| | {}
|
-| [triggers](variables.tf#L70) | Cloud Build triggers. | map(object({…}))
| | {}
|
+| [iam_bindings](variables.tf#L31) | Authoritative IAM bindings in {KEY => {role = ROLE, members = [], condition = {}}}. Keys are arbitrary. | map(object({…}))
| | {}
|
+| [iam_bindings_additive](variables.tf#L46) | Individual additive IAM bindings. Keys are arbitrary. | map(object({…}))
| | {}
|
+| [triggers](variables.tf#L71) | Cloud Build triggers. | map(object({…}))
| | {}
|
## Outputs
diff --git a/modules/source-repository/iam.tf b/modules/source-repository/iam.tf
index be0cf6886a..1b225d1b29 100644
--- a/modules/source-repository/iam.tf
+++ b/modules/source-repository/iam.tf
@@ -44,7 +44,7 @@ resource "google_sourcerepo_repository_iam_binding" "bindings" {
for_each = var.iam_bindings
project = var.project_id
repository = google_sourcerepo_repository.default.name
- role = each.key
+ role = each.value.role
members = each.value.members
dynamic "condition" {
for_each = each.value.condition == null ? [] : [""]
diff --git a/modules/source-repository/variables.tf b/modules/source-repository/variables.tf
index ce1c34e70d..23bfa789eb 100644
--- a/modules/source-repository/variables.tf
+++ b/modules/source-repository/variables.tf
@@ -29,9 +29,10 @@ variable "iam" {
}
variable "iam_bindings" {
- description = "Authoritative IAM bindings in {ROLE => {members = [], condition = {}}}."
+ description = "Authoritative IAM bindings in {KEY => {role = ROLE, members = [], condition = {}}}. Keys are arbitrary."
type = map(object({
members = list(string)
+ role = string
condition = optional(object({
expression = string
title = string
diff --git a/tests/modules/project/examples/iam-bindings.yaml b/tests/modules/project/examples/iam-bindings.yaml
index f1f09e3654..c9fee92524 100644
--- a/tests/modules/project/examples/iam-bindings.yaml
+++ b/tests/modules/project/examples/iam-bindings.yaml
@@ -23,7 +23,7 @@ values:
project_id: foo-project-example
skip_delete: false
timeouts: null
- module.project.google_project_iam_binding.bindings["roles/resourcemanager.projectIamAdmin"]:
+ module.project.google_project_iam_binding.bindings["iam_admin_conditional"]:
condition:
- description: null
expression: "api.getAttribute(\n 'iam.googleapis.com/modifiedGrantsByRole',\
@@ -54,4 +54,3 @@ counts:
resources: 4
outputs: {}
-