Implement the full IAM interface for tags (#2269)

* IAM authoritative bindings in org module

* remove extra newline

* organization module

* project module

* tfdoc
This commit is contained in:
Ludovico Magnocavallo
2024-05-13 20:18:51 +02:00
committed by GitHub
parent 604920dec9
commit e4941c27f2
9 changed files with 504 additions and 104 deletions

View File

@@ -120,14 +120,14 @@ module "kms" {
| name | description | type | required | default |
|---|---|:---:|:---:|:---:|
| [keyring](variables.tf#L64) | Keyring attributes. | <code title="object&#40;&#123;&#10; location &#61; string&#10; name &#61; string&#10;&#125;&#41;">object&#40;&#123;&#8230;&#125;&#41;</code> | ✓ | |
| [project_id](variables.tf#L115) | Project id where the keyring will be created. | <code>string</code> | ✓ | |
| [project_id](variables.tf#L114) | Project id where the keyring will be created. | <code>string</code> | ✓ | |
| [iam](variables.tf#L17) | Keyring IAM bindings in {ROLE => [MEMBERS]} format. | <code>map&#40;list&#40;string&#41;&#41;</code> | | <code>&#123;&#125;</code> |
| [iam_bindings](variables.tf#L24) | Authoritative IAM bindings in {KEY => {role = ROLE, members = [], condition = {}}}. Keys are arbitrary. | <code title="map&#40;object&#40;&#123;&#10; members &#61; list&#40;string&#41;&#10; role &#61; string&#10; condition &#61; optional&#40;object&#40;&#123;&#10; expression &#61; string&#10; title &#61; string&#10; description &#61; optional&#40;string&#41;&#10; &#125;&#41;&#41;&#10;&#125;&#41;&#41;">map&#40;object&#40;&#123;&#8230;&#125;&#41;&#41;</code> | | <code>&#123;&#125;</code> |
| [iam_bindings_additive](variables.tf#L39) | Keyring individual additive IAM bindings. Keys are arbitrary. | <code title="map&#40;object&#40;&#123;&#10; member &#61; string&#10; role &#61; string&#10; condition &#61; optional&#40;object&#40;&#123;&#10; expression &#61; string&#10; title &#61; string&#10; description &#61; optional&#40;string&#41;&#10; &#125;&#41;&#41;&#10;&#125;&#41;&#41;">map&#40;object&#40;&#123;&#8230;&#125;&#41;&#41;</code> | | <code>&#123;&#125;</code> |
| [import_job](variables.tf#L54) | Keyring import job attributes. | <code title="object&#40;&#123;&#10; id &#61; string&#10; import_method &#61; string&#10; protection_level &#61; string&#10;&#125;&#41;">object&#40;&#123;&#8230;&#125;&#41;</code> | | <code>null</code> |
| [keyring_create](variables.tf#L72) | Set to false to manage keys and IAM bindings in an existing keyring. | <code>bool</code> | | <code>true</code> |
| [keys](variables.tf#L78) | Key names and base attributes. Set attributes to null if not needed. | <code title="map&#40;object&#40;&#123;&#10; destroy_scheduled_duration &#61; optional&#40;string&#41;&#10; rotation_period &#61; optional&#40;string&#41;&#10; labels &#61; optional&#40;map&#40;string&#41;&#41;&#10; purpose &#61; optional&#40;string, &#34;ENCRYPT_DECRYPT&#34;&#41;&#10; skip_initial_version_creation &#61; optional&#40;bool, false&#41;&#10; version_template &#61; optional&#40;object&#40;&#123;&#10; algorithm &#61; string&#10; protection_level &#61; optional&#40;string, &#34;SOFTWARE&#34;&#41;&#10; &#125;&#41;&#41;&#10;&#10;&#10; iam &#61; optional&#40;map&#40;list&#40;string&#41;&#41;, &#123;&#125;&#41;&#10; iam_bindings &#61; optional&#40;map&#40;object&#40;&#123;&#10; members &#61; list&#40;string&#41;&#10; role &#61; string&#10; condition &#61; optional&#40;object&#40;&#123;&#10; expression &#61; string&#10; title &#61; string&#10; description &#61; optional&#40;string&#41;&#10; &#125;&#41;&#41;&#10; &#125;&#41;&#41;, &#123;&#125;&#41;&#10; iam_bindings_additive &#61; optional&#40;map&#40;object&#40;&#123;&#10; member &#61; string&#10; role &#61; string&#10; condition &#61; optional&#40;object&#40;&#123;&#10; expression &#61; string&#10; title &#61; string&#10; description &#61; optional&#40;string&#41;&#10; &#125;&#41;&#41;&#10; &#125;&#41;&#41;, &#123;&#125;&#41;&#10;&#125;&#41;&#41;">map&#40;object&#40;&#123;&#8230;&#125;&#41;&#41;</code> | | <code>&#123;&#125;</code> |
| [tag_bindings](variables.tf#L120) | Tag bindings for this keyring, in key => tag value id format. | <code>map&#40;string&#41;</code> | | <code>&#123;&#125;</code> |
| [keys](variables.tf#L78) | Key names and base attributes. Set attributes to null if not needed. | <code title="map&#40;object&#40;&#123;&#10; destroy_scheduled_duration &#61; optional&#40;string&#41;&#10; rotation_period &#61; optional&#40;string&#41;&#10; labels &#61; optional&#40;map&#40;string&#41;&#41;&#10; purpose &#61; optional&#40;string, &#34;ENCRYPT_DECRYPT&#34;&#41;&#10; skip_initial_version_creation &#61; optional&#40;bool, false&#41;&#10; version_template &#61; optional&#40;object&#40;&#123;&#10; algorithm &#61; string&#10; protection_level &#61; optional&#40;string, &#34;SOFTWARE&#34;&#41;&#10; &#125;&#41;&#41;&#10; iam &#61; optional&#40;map&#40;list&#40;string&#41;&#41;, &#123;&#125;&#41;&#10; iam_bindings &#61; optional&#40;map&#40;object&#40;&#123;&#10; members &#61; list&#40;string&#41;&#10; role &#61; string&#10; condition &#61; optional&#40;object&#40;&#123;&#10; expression &#61; string&#10; title &#61; string&#10; description &#61; optional&#40;string&#41;&#10; &#125;&#41;&#41;&#10; &#125;&#41;&#41;, &#123;&#125;&#41;&#10; iam_bindings_additive &#61; optional&#40;map&#40;object&#40;&#123;&#10; member &#61; string&#10; role &#61; string&#10; condition &#61; optional&#40;object&#40;&#123;&#10; expression &#61; string&#10; title &#61; string&#10; description &#61; optional&#40;string&#41;&#10; &#125;&#41;&#41;&#10; &#125;&#41;&#41;, &#123;&#125;&#41;&#10;&#125;&#41;&#41;">map&#40;object&#40;&#123;&#8230;&#125;&#41;&#41;</code> | | <code>&#123;&#125;</code> |
| [tag_bindings](variables.tf#L119) | Tag bindings for this keyring, in key => tag value id format. | <code>map&#40;string&#41;</code> | | <code>&#123;&#125;</code> |
## Outputs

View File

@@ -87,7 +87,6 @@ variable "keys" {
algorithm = string
protection_level = optional(string, "SOFTWARE")
}))
iam = optional(map(list(string)), {})
iam_bindings = optional(map(object({
members = list(string)

View File

@@ -440,12 +440,44 @@ module "org" {
iam = {
"roles/resourcemanager.tagAdmin" = ["group:${var.group_email}"]
}
iam_bindings = {
viewer = {
role = "roles/resourcemanager.tagViewer"
members = ["group:gcp-support@example.org"]
}
}
iam_bindings_additive = {
user_app1 = {
role = "roles/resourcemanager.tagUser"
member = "group:app1-team@example.org"
}
}
values = {
dev = {}
dev = {
iam_bindings_additive = {
user_app2 = {
role = "roles/resourcemanager.tagUser"
member = "group:app2-team@example.org"
}
}
}
prod = {
description = "Environment: production."
iam = {
"roles/resourcemanager.tagViewer" = ["group:${var.group_email}"]
"roles/resourcemanager.tagViewer" = ["group:app1-team@example.org"]
}
iam_bindings = {
admin = {
role = "roles/resourcemanager.tagAdmin"
members = ["group:gcp-support@example.org"]
condition = {
title = "gcp_support"
expression = <<-END
request.time.getHours("Europe/Berlin") <= 9 &&
request.time.getHours("Europe/Berlin") >= 17
END
}
}
}
}
}
@@ -455,8 +487,9 @@ module "org" {
env-prod = module.org.tag_values["environment/prod"].id
}
}
# tftest modules=1 resources=6 inventory=tags.yaml e2e serial
# tftest modules=1 resources=10 inventory=tags.yaml
```
<!-- TODO: reinstate e2e serial -->
You can also define network tags, through a dedicated variable *network_tags*:
@@ -498,7 +531,7 @@ module "org" {
| [org-policy-custom-constraints.tf](./org-policy-custom-constraints.tf) | None | <code>google_org_policy_custom_constraint</code> |
| [organization-policies.tf](./organization-policies.tf) | Organization-level organization policies. | <code>google_org_policy_policy</code> |
| [outputs.tf](./outputs.tf) | Module outputs. | |
| [tags.tf](./tags.tf) | None | <code>google_tags_tag_binding</code> · <code>google_tags_tag_key</code> · <code>google_tags_tag_key_iam_binding</code> · <code>google_tags_tag_value</code> · <code>google_tags_tag_value_iam_binding</code> |
| [tags.tf](./tags.tf) | None | <code>google_tags_tag_binding</code> · <code>google_tags_tag_key</code> · <code>google_tags_tag_key_iam_binding</code> · <code>google_tags_tag_key_iam_member</code> · <code>google_tags_tag_value</code> · <code>google_tags_tag_value_iam_binding</code> · <code>google_tags_tag_value_iam_member</code> |
| [variables-iam.tf](./variables-iam.tf) | None | |
| [variables-logging.tf](./variables-logging.tf) | None | |
| [variables-tags.tf](./variables-tags.tf) | None | |
@@ -522,11 +555,11 @@ module "org" {
| [logging_exclusions](variables-logging.tf#L32) | Logging exclusions for this organization in the form {NAME -> FILTER}. | <code>map&#40;string&#41;</code> | | <code>&#123;&#125;</code> |
| [logging_settings](variables-logging.tf#L39) | Default settings for logging resources. | <code title="object&#40;&#123;&#10; disable_default_sink &#61; optional&#40;bool&#41;&#10; storage_location &#61; optional&#40;string&#41;&#10;&#125;&#41;">object&#40;&#123;&#8230;&#125;&#41;</code> | | <code>null</code> |
| [logging_sinks](variables-logging.tf#L49) | Logging sinks to create for the organization. | <code title="map&#40;object&#40;&#123;&#10; bq_partitioned_table &#61; optional&#40;bool, false&#41;&#10; description &#61; optional&#40;string&#41;&#10; destination &#61; string&#10; disabled &#61; optional&#40;bool, false&#41;&#10; exclusions &#61; optional&#40;map&#40;string&#41;, &#123;&#125;&#41;&#10; filter &#61; optional&#40;string&#41;&#10; iam &#61; optional&#40;bool, true&#41;&#10; include_children &#61; optional&#40;bool, true&#41;&#10; type &#61; string&#10;&#125;&#41;&#41;">map&#40;object&#40;&#123;&#8230;&#125;&#41;&#41;</code> | | <code>&#123;&#125;</code> |
| [network_tags](variables-tags.tf#L17) | 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. | <code title="map&#40;object&#40;&#123;&#10; description &#61; optional&#40;string, &#34;Managed by the Terraform organization module.&#34;&#41;&#10; iam &#61; optional&#40;map&#40;list&#40;string&#41;&#41;, &#123;&#125;&#41;&#10; id &#61; optional&#40;string&#41;&#10; network &#61; string &#35; project_id&#47;vpc_name&#10; values &#61; optional&#40;map&#40;object&#40;&#123;&#10; description &#61; optional&#40;string, &#34;Managed by the Terraform organization module.&#34;&#41;&#10; iam &#61; optional&#40;map&#40;list&#40;string&#41;&#41;, &#123;&#125;&#41;&#10; &#125;&#41;&#41;, &#123;&#125;&#41;&#10;&#125;&#41;&#41;">map&#40;object&#40;&#123;&#8230;&#125;&#41;&#41;</code> | | <code>&#123;&#125;</code> |
| [network_tags](variables-tags.tf#L17) | 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. | <code title="map&#40;object&#40;&#123;&#10; description &#61; optional&#40;string, &#34;Managed by the Terraform organization module.&#34;&#41;&#10; iam &#61; optional&#40;map&#40;list&#40;string&#41;&#41;, &#123;&#125;&#41;&#10; iam_bindings &#61; optional&#40;map&#40;object&#40;&#123;&#10; members &#61; list&#40;string&#41;&#10; role &#61; string&#10; condition &#61; optional&#40;object&#40;&#123;&#10; expression &#61; string&#10; title &#61; string&#10; description &#61; optional&#40;string&#41;&#10; &#125;&#41;&#41;&#10; &#125;&#41;&#41;, &#123;&#125;&#41;&#10; iam_bindings_additive &#61; optional&#40;map&#40;object&#40;&#123;&#10; member &#61; string&#10; role &#61; string&#10; condition &#61; optional&#40;object&#40;&#123;&#10; expression &#61; string&#10; title &#61; string&#10; description &#61; optional&#40;string&#41;&#10; &#125;&#41;&#41;&#10; &#125;&#41;&#41;, &#123;&#125;&#41;&#10; id &#61; optional&#40;string&#41;&#10; network &#61; string &#35; project_id&#47;vpc_name&#10; values &#61; optional&#40;map&#40;object&#40;&#123;&#10; description &#61; optional&#40;string, &#34;Managed by the Terraform organization module.&#34;&#41;&#10; iam &#61; optional&#40;map&#40;list&#40;string&#41;&#41;, &#123;&#125;&#41;&#10; iam_bindings &#61; optional&#40;map&#40;object&#40;&#123;&#10; members &#61; list&#40;string&#41;&#10; role &#61; string&#10; condition &#61; optional&#40;object&#40;&#123;&#10; expression &#61; string&#10; title &#61; string&#10; description &#61; optional&#40;string&#41;&#10; &#125;&#41;&#41;&#10; &#125;&#41;&#41;, &#123;&#125;&#41;&#10; iam_bindings_additive &#61; optional&#40;map&#40;object&#40;&#123;&#10; member &#61; string&#10; role &#61; string&#10; condition &#61; optional&#40;object&#40;&#123;&#10; expression &#61; string&#10; title &#61; string&#10; description &#61; optional&#40;string&#41;&#10; &#125;&#41;&#41;&#10; &#125;&#41;&#41;, &#123;&#125;&#41;&#10; &#125;&#41;&#41;, &#123;&#125;&#41;&#10;&#125;&#41;&#41;">map&#40;object&#40;&#123;&#8230;&#125;&#41;&#41;</code> | | <code>&#123;&#125;</code> |
| [org_policies](variables.tf#L51) | Organization policies applied to this organization keyed by policy name. | <code title="map&#40;object&#40;&#123;&#10; inherit_from_parent &#61; optional&#40;bool&#41; &#35; for list policies only.&#10; reset &#61; optional&#40;bool&#41;&#10; rules &#61; optional&#40;list&#40;object&#40;&#123;&#10; allow &#61; optional&#40;object&#40;&#123;&#10; all &#61; optional&#40;bool&#41;&#10; values &#61; optional&#40;list&#40;string&#41;&#41;&#10; &#125;&#41;&#41;&#10; deny &#61; optional&#40;object&#40;&#123;&#10; all &#61; optional&#40;bool&#41;&#10; values &#61; optional&#40;list&#40;string&#41;&#41;&#10; &#125;&#41;&#41;&#10; enforce &#61; optional&#40;bool&#41; &#35; for boolean policies only.&#10; condition &#61; optional&#40;object&#40;&#123;&#10; description &#61; optional&#40;string&#41;&#10; expression &#61; optional&#40;string&#41;&#10; location &#61; optional&#40;string&#41;&#10; title &#61; optional&#40;string&#41;&#10; &#125;&#41;, &#123;&#125;&#41;&#10; &#125;&#41;&#41;, &#91;&#93;&#41;&#10;&#125;&#41;&#41;">map&#40;object&#40;&#123;&#8230;&#125;&#41;&#41;</code> | | <code>&#123;&#125;</code> |
| [org_policy_custom_constraints](variables.tf#L78) | Organization policy custom constraints keyed by constraint name. | <code title="map&#40;object&#40;&#123;&#10; display_name &#61; optional&#40;string&#41;&#10; description &#61; optional&#40;string&#41;&#10; action_type &#61; string&#10; condition &#61; string&#10; method_types &#61; list&#40;string&#41;&#10; resource_types &#61; list&#40;string&#41;&#10;&#125;&#41;&#41;">map&#40;object&#40;&#123;&#8230;&#125;&#41;&#41;</code> | | <code>&#123;&#125;</code> |
| [tag_bindings](variables-tags.tf#L45) | Tag bindings for this organization, in key => tag value id format. | <code>map&#40;string&#41;</code> | | <code>&#123;&#125;</code> |
| [tags](variables-tags.tf#L52) | 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. | <code title="map&#40;object&#40;&#123;&#10; description &#61; optional&#40;string, &#34;Managed by the Terraform organization module.&#34;&#41;&#10; iam &#61; optional&#40;map&#40;list&#40;string&#41;&#41;, &#123;&#125;&#41;&#10; id &#61; optional&#40;string&#41;&#10; values &#61; optional&#40;map&#40;object&#40;&#123;&#10; description &#61; optional&#40;string, &#34;Managed by the Terraform organization module.&#34;&#41;&#10; iam &#61; optional&#40;map&#40;list&#40;string&#41;&#41;, &#123;&#125;&#41;&#10; id &#61; optional&#40;string&#41;&#10; &#125;&#41;&#41;, &#123;&#125;&#41;&#10;&#125;&#41;&#41;">map&#40;object&#40;&#123;&#8230;&#125;&#41;&#41;</code> | | <code>&#123;&#125;</code> |
| [tag_bindings](variables-tags.tf#L81) | Tag bindings for this organization, in key => tag value id format. | <code>map&#40;string&#41;</code> | | <code>&#123;&#125;</code> |
| [tags](variables-tags.tf#L88) | 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. | <code title="map&#40;object&#40;&#123;&#10; description &#61; optional&#40;string, &#34;Managed by the Terraform organization module.&#34;&#41;&#10; iam &#61; optional&#40;map&#40;list&#40;string&#41;&#41;, &#123;&#125;&#41;&#10; iam_bindings &#61; optional&#40;map&#40;object&#40;&#123;&#10; members &#61; list&#40;string&#41;&#10; role &#61; string&#10; condition &#61; optional&#40;object&#40;&#123;&#10; expression &#61; string&#10; title &#61; string&#10; description &#61; optional&#40;string&#41;&#10; &#125;&#41;&#41;&#10; &#125;&#41;&#41;, &#123;&#125;&#41;&#10; iam_bindings_additive &#61; optional&#40;map&#40;object&#40;&#123;&#10; member &#61; string&#10; role &#61; string&#10; condition &#61; optional&#40;object&#40;&#123;&#10; expression &#61; string&#10; title &#61; string&#10; description &#61; optional&#40;string&#41;&#10; &#125;&#41;&#41;&#10; &#125;&#41;&#41;, &#123;&#125;&#41;&#10; id &#61; optional&#40;string&#41;&#10; values &#61; optional&#40;map&#40;object&#40;&#123;&#10; description &#61; optional&#40;string, &#34;Managed by the Terraform organization module.&#34;&#41;&#10; iam &#61; optional&#40;map&#40;list&#40;string&#41;&#41;, &#123;&#125;&#41;&#10; iam_bindings &#61; optional&#40;map&#40;object&#40;&#123;&#10; members &#61; list&#40;string&#41;&#10; role &#61; string&#10; condition &#61; optional&#40;object&#40;&#123;&#10; expression &#61; string&#10; title &#61; string&#10; description &#61; optional&#40;string&#41;&#10; &#125;&#41;&#41;&#10; &#125;&#41;&#41;, &#123;&#125;&#41;&#10; iam_bindings_additive &#61; optional&#40;map&#40;object&#40;&#123;&#10; member &#61; string&#10; role &#61; string&#10; condition &#61; optional&#40;object&#40;&#123;&#10; expression &#61; string&#10; title &#61; string&#10; description &#61; optional&#40;string&#41;&#10; &#125;&#41;&#41;&#10; &#125;&#41;&#41;, &#123;&#125;&#41;&#10; id &#61; optional&#40;string&#41;&#10; &#125;&#41;&#41;, &#123;&#125;&#41;&#10;&#125;&#41;&#41;">map&#40;object&#40;&#123;&#8230;&#125;&#41;&#41;</code> | | <code>&#123;&#125;</code> |
## Outputs

View File

@@ -15,50 +15,96 @@
*/
locals {
_tag_values = flatten([
for tag, attrs in local.tags : [
for value, value_attrs in attrs.values : {
description = value_attrs.description,
key = "${tag}/${value}"
id = try(value_attrs.id, null)
name = value
roles = keys(value_attrs.iam)
tag = tag
tag_id = attrs.id
tag_network = try(attrs.network, null) != null
}
]
])
_tag_values_iam = flatten([
for key, value_attrs in local.tag_values : [
for role in value_attrs.roles : {
id = value_attrs.id
key = value_attrs.key
name = value_attrs.name
role = role
tag = value_attrs.tag
}
]
])
_tags_iam = flatten([
for tag, attrs in local.tags : [
for role in keys(attrs.iam) : {
_tag_iam = flatten([
for k, v in local.tags : [
for role in keys(v.iam) : {
# we cycle on keys here so we don't risk injecting dynamic values
role = role
tag = tag
tag_id = attrs.id
tag = k
tag_id = v.id
}
]
])
tag_values = {
for t in local._tag_values : t.key => t
_tag_value_iam = flatten([
for k, v in local.tag_values : [
for role in v.roles : {
id = v.id
key = v.key
name = v.name
role = role
tag = v.tag
}
]
])
_tag_values = flatten([
for k, v in local.tags : [
for vk, vv in v.values : {
description = vv.description,
key = "${k}/${vk}"
iam_bindings = keys(vv.iam_bindings)
iam_bindings_additive = keys(vv.iam_bindings_additive)
id = try(vv.id, null)
name = vk
# we only store keys here so we don't risk injecting dynamic values
roles = keys(vv.iam)
tag = k
tag_id = v.id
tag_network = try(v.network, null) != null
}
]
])
tag_iam = {
for t in local._tag_iam : "${t.tag}:${t.role}" => t
}
tag_values_iam = {
for t in local._tag_values_iam : "${t.key}:${t.role}" => t
tag_iam_bindings = merge([
for k, v in local.tags : {
for bk in keys(v.iam_bindings) : "${k}:${bk}" => {
binding = bk
tag = k
tag_id = v.id
}
}
]...)
tag_iam_bindings_additive = merge([
for k, v in local.tags : {
for bk in keys(v.iam_bindings_additive) : "${k}:${bk}" => {
binding = bk
tag = k
tag_id = v.id
}
}
]...)
tag_value_iam = {
for v in local._tag_value_iam : "${v.key}:${v.role}" => v
}
tag_value_iam_bindings = merge([
for k, v in local.tag_values : {
for bk in v.iam_bindings : "${k}:${bk}" => {
binding = bk
id = v.id
key = k
name = v.name
tag = v.tag
tag_id = v.id
}
}
]...)
tag_value_iam_bindings_additive = merge([
for k, v in local.tag_values : {
for bk in v.iam_bindings_additive : "${k}:${bk}" => {
binding = bk
id = v.id
key = k
name = v.name
tag = v.tag
tag_id = v.id
}
}
]...)
tag_values = {
for v in local._tag_values : v.key => v
}
tags = merge(var.tags, var.network_tags)
tags_iam = {
for t in local._tags_iam : "${t.tag}:${t.role}" => t
}
}
# keys
@@ -82,7 +128,7 @@ resource "google_tags_tag_key" "default" {
}
resource "google_tags_tag_key_iam_binding" "default" {
for_each = local.tags_iam
for_each = local.tag_iam
tag_key = (
each.value.tag_id == null
? google_tags_tag_key.default[each.value.tag].id
@@ -94,6 +140,30 @@ resource "google_tags_tag_key_iam_binding" "default" {
)
}
resource "google_tags_tag_key_iam_binding" "bindings" {
for_each = local.tag_iam_bindings
tag_key = (
each.value.tag_id == null
? google_tags_tag_key.default[each.value.tag].id
: each.value.tag_id
)
role = local.tags[each.value.tag]["iam_bindings"][each.value.binding].role
members = (
local.tags[each.value.tag]["iam_bindings"][each.value.binding].members
)
}
resource "google_tags_tag_key_iam_member" "bindings" {
for_each = local.tag_iam_bindings_additive
tag_key = (
each.value.tag_id == null
? google_tags_tag_key.default[each.value.tag].id
: each.value.tag_id
)
role = local.tags[each.value.tag]["iam_bindings_additive"][each.value.binding].role
member = local.tags[each.value.tag]["iam_bindings_additive"][each.value.binding].member
}
# values
resource "google_tags_tag_value" "default" {
@@ -108,7 +178,7 @@ resource "google_tags_tag_value" "default" {
}
resource "google_tags_tag_value_iam_binding" "default" {
for_each = local.tag_values_iam
for_each = local.tag_value_iam
tag_value = (
each.value.id == null
? google_tags_tag_value.default[each.value.key].id
@@ -121,6 +191,36 @@ resource "google_tags_tag_value_iam_binding" "default" {
)
}
resource "google_tags_tag_value_iam_binding" "bindings" {
for_each = local.tag_value_iam_bindings
tag_value = (
each.value.id == null
? google_tags_tag_value.default[each.value.key].id
: each.value.id
)
role = (
local.tags[each.value.tag]["values"][each.value.name]["iam_bindings"][each.value.binding].role
)
members = (
local.tags[each.value.tag]["values"][each.value.name]["iam_bindings"][each.value.binding].members
)
}
resource "google_tags_tag_value_iam_member" "bindings" {
for_each = local.tag_value_iam_bindings_additive
tag_value = (
each.value.id == null
? google_tags_tag_value.default[each.value.key].id
: each.value.id
)
role = (
local.tags[each.value.tag]["values"][each.value.name]["iam_bindings_additive"][each.value.binding].role
)
member = (
local.tags[each.value.tag]["values"][each.value.name]["iam_bindings_additive"][each.value.binding].member
)
}
# bindings
resource "google_tags_tag_binding" "binding" {

View File

@@ -19,11 +19,47 @@ variable "network_tags" {
type = map(object({
description = optional(string, "Managed by the Terraform organization module.")
iam = optional(map(list(string)), {})
id = optional(string)
network = string # project_id/vpc_name
iam_bindings = optional(map(object({
members = list(string)
role = string
condition = optional(object({
expression = string
title = string
description = optional(string)
}))
})), {})
iam_bindings_additive = optional(map(object({
member = string
role = string
condition = optional(object({
expression = string
title = string
description = optional(string)
}))
})), {})
id = optional(string)
network = string # project_id/vpc_name
values = optional(map(object({
description = optional(string, "Managed by the Terraform organization module.")
iam = optional(map(list(string)), {})
iam_bindings = optional(map(object({
members = list(string)
role = string
condition = optional(object({
expression = string
title = string
description = optional(string)
}))
})), {})
iam_bindings_additive = optional(map(object({
member = string
role = string
condition = optional(object({
expression = string
title = string
description = optional(string)
}))
})), {})
})), {})
}))
nullable = false
@@ -54,11 +90,47 @@ variable "tags" {
type = map(object({
description = optional(string, "Managed by the Terraform organization module.")
iam = optional(map(list(string)), {})
id = optional(string)
iam_bindings = optional(map(object({
members = list(string)
role = string
condition = optional(object({
expression = string
title = string
description = optional(string)
}))
})), {})
iam_bindings_additive = optional(map(object({
member = string
role = string
condition = optional(object({
expression = string
title = string
description = optional(string)
}))
})), {})
id = optional(string)
values = optional(map(object({
description = optional(string, "Managed by the Terraform organization module.")
iam = optional(map(list(string)), {})
id = optional(string)
iam_bindings = optional(map(object({
members = list(string)
role = string
condition = optional(object({
expression = string
title = string
description = optional(string)
}))
})), {})
iam_bindings_additive = optional(map(object({
member = string
role = string
condition = optional(object({
expression = string
title = string
description = optional(string)
}))
})), {})
id = optional(string)
})), {})
}))
nullable = false

View File

@@ -1173,7 +1173,7 @@ module "bucket" {
| [quotas.tf](./quotas.tf) | None | <code>google_cloud_quotas_quota_preference</code> |
| [service-accounts.tf](./service-accounts.tf) | Service identities and supporting resources. | <code>google_kms_crypto_key_iam_member</code> · <code>google_project_default_service_accounts</code> · <code>google_project_iam_member</code> · <code>google_project_service_identity</code> |
| [shared-vpc.tf](./shared-vpc.tf) | Shared VPC project-level configuration. | <code>google_compute_shared_vpc_host_project</code> · <code>google_compute_shared_vpc_service_project</code> · <code>google_compute_subnetwork_iam_member</code> · <code>google_project_iam_member</code> |
| [tags.tf](./tags.tf) | None | <code>google_tags_tag_binding</code> · <code>google_tags_tag_key</code> · <code>google_tags_tag_key_iam_binding</code> · <code>google_tags_tag_value</code> · <code>google_tags_tag_value_iam_binding</code> |
| [tags.tf](./tags.tf) | None | <code>google_tags_tag_binding</code> · <code>google_tags_tag_key</code> · <code>google_tags_tag_key_iam_binding</code> · <code>google_tags_tag_key_iam_member</code> · <code>google_tags_tag_value</code> · <code>google_tags_tag_value_iam_binding</code> · <code>google_tags_tag_value_iam_member</code> |
| [variables-iam.tf](./variables-iam.tf) | None | |
| [variables-quotas.tf](./variables-quotas.tf) | None | |
| [variables-tags.tf](./variables-tags.tf) | None | |
@@ -1204,7 +1204,7 @@ module "bucket" {
| [logging_exclusions](variables.tf#L108) | Logging exclusions for this project in the form {NAME -> FILTER}. | <code>map&#40;string&#41;</code> | | <code>&#123;&#125;</code> |
| [logging_sinks](variables.tf#L115) | Logging sinks to create for this project. | <code title="map&#40;object&#40;&#123;&#10; bq_partitioned_table &#61; optional&#40;bool, false&#41;&#10; description &#61; optional&#40;string&#41;&#10; destination &#61; string&#10; disabled &#61; optional&#40;bool, false&#41;&#10; exclusions &#61; optional&#40;map&#40;string&#41;, &#123;&#125;&#41;&#10; filter &#61; optional&#40;string&#41;&#10; iam &#61; optional&#40;bool, true&#41;&#10; type &#61; string&#10; unique_writer &#61; optional&#40;bool, true&#41;&#10;&#125;&#41;&#41;">map&#40;object&#40;&#123;&#8230;&#125;&#41;&#41;</code> | | <code>&#123;&#125;</code> |
| [metric_scopes](variables.tf#L146) | List of projects that will act as metric scopes for this project. | <code>list&#40;string&#41;</code> | | <code>&#91;&#93;</code> |
| [network_tags](variables-tags.tf#L17) | 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. | <code title="map&#40;object&#40;&#123;&#10; description &#61; optional&#40;string, &#34;Managed by the Terraform project module.&#34;&#41;&#10; iam &#61; optional&#40;map&#40;list&#40;string&#41;&#41;, &#123;&#125;&#41;&#10; id &#61; optional&#40;string&#41;&#10; network &#61; string &#35; project_id&#47;vpc_name&#10; values &#61; optional&#40;map&#40;object&#40;&#123;&#10; description &#61; optional&#40;string, &#34;Managed by the Terraform project module.&#34;&#41;&#10; iam &#61; optional&#40;map&#40;list&#40;string&#41;&#41;, &#123;&#125;&#41;&#10; &#125;&#41;&#41;, &#123;&#125;&#41;&#10;&#125;&#41;&#41;">map&#40;object&#40;&#123;&#8230;&#125;&#41;&#41;</code> | | <code>&#123;&#125;</code> |
| [network_tags](variables-tags.tf#L17) | 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. | <code title="map&#40;object&#40;&#123;&#10; description &#61; optional&#40;string, &#34;Managed by the Terraform project module.&#34;&#41;&#10; iam &#61; optional&#40;map&#40;list&#40;string&#41;&#41;, &#123;&#125;&#41;&#10; iam_bindings &#61; optional&#40;map&#40;object&#40;&#123;&#10; members &#61; list&#40;string&#41;&#10; role &#61; string&#10; condition &#61; optional&#40;object&#40;&#123;&#10; expression &#61; string&#10; title &#61; string&#10; description &#61; optional&#40;string&#41;&#10; &#125;&#41;&#41;&#10; &#125;&#41;&#41;, &#123;&#125;&#41;&#10; iam_bindings_additive &#61; optional&#40;map&#40;object&#40;&#123;&#10; member &#61; string&#10; role &#61; string&#10; condition &#61; optional&#40;object&#40;&#123;&#10; expression &#61; string&#10; title &#61; string&#10; description &#61; optional&#40;string&#41;&#10; &#125;&#41;&#41;&#10; &#125;&#41;&#41;, &#123;&#125;&#41;&#10; id &#61; optional&#40;string&#41;&#10; network &#61; string &#35; project_id&#47;vpc_name&#10; values &#61; optional&#40;map&#40;object&#40;&#123;&#10; description &#61; optional&#40;string, &#34;Managed by the Terraform project module.&#34;&#41;&#10; iam &#61; optional&#40;map&#40;list&#40;string&#41;&#41;, &#123;&#125;&#41;&#10; iam_bindings &#61; optional&#40;map&#40;object&#40;&#123;&#10; members &#61; list&#40;string&#41;&#10; role &#61; string&#10; condition &#61; optional&#40;object&#40;&#123;&#10; expression &#61; string&#10; title &#61; string&#10; description &#61; optional&#40;string&#41;&#10; &#125;&#41;&#41;&#10; &#125;&#41;&#41;, &#123;&#125;&#41;&#10; iam_bindings_additive &#61; optional&#40;map&#40;object&#40;&#123;&#10; member &#61; string&#10; role &#61; string&#10; condition &#61; optional&#40;object&#40;&#123;&#10; expression &#61; string&#10; title &#61; string&#10; description &#61; optional&#40;string&#41;&#10; &#125;&#41;&#41;&#10; &#125;&#41;&#41;, &#123;&#125;&#41;&#10; &#125;&#41;&#41;, &#123;&#125;&#41;&#10;&#125;&#41;&#41;">map&#40;object&#40;&#123;&#8230;&#125;&#41;&#41;</code> | | <code>&#123;&#125;</code> |
| [org_policies](variables.tf#L158) | Organization policies applied to this project keyed by policy name. | <code title="map&#40;object&#40;&#123;&#10; inherit_from_parent &#61; optional&#40;bool&#41; &#35; for list policies only.&#10; reset &#61; optional&#40;bool&#41;&#10; rules &#61; optional&#40;list&#40;object&#40;&#123;&#10; allow &#61; optional&#40;object&#40;&#123;&#10; all &#61; optional&#40;bool&#41;&#10; values &#61; optional&#40;list&#40;string&#41;&#41;&#10; &#125;&#41;&#41;&#10; deny &#61; optional&#40;object&#40;&#123;&#10; all &#61; optional&#40;bool&#41;&#10; values &#61; optional&#40;list&#40;string&#41;&#41;&#10; &#125;&#41;&#41;&#10; enforce &#61; optional&#40;bool&#41; &#35; for boolean policies only.&#10; condition &#61; optional&#40;object&#40;&#123;&#10; description &#61; optional&#40;string&#41;&#10; expression &#61; optional&#40;string&#41;&#10; location &#61; optional&#40;string&#41;&#10; title &#61; optional&#40;string&#41;&#10; &#125;&#41;, &#123;&#125;&#41;&#10; &#125;&#41;&#41;, &#91;&#93;&#41;&#10;&#125;&#41;&#41;">map&#40;object&#40;&#123;&#8230;&#125;&#41;&#41;</code> | | <code>&#123;&#125;</code> |
| [parent](variables.tf#L185) | Parent folder or organization in 'folders/folder_id' or 'organizations/org_id' format. | <code>string</code> | | <code>null</code> |
| [prefix](variables.tf#L195) | Optional prefix used to generate project id and name. | <code>string</code> | | <code>null</code> |
@@ -1216,8 +1216,8 @@ module "bucket" {
| [shared_vpc_host_config](variables.tf#L235) | Configures this project as a Shared VPC host project (mutually exclusive with shared_vpc_service_project). | <code title="object&#40;&#123;&#10; enabled &#61; bool&#10; service_projects &#61; optional&#40;list&#40;string&#41;, &#91;&#93;&#41;&#10;&#125;&#41;">object&#40;&#123;&#8230;&#125;&#41;</code> | | <code>null</code> |
| [shared_vpc_service_config](variables.tf#L244) | Configures this project as a Shared VPC service project (mutually exclusive with shared_vpc_host_config). | <code title="object&#40;&#123;&#10; host_project &#61; string&#10; network_users &#61; optional&#40;list&#40;string&#41;, &#91;&#93;&#41;&#10; service_identity_iam &#61; optional&#40;map&#40;list&#40;string&#41;&#41;, &#123;&#125;&#41;&#10; service_identity_subnet_iam &#61; optional&#40;map&#40;list&#40;string&#41;&#41;, &#123;&#125;&#41;&#10; service_iam_grants &#61; optional&#40;list&#40;string&#41;, &#91;&#93;&#41;&#10; network_subnet_users &#61; optional&#40;map&#40;list&#40;string&#41;&#41;, &#123;&#125;&#41;&#10;&#125;&#41;">object&#40;&#123;&#8230;&#125;&#41;</code> | | <code title="&#123;&#10; host_project &#61; null&#10;&#125;">&#123;&#8230;&#125;</code> |
| [skip_delete](variables.tf#L272) | Allows the underlying resources to be destroyed without destroying the project itself. | <code>bool</code> | | <code>false</code> |
| [tag_bindings](variables-tags.tf#L45) | Tag bindings for this project, in key => tag value id format. | <code>map&#40;string&#41;</code> | | <code>null</code> |
| [tags](variables-tags.tf#L51) | 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. | <code title="map&#40;object&#40;&#123;&#10; description &#61; optional&#40;string, &#34;Managed by the Terraform project module.&#34;&#41;&#10; iam &#61; optional&#40;map&#40;list&#40;string&#41;&#41;, &#123;&#125;&#41;&#10; id &#61; optional&#40;string&#41;&#10; values &#61; optional&#40;map&#40;object&#40;&#123;&#10; description &#61; optional&#40;string, &#34;Managed by the Terraform project module.&#34;&#41;&#10; iam &#61; optional&#40;map&#40;list&#40;string&#41;&#41;, &#123;&#125;&#41;&#10; id &#61; optional&#40;string&#41;&#10; &#125;&#41;&#41;, &#123;&#125;&#41;&#10;&#125;&#41;&#41;">map&#40;object&#40;&#123;&#8230;&#125;&#41;&#41;</code> | | <code>&#123;&#125;</code> |
| [tag_bindings](variables-tags.tf#L81) | Tag bindings for this project, in key => tag value id format. | <code>map&#40;string&#41;</code> | | <code>null</code> |
| [tags](variables-tags.tf#L88) | 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. | <code title="map&#40;object&#40;&#123;&#10; description &#61; optional&#40;string, &#34;Managed by the Terraform project module.&#34;&#41;&#10; iam &#61; optional&#40;map&#40;list&#40;string&#41;&#41;, &#123;&#125;&#41;&#10; iam_bindings &#61; optional&#40;map&#40;object&#40;&#123;&#10; members &#61; list&#40;string&#41;&#10; role &#61; string&#10; condition &#61; optional&#40;object&#40;&#123;&#10; expression &#61; string&#10; title &#61; string&#10; description &#61; optional&#40;string&#41;&#10; &#125;&#41;&#41;&#10; &#125;&#41;&#41;, &#123;&#125;&#41;&#10; iam_bindings_additive &#61; optional&#40;map&#40;object&#40;&#123;&#10; member &#61; string&#10; role &#61; string&#10; condition &#61; optional&#40;object&#40;&#123;&#10; expression &#61; string&#10; title &#61; string&#10; description &#61; optional&#40;string&#41;&#10; &#125;&#41;&#41;&#10; &#125;&#41;&#41;, &#123;&#125;&#41;&#10; id &#61; optional&#40;string&#41;&#10; values &#61; optional&#40;map&#40;object&#40;&#123;&#10; description &#61; optional&#40;string, &#34;Managed by the Terraform project module.&#34;&#41;&#10; iam &#61; optional&#40;map&#40;list&#40;string&#41;&#41;, &#123;&#125;&#41;&#10; iam_bindings &#61; optional&#40;map&#40;object&#40;&#123;&#10; members &#61; list&#40;string&#41;&#10; role &#61; string&#10; condition &#61; optional&#40;object&#40;&#123;&#10; expression &#61; string&#10; title &#61; string&#10; description &#61; optional&#40;string&#41;&#10; &#125;&#41;&#41;&#10; &#125;&#41;&#41;, &#123;&#125;&#41;&#10; iam_bindings_additive &#61; optional&#40;map&#40;object&#40;&#123;&#10; member &#61; string&#10; role &#61; string&#10; condition &#61; optional&#40;object&#40;&#123;&#10; expression &#61; string&#10; title &#61; string&#10; description &#61; optional&#40;string&#41;&#10; &#125;&#41;&#41;&#10; &#125;&#41;&#41;, &#123;&#125;&#41;&#10; id &#61; optional&#40;string&#41;&#10; &#125;&#41;&#41;, &#123;&#125;&#41;&#10;&#125;&#41;&#41;">map&#40;object&#40;&#123;&#8230;&#125;&#41;&#41;</code> | | <code>&#123;&#125;</code> |
| [vpc_sc](variables.tf#L278) | VPC-SC configuration for the project, use when `ignore_changes` for resources is set in the VPC-SC module. | <code title="object&#40;&#123;&#10; perimeter_name &#61; string&#10; perimeter_bridges &#61; optional&#40;list&#40;string&#41;, &#91;&#93;&#41;&#10; is_dry_run &#61; optional&#40;bool, false&#41;&#10;&#125;&#41;">object&#40;&#123;&#8230;&#125;&#41;</code> | | <code>null</code> |
## Outputs

View File

@@ -15,50 +15,96 @@
*/
locals {
_tag_values = flatten([
for tag, attrs in local.tags : [
for value, value_attrs in attrs.values : {
description = value_attrs.description,
key = "${tag}/${value}"
id = try(value_attrs.id, null)
name = value
roles = keys(value_attrs.iam)
tag = tag
tag_id = attrs.id
tag_network = try(attrs.network, null) != null
}
]
])
_tag_values_iam = flatten([
for key, value_attrs in local.tag_values : [
for role in value_attrs.roles : {
id = value_attrs.id
key = value_attrs.key
name = value_attrs.name
role = role
tag = value_attrs.tag
}
]
])
_tags_iam = flatten([
for tag, attrs in local.tags : [
for role in keys(attrs.iam) : {
_tag_iam = flatten([
for k, v in local.tags : [
for role in keys(v.iam) : {
# we cycle on keys here so we don't risk injecting dynamic values
role = role
tag = tag
tag_id = attrs.id
tag = k
tag_id = v.id
}
]
])
tag_values = {
for t in local._tag_values : t.key => t
_tag_value_iam = flatten([
for k, v in local.tag_values : [
for role in v.roles : {
id = v.id
key = v.key
name = v.name
role = role
tag = v.tag
}
]
])
_tag_values = flatten([
for k, v in local.tags : [
for vk, vv in v.values : {
description = vv.description,
key = "${k}/${vk}"
iam_bindings = keys(vv.iam_bindings)
iam_bindings_additive = keys(vv.iam_bindings_additive)
id = try(vv.id, null)
name = vk
# we only store keys here so we don't risk injecting dynamic values
roles = keys(vv.iam)
tag = k
tag_id = v.id
tag_network = try(v.network, null) != null
}
]
])
tag_iam = {
for t in local._tag_iam : "${t.tag}:${t.role}" => t
}
tag_values_iam = {
for t in local._tag_values_iam : "${t.key}:${t.role}" => t
tag_iam_bindings = merge([
for k, v in local.tags : {
for bk in keys(v.iam_bindings) : "${k}:${bk}" => {
binding = bk
tag = k
tag_id = v.id
}
}
]...)
tag_iam_bindings_additive = merge([
for k, v in local.tags : {
for bk in keys(v.iam_bindings_additive) : "${k}:${bk}" => {
binding = bk
tag = k
tag_id = v.id
}
}
]...)
tag_value_iam = {
for v in local._tag_value_iam : "${v.key}:${v.role}" => v
}
tag_value_iam_bindings = merge([
for k, v in local.tag_values : {
for bk in v.iam_bindings : "${k}:${bk}" => {
binding = bk
id = v.id
key = k
name = v.name
tag = v.tag
tag_id = v.id
}
}
]...)
tag_value_iam_bindings_additive = merge([
for k, v in local.tag_values : {
for bk in v.iam_bindings_additive : "${k}:${bk}" => {
binding = bk
id = v.id
key = k
name = v.name
tag = v.tag
tag_id = v.id
}
}
]...)
tag_values = {
for v in local._tag_values : v.key => v
}
tags = merge(var.tags, var.network_tags)
tags_iam = {
for t in local._tags_iam : "${t.tag}:${t.role}" => t
}
}
# keys
@@ -82,7 +128,7 @@ resource "google_tags_tag_key" "default" {
}
resource "google_tags_tag_key_iam_binding" "default" {
for_each = local.tags_iam
for_each = local.tag_iam
tag_key = (
each.value.tag_id == null
? google_tags_tag_key.default[each.value.tag].id
@@ -94,6 +140,30 @@ resource "google_tags_tag_key_iam_binding" "default" {
)
}
resource "google_tags_tag_key_iam_binding" "bindings" {
for_each = local.tag_iam_bindings
tag_key = (
each.value.tag_id == null
? google_tags_tag_key.default[each.value.tag].id
: each.value.tag_id
)
role = local.tags[each.value.tag]["iam_bindings"][each.value.binding].role
members = (
local.tags[each.value.tag]["iam_bindings"][each.value.binding].members
)
}
resource "google_tags_tag_key_iam_member" "bindings" {
for_each = local.tag_iam_bindings_additive
tag_key = (
each.value.tag_id == null
? google_tags_tag_key.default[each.value.tag].id
: each.value.tag_id
)
role = local.tags[each.value.tag]["iam_bindings_additive"][each.value.binding].role
member = local.tags[each.value.tag]["iam_bindings_additive"][each.value.binding].member
}
# values
resource "google_tags_tag_value" "default" {
@@ -108,7 +178,7 @@ resource "google_tags_tag_value" "default" {
}
resource "google_tags_tag_value_iam_binding" "default" {
for_each = local.tag_values_iam
for_each = local.tag_value_iam
tag_value = (
each.value.id == null
? google_tags_tag_value.default[each.value.key].id
@@ -121,6 +191,36 @@ resource "google_tags_tag_value_iam_binding" "default" {
)
}
resource "google_tags_tag_value_iam_binding" "bindings" {
for_each = local.tag_value_iam_bindings
tag_value = (
each.value.id == null
? google_tags_tag_value.default[each.value.key].id
: each.value.id
)
role = (
local.tags[each.value.tag]["values"][each.value.name]["iam_bindings"][each.value.binding].role
)
members = (
local.tags[each.value.tag]["values"][each.value.name]["iam_bindings"][each.value.binding].members
)
}
resource "google_tags_tag_value_iam_member" "bindings" {
for_each = local.tag_value_iam_bindings_additive
tag_value = (
each.value.id == null
? google_tags_tag_value.default[each.value.key].id
: each.value.id
)
role = (
local.tags[each.value.tag]["values"][each.value.name]["iam_bindings_additive"][each.value.binding].role
)
member = (
local.tags[each.value.tag]["values"][each.value.name]["iam_bindings_additive"][each.value.binding].member
)
}
# bindings
resource "google_tags_tag_binding" "binding" {

View File

@@ -19,11 +19,47 @@ variable "network_tags" {
type = map(object({
description = optional(string, "Managed by the Terraform project module.")
iam = optional(map(list(string)), {})
id = optional(string)
network = string # project_id/vpc_name
iam_bindings = optional(map(object({
members = list(string)
role = string
condition = optional(object({
expression = string
title = string
description = optional(string)
}))
})), {})
iam_bindings_additive = optional(map(object({
member = string
role = string
condition = optional(object({
expression = string
title = string
description = optional(string)
}))
})), {})
id = optional(string)
network = string # project_id/vpc_name
values = optional(map(object({
description = optional(string, "Managed by the Terraform project module.")
iam = optional(map(list(string)), {})
iam_bindings = optional(map(object({
members = list(string)
role = string
condition = optional(object({
expression = string
title = string
description = optional(string)
}))
})), {})
iam_bindings_additive = optional(map(object({
member = string
role = string
condition = optional(object({
expression = string
title = string
description = optional(string)
}))
})), {})
})), {})
}))
nullable = false
@@ -45,7 +81,8 @@ variable "network_tags" {
variable "tag_bindings" {
description = "Tag bindings for this project, in key => tag value id format."
type = map(string)
default = null
# we need default null here for the project factory module
default = null
}
variable "tags" {
@@ -53,11 +90,47 @@ variable "tags" {
type = map(object({
description = optional(string, "Managed by the Terraform project module.")
iam = optional(map(list(string)), {})
id = optional(string)
iam_bindings = optional(map(object({
members = list(string)
role = string
condition = optional(object({
expression = string
title = string
description = optional(string)
}))
})), {})
iam_bindings_additive = optional(map(object({
member = string
role = string
condition = optional(object({
expression = string
title = string
description = optional(string)
}))
})), {})
id = optional(string)
values = optional(map(object({
description = optional(string, "Managed by the Terraform project module.")
iam = optional(map(list(string)), {})
id = optional(string)
iam_bindings = optional(map(object({
members = list(string)
role = string
condition = optional(object({
expression = string
title = string
description = optional(string)
}))
})), {})
iam_bindings_additive = optional(map(object({
member = string
role = string
condition = optional(object({
expression = string
title = string
description = optional(string)
}))
})), {})
id = optional(string)
})), {})
}))
nullable = false

View File

@@ -23,11 +23,20 @@ values:
purpose_data: null
short_name: environment
timeouts: null
module.org.google_tags_tag_key_iam_binding.bindings["environment:viewer"]:
condition: []
members:
- group:gcp-support@example.org
role: roles/resourcemanager.tagViewer
module.org.google_tags_tag_key_iam_binding.default["environment:roles/resourcemanager.tagAdmin"]:
condition: []
members:
- group:organization-admins@example.org
role: roles/resourcemanager.tagAdmin
module.org.google_tags_tag_key_iam_member.bindings["environment:user_app1"]:
condition: []
member: group:app1-team@example.org
role: roles/resourcemanager.tagUser
module.org.google_tags_tag_value.default["environment/dev"]:
description: Managed by the Terraform organization module.
short_name: dev
@@ -36,14 +45,28 @@ values:
description: 'Environment: production.'
short_name: prod
timeouts: null
module.org.google_tags_tag_value_iam_binding.bindings["environment/prod:admin"]:
condition: []
members:
- group:gcp-support@example.org
role: roles/resourcemanager.tagAdmin
module.org.google_tags_tag_value_iam_binding.default["environment/prod:roles/resourcemanager.tagViewer"]:
condition: []
members:
- group:organization-admins@example.org
- group:app1-team@example.org
role: roles/resourcemanager.tagViewer
module.org.google_tags_tag_value_iam_member.bindings["environment/dev:user_app2"]:
condition: []
member: group:app2-team@example.org
role: roles/resourcemanager.tagUser
counts:
google_tags_tag_binding: 1
google_tags_tag_key: 1
google_tags_tag_key_iam_binding: 1
google_tags_tag_key_iam_binding: 2
google_tags_tag_key_iam_member: 1
google_tags_tag_value: 2
google_tags_tag_value_iam_binding: 2
google_tags_tag_value_iam_member: 1
modules: 1
resources: 10