Add context to organization policiy factories (#2876)

This commit is contained in:
Julio Castillo
2025-02-10 23:24:01 +01:00
committed by GitHub
parent cfe8c130f0
commit 3ffe838e06
12 changed files with 192 additions and 70 deletions

View File

@@ -125,7 +125,7 @@ module "folder" {
"iam.allowedPolicyMemberDomains" = {
rules = [{
allow = {
values = ["C0xxxxxxx", "C0yyyyyyy"]
values = ["C0xxxxxxx", "C0yyyyyyy", "C0zzzzzzz"]
}
}]
}
@@ -144,7 +144,7 @@ module "folder" {
{
enforce = true
parameters = jsonencode({
allowedDomains = ["@example.com"]
allowedDomains = ["@example.com", "@secondary.example.com"]
})
}
]
@@ -169,6 +169,19 @@ module "folder" {
name = "Folder name"
factories_config = {
org_policies = "configs/org-policies/"
context = {
org_policies = {
tags = {
my_conditional_tag = "tagKeys/1234"
}
domains = {
secondary = "@secondary.example.com"
}
customer_ids = {
extra = "C0zzzzzzz"
}
}
}
}
}
# tftest modules=1 resources=9 files=boolean,list inventory=org-policies.yaml e2e
@@ -188,7 +201,7 @@ iam.disableServiceAccountKeyUpload:
rules:
- condition:
description: test condition
expression: resource.matchTagId('tagKeys/1234', 'tagValues/1234')
expression: resource.matchTagId('${tags.my_conditional_tag}', 'tagValues/1234')
location: somewhere
title: condition
enforce: true
@@ -197,7 +210,7 @@ essentialcontacts.managed.allowedContactDomains:
rules:
- enforce: true
parameters: |
{"allowedDomains": ["@example.com"]}
{"allowedDomains": ["@example.com", "${domains.secondary}"]}
# tftest-file id=boolean path=configs/org-policies/boolean.yaml schema=org-policies.schema.json
```
@@ -218,6 +231,7 @@ iam.allowedPolicyMemberDomains:
values:
- C0xxxxxxx
- C0yyyyyyy
- ${customer_ids.extra}
# tftest-file id=list path=configs/org-policies/list.yaml schema=org-policies.schema.json
```
@@ -413,23 +427,23 @@ module "folder" {
| [assured_workload_config](variables.tf#L17) | Create AssuredWorkloads folder instead of regular folder when value is provided. Incompatible with folder_create=false. | <code title="object&#40;&#123;&#10; compliance_regime &#61; string&#10; display_name &#61; string&#10; location &#61; string&#10; organization &#61; string&#10; enable_sovereign_controls &#61; optional&#40;bool&#41;&#10; labels &#61; optional&#40;map&#40;string&#41;, &#123;&#125;&#41;&#10; partner &#61; optional&#40;string&#41;&#10; partner_permissions &#61; optional&#40;object&#40;&#123;&#10; assured_workloads_monitoring &#61; optional&#40;bool&#41;&#10; data_logs_viewer &#61; optional&#40;bool&#41;&#10; service_access_approver &#61; optional&#40;bool&#41;&#10; &#125;&#41;&#41;&#10; violation_notifications_enabled &#61; optional&#40;bool&#41;&#10;&#10;&#10;&#125;&#41;">object&#40;&#123;&#8230;&#125;&#41;</code> | | <code>null</code> |
| [contacts](variables.tf#L70) | 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&#40;list&#40;string&#41;&#41;</code> | | <code>&#123;&#125;</code> |
| [deletion_protection](variables.tf#L77) | Deletion protection setting for this folder. | <code>bool</code> | | <code>false</code> |
| [factories_config](variables.tf#L83) | Paths to data files and folders that enable factory functionality. | <code title="object&#40;&#123;&#10; org_policies &#61; optional&#40;string&#41;&#10;&#125;&#41;">object&#40;&#123;&#8230;&#125;&#41;</code> | | <code>&#123;&#125;</code> |
| [firewall_policy](variables.tf#L92) | Hierarchical firewall policy to associate to this folder. | <code title="object&#40;&#123;&#10; name &#61; string&#10; policy &#61; string&#10;&#125;&#41;">object&#40;&#123;&#8230;&#125;&#41;</code> | | <code>null</code> |
| [folder_create](variables.tf#L101) | Create folder. When set to false, uses id to reference an existing folder. | <code>bool</code> | | <code>true</code> |
| [factories_config](variables.tf#L83) | Paths to data files and folders that enable factory functionality. | <code title="object&#40;&#123;&#10; org_policies &#61; optional&#40;string&#41;&#10; context &#61; optional&#40;object&#40;&#123;&#10; org_policies &#61; optional&#40;map&#40;map&#40;string&#41;&#41;, &#123;&#125;&#41;&#10; &#125;&#41;, &#123;&#125;&#41;&#10;&#125;&#41;">object&#40;&#123;&#8230;&#125;&#41;</code> | | <code>&#123;&#125;</code> |
| [firewall_policy](variables.tf#L95) | Hierarchical firewall policy to associate to this folder. | <code title="object&#40;&#123;&#10; name &#61; string&#10; policy &#61; string&#10;&#125;&#41;">object&#40;&#123;&#8230;&#125;&#41;</code> | | <code>null</code> |
| [folder_create](variables.tf#L104) | Create folder. When set to false, uses id to reference an existing folder. | <code>bool</code> | | <code>true</code> |
| [iam](variables-iam.tf#L17) | IAM bindings in {ROLE => [MEMBERS]} format. | <code>map&#40;list&#40;string&#41;&#41;</code> | | <code>&#123;&#125;</code> |
| [iam_bindings](variables-iam.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-iam.tf#L39) | 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> |
| [iam_by_principals](variables-iam.tf#L61) | Authoritative IAM binding in {PRINCIPAL => [ROLES]} format. Principals need to be statically defined to avoid errors. Merged internally with the `iam` variable. | <code>map&#40;list&#40;string&#41;&#41;</code> | | <code>&#123;&#125;</code> |
| [iam_by_principals_additive](variables-iam.tf#L54) | Additive IAM binding in {PRINCIPAL => [ROLES]} format. Principals need to be statically defined to avoid errors. Merged internally with the `iam_bindings_additive` variable. | <code>map&#40;list&#40;string&#41;&#41;</code> | | <code>&#123;&#125;</code> |
| [id](variables.tf#L107) | Folder ID in case you use folder_create=false. | <code>string</code> | | <code>null</code> |
| [id](variables.tf#L110) | Folder ID in case you use folder_create=false. | <code>string</code> | | <code>null</code> |
| [logging_data_access](variables-logging.tf#L17) | Control activation of data access logs. The special 'allServices' key denotes configuration for all services. | <code title="map&#40;object&#40;&#123;&#10; ADMIN_READ &#61; optional&#40;object&#40;&#123; exempted_members &#61; optional&#40;list&#40;string&#41;&#41; &#125;&#41;&#41;,&#10; DATA_READ &#61; optional&#40;object&#40;&#123; exempted_members &#61; optional&#40;list&#40;string&#41;&#41; &#125;&#41;&#41;,&#10; DATA_WRITE &#61; optional&#40;object&#40;&#123; exempted_members &#61; optional&#40;list&#40;string&#41;&#41; &#125;&#41;&#41;&#10;&#125;&#41;&#41;">map&#40;object&#40;&#123;&#8230;&#125;&#41;&#41;</code> | | <code>&#123;&#125;</code> |
| [logging_exclusions](variables-logging.tf#L28) | Logging exclusions for this folder in the form {NAME -> FILTER}. | <code>map&#40;string&#41;</code> | | <code>&#123;&#125;</code> |
| [logging_settings](variables-logging.tf#L35) | 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#L45) | Logging sinks to create for the folder. | <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; intercept_children &#61; optional&#40;bool, false&#41;&#10; type &#61; string&#10;&#125;&#41;&#41;">map&#40;object&#40;&#123;&#8230;&#125;&#41;&#41;</code> | | <code>&#123;&#125;</code> |
| [name](variables.tf#L113) | Folder name. | <code>string</code> | | <code>null</code> |
| [org_policies](variables.tf#L119) | Organization policies applied to this folder 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; parameters &#61; optional&#40;string&#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#L147) | Parent in folders/folder_id or organizations/org_id format. | <code>string</code> | | <code>null</code> |
| [tag_bindings](variables.tf#L157) | Tag bindings for this folder, in key => tag value id format. | <code>map&#40;string&#41;</code> | | <code>null</code> |
| [name](variables.tf#L116) | Folder name. | <code>string</code> | | <code>null</code> |
| [org_policies](variables.tf#L122) | Organization policies applied to this folder 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; parameters &#61; optional&#40;string&#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#L150) | Parent in folders/folder_id or organizations/org_id format. | <code>string</code> | | <code>null</code> |
| [tag_bindings](variables.tf#L160) | Tag bindings for this folder, in key => tag value id format. | <code>map&#40;string&#41;</code> | | <code>null</code> |
## Outputs

View File

@@ -31,21 +31,49 @@ locals {
rules = [
for r in try(v.rules, []) : {
allow = can(r.allow) ? {
all = try(r.allow.all, null)
values = try(r.allow.values, null)
all = try(r.allow.all, null)
values = (
can(r.allow.values)
? [for x in r.allow.values : templatestring(x, var.factories_config.context.org_policies)]
: null
)
} : null
deny = can(r.deny) ? {
all = try(r.deny.all, null)
values = try(r.deny.values, null)
all = try(r.deny.all, null)
values = (
can(r.deny.values)
? [for x in r.deny.values : templatestring(x, var.factories_config.context.org_policies)]
: null
)
} : null
enforce = try(r.enforce, null)
condition = {
description = try(r.condition.description, null)
expression = try(r.condition.expression, null)
location = try(r.condition.location, null)
title = try(r.condition.title, null)
description = (
can(r.condition.description)
? templatestring(r.condition.description, var.factories_config.context.org_policies)
: null
)
expression = (
can(r.condition.expression)
? templatestring(r.condition.expression, var.factories_config.context.org_policies)
: null
)
location = (
can(r.condition.location)
? templatestring(r.condition.location, var.factories_config.context.org_policies)
: null
)
title = (
can(r.condition.title)
? templatestring(r.condition.title, var.factories_config.context.org_policies)
: null
)
}
parameters = try(r.parameters, null)
parameters = (
can(r.parameters)
? templatestring(r.parameters, var.factories_config.context.org_policies)
: null
)
}
]
}

View File

@@ -84,6 +84,9 @@ variable "factories_config" {
description = "Paths to data files and folders that enable factory functionality."
type = object({
org_policies = optional(string)
context = optional(object({
org_policies = optional(map(map(string)), {})
}), {})
})
nullable = false
default = {}

View File

@@ -535,11 +535,11 @@ module "org" {
| name | description | type | required | default |
|---|---|:---:|:---:|:---:|
| [organization_id](variables.tf#L93) | Organization id in organizations/nnnnnn format. | <code>string</code> | ✓ | |
| [organization_id](variables.tf#L96) | 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&#40;list&#40;string&#41;&#41;</code> | | <code>&#123;&#125;</code> |
| [custom_roles](variables.tf#L24) | Map of role name => list of permissions to create in this project. | <code>map&#40;list&#40;string&#41;&#41;</code> | | <code>&#123;&#125;</code> |
| [factories_config](variables.tf#L31) | Paths to data files and folders that enable factory functionality. | <code title="object&#40;&#123;&#10; custom_roles &#61; optional&#40;string&#41;&#10; org_policies &#61; optional&#40;string&#41;&#10; org_policy_custom_constraints &#61; optional&#40;string&#41;&#10;&#125;&#41;">object&#40;&#123;&#8230;&#125;&#41;</code> | | <code>&#123;&#125;</code> |
| [firewall_policy](variables.tf#L42) | Hierarchical firewall policies to associate to the organization. | <code title="object&#40;&#123;&#10; name &#61; string&#10; policy &#61; string&#10;&#125;&#41;">object&#40;&#123;&#8230;&#125;&#41;</code> | | <code>null</code> |
| [factories_config](variables.tf#L31) | Paths to data files and folders that enable factory functionality. | <code title="object&#40;&#123;&#10; custom_roles &#61; optional&#40;string&#41;&#10; org_policies &#61; optional&#40;string&#41;&#10; org_policy_custom_constraints &#61; optional&#40;string&#41;&#10; context &#61; optional&#40;object&#40;&#123;&#10; org_policies &#61; optional&#40;map&#40;map&#40;string&#41;&#41;, &#123;&#125;&#41;&#10; &#125;&#41;, &#123;&#125;&#41;&#10;&#125;&#41;">object&#40;&#123;&#8230;&#125;&#41;</code> | | <code>&#123;&#125;</code> |
| [firewall_policy](variables.tf#L45) | Hierarchical firewall policies to associate to the organization. | <code title="object&#40;&#123;&#10; name &#61; string&#10; policy &#61; string&#10;&#125;&#41;">object&#40;&#123;&#8230;&#125;&#41;</code> | | <code>null</code> |
| [iam](variables-iam.tf#L17) | IAM bindings, in {ROLE => [MEMBERS]} format. | <code>map&#40;list&#40;string&#41;&#41;</code> | | <code>&#123;&#125;</code> |
| [iam_bindings](variables-iam.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-iam.tf#L39) | 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> |
@@ -550,8 +550,8 @@ module "org" {
| [logging_settings](variables-logging.tf#L35) | 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#L45) | 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; intercept_children &#61; optional&#40;bool, false&#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; 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; parameters &#61; optional&#40;string&#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#L79) | 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> |
| [org_policies](variables.tf#L54) | 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; parameters &#61; optional&#40;string&#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#L82) | 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#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> |

View File

@@ -31,21 +31,49 @@ locals {
rules = [
for r in try(v.rules, []) : {
allow = can(r.allow) ? {
all = try(r.allow.all, null)
values = try(r.allow.values, null)
all = try(r.allow.all, null)
values = (
can(r.allow.values)
? [for x in r.allow.values : templatestring(x, var.factories_config.context.org_policies)]
: null
)
} : null
deny = can(r.deny) ? {
all = try(r.deny.all, null)
values = try(r.deny.values, null)
all = try(r.deny.all, null)
values = (
can(r.deny.values)
? [for x in r.deny.values : templatestring(x, var.factories_config.context.org_policies)]
: null
)
} : null
enforce = try(r.enforce, null)
condition = {
description = try(r.condition.description, null)
expression = try(r.condition.expression, null)
location = try(r.condition.location, null)
title = try(r.condition.title, null)
description = (
can(r.condition.description)
? templatestring(r.condition.description, var.factories_config.context.org_policies)
: null
)
expression = (
can(r.condition.expression)
? templatestring(r.condition.expression, var.factories_config.context.org_policies)
: null
)
location = (
can(r.condition.location)
? templatestring(r.condition.location, var.factories_config.context.org_policies)
: null
)
title = (
can(r.condition.title)
? templatestring(r.condition.title, var.factories_config.context.org_policies)
: null
)
}
parameters = try(r.parameters, null)
parameters = (
can(r.parameters)
? templatestring(r.parameters, var.factories_config.context.org_policies)
: null
)
}
]
}

View File

@@ -34,6 +34,9 @@ variable "factories_config" {
custom_roles = optional(string)
org_policies = optional(string)
org_policy_custom_constraints = optional(string)
context = optional(object({
org_policies = optional(map(map(string)), {})
}), {})
})
nullable = false
default = {}

File diff suppressed because one or more lines are too long

View File

@@ -31,21 +31,49 @@ locals {
rules = [
for r in try(v.rules, []) : {
allow = can(r.allow) ? {
all = try(r.allow.all, null)
values = try(r.allow.values, null)
all = try(r.allow.all, null)
values = (
can(r.allow.values)
? [for x in r.allow.values : templatestring(x, var.factories_config.context.org_policies)]
: null
)
} : null
deny = can(r.deny) ? {
all = try(r.deny.all, null)
values = try(r.deny.values, null)
all = try(r.deny.all, null)
values = (
can(r.deny.values)
? [for x in r.deny.values : templatestring(x, var.factories_config.context.org_policies)]
: null
)
} : null
enforce = try(r.enforce, null)
condition = {
description = try(r.condition.description, null)
expression = try(r.condition.expression, null)
location = try(r.condition.location, null)
title = try(r.condition.title, null)
description = (
can(r.condition.description)
? templatestring(r.condition.description, var.factories_config.context.org_policies)
: null
)
expression = (
can(r.condition.expression)
? templatestring(r.condition.expression, var.factories_config.context.org_policies)
: null
)
location = (
can(r.condition.location)
? templatestring(r.condition.location, var.factories_config.context.org_policies)
: null
)
title = (
can(r.condition.title)
? templatestring(r.condition.title, var.factories_config.context.org_policies)
: null
)
}
parameters = try(r.parameters, null)
parameters = (
can(r.parameters)
? templatestring(r.parameters, var.factories_config.context.org_policies)
: null
)
}
]
}

View File

@@ -87,6 +87,7 @@ variable "factories_config" {
quotas = optional(string)
context = optional(object({
notification_channels = optional(map(string), {})
org_policies = optional(map(map(string)), {})
}), {})
})
nullable = false

View File

@@ -84,7 +84,7 @@ values:
condition: []
deny_all: null
enforce: 'TRUE'
parameters: '{"allowedDomains":["@example.com"]}'
parameters: '{"allowedDomains":["@example.com","@secondary.example.com"]}'
values: []
timeouts: null
module.folder.google_org_policy_policy.default["iam.allowedPolicyMemberDomains"]:
@@ -102,6 +102,7 @@ values:
- allowed_values:
- C0xxxxxxx
- C0yyyyyyy
- C0zzzzzzz
denied_values: null
timeouts: null
module.folder.google_org_policy_policy.default["iam.disableServiceAccountKeyCreation"]:

View File

@@ -34,7 +34,7 @@ def test_policy_implementation():
'@@ -17 +17 @@\n',
'-# tfdoc:file:description Project-level organization policies.\n',
'+# tfdoc:file:description Folder-level organization policies.\n',
'@@ -81,2 +81,2 @@\n',
'@@ -109,2 +109,2 @@\n',
'- name = "projects/${local.project.project_id}/policies/${each.value}"\n',
'- parent = "projects/${local.project.project_id}"\n',
'+ name = "${local.folder_id}/policies/${each.value}"\n',
@@ -49,12 +49,12 @@ def test_policy_implementation():
'@@ -17 +17 @@\n',
'-# tfdoc:file:description Folder-level organization policies.\n',
'+# tfdoc:file:description Organization-level organization policies.\n',
'@@ -81,2 +81,2 @@\n',
'@@ -109,2 +109,2 @@\n',
'- name = "${local.folder_id}/policies/${each.value}"\n',
'- parent = local.folder_id\n',
'+ name = "${var.organization_id}/policies/${each.value}"\n',
'+ parent = var.organization_id\n',
'@@ -159,0 +160,9 @@\n',
'@@ -187,0 +188,9 @@\n',
'+ depends_on = [\n',
'+ google_organization_iam_binding.authoritative,\n',
'+ google_organization_iam_binding.bindings,\n',

View File

@@ -88,7 +88,7 @@ values:
condition: []
deny_all: null
enforce: 'TRUE'
parameters: '{"allowedDomains":["@example.com"]}'
parameters: '{"allowedDomains":["@example.com","@secondary.example.com"]}'
values: []
timeouts: null
module.project.google_org_policy_policy.default["iam.allowedPolicyMemberDomains"]:
@@ -108,6 +108,7 @@ values:
- allowed_values:
- C0xxxxxxx
- C0yyyyyyy
- C0zzzzzzz
denied_values: null
timeouts: null
module.project.google_org_policy_policy.default["iam.disableServiceAccountKeyCreation"]: