diff --git a/modules/data-catalog-policy-tag/README.md b/modules/data-catalog-policy-tag/README.md
index 6f53fcbd3..5a1c2055e 100644
--- a/modules/data-catalog-policy-tag/README.md
+++ b/modules/data-catalog-policy-tag/README.md
@@ -66,18 +66,18 @@ module "cmn-dc" {
| name | description | type | required | default |
|---|---|:---:|:---:|:---:|
-| [name](variables.tf#L69) | Name of this taxonomy. | string | ✓ | |
-| [project_id](variables.tf#L84) | GCP project id. | | ✓ | |
+| [name](variables.tf#L74) | Name of this taxonomy. | string | ✓ | |
+| [project_id](variables.tf#L89) | 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_additive](variables.tf#L41) | IAM additive bindings in {ROLE => [MEMBERS]} format. | map(list(string)) | | {} |
| [iam_additive_members](variables.tf#L47) | IAM additive bindings in {MEMBERS => [ROLE]} format. This might break if members are dynamic values. | map(list(string)) | | {} |
-| [iam_members](variables.tf#L53) | Individual additive IAM bindings, use this when iam_additive does not work due to dynamic resources. Keys are arbitrary and only used for the internal loop. | map(object({…})) | | {} |
-| [location](variables.tf#L63) | Data Catalog Taxonomy location. | string | | "eu" |
-| [prefix](variables.tf#L74) | Optional prefix used to generate project id and name. | string | | null |
-| [tags](variables.tf#L88) | List of Data Catalog Policy tags to be created with optional IAM binging configuration in {tag => {ROLE => [MEMBERS]}} format. | map(object({…})) | | {} |
+| [iam_members](variables.tf#L53) | Individual additive IAM bindings, use this when iam_additive does not work due to dynamic resources. Keys are arbitrary and only used for the internal loop. | map(object({…})) | | {} |
+| [location](variables.tf#L68) | Data Catalog Taxonomy location. | string | | "eu" |
+| [prefix](variables.tf#L79) | Optional prefix used to generate project id and name. | string | | null |
+| [tags](variables.tf#L93) | 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 6f79aebff..9e7f3a093 100644
--- a/modules/data-catalog-policy-tag/iam.tf
+++ b/modules/data-catalog-policy-tag/iam.tf
@@ -80,6 +80,14 @@ resource "google_data_catalog_taxonomy_iam_member" "members" {
taxonomy = google_data_catalog_taxonomy.default.id
role = each.value.role
member = each.value.member
+ dynamic "condition" {
+ for_each = each.value.condition == null ? [] : [""]
+ content {
+ expression = each.value.condition.expression
+ title = each.value.condition.title
+ description = each.value.condition.description
+ }
+ }
}
resource "google_data_catalog_policy_tag_iam_binding" "authoritative" {
diff --git a/modules/data-catalog-policy-tag/variables.tf b/modules/data-catalog-policy-tag/variables.tf
index c7c8eb072..2b799a961 100644
--- a/modules/data-catalog-policy-tag/variables.tf
+++ b/modules/data-catalog-policy-tag/variables.tf
@@ -55,6 +55,11 @@ variable "iam_members" {
type = map(object({
member = string
role = string
+ condition = optional(object({
+ expression = string
+ title = string
+ description = optional(string)
+ }))
}))
nullable = false
default = {}
diff --git a/modules/dataplex-datascan/README.md b/modules/dataplex-datascan/README.md
index 65436af68..ca8afca7c 100644
--- a/modules/dataplex-datascan/README.md
+++ b/modules/dataplex-datascan/README.md
@@ -433,9 +433,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#L161) | Name of Dataplex Scan. | string | ✓ | |
+| [project_id](variables.tf#L172) | The ID of the project where the Dataplex DataScan will be created. | string | ✓ | |
+| [region](variables.tf#L177) | 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 |
@@ -445,11 +445,11 @@ module "dataplex-datascan" {
| [iam](variables.tf#L107) | Dataplex DataScan IAM bindings in {ROLE => [MEMBERS]} format. | map(list(string)) | | {} |
| [iam_additive](variables.tf#L114) | IAM additive bindings in {ROLE => [MEMBERS]} format. | map(list(string)) | | {} |
| [iam_additive_members](variables.tf#L121) | IAM additive bindings in {MEMBERS => [ROLE]} format. This might break if members are dynamic values. | map(list(string)) | | {} |
-| [iam_members](variables.tf#L127) | Individual additive IAM bindings, use this when iam_additive does not work due to dynamic resources. Keys are arbitrary and only used for the internal loop. | map(object({…})) | | {} |
-| [iam_policy](variables.tf#L137) | IAM authoritative policy in {ROLE => [MEMBERS]} format. Roles and members not explicitly listed will be cleared, use with extreme caution. | map(list(string)) | | null |
-| [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_members](variables.tf#L127) | Individual additive IAM bindings, use this when iam_additive does not work due to dynamic resources. Keys are arbitrary and only used for the internal loop. | map(object({…})) | | {} |
+| [iam_policy](variables.tf#L142) | IAM authoritative policy in {ROLE => [MEMBERS]} format. Roles and members not explicitly listed will be cleared, use with extreme caution. | map(list(string)) | | null |
+| [incremental_field](variables.tf#L148) | 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#L154) | Resource labels. | map(string) | | {} |
+| [prefix](variables.tf#L166) | 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 e1a7c057c..2a6c4c781 100644
--- a/modules/dataplex-datascan/iam.tf
+++ b/modules/dataplex-datascan/iam.tf
@@ -76,6 +76,14 @@ resource "google_dataplex_datascan_iam_member" "members" {
data_scan_id = google_dataplex_datascan.datascan.data_scan_id
role = each.value.role
member = each.value.member
+ dynamic "condition" {
+ for_each = each.value.condition == null ? [] : [""]
+ content {
+ expression = each.value.condition.expression
+ title = each.value.condition.title
+ description = each.value.condition.description
+ }
+ }
}
resource "google_dataplex_datascan_iam_policy" "authoritative_for_resource" {
diff --git a/modules/dataplex-datascan/variables.tf b/modules/dataplex-datascan/variables.tf
index 47ca7332e..f40ca4ec1 100644
--- a/modules/dataplex-datascan/variables.tf
+++ b/modules/dataplex-datascan/variables.tf
@@ -129,6 +129,11 @@ variable "iam_members" {
type = map(object({
member = string
role = string
+ condition = optional(object({
+ expression = string
+ title = string
+ description = optional(string)
+ }))
}))
nullable = false
default = {}
diff --git a/modules/dataproc/README.md b/modules/dataproc/README.md
index 3e454e504..b9dfe3d0e 100644
--- a/modules/dataproc/README.md
+++ b/modules/dataproc/README.md
@@ -165,17 +165,17 @@ module "processing-dp-cluster" {
| name | description | type | required | default |
|---|---|:---:|:---:|:---:|
-| [name](variables.tf#L222) | Cluster name. | string | ✓ | |
-| [project_id](variables.tf#L237) | Project ID. | string | ✓ | |
-| [region](variables.tf#L242) | Dataproc region. | string | ✓ | |
+| [name](variables.tf#L227) | Cluster name. | string | ✓ | |
+| [project_id](variables.tf#L242) | Project ID. | string | ✓ | |
+| [region](variables.tf#L247) | 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_additive](variables.tf#L199) | IAM additive bindings in {ROLE => [MEMBERS]} format. | map(list(string)) | | {} |
-| [iam_members](variables.tf#L206) | Individual additive IAM bindings, use this when iam_additive does not work due to dynamic resources. Keys are arbitrary and only used for the internal loop. | map(object({…})) | | {} |
-| [labels](variables.tf#L216) | The resource labels for instance to use to annotate any related underlying resources, such as Compute Engine VMs. | map(string) | | {} |
-| [prefix](variables.tf#L227) | Optional prefix used to generate project id and name. | string | | null |
-| [service_account](variables.tf#L247) | Service account to set on the Dataproc cluster. | string | | null |
+| [iam_members](variables.tf#L206) | Individual additive IAM bindings, use this when iam_additive does not work due to dynamic resources. Keys are arbitrary and only used for the internal loop. | map(object({…})) | | {} |
+| [labels](variables.tf#L221) | The resource labels for instance to use to annotate any related underlying resources, such as Compute Engine VMs. | map(string) | | {} |
+| [prefix](variables.tf#L232) | Optional prefix used to generate project id and name. | string | | null |
+| [service_account](variables.tf#L252) | Service account to set on the Dataproc cluster. | string | | null |
## Outputs
diff --git a/modules/dataproc/iam.tf b/modules/dataproc/iam.tf
index 84d49f357..047561920 100644
--- a/modules/dataproc/iam.tf
+++ b/modules/dataproc/iam.tf
@@ -72,4 +72,12 @@ resource "google_dataproc_cluster_iam_member" "members" {
cluster = google_dataproc_cluster.cluster.name
role = each.value.role
member = each.value.member
+ dynamic "condition" {
+ for_each = each.value.condition == null ? [] : [""]
+ content {
+ expression = each.value.condition.expression
+ title = each.value.condition.title
+ description = each.value.condition.description
+ }
+ }
}
diff --git a/modules/dataproc/variables.tf b/modules/dataproc/variables.tf
index b28b9c279..37aad39fc 100644
--- a/modules/dataproc/variables.tf
+++ b/modules/dataproc/variables.tf
@@ -208,6 +208,11 @@ variable "iam_members" {
type = map(object({
member = string
role = string
+ condition = optional(object({
+ expression = string
+ title = string
+ description = optional(string)
+ }))
}))
nullable = false
default = {}
diff --git a/modules/folder/README.md b/modules/folder/README.md
index b46c5e8b9..03c2a7554 100644
--- a/modules/folder/README.md
+++ b/modules/folder/README.md
@@ -325,17 +325,17 @@ module "folder" {
| [iam](variables.tf#L44) | IAM bindings in {ROLE => [MEMBERS]} format. | map(list(string)) | | {} |
| [iam_additive](variables.tf#L51) | Non authoritative IAM bindings, in {ROLE => [MEMBERS]} format. | map(list(string)) | | {} |
| [iam_additive_members](variables.tf#L58) | IAM additive bindings in {MEMBERS => [ROLE]} format. This might break if members are dynamic values. | map(list(string)) | | {} |
-| [iam_members](variables.tf#L65) | Individual additive IAM bindings, use this when iam_additive does not work due to dynamic resources. Keys are arbitrary and only used for the internal loop. | map(object({…})) | | {} |
-| [iam_policy](variables.tf#L75) | IAM authoritative policy in {ROLE => [MEMBERS]} format. Roles and members not explicitly listed will be cleared, use with extreme caution. | map(list(string)) | | null |
-| [id](variables.tf#L81) | Folder ID in case you use folder_create=false. | string | | null |
-| [logging_data_access](variables.tf#L87) | 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#L102) | Logging exclusions for this folder in the form {NAME -> FILTER}. | map(string) | | {} |
-| [logging_sinks](variables.tf#L109) | Logging sinks to create for the organization. | map(object({…})) | | {} |
-| [name](variables.tf#L139) | Folder name. | string | | null |
-| [org_policies](variables.tf#L145) | Organization policies applied to this folder keyed by policy name. | map(object({…})) | | {} |
-| [org_policies_data_path](variables.tf#L172) | Path containing org policies in YAML format. | string | | null |
-| [parent](variables.tf#L178) | Parent in folders/folder_id or organizations/org_id format. | string | | null |
-| [tag_bindings](variables.tf#L188) | Tag bindings for this folder, in key => tag value id format. | map(string) | | null |
+| [iam_members](variables.tf#L65) | Individual additive IAM bindings, use this when iam_additive does not work due to dynamic resources. Keys are arbitrary and only used for the internal loop. | map(object({…})) | | {} |
+| [iam_policy](variables.tf#L80) | IAM authoritative policy in {ROLE => [MEMBERS]} format. Roles and members not explicitly listed will be cleared, use with extreme caution. | map(list(string)) | | null |
+| [id](variables.tf#L86) | Folder ID in case you use folder_create=false. | string | | null |
+| [logging_data_access](variables.tf#L92) | 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#L107) | Logging exclusions for this folder in the form {NAME -> FILTER}. | map(string) | | {} |
+| [logging_sinks](variables.tf#L114) | Logging sinks to create for the organization. | map(object({…})) | | {} |
+| [name](variables.tf#L144) | Folder name. | string | | null |
+| [org_policies](variables.tf#L150) | Organization policies applied to this folder keyed by policy name. | map(object({…})) | | {} |
+| [org_policies_data_path](variables.tf#L177) | Path containing org policies in YAML format. | string | | null |
+| [parent](variables.tf#L183) | Parent in folders/folder_id or organizations/org_id format. | string | | null |
+| [tag_bindings](variables.tf#L193) | 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 6b8fc1b18..cc457e289 100644
--- a/modules/folder/iam.tf
+++ b/modules/folder/iam.tf
@@ -69,6 +69,14 @@ resource "google_folder_iam_member" "members" {
folder = local.folder.name
role = each.value.role
member = each.value.member
+ dynamic "condition" {
+ for_each = each.value.condition == null ? [] : [""]
+ content {
+ expression = each.value.condition.expression
+ title = each.value.condition.title
+ description = each.value.condition.description
+ }
+ }
}
resource "google_folder_iam_policy" "authoritative" {
diff --git a/modules/folder/variables.tf b/modules/folder/variables.tf
index be7aad32a..df0579955 100644
--- a/modules/folder/variables.tf
+++ b/modules/folder/variables.tf
@@ -67,6 +67,11 @@ variable "iam_members" {
type = map(object({
member = string
role = string
+ condition = optional(object({
+ expression = string
+ title = string
+ description = optional(string)
+ }))
}))
nullable = false
default = {}
diff --git a/modules/iam-service-account/README.md b/modules/iam-service-account/README.md
index 061b651e7..6c03b8249 100644
--- a/modules/iam-service-account/README.md
+++ b/modules/iam-service-account/README.md
@@ -41,8 +41,8 @@ module "myproject-default-service-accounts" {
| name | description | type | required | default |
|---|---|:---:|:---:|:---:|
-| [name](variables.tf#L101) | Name of the service account to create. | string | ✓ | |
-| [project_id](variables.tf#L116) | Project id where service account will be created. | string | ✓ | |
+| [name](variables.tf#L106) | Name of the service account to create. | string | ✓ | |
+| [project_id](variables.tf#L121) | 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 |
@@ -50,14 +50,14 @@ module "myproject-default-service-accounts" {
| [iam_additive](variables.tf#L42) | IAM additive bindings on the service account in {ROLE => [MEMBERS]} format. | map(list(string)) | | {} |
| [iam_billing_roles](variables.tf#L49) | Billing account roles granted to this service account, by billing account id. Non-authoritative. | map(list(string)) | | {} |
| [iam_folder_roles](variables.tf#L56) | Folder roles granted to this service account, by folder id. Non-authoritative. | map(list(string)) | | {} |
-| [iam_members](variables.tf#L63) | Individual additive IAM bindings, use this when iam_additive does not work due to dynamic resources. Keys are arbitrary and only used for the internal loop. | map(object({…})) | | {} |
-| [iam_organization_roles](variables.tf#L73) | Organization roles granted to this service account, by organization id. Non-authoritative. | map(list(string)) | | {} |
-| [iam_project_roles](variables.tf#L80) | Project roles granted to this service account, by project id. | map(list(string)) | | {} |
-| [iam_sa_roles](variables.tf#L87) | Service account roles granted to this service account, by service account name. | map(list(string)) | | {} |
-| [iam_storage_roles](variables.tf#L94) | Storage roles granted to this service account, by bucket name. | map(list(string)) | | {} |
-| [prefix](variables.tf#L106) | Prefix applied to service account names. | string | | null |
-| [public_keys_directory](variables.tf#L121) | Path to public keys data files to upload to the service account (should have `.pem` extension). | string | | "" |
-| [service_account_create](variables.tf#L127) | Create service account. When set to false, uses a data source to reference an existing service account. | bool | | true |
+| [iam_members](variables.tf#L63) | Individual additive IAM bindings, use this when iam_additive does not work due to dynamic resources. Keys are arbitrary and only used for the internal loop. | map(object({…})) | | {} |
+| [iam_organization_roles](variables.tf#L78) | Organization roles granted to this service account, by organization id. Non-authoritative. | map(list(string)) | | {} |
+| [iam_project_roles](variables.tf#L85) | Project roles granted to this service account, by project id. | map(list(string)) | | {} |
+| [iam_sa_roles](variables.tf#L92) | Service account roles granted to this service account, by service account name. | map(list(string)) | | {} |
+| [iam_storage_roles](variables.tf#L99) | Storage roles granted to this service account, by bucket name. | map(list(string)) | | {} |
+| [prefix](variables.tf#L111) | Prefix applied to service account names. | string | | null |
+| [public_keys_directory](variables.tf#L126) | Path to public keys data files to upload to the service account (should have `.pem` extension). | string | | "" |
+| [service_account_create](variables.tf#L132) | 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 ae388c8e3..a92d5e2ad 100644
--- a/modules/iam-service-account/iam.tf
+++ b/modules/iam-service-account/iam.tf
@@ -139,6 +139,14 @@ resource "google_service_account_iam_member" "members" {
service_account_id = each.value.entity
role = each.value.role
member = each.value.member
+ dynamic "condition" {
+ for_each = each.value.condition == null ? [] : [""]
+ content {
+ expression = each.value.condition.expression
+ title = each.value.condition.title
+ description = each.value.condition.description
+ }
+ }
}
resource "google_storage_bucket_iam_member" "bucket-roles" {
diff --git a/modules/iam-service-account/variables.tf b/modules/iam-service-account/variables.tf
index 3594fbbcd..87c350b69 100644
--- a/modules/iam-service-account/variables.tf
+++ b/modules/iam-service-account/variables.tf
@@ -65,6 +65,11 @@ variable "iam_members" {
type = map(object({
member = string
role = string
+ condition = optional(object({
+ expression = string
+ title = string
+ description = optional(string)
+ }))
}))
nullable = false
default = {}
diff --git a/modules/kms/README.md b/modules/kms/README.md
index 7b8eb487c..5bd82d5f1 100644
--- a/modules/kms/README.md
+++ b/modules/kms/README.md
@@ -101,19 +101,19 @@ module "kms" {
| name | description | type | required | default |
|---|---|:---:|:---:|:---:|
-| [keyring](variables.tf#L91) | Keyring attributes. | object({…}) | ✓ | |
-| [project_id](variables.tf#L114) | Project id where the keyring will be created. | string | ✓ | |
+| [keyring](variables.tf#L101) | Keyring attributes. | object({…}) | ✓ | |
+| [project_id](variables.tf#L124) | Project id where the keyring will be created. | string | ✓ | |
| [iam](variables.tf#L17) | Keyring IAM bindings in {ROLE => [MEMBERS]} format. | map(list(string)) | | {} |
| [iam_additive](variables.tf#L23) | Keyring IAM additive bindings in {ROLE => [MEMBERS]} format. | map(list(string)) | | {} |
-| [iam_members](variables.tf#L29) | Individual additive IAM bindings, use this when iam_additive does not work due to dynamic resources. Keys are arbitrary and only used for the internal loop. | map(object({…})) | | {} |
-| [key_iam](variables.tf#L39) | Key IAM bindings in {KEY => {ROLE => [MEMBERS]}} format. | map(map(list(string))) | | {} |
-| [key_iam_additive](variables.tf#L45) | Key IAM additive bindings in {KEY => {ROLE => [MEMBERS]}} format. | map(map(list(string))) | | {} |
-| [key_iam_members](variables.tf#L51) | Individual additive IAM bindings, use this when iam_additive does not work due to dynamic resources. Keys are arbitrary and only used for the internal loop. | map(object({…})) | | {} |
-| [key_purpose](variables.tf#L62) | 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#L74) | 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#L99) | Set to false to manage keys and IAM bindings in an existing keyring. | bool | | true |
-| [keys](variables.tf#L105) | Key names and base attributes. Set attributes to null if not needed. | map(object({…})) | | {} |
-| [tag_bindings](variables.tf#L119) | Tag bindings for this keyring, in key => tag value id format. | map(string) | | null |
+| [iam_members](variables.tf#L29) | Individual additive IAM bindings, use this when iam_additive does not work due to dynamic resources. Keys are arbitrary and only used for the internal loop. | map(object({…})) | | {} |
+| [key_iam](variables.tf#L44) | Key IAM bindings in {KEY => {ROLE => [MEMBERS]}} format. | map(map(list(string))) | | {} |
+| [key_iam_additive](variables.tf#L50) | Key IAM additive bindings in {KEY => {ROLE => [MEMBERS]}} format. | map(map(list(string))) | | {} |
+| [key_iam_members](variables.tf#L56) | Individual additive IAM bindings, use this when iam_additive does not work due to dynamic resources. Keys are arbitrary and only used for the internal loop. | map(object({…})) | | {} |
+| [key_purpose](variables.tf#L72) | 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#L84) | 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#L109) | Set to false to manage keys and IAM bindings in an existing keyring. | bool | | true |
+| [keys](variables.tf#L115) | Key names and base attributes. Set attributes to null if not needed. | map(object({…})) | | {} |
+| [tag_bindings](variables.tf#L129) | 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 3da20d083..9289a4e83 100644
--- a/modules/kms/iam.tf
+++ b/modules/kms/iam.tf
@@ -67,6 +67,14 @@ resource "google_kms_key_ring_iam_member" "members" {
key_ring_id = local.keyring.id
role = each.value.role
member = each.value.member
+ dynamic "condition" {
+ for_each = each.value.condition == null ? [] : [""]
+ content {
+ expression = each.value.condition.expression
+ title = each.value.condition.title
+ description = each.value.condition.description
+ }
+ }
}
resource "google_kms_crypto_key_iam_binding" "default" {
@@ -94,4 +102,12 @@ resource "google_kms_crypto_key_iam_member" "members" {
crypto_key_id = google_kms_crypto_key.default[each.value.key].id
role = each.value.role
member = each.value.member
+ dynamic "condition" {
+ for_each = each.value.condition == null ? [] : [""]
+ content {
+ expression = each.value.condition.expression
+ title = each.value.condition.title
+ description = each.value.condition.description
+ }
+ }
}
diff --git a/modules/kms/variables.tf b/modules/kms/variables.tf
index 01e96c04a..c34aaaacc 100644
--- a/modules/kms/variables.tf
+++ b/modules/kms/variables.tf
@@ -31,6 +31,11 @@ variable "iam_members" {
type = map(object({
member = string
role = string
+ condition = optional(object({
+ expression = string
+ title = string
+ description = optional(string)
+ }))
}))
nullable = false
default = {}
@@ -54,6 +59,11 @@ variable "key_iam_members" {
key = string
member = string
role = string
+ condition = optional(object({
+ expression = string
+ title = string
+ description = optional(string)
+ }))
}))
nullable = false
default = {}
diff --git a/modules/net-vpc/README.md b/modules/net-vpc/README.md
index 8106e1d97..0ccfeb866 100644
--- a/modules/net-vpc/README.md
+++ b/modules/net-vpc/README.md
@@ -541,11 +541,11 @@ module "vpc" {
| [shared_vpc_service_projects](variables.tf#L161) | Shared VPC service projects to register with this host. | list(string) | | [] |
| [subnet_iam](variables.tf#L167) | Subnet IAM bindings in {REGION/NAME => {ROLE => [MEMBERS]} format. | map(map(list(string))) | | {} |
| [subnet_iam_additive](variables.tf#L173) | Subnet IAM additive bindings in {REGION/NAME => {ROLE => [MEMBERS]}} format. | map(map(list(string))) | | {} |
-| [subnet_iam_members](variables.tf#L180) | Individual additive IAM bindings, use this when iam_additive does not work due to dynamic resources. Keys are arbitrary and only used for the internal loop. | map(object({…})) | | {} |
-| [subnets](variables.tf#L191) | Subnet configuration. | list(object({…})) | | [] |
-| [subnets_proxy_only](variables.tf#L217) | List of proxy-only subnets for Regional HTTPS or Internal HTTPS load balancers. Note: Only one proxy-only subnet for each VPC network in each region can be active. | list(object({…})) | | [] |
-| [subnets_psc](variables.tf#L229) | List of subnets for Private Service Connect service producers. | list(object({…})) | | [] |
-| [vpc_create](variables.tf#L240) | Create VPC. When set to false, uses a data source to reference existing VPC. | bool | | true |
+| [subnet_iam_members](variables.tf#L180) | Individual additive IAM bindings, use this when iam_additive does not work due to dynamic resources. Keys are arbitrary and only used for the internal loop. | map(object({…})) | | {} |
+| [subnets](variables.tf#L196) | Subnet configuration. | list(object({…})) | | [] |
+| [subnets_proxy_only](variables.tf#L222) | List of proxy-only subnets for Regional HTTPS or Internal HTTPS load balancers. Note: Only one proxy-only subnet for each VPC network in each region can be active. | list(object({…})) | | [] |
+| [subnets_psc](variables.tf#L234) | List of subnets for Private Service Connect service producers. | list(object({…})) | | [] |
+| [vpc_create](variables.tf#L245) | Create VPC. When set to false, uses a data source to reference existing VPC. | bool | | true |
## Outputs
diff --git a/modules/net-vpc/subnets.tf b/modules/net-vpc/subnets.tf
index 16f6398c7..b6eab1821 100644
--- a/modules/net-vpc/subnets.tf
+++ b/modules/net-vpc/subnets.tf
@@ -197,4 +197,12 @@ resource "google_compute_subnetwork_iam_member" "members" {
region = google_compute_subnetwork.subnetwork[each.value.subnet].region
role = each.value.role
member = each.value.member
+ dynamic "condition" {
+ for_each = each.value.condition == null ? [] : [""]
+ content {
+ expression = each.value.condition.expression
+ title = each.value.condition.title
+ description = each.value.condition.description
+ }
+ }
}
diff --git a/modules/net-vpc/variables.tf b/modules/net-vpc/variables.tf
index 4e114dfe5..c49455fab 100644
--- a/modules/net-vpc/variables.tf
+++ b/modules/net-vpc/variables.tf
@@ -183,6 +183,11 @@ variable "subnet_iam_members" {
member = string
role = string
subnet = string
+ condition = optional(object({
+ expression = string
+ title = string
+ description = optional(string)
+ }))
}))
nullable = false
default = {}
diff --git a/modules/organization/README.md b/modules/organization/README.md
index d232dfd43..4984d2a83 100644
--- a/modules/organization/README.md
+++ b/modules/organization/README.md
@@ -475,7 +475,7 @@ module "org" {
| name | description | type | required | default |
|---|---|:---:|:---:|:---:|
-| [organization_id](variables.tf#L209) | Organization id in organizations/nnnnnn format. | string | ✓ | |
+| [organization_id](variables.tf#L214) | 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_associations](variables.tf#L31) | Hierarchical firewall policies to associate to this folder, in association name => policy id format. | map(string) | | {} |
@@ -483,18 +483,18 @@ module "org" {
| [iam](variables.tf#L45) | IAM bindings, in {ROLE => [MEMBERS]} format. | map(list(string)) | | {} |
| [iam_additive](variables.tf#L52) | Non authoritative IAM bindings, in {ROLE => [MEMBERS]} format. | map(list(string)) | | {} |
| [iam_additive_members](variables.tf#L59) | IAM additive bindings in {MEMBERS => [ROLE]} format. This might break if members are dynamic values. | map(list(string)) | | {} |
-| [iam_members](variables.tf#L66) | Individual additive IAM bindings, use this when iam_additive does not work due to dynamic resources. Keys are arbitrary and only used for the internal loop. | map(object({…})) | | {} |
-| [iam_policy](variables.tf#L76) | IAM authoritative policy in {ROLE => [MEMBERS]} format. Roles and members not explicitly listed will be cleared, use with extreme caution. | map(list(string)) | | null |
-| [logging_data_access](variables.tf#L82) | 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#L97) | Logging exclusions for this organization in the form {NAME -> FILTER}. | map(string) | | {} |
-| [logging_sinks](variables.tf#L104) | Logging sinks to create for the organization. | map(object({…})) | | {} |
-| [network_tags](variables.tf#L134) | 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#L156) | Organization policies applied to this organization keyed by policy name. | map(object({…})) | | {} |
-| [org_policies_data_path](variables.tf#L183) | Path containing org policies in YAML format. | string | | null |
-| [org_policy_custom_constraints](variables.tf#L189) | Organization policy custom constraints keyed by constraint name. | map(object({…})) | | {} |
-| [org_policy_custom_constraints_data_path](variables.tf#L203) | Path containing org policy custom constraints in YAML format. | string | | null |
-| [tag_bindings](variables.tf#L218) | Tag bindings for this organization, in key => tag value id format. | map(string) | | null |
-| [tags](variables.tf#L224) | 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_members](variables.tf#L66) | Individual additive IAM bindings, use this when iam_additive does not work due to dynamic resources. Keys are arbitrary and only used for the internal loop. | map(object({…})) | | {} |
+| [iam_policy](variables.tf#L81) | IAM authoritative policy in {ROLE => [MEMBERS]} format. Roles and members not explicitly listed will be cleared, use with extreme caution. | map(list(string)) | | null |
+| [logging_data_access](variables.tf#L87) | 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#L102) | Logging exclusions for this organization in the form {NAME -> FILTER}. | map(string) | | {} |
+| [logging_sinks](variables.tf#L109) | Logging sinks to create for the organization. | map(object({…})) | | {} |
+| [network_tags](variables.tf#L139) | 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#L161) | Organization policies applied to this organization keyed by policy name. | map(object({…})) | | {} |
+| [org_policies_data_path](variables.tf#L188) | Path containing org policies in YAML format. | string | | null |
+| [org_policy_custom_constraints](variables.tf#L194) | Organization policy custom constraints keyed by constraint name. | map(object({…})) | | {} |
+| [org_policy_custom_constraints_data_path](variables.tf#L208) | Path containing org policy custom constraints in YAML format. | string | | null |
+| [tag_bindings](variables.tf#L223) | Tag bindings for this organization, in key => tag value id format. | map(string) | | null |
+| [tags](variables.tf#L229) | 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 f5d3b2d7c..e5ba3771b 100644
--- a/modules/organization/iam.tf
+++ b/modules/organization/iam.tf
@@ -78,6 +78,14 @@ resource "google_organization_iam_member" "members" {
org_id = local.organization_id_numeric
role = each.value.role
member = each.value.member
+ dynamic "condition" {
+ for_each = each.value.condition == null ? [] : [""]
+ content {
+ expression = each.value.condition.expression
+ title = each.value.condition.title
+ description = each.value.condition.description
+ }
+ }
}
resource "google_organization_iam_policy" "authoritative" {
diff --git a/modules/organization/variables.tf b/modules/organization/variables.tf
index 65f0672be..2426f8e91 100644
--- a/modules/organization/variables.tf
+++ b/modules/organization/variables.tf
@@ -68,6 +68,11 @@ variable "iam_members" {
type = map(object({
member = string
role = string
+ condition = optional(object({
+ expression = string
+ title = string
+ description = optional(string)
+ }))
}))
nullable = false
default = {}
diff --git a/modules/project/README.md b/modules/project/README.md
index 8a867b519..8ec483fb2 100644
--- a/modules/project/README.md
+++ b/modules/project/README.md
@@ -154,7 +154,7 @@ module "project" {
#### Additive IAM by Binding
-When the above approaches to additive IAM are unworkable due to dynamically generated principals, the `iam_members` variable allows specifying individual role/principal pairs using arbitrary keys:
+When the above approaches to additive IAM are unworkable due to dynamically generated principals, the `iam_members` variable allows specifying individual role/principal pairs using arbitrary keys. This IAM variable also supports conditions.
```hcl
module "project" {
@@ -173,10 +173,23 @@ module "project" {
member = "user:two@example.org"
role = "roles/compute.admin"
}
+ one-delegated-grant = {
+ member = "user:one@example.org"
+ role = "roles/resourcemanager.projectIamAdmin"
+ condition = {
+ title = "delegated_network_user_one"
+ expression = <<-END
+ api.getAttribute(
+ 'iam.googleapis.com/modifiedGrantsByRole', []
+ ).hasOnly([
+ 'roles/compute.networkAdmin'
+ ])
+ END
+ }
+ }
}
-
}
-# tftest modules=1 resources=4 inventory=iam-members.yaml
+# tftest modules=1 resources=5 inventory=iam-members.yaml
```
### Service Identities and Authoritative IAM
@@ -658,7 +671,7 @@ output "compute_robot" {
| name | description | type | required | default |
|---|---|:---:|:---:|:---:|
-| [name](variables.tf#L171) | Project name and id suffix. | string | ✓ | |
+| [name](variables.tf#L176) | 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 |
| [contacts](variables.tf#L29) | 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)) | | {} |
@@ -669,31 +682,31 @@ output "compute_robot" {
| [iam](variables.tf#L62) | IAM bindings in {ROLE => [MEMBERS]} format. | map(list(string)) | | {} |
| [iam_additive](variables.tf#L69) | IAM additive bindings in {ROLE => [MEMBERS]} format. | map(list(string)) | | {} |
| [iam_additive_members](variables.tf#L76) | IAM additive bindings in {MEMBERS => [ROLE]} format. This might break if members are dynamic values. | map(list(string)) | | {} |
-| [iam_members](variables.tf#L82) | Individual additive IAM bindings, use this when iam_additive does not work due to dynamic resources. Keys are arbitrary and only used for the internal loop. | map(object({…})) | | {} |
-| [iam_policy](variables.tf#L92) | IAM authoritative policy in {ROLE => [MEMBERS]} format. Roles and members not explicitly listed will be cleared, use with extreme caution. | map(list(string)) | | null |
-| [labels](variables.tf#L98) | Resource labels. | map(string) | | {} |
-| [lien_reason](variables.tf#L105) | If non-empty, creates a project lien with this description. | string | | "" |
-| [logging_data_access](variables.tf#L111) | 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#L126) | Logging exclusions for this project in the form {NAME -> FILTER}. | map(string) | | {} |
-| [logging_sinks](variables.tf#L133) | Logging sinks to create for this project. | map(object({…})) | | {} |
-| [metric_scopes](variables.tf#L164) | List of projects that will act as metric scopes for this project. | list(string) | | [] |
-| [org_policies](variables.tf#L176) | Organization policies applied to this project keyed by policy name. | map(object({…})) | | {} |
-| [org_policies_data_path](variables.tf#L203) | Path containing org policies in YAML format. | string | | null |
-| [oslogin](variables.tf#L209) | Enable OS Login. | bool | | false |
-| [oslogin_admins](variables.tf#L215) | List of IAM-style identities that will be granted roles necessary for OS Login administrators. | list(string) | | [] |
-| [oslogin_users](variables.tf#L223) | List of IAM-style identities that will be granted roles necessary for OS Login users. | list(string) | | [] |
-| [parent](variables.tf#L230) | Parent folder or organization in 'folders/folder_id' or 'organizations/org_id' format. | string | | null |
-| [prefix](variables.tf#L240) | Optional prefix used to generate project id and name. | string | | null |
-| [project_create](variables.tf#L250) | Create project. When set to false, uses a data source to reference existing project. | bool | | true |
-| [service_config](variables.tf#L256) | Configure service API activation. | object({…}) | | {…} |
-| [service_encryption_key_ids](variables.tf#L268) | Cloud KMS encryption key in {SERVICE => [KEY_URL]} format. | map(list(string)) | | {} |
-| [service_perimeter_bridges](variables.tf#L275) | 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#L282) | Name of VPC-SC Standard perimeter to add project into. See comment in the variables file for format. | string | | null |
-| [services](variables.tf#L288) | Service APIs to enable. | list(string) | | [] |
-| [shared_vpc_host_config](variables.tf#L294) | Configures this project as a Shared VPC host project (mutually exclusive with shared_vpc_service_project). | object({…}) | | null |
-| [shared_vpc_service_config](variables.tf#L303) | Configures this project as a Shared VPC service project (mutually exclusive with shared_vpc_host_config). | object({…}) | | {…} |
-| [skip_delete](variables.tf#L325) | Allows the underlying resources to be destroyed without destroying the project itself. | bool | | false |
-| [tag_bindings](variables.tf#L331) | Tag bindings for this project, in key => tag value id format. | map(string) | | null |
+| [iam_members](variables.tf#L82) | Individual additive IAM bindings, use this when iam_additive does not work due to dynamic resources. Keys are arbitrary and only used for the internal loop. | map(object({…})) | | {} |
+| [iam_policy](variables.tf#L97) | IAM authoritative policy in {ROLE => [MEMBERS]} format. Roles and members not explicitly listed will be cleared, use with extreme caution. | map(list(string)) | | null |
+| [labels](variables.tf#L103) | Resource labels. | map(string) | | {} |
+| [lien_reason](variables.tf#L110) | If non-empty, creates a project lien with this description. | string | | "" |
+| [logging_data_access](variables.tf#L116) | 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#L131) | Logging exclusions for this project in the form {NAME -> FILTER}. | map(string) | | {} |
+| [logging_sinks](variables.tf#L138) | Logging sinks to create for this project. | map(object({…})) | | {} |
+| [metric_scopes](variables.tf#L169) | List of projects that will act as metric scopes for this project. | list(string) | | [] |
+| [org_policies](variables.tf#L181) | Organization policies applied to this project keyed by policy name. | map(object({…})) | | {} |
+| [org_policies_data_path](variables.tf#L208) | Path containing org policies in YAML format. | string | | null |
+| [oslogin](variables.tf#L214) | Enable OS Login. | bool | | false |
+| [oslogin_admins](variables.tf#L220) | List of IAM-style identities that will be granted roles necessary for OS Login administrators. | list(string) | | [] |
+| [oslogin_users](variables.tf#L228) | List of IAM-style identities that will be granted roles necessary for OS Login users. | list(string) | | [] |
+| [parent](variables.tf#L235) | Parent folder or organization in 'folders/folder_id' or 'organizations/org_id' format. | string | | null |
+| [prefix](variables.tf#L245) | Optional prefix used to generate project id and name. | string | | null |
+| [project_create](variables.tf#L255) | Create project. When set to false, uses a data source to reference existing project. | bool | | true |
+| [service_config](variables.tf#L261) | Configure service API activation. | object({…}) | | {…} |
+| [service_encryption_key_ids](variables.tf#L273) | Cloud KMS encryption key in {SERVICE => [KEY_URL]} format. | map(list(string)) | | {} |
+| [service_perimeter_bridges](variables.tf#L280) | 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#L287) | Name of VPC-SC Standard perimeter to add project into. See comment in the variables file for format. | string | | null |
+| [services](variables.tf#L293) | Service APIs to enable. | list(string) | | [] |
+| [shared_vpc_host_config](variables.tf#L299) | Configures this project as a Shared VPC host project (mutually exclusive with shared_vpc_service_project). | object({…}) | | null |
+| [shared_vpc_service_config](variables.tf#L308) | Configures this project as a Shared VPC service project (mutually exclusive with shared_vpc_host_config). | object({…}) | | {…} |
+| [skip_delete](variables.tf#L330) | Allows the underlying resources to be destroyed without destroying the project itself. | bool | | false |
+| [tag_bindings](variables.tf#L336) | 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 7b67d895c..0918b5529 100644
--- a/modules/project/iam.tf
+++ b/modules/project/iam.tf
@@ -102,6 +102,14 @@ resource "google_project_iam_member" "members" {
project = local.project.project_id
role = each.value.role
member = each.value.member
+ dynamic "condition" {
+ for_each = each.value.condition == null ? [] : [""]
+ content {
+ expression = each.value.condition.expression
+ title = each.value.condition.title
+ description = each.value.condition.description
+ }
+ }
depends_on = [
google_project_service.project_services,
google_project_iam_custom_role.roles
diff --git a/modules/project/variables.tf b/modules/project/variables.tf
index 4ab510626..18f55886b 100644
--- a/modules/project/variables.tf
+++ b/modules/project/variables.tf
@@ -84,6 +84,11 @@ variable "iam_members" {
type = map(object({
member = string
role = string
+ condition = optional(object({
+ expression = string
+ title = string
+ description = optional(string)
+ }))
}))
nullable = false
default = {}
diff --git a/modules/source-repository/README.md b/modules/source-repository/README.md
index 4cfae8eae..01fff2d8f 100644
--- a/modules/source-repository/README.md
+++ b/modules/source-repository/README.md
@@ -75,14 +75,14 @@ module "repo" {
| name | description | type | required | default |
|---|---|:---:|:---:|:---:|
-| [name](variables.tf#L54) | Repository name. | string | ✓ | |
-| [project_id](variables.tf#L59) | Project used for resources. | string | ✓ | |
+| [name](variables.tf#L59) | Repository name. | string | ✓ | |
+| [project_id](variables.tf#L64) | 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_additive](variables.tf#L31) | IAM additive bindings in {ROLE => [MEMBERS]} format. | map(list(string)) | | {} |
| [iam_additive_members](variables.tf#L38) | IAM additive bindings in {MEMBERS => [ROLE]} format. This might break if members are dynamic values. | map(list(string)) | | {} |
-| [iam_members](variables.tf#L44) | Individual additive IAM bindings, use this when iam_additive does not work due to dynamic resources. Keys are arbitrary and only used for the internal loop. | map(object({…})) | | {} |
-| [triggers](variables.tf#L64) | Cloud Build triggers. | map(object({…})) | | {} |
+| [iam_members](variables.tf#L44) | Individual additive IAM bindings, use this when iam_additive does not work due to dynamic resources. Keys are arbitrary and only used for the internal loop. | map(object({…})) | | {} |
+| [triggers](variables.tf#L69) | Cloud Build triggers. | map(object({…})) | | {} |
## Outputs
diff --git a/modules/source-repository/iam.tf b/modules/source-repository/iam.tf
index f1ec3ebca..75d00fd18 100644
--- a/modules/source-repository/iam.tf
+++ b/modules/source-repository/iam.tf
@@ -72,4 +72,12 @@ resource "google_sourcerepo_repository_iam_member" "members" {
repository = google_sourcerepo_repository.default.name
role = each.value.role
member = each.value.member
+ dynamic "condition" {
+ for_each = each.value.condition == null ? [] : [""]
+ content {
+ expression = each.value.condition.expression
+ title = each.value.condition.title
+ description = each.value.condition.description
+ }
+ }
}
diff --git a/modules/source-repository/variables.tf b/modules/source-repository/variables.tf
index 74e44aa45..61975fb94 100644
--- a/modules/source-repository/variables.tf
+++ b/modules/source-repository/variables.tf
@@ -46,6 +46,11 @@ variable "iam_members" {
type = map(object({
member = string
role = string
+ condition = optional(object({
+ expression = string
+ title = string
+ description = optional(string)
+ }))
}))
nullable = false
default = {}
diff --git a/tests/modules/project/examples/iam-members.yaml b/tests/modules/project/examples/iam-members.yaml
index b80fc2bf1..41f48a562 100644
--- a/tests/modules/project/examples/iam-members.yaml
+++ b/tests/modules/project/examples/iam-members.yaml
@@ -23,6 +23,15 @@ values:
project_id: project-example
skip_delete: false
timeouts: null
+ module.project.google_project_iam_member.members["one-delegated-grant"]:
+ condition:
+ - description: null
+ expression: "api.getAttribute(\n 'iam.googleapis.com/modifiedGrantsByRole',\
+ \ []\n).hasOnly([\n 'roles/compute.networkAdmin'\n])\n"
+ title: delegated_network_user_one
+ member: user:one@example.org
+ project: project-example
+ role: roles/resourcemanager.projectIamAdmin
module.project.google_project_iam_member.members["one-owner"]:
condition: []
member: user:one@example.org
@@ -41,8 +50,9 @@ values:
counts:
google_project: 1
- google_project_iam_member: 3
+ google_project_iam_member: 4
modules: 1
- resources: 4
+ resources: 5
outputs: {}
+