diff --git a/fast/stages/1-resman/README.md b/fast/stages/1-resman/README.md
index c867b2308..0bbb2f81f 100644
--- a/fast/stages/1-resman/README.md
+++ b/fast/stages/1-resman/README.md
@@ -269,7 +269,7 @@ terraform apply
| [environments](variables-fast.tf#L72) | Environment names. | map(object({…})) | ✓ | | 0-globals |
| [logging](variables-fast.tf#L118) | Logging configuration for tenants. | object({…}) | ✓ | | 1-tenant-factory |
| [organization](variables-fast.tf#L131) | Organization details. | object({…}) | ✓ | | 0-bootstrap |
-| [prefix](variables-fast.tf#L149) | Prefix used for resources that need unique names. Use 9 characters or less. | string | ✓ | | 0-bootstrap |
+| [prefix](variables-fast.tf#L161) | Prefix used for resources that need unique names. Use 9 characters or less. | string | ✓ | | 0-bootstrap |
| [custom_roles](variables-fast.tf#L54) | Custom roles defined at the org level, in key => id format. | object({…}) | | null | 0-bootstrap |
| [factories_config](variables.tf#L20) | Configuration for the resource factories or external data. | object({…}) | | {} | |
| [fast_addon](variables-addons.tf#L17) | FAST addons configurations for stages 2. Keys are used as short names for the add-on resources. | map(object({…})) | | {} | |
@@ -277,11 +277,12 @@ terraform apply
| [fast_stage_3](variables-stages.tf#L113) | FAST stages 3 configurations. | map(object({…})) | | {} | |
| [groups](variables-fast.tf#L90) | Group names or IAM-format principals to grant organization-level permissions. If just the name is provided, the 'group:' principal and organization domain are interpolated. | object({…}) | | {} | 0-bootstrap |
| [locations](variables-fast.tf#L105) | Optional locations for GCS, BigQuery, and logging buckets created here. | object({…}) | | {} | 0-bootstrap |
+| [org_policy_tags](variables-fast.tf#L149) | Organization policy tags. | object({…}) | | {} | 0-bootstrap |
| [outputs_location](variables.tf#L31) | Enable writing provider, tfvars and CI/CD workflow files to local filesystem. Leave null to disable. | string | | null | |
| [resource_names](variables.tf#L37) | Resource names overrides for specific resources. Stage names are interpolated via `$${name}`. Prefix is always set via code, except where noted in the variable type. | object({…}) | | {} | |
-| [root_node](variables-fast.tf#L155) | Root node for the hierarchy, if running in tenant mode. | string | | null | 0-bootstrap |
+| [root_node](variables-fast.tf#L167) | Root node for the hierarchy, if running in tenant mode. | string | | null | 0-bootstrap |
| [tag_names](variables.tf#L57) | Customized names for resource management tags. | object({…}) | | {} | |
-| [tags](variables.tf#L71) | Custom secure tags by key name. The `iam` attribute behaves like the similarly named one at module level. | map(object({…})) | | {} | |
+| [tags](variables.tf#L71) | Custom secure tags by key name. The `iam` attribute behaves like the similarly named one at module level. | map(object({…})) | | {} | |
| [top_level_folders](variables-toplevel-folders.tf#L17) | Additional top-level folders. Keys are used for service account and bucket names, values implement the folders module interface with the addition of the 'automation' attribute. | map(object({…})) | | {} | |
## Outputs
diff --git a/fast/stages/1-resman/organization.tf b/fast/stages/1-resman/organization.tf
index 3927e13d3..953234b03 100644
--- a/fast/stages/1-resman/organization.tf
+++ b/fast/stages/1-resman/organization.tf
@@ -72,6 +72,10 @@ locals {
]...),
local.billing_mode != "org" ? {} : local.billing_iam
)
+ org_policy_tags = {
+ for k, v in var.org_policy_tags.values :
+ "${var.org_policy_tags.key_name}/${k}" => v
+ }
# IAM principal expansion for user-specified tag values
tags = {
for k, v in var.tags : k => merge(v, {
@@ -80,6 +84,11 @@ locals {
for rm in rv : lookup(local.principals_iam, rm, rm)
]
}
+ id = (
+ v.id == null || v.id != var.org_policy_tags.key_name
+ ? v.id
+ : var.org_policy_tags.key_id
+ )
values = {
for vk, vv in v.values : vk => merge(vv, {
iam = {
@@ -87,6 +96,9 @@ locals {
for rm in rv : lookup(local.principals_iam, rm, rm)
]
}
+ id = (
+ vv.id == null ? null : lookup(local.org_policy_tags, vv.id, vv.id)
+ )
})
}
})
diff --git a/fast/stages/1-resman/variables-fast.tf b/fast/stages/1-resman/variables-fast.tf
index 439139b84..d35c24a48 100644
--- a/fast/stages/1-resman/variables-fast.tf
+++ b/fast/stages/1-resman/variables-fast.tf
@@ -146,6 +146,18 @@ check "prefix_validator" {
}
}
+variable "org_policy_tags" {
+ # tfdoc:variable:source 0-bootstrap
+ description = "Organization policy tags."
+ type = object({
+ key_id = optional(string)
+ key_name = optional(string, "org-policies")
+ values = optional(map(string), {})
+ })
+ nullable = false
+ default = {}
+}
+
variable "prefix" {
# tfdoc:variable:source 0-bootstrap
description = "Prefix used for resources that need unique names. Use 9 characters or less."
diff --git a/fast/stages/1-resman/variables.tf b/fast/stages/1-resman/variables.tf
index 37ab5325f..5bdf85ee1 100644
--- a/fast/stages/1-resman/variables.tf
+++ b/fast/stages/1-resman/variables.tf
@@ -73,6 +73,7 @@ variable "tags" {
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)), {})
diff --git a/fast/stages/2-project-factory/README.md b/fast/stages/2-project-factory/README.md
index cbe55e472..73b8a4d85 100644
--- a/fast/stages/2-project-factory/README.md
+++ b/fast/stages/2-project-factory/README.md
@@ -354,17 +354,18 @@ The approach is not shown here but reasonably easy to implement. The main projec
|---|---|:---:|:---:|:---:|:---:|
| [automation](variables-fast.tf#L17) | Automation resources created by the bootstrap stage. | object({…}) | ✓ | | 0-bootstrap |
| [billing_account](variables-fast.tf#L26) | Billing account id. If billing account is not part of the same org set `is_org_level` to false. | object({…}) | ✓ | | 0-bootstrap |
-| [prefix](variables-fast.tf#L82) | Prefix used for resources that need unique names. Use a maximum of 9 chars for organizations, and 11 chars for tenants. | string | ✓ | | 0-bootstrap |
+| [prefix](variables-fast.tf#L93) | Prefix used for resources that need unique names. Use a maximum of 9 chars for organizations, and 11 chars for tenants. | string | ✓ | | 0-bootstrap |
| [factories_config](variables.tf#L17) | Configuration for YAML-based factories. | object({…}) | | {} | |
| [folder_ids](variables-fast.tf#L39) | Folders created in the resource management stage. | map(string) | | {} | 1-resman |
| [groups](variables-fast.tf#L47) | Group names or IAM-format principals to grant organization-level permissions. If just the name is provided, the 'group:' principal and organization domain are interpolated. | map(string) | | {} | 0-bootstrap |
| [host_project_ids](variables-fast.tf#L56) | Host project for the shared VPC. | map(string) | | {} | 2-networking |
| [locations](variables-fast.tf#L64) | Optional locations for GCS, BigQuery, and logging buckets created here. | object({…}) | | {} | 0-bootstrap |
+| [org_policy_tags](variables-fast.tf#L82) | Optional organization policy tag values. | object({…}) | | {} | 0-bootstrap |
| [outputs_location](variables.tf#L39) | Enable writing provider, tfvars and CI/CD workflow files to local filesystem. Leave null to disable. | string | | null | |
| [perimeters](variables-fast.tf#L74) | Optional VPC-SC perimeter ids. | map(string) | | {} | 1-vpcsc |
-| [service_accounts](variables-fast.tf#L92) | Automation service accounts in name => email format. | map(string) | | {} | 1-resman |
+| [service_accounts](variables-fast.tf#L103) | Automation service accounts in name => email format. | map(string) | | {} | 1-resman |
| [stage_name](variables.tf#L45) | FAST stage name. Used to separate output files across different factories. | string | | "2-project-factory" | |
-| [tag_values](variables-fast.tf#L100) | FAST-managed resource manager tag values. | map(string) | | {} | 1-resman |
+| [tag_values](variables-fast.tf#L111) | FAST-managed resource manager tag values. | map(string) | | {} | 1-resman |
## Outputs
diff --git a/fast/stages/2-project-factory/main.tf b/fast/stages/2-project-factory/main.tf
index eccc0e428..c811e06df 100644
--- a/fast/stages/2-project-factory/main.tf
+++ b/fast/stages/2-project-factory/main.tf
@@ -47,6 +47,10 @@ module "projects" {
)
perimeters = var.perimeters
tag_values = merge(
+ {
+ for k, v in var.org_policy_tags.values :
+ "${var.org_policy_tags.key_name}/${k}" => v
+ },
var.tag_values,
var.factories_config.context.tag_values
)
diff --git a/fast/stages/2-project-factory/variables-fast.tf b/fast/stages/2-project-factory/variables-fast.tf
index bf2d1c9a1..0f99ddbe4 100644
--- a/fast/stages/2-project-factory/variables-fast.tf
+++ b/fast/stages/2-project-factory/variables-fast.tf
@@ -79,6 +79,17 @@ variable "perimeters" {
default = {}
}
+variable "org_policy_tags" {
+ # tfdoc:variable:source 0-bootstrap
+ description = "Optional organization policy tag values."
+ type = object({
+ key_name = optional(string, "org-policies")
+ values = optional(map(string), {})
+ })
+ nullable = false
+ default = {}
+}
+
variable "prefix" {
# tfdoc:variable:source 0-bootstrap
description = "Prefix used for resources that need unique names. Use a maximum of 9 chars for organizations, and 11 chars for tenants."
diff --git a/modules/project-factory/README.md b/modules/project-factory/README.md
index edc48991e..8165d0697 100644
--- a/modules/project-factory/README.md
+++ b/modules/project-factory/README.md
@@ -494,7 +494,7 @@ service_accounts:
| name | description | type | required | default |
|---|---|:---:|:---:|:---:|
-| [factories_config](variables.tf#L121) | Path to folder with YAML resource description data files. | object({…}) | ✓ | |
+| [factories_config](variables.tf#L121) | Path to folder with YAML resource description data files. | object({…}) | ✓ | |
| [data_defaults](variables.tf#L17) | Optional default values used when corresponding project data from files are missing. | object({…}) | | {} |
| [data_merges](variables.tf#L64) | Optional values that will be merged with corresponding data from files. Combines with `data_defaults`, file data, and `data_overrides`. | object({…}) | | {} |
| [data_overrides](variables.tf#L83) | Optional values that override corresponding data from files. Takes precedence over file data and `data_defaults`. | object({…}) | | {} |