Add project-scoped secure tags (#1933)
This commit is contained in:
parent
b6e0557bbb
commit
01bd0b7b01
|
@ -480,6 +480,7 @@ module "org" {
|
||||||
| [organization-policies.tf](./organization-policies.tf) | Organization-level organization policies. | <code>google_org_policy_policy</code> |
|
| [organization-policies.tf](./organization-policies.tf) | Organization-level organization policies. | <code>google_org_policy_policy</code> |
|
||||||
| [outputs.tf](./outputs.tf) | Module outputs. | |
|
| [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_value</code> · <code>google_tags_tag_value_iam_binding</code> |
|
||||||
|
| [variables-tags.tf](./variables-tags.tf) | None | |
|
||||||
| [variables.tf](./variables.tf) | Module variables. | |
|
| [variables.tf](./variables.tf) | Module variables. | |
|
||||||
| [versions.tf](./versions.tf) | Version pins. | |
|
| [versions.tf](./versions.tf) | Version pins. | |
|
||||||
|
|
||||||
|
@ -487,7 +488,7 @@ module "org" {
|
||||||
|
|
||||||
| name | description | type | required | default |
|
| name | description | type | required | default |
|
||||||
|---|---|:---:|:---:|:---:|
|
|---|---|:---:|:---:|:---:|
|
||||||
| [organization_id](variables.tf#L211) | Organization id in organizations/nnnnnn format. | <code>string</code> | ✓ | |
|
| [organization_id](variables.tf#L189) | Organization id in organizations/nnnnnn format. | <code>string</code> | ✓ | |
|
||||||
| [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. | <code>map(list(string))</code> | | <code>{}</code> |
|
| [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. | <code>map(list(string))</code> | | <code>{}</code> |
|
||||||
| [custom_roles](variables.tf#L24) | Map of role name => list of permissions to create in this project. | <code>map(list(string))</code> | | <code>{}</code> |
|
| [custom_roles](variables.tf#L24) | Map of role name => list of permissions to create in this project. | <code>map(list(string))</code> | | <code>{}</code> |
|
||||||
| [factories_config](variables.tf#L31) | Paths to data files and folders that enable factory functionality. | <code title="object({ custom_roles = optional(string) org_policies = optional(string) org_policy_custom_constraints = optional(string) })">object({…})</code> | | <code>{}</code> |
|
| [factories_config](variables.tf#L31) | Paths to data files and folders that enable factory functionality. | <code title="object({ custom_roles = optional(string) org_policies = optional(string) org_policy_custom_constraints = optional(string) })">object({…})</code> | | <code>{}</code> |
|
||||||
|
@ -499,11 +500,11 @@ module "org" {
|
||||||
| [logging_data_access](variables.tf#L95) | Control activation of data access logs. Format is service => { log type => [exempted members]}. The special 'allServices' key denotes configuration for all services. | <code>map(map(list(string)))</code> | | <code>{}</code> |
|
| [logging_data_access](variables.tf#L95) | Control activation of data access logs. Format is service => { log type => [exempted members]}. The special 'allServices' key denotes configuration for all services. | <code>map(map(list(string)))</code> | | <code>{}</code> |
|
||||||
| [logging_exclusions](variables.tf#L110) | Logging exclusions for this organization in the form {NAME -> FILTER}. | <code>map(string)</code> | | <code>{}</code> |
|
| [logging_exclusions](variables.tf#L110) | Logging exclusions for this organization in the form {NAME -> FILTER}. | <code>map(string)</code> | | <code>{}</code> |
|
||||||
| [logging_sinks](variables.tf#L117) | Logging sinks to create for the organization. | <code title="map(object({ bq_partitioned_table = optional(bool) description = optional(string) destination = string disabled = optional(bool, false) exclusions = optional(map(string), {}) filter = string iam = optional(bool, true) include_children = optional(bool, true) type = string }))">map(object({…}))</code> | | <code>{}</code> |
|
| [logging_sinks](variables.tf#L117) | Logging sinks to create for the organization. | <code title="map(object({ bq_partitioned_table = optional(bool) description = optional(string) destination = string disabled = optional(bool, false) exclusions = optional(map(string), {}) filter = string iam = optional(bool, true) include_children = optional(bool, true) type = string }))">map(object({…}))</code> | | <code>{}</code> |
|
||||||
| [network_tags](variables.tf#L148) | 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(object({ description = optional(string, "Managed by the Terraform organization module.") iam = optional(map(list(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)), {}) })), {}) }))">map(object({…}))</code> | | <code>{}</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(object({ description = optional(string, "Managed by the Terraform organization module.") iam = optional(map(list(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)), {}) })), {}) }))">map(object({…}))</code> | | <code>{}</code> |
|
||||||
| [org_policies](variables.tf#L170) | Organization policies applied to this organization keyed by policy name. | <code title="map(object({ inherit_from_parent = optional(bool) # for list policies only. reset = optional(bool) rules = optional(list(object({ allow = optional(object({ all = optional(bool) values = optional(list(string)) })) deny = optional(object({ all = optional(bool) values = optional(list(string)) })) enforce = optional(bool) # for boolean policies only. condition = optional(object({ description = optional(string) expression = optional(string) location = optional(string) title = optional(string) }), {}) })), []) }))">map(object({…}))</code> | | <code>{}</code> |
|
| [org_policies](variables.tf#L148) | Organization policies applied to this organization keyed by policy name. | <code title="map(object({ inherit_from_parent = optional(bool) # for list policies only. reset = optional(bool) rules = optional(list(object({ allow = optional(object({ all = optional(bool) values = optional(list(string)) })) deny = optional(object({ all = optional(bool) values = optional(list(string)) })) enforce = optional(bool) # for boolean policies only. condition = optional(object({ description = optional(string) expression = optional(string) location = optional(string) title = optional(string) }), {}) })), []) }))">map(object({…}))</code> | | <code>{}</code> |
|
||||||
| [org_policy_custom_constraints](variables.tf#L197) | Organization policy custom constraints keyed by constraint name. | <code title="map(object({ display_name = optional(string) description = optional(string) action_type = string condition = string method_types = list(string) resource_types = list(string) }))">map(object({…}))</code> | | <code>{}</code> |
|
| [org_policy_custom_constraints](variables.tf#L175) | Organization policy custom constraints keyed by constraint name. | <code title="map(object({ display_name = optional(string) description = optional(string) action_type = string condition = string method_types = list(string) resource_types = list(string) }))">map(object({…}))</code> | | <code>{}</code> |
|
||||||
| [tag_bindings](variables.tf#L220) | Tag bindings for this organization, in key => tag value id format. | <code>map(string)</code> | | <code>{}</code> |
|
| [tag_bindings](variables-tags.tf#L45) | Tag bindings for this organization, in key => tag value id format. | <code>map(string)</code> | | <code>{}</code> |
|
||||||
| [tags](variables.tf#L227) | 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(object({ description = optional(string, "Managed by the Terraform organization module.") iam = optional(map(list(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) })), {}) }))">map(object({…}))</code> | | <code>{}</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(object({ description = optional(string, "Managed by the Terraform organization module.") iam = optional(map(list(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) })), {}) }))">map(object({…}))</code> | | <code>{}</code> |
|
||||||
|
|
||||||
## Outputs
|
## Outputs
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,79 @@
|
||||||
|
/**
|
||||||
|
* Copyright 2023 Google LLC
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
variable "network_tags" {
|
||||||
|
description = "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."
|
||||||
|
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
|
||||||
|
values = optional(map(object({
|
||||||
|
description = optional(string, "Managed by the Terraform organization module.")
|
||||||
|
iam = optional(map(list(string)), {})
|
||||||
|
})), {})
|
||||||
|
}))
|
||||||
|
nullable = false
|
||||||
|
default = {}
|
||||||
|
validation {
|
||||||
|
condition = (
|
||||||
|
alltrue([
|
||||||
|
for k, v in var.network_tags : v != null
|
||||||
|
]) &&
|
||||||
|
# all values are non-null
|
||||||
|
alltrue(flatten([
|
||||||
|
for k, v in var.network_tags : [for k2, v2 in v.values : v2 != null]
|
||||||
|
]))
|
||||||
|
)
|
||||||
|
error_message = "Use an empty map instead of null as value."
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
variable "tag_bindings" {
|
||||||
|
description = "Tag bindings for this organization, in key => tag value id format."
|
||||||
|
type = map(string)
|
||||||
|
default = {}
|
||||||
|
nullable = false
|
||||||
|
}
|
||||||
|
|
||||||
|
variable "tags" {
|
||||||
|
description = "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."
|
||||||
|
type = map(object({
|
||||||
|
description = optional(string, "Managed by the Terraform organization module.")
|
||||||
|
iam = optional(map(list(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)
|
||||||
|
})), {})
|
||||||
|
}))
|
||||||
|
nullable = false
|
||||||
|
default = {}
|
||||||
|
validation {
|
||||||
|
condition = (
|
||||||
|
# all keys are non-null
|
||||||
|
alltrue([
|
||||||
|
for k, v in var.tags : v != null
|
||||||
|
]) &&
|
||||||
|
# all values are non-null
|
||||||
|
alltrue(flatten([
|
||||||
|
for k, v in var.tags : [for k2, v2 in v.values : v2 != null]
|
||||||
|
]))
|
||||||
|
)
|
||||||
|
error_message = "Use an empty map instead of null as value."
|
||||||
|
}
|
||||||
|
}
|
|
@ -145,28 +145,6 @@ variable "logging_sinks" {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
variable "network_tags" {
|
|
||||||
description = "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."
|
|
||||||
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
|
|
||||||
values = optional(map(object({
|
|
||||||
description = optional(string, "Managed by the Terraform organization module.")
|
|
||||||
iam = optional(map(list(string)), {})
|
|
||||||
})), {})
|
|
||||||
}))
|
|
||||||
nullable = false
|
|
||||||
default = {}
|
|
||||||
validation {
|
|
||||||
condition = alltrue([
|
|
||||||
for k, v in var.network_tags : v != null
|
|
||||||
])
|
|
||||||
error_message = "Use an empty map instead of null as value."
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
variable "org_policies" {
|
variable "org_policies" {
|
||||||
description = "Organization policies applied to this organization keyed by policy name."
|
description = "Organization policies applied to this organization keyed by policy name."
|
||||||
type = map(object({
|
type = map(object({
|
||||||
|
@ -216,39 +194,3 @@ variable "organization_id" {
|
||||||
error_message = "The organization_id must in the form organizations/nnn."
|
error_message = "The organization_id must in the form organizations/nnn."
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
variable "tag_bindings" {
|
|
||||||
description = "Tag bindings for this organization, in key => tag value id format."
|
|
||||||
type = map(string)
|
|
||||||
default = {}
|
|
||||||
nullable = false
|
|
||||||
}
|
|
||||||
|
|
||||||
variable "tags" {
|
|
||||||
description = "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."
|
|
||||||
type = map(object({
|
|
||||||
description = optional(string, "Managed by the Terraform organization module.")
|
|
||||||
iam = optional(map(list(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)
|
|
||||||
})), {})
|
|
||||||
}))
|
|
||||||
nullable = false
|
|
||||||
default = {}
|
|
||||||
validation {
|
|
||||||
condition = (
|
|
||||||
# all keys are non-null
|
|
||||||
alltrue([
|
|
||||||
for k, v in var.tags : v != null
|
|
||||||
]) &&
|
|
||||||
# all values are non-null
|
|
||||||
alltrue(flatten([
|
|
||||||
for k, v in var.tags : [for k2, v2 in v.values : v2 != null]
|
|
||||||
]))
|
|
||||||
)
|
|
||||||
error_message = "Use an empty map instead of null as value."
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -18,7 +18,8 @@ This module implements the creation and management of one GCP project including
|
||||||
- [Log Sinks](#log-sinks)
|
- [Log Sinks](#log-sinks)
|
||||||
- [Data Access Logs](#data-access-logs)
|
- [Data Access Logs](#data-access-logs)
|
||||||
- [Cloud KMS Encryption Keys](#cloud-kms-encryption-keys)
|
- [Cloud KMS Encryption Keys](#cloud-kms-encryption-keys)
|
||||||
- [Tags](#tags)
|
- [Attaching Tags](#attaching-tags)
|
||||||
|
- [Project-scoped Tags](#project-scoped-tags)
|
||||||
- [Outputs](#outputs)
|
- [Outputs](#outputs)
|
||||||
- [Managing project related configuration without creating it](#managing-project-related-configuration-without-creating-it)
|
- [Managing project related configuration without creating it](#managing-project-related-configuration-without-creating-it)
|
||||||
- [Files](#files)
|
- [Files](#files)
|
||||||
|
@ -655,9 +656,9 @@ module "project" {
|
||||||
# tftest modules=1 resources=6 e2e
|
# tftest modules=1 resources=6 e2e
|
||||||
```
|
```
|
||||||
|
|
||||||
## Tags
|
## Attaching Tags
|
||||||
|
|
||||||
Refer to the [Creating and managing tags](https://cloud.google.com/resource-manager/docs/tags/tags-creating-and-managing) documentation for details on usage.
|
You can attach secure tags to a project with the `tag_bindings` attribute
|
||||||
|
|
||||||
```hcl
|
```hcl
|
||||||
module "org" {
|
module "org" {
|
||||||
|
@ -686,6 +687,41 @@ module "project" {
|
||||||
# tftest modules=2 resources=6
|
# tftest modules=2 resources=6
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## Project-scoped Tags
|
||||||
|
|
||||||
|
To create project-scoped secure tags, use the `tags` and `network_tags` attributes.
|
||||||
|
|
||||||
|
```hcl
|
||||||
|
module "project" {
|
||||||
|
source = "./fabric/modules/project"
|
||||||
|
name = "project"
|
||||||
|
parent = var.folder_id
|
||||||
|
tags = {
|
||||||
|
mytag1 = {}
|
||||||
|
mytag2 = {
|
||||||
|
iam = {
|
||||||
|
"roles/resourcemanager.tagAdmin" = ["user:admin@example.com"]
|
||||||
|
}
|
||||||
|
values = {
|
||||||
|
myvalue1 = {}
|
||||||
|
myvalue2 = {
|
||||||
|
iam = {
|
||||||
|
"roles/resourcemanager.tagUser" = ["user:user@example.com"]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
network_tags = {
|
||||||
|
my_net_tag = {
|
||||||
|
network = "${var.project_id}/${var.vpc.name}"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
# tftest modules=1 resources=8
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
## Outputs
|
## Outputs
|
||||||
|
|
||||||
Most of this module's outputs depend on its resources, to allow Terraform to compute all dependencies required for the project to be correctly configured. This allows you to reference outputs like `project_id` in other modules or resources without having to worry about setting `depends_on` blocks manually.
|
Most of this module's outputs depend on its resources, to allow Terraform to compute all dependencies required for the project to be correctly configured. This allows you to reference outputs like `project_id` in other modules or resources without having to worry about setting `depends_on` blocks manually.
|
||||||
|
@ -935,7 +971,8 @@ module "bucket" {
|
||||||
| [outputs.tf](./outputs.tf) | Module outputs. | |
|
| [outputs.tf](./outputs.tf) | Module outputs. | |
|
||||||
| [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> |
|
| [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> |
|
| [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> |
|
| [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> |
|
||||||
|
| [variables-tags.tf](./variables-tags.tf) | None | |
|
||||||
| [variables.tf](./variables.tf) | Module variables. | |
|
| [variables.tf](./variables.tf) | Module variables. | |
|
||||||
| [versions.tf](./versions.tf) | Version pins. | |
|
| [versions.tf](./versions.tf) | Version pins. | |
|
||||||
| [vpc-sc.tf](./vpc-sc.tf) | VPC-SC project-level perimeter configuration. | <code>google_access_context_manager_service_perimeter_resource</code> |
|
| [vpc-sc.tf](./vpc-sc.tf) | VPC-SC project-level perimeter configuration. | <code>google_access_context_manager_service_perimeter_resource</code> |
|
||||||
|
@ -963,6 +1000,7 @@ module "bucket" {
|
||||||
| [logging_exclusions](variables.tf#L151) | Logging exclusions for this project in the form {NAME -> FILTER}. | <code>map(string)</code> | | <code>{}</code> |
|
| [logging_exclusions](variables.tf#L151) | Logging exclusions for this project in the form {NAME -> FILTER}. | <code>map(string)</code> | | <code>{}</code> |
|
||||||
| [logging_sinks](variables.tf#L158) | Logging sinks to create for this project. | <code title="map(object({ bq_partitioned_table = optional(bool) description = optional(string) destination = string disabled = optional(bool, false) exclusions = optional(map(string), {}) filter = string iam = optional(bool, true) type = string unique_writer = optional(bool, true) }))">map(object({…}))</code> | | <code>{}</code> |
|
| [logging_sinks](variables.tf#L158) | Logging sinks to create for this project. | <code title="map(object({ bq_partitioned_table = optional(bool) description = optional(string) destination = string disabled = optional(bool, false) exclusions = optional(map(string), {}) filter = string iam = optional(bool, true) type = string unique_writer = optional(bool, true) }))">map(object({…}))</code> | | <code>{}</code> |
|
||||||
| [metric_scopes](variables.tf#L189) | List of projects that will act as metric scopes for this project. | <code>list(string)</code> | | <code>[]</code> |
|
| [metric_scopes](variables.tf#L189) | List of projects that will act as metric scopes for this project. | <code>list(string)</code> | | <code>[]</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(object({ description = optional(string, "Managed by the Terraform project module.") iam = optional(map(list(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)), {}) })), {}) }))">map(object({…}))</code> | | <code>{}</code> |
|
||||||
| [org_policies](variables.tf#L201) | Organization policies applied to this project keyed by policy name. | <code title="map(object({ inherit_from_parent = optional(bool) # for list policies only. reset = optional(bool) rules = optional(list(object({ allow = optional(object({ all = optional(bool) values = optional(list(string)) })) deny = optional(object({ all = optional(bool) values = optional(list(string)) })) enforce = optional(bool) # for boolean policies only. condition = optional(object({ description = optional(string) expression = optional(string) location = optional(string) title = optional(string) }), {}) })), []) }))">map(object({…}))</code> | | <code>{}</code> |
|
| [org_policies](variables.tf#L201) | Organization policies applied to this project keyed by policy name. | <code title="map(object({ inherit_from_parent = optional(bool) # for list policies only. reset = optional(bool) rules = optional(list(object({ allow = optional(object({ all = optional(bool) values = optional(list(string)) })) deny = optional(object({ all = optional(bool) values = optional(list(string)) })) enforce = optional(bool) # for boolean policies only. condition = optional(object({ description = optional(string) expression = optional(string) location = optional(string) title = optional(string) }), {}) })), []) }))">map(object({…}))</code> | | <code>{}</code> |
|
||||||
| [parent](variables.tf#L228) | Parent folder or organization in 'folders/folder_id' or 'organizations/org_id' format. | <code>string</code> | | <code>null</code> |
|
| [parent](variables.tf#L228) | Parent folder or organization in 'folders/folder_id' or 'organizations/org_id' format. | <code>string</code> | | <code>null</code> |
|
||||||
| [prefix](variables.tf#L238) | Optional prefix used to generate project id and name. | <code>string</code> | | <code>null</code> |
|
| [prefix](variables.tf#L238) | Optional prefix used to generate project id and name. | <code>string</code> | | <code>null</code> |
|
||||||
|
@ -975,7 +1013,8 @@ module "bucket" {
|
||||||
| [shared_vpc_host_config](variables.tf#L292) | Configures this project as a Shared VPC host project (mutually exclusive with shared_vpc_service_project). | <code title="object({ enabled = bool service_projects = optional(list(string), []) })">object({…})</code> | | <code>null</code> |
|
| [shared_vpc_host_config](variables.tf#L292) | Configures this project as a Shared VPC host project (mutually exclusive with shared_vpc_service_project). | <code title="object({ enabled = bool service_projects = optional(list(string), []) })">object({…})</code> | | <code>null</code> |
|
||||||
| [shared_vpc_service_config](variables.tf#L301) | Configures this project as a Shared VPC service project (mutually exclusive with shared_vpc_host_config). | <code title="object({ host_project = string network_users = optional(list(string), []) service_identity_iam = optional(map(list(string)), {}) service_identity_subnet_iam = optional(map(list(string)), {}) service_iam_grants = optional(list(string), []) network_subnet_users = optional(map(list(string)), {}) })">object({…})</code> | | <code title="{ host_project = null }">{…}</code> |
|
| [shared_vpc_service_config](variables.tf#L301) | Configures this project as a Shared VPC service project (mutually exclusive with shared_vpc_host_config). | <code title="object({ host_project = string network_users = optional(list(string), []) service_identity_iam = optional(map(list(string)), {}) service_identity_subnet_iam = optional(map(list(string)), {}) service_iam_grants = optional(list(string), []) network_subnet_users = optional(map(list(string)), {}) })">object({…})</code> | | <code title="{ host_project = null }">{…}</code> |
|
||||||
| [skip_delete](variables.tf#L329) | Allows the underlying resources to be destroyed without destroying the project itself. | <code>bool</code> | | <code>false</code> |
|
| [skip_delete](variables.tf#L329) | Allows the underlying resources to be destroyed without destroying the project itself. | <code>bool</code> | | <code>false</code> |
|
||||||
| [tag_bindings](variables.tf#L335) | Tag bindings for this project, in key => tag value id format. | <code>map(string)</code> | | <code>null</code> |
|
| [tag_bindings](variables-tags.tf#L45) | Tag bindings for this project, in key => tag value id format. | <code>map(string)</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(object({ description = optional(string, "Managed by the Terraform project module.") iam = optional(map(list(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) })), {}) }))">map(object({…}))</code> | | <code>{}</code> |
|
||||||
|
|
||||||
## Outputs
|
## Outputs
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/**
|
/**
|
||||||
* Copyright 2022 Google LLC
|
* Copyright 2023 Google LLC
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
@ -14,6 +14,115 @@
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
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) : {
|
||||||
|
role = role
|
||||||
|
tag = tag
|
||||||
|
tag_id = attrs.id
|
||||||
|
}
|
||||||
|
]
|
||||||
|
])
|
||||||
|
tag_values = {
|
||||||
|
for t in local._tag_values : t.key => t
|
||||||
|
}
|
||||||
|
tag_values_iam = {
|
||||||
|
for t in local._tag_values_iam : "${t.key}:${t.role}" => t
|
||||||
|
}
|
||||||
|
tags = merge(var.tags, var.network_tags)
|
||||||
|
tags_iam = {
|
||||||
|
for t in local._tags_iam : "${t.tag}:${t.role}" => t
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# keys
|
||||||
|
|
||||||
|
resource "google_tags_tag_key" "default" {
|
||||||
|
for_each = { for k, v in local.tags : k => v if v.id == null }
|
||||||
|
parent = "projects/${local.project.project_id}"
|
||||||
|
purpose = (
|
||||||
|
lookup(each.value, "network", null) == null ? null : "GCE_FIREWALL"
|
||||||
|
)
|
||||||
|
purpose_data = (
|
||||||
|
lookup(each.value, "network", null) == null ? null : { network = each.value.network }
|
||||||
|
)
|
||||||
|
short_name = each.key
|
||||||
|
description = each.value.description
|
||||||
|
# depends_on = [
|
||||||
|
# google_organization_iam_binding.authoritative,
|
||||||
|
# google_organization_iam_binding.bindings,
|
||||||
|
# google_organization_iam_member.bindings
|
||||||
|
# ]
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "google_tags_tag_key_iam_binding" "default" {
|
||||||
|
for_each = local.tags_iam
|
||||||
|
tag_key = (
|
||||||
|
each.value.tag_id == null
|
||||||
|
? google_tags_tag_key.default[each.value.tag].id
|
||||||
|
: each.value.tag_id
|
||||||
|
)
|
||||||
|
role = each.value.role
|
||||||
|
members = coalesce(
|
||||||
|
local.tags[each.value.tag]["iam"][each.value.role], []
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
# values
|
||||||
|
|
||||||
|
resource "google_tags_tag_value" "default" {
|
||||||
|
for_each = { for k, v in local.tag_values : k => v if v.id == null }
|
||||||
|
parent = (
|
||||||
|
each.value.tag_id == null
|
||||||
|
? google_tags_tag_key.default[each.value.tag].id
|
||||||
|
: each.value.tag_id
|
||||||
|
)
|
||||||
|
short_name = each.value.name
|
||||||
|
description = each.value.description
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "google_tags_tag_value_iam_binding" "default" {
|
||||||
|
for_each = local.tag_values_iam
|
||||||
|
tag_value = (
|
||||||
|
each.value.id == null
|
||||||
|
? google_tags_tag_value.default[each.value.key].id
|
||||||
|
: each.value.id
|
||||||
|
)
|
||||||
|
role = each.value.role
|
||||||
|
members = coalesce(
|
||||||
|
local.tags[each.value.tag]["values"][each.value.name]["iam"][each.value.role],
|
||||||
|
[]
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
# bindings
|
||||||
|
|
||||||
resource "google_tags_tag_binding" "binding" {
|
resource "google_tags_tag_binding" "binding" {
|
||||||
for_each = coalesce(var.tag_bindings, {})
|
for_each = coalesce(var.tag_bindings, {})
|
||||||
parent = "//cloudresourcemanager.googleapis.com/projects/${local.project.number}"
|
parent = "//cloudresourcemanager.googleapis.com/projects/${local.project.number}"
|
||||||
|
|
|
@ -0,0 +1,78 @@
|
||||||
|
/**
|
||||||
|
* Copyright 2023 Google LLC
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
variable "network_tags" {
|
||||||
|
description = "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."
|
||||||
|
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
|
||||||
|
values = optional(map(object({
|
||||||
|
description = optional(string, "Managed by the Terraform project module.")
|
||||||
|
iam = optional(map(list(string)), {})
|
||||||
|
})), {})
|
||||||
|
}))
|
||||||
|
nullable = false
|
||||||
|
default = {}
|
||||||
|
validation {
|
||||||
|
condition = (
|
||||||
|
alltrue([
|
||||||
|
for k, v in var.network_tags : v != null
|
||||||
|
]) &&
|
||||||
|
# all values are non-null
|
||||||
|
alltrue(flatten([
|
||||||
|
for k, v in var.network_tags : [for k2, v2 in v.values : v2 != null]
|
||||||
|
]))
|
||||||
|
)
|
||||||
|
error_message = "Use an empty map instead of null as value."
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
variable "tag_bindings" {
|
||||||
|
description = "Tag bindings for this project, in key => tag value id format."
|
||||||
|
type = map(string)
|
||||||
|
default = null
|
||||||
|
}
|
||||||
|
|
||||||
|
variable "tags" {
|
||||||
|
description = "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."
|
||||||
|
type = map(object({
|
||||||
|
description = optional(string, "Managed by the Terraform project module.")
|
||||||
|
iam = optional(map(list(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)
|
||||||
|
})), {})
|
||||||
|
}))
|
||||||
|
nullable = false
|
||||||
|
default = {}
|
||||||
|
validation {
|
||||||
|
condition = (
|
||||||
|
# all keys are non-null
|
||||||
|
alltrue([
|
||||||
|
for k, v in var.tags : v != null
|
||||||
|
]) &&
|
||||||
|
# all values are non-null
|
||||||
|
alltrue(flatten([
|
||||||
|
for k, v in var.tags : [for k2, v2 in v.values : v2 != null]
|
||||||
|
]))
|
||||||
|
)
|
||||||
|
error_message = "Use an empty map instead of null as value."
|
||||||
|
}
|
||||||
|
}
|
|
@ -331,9 +331,3 @@ variable "skip_delete" {
|
||||||
type = bool
|
type = bool
|
||||||
default = false
|
default = false
|
||||||
}
|
}
|
||||||
|
|
||||||
variable "tag_bindings" {
|
|
||||||
description = "Tag bindings for this project, in key => tag value id format."
|
|
||||||
type = map(string)
|
|
||||||
default = null
|
|
||||||
}
|
|
||||||
|
|
Loading…
Reference in New Issue