diff --git a/blueprints/factories/project-factory/README.md b/blueprints/factories/project-factory/README.md
index e496aa4d1..6f2aaec59 100644
--- a/blueprints/factories/project-factory/README.md
+++ b/blueprints/factories/project-factory/README.md
@@ -68,7 +68,7 @@ module "projects" {
iam = try(each.value.iam, {})
kms_service_agents = try(each.value.kms, {})
labels = try(each.value.labels, {})
- org_policies = try(each.value.org_policies, null)
+ org_policies = try(each.value.org_policies, {})
service_accounts = try(each.value.service_accounts, {})
services = try(each.value.services, [])
service_identities_iam = try(each.value.service_identities_iam, {})
@@ -153,16 +153,13 @@ labels:
environment: prod
# [opt] Org policy overrides defined at project level
-org_policies:
- policy_boolean:
- constraints/compute.disableGuestAttributesAccess: true
- policy_list:
- constraints/compute.trustedImageProjects:
- inherit_from_parent: null
- status: true
- suggested_value: null
+org_policies:
+ constraints/compute.disableGuestAttributesAccess:
+ enforce: true
+ constraints/compute.trustedImageProjects:
+ allow:
values:
- - projects/fast-prod-iac-core-0
+ - projects/fast-dev-iac-core-0
# [opt] Service account to create for the project and their roles on the project
# in name => [roles] format
@@ -221,7 +218,7 @@ vpc:
| name | description | type | required | default |
|---|---|:---:|:---:|:---:|
| [billing_account_id](variables.tf#L17) | Billing account id. | string | ✓ | |
-| [project_id](variables.tf#L119) | Project id. | string | ✓ | |
+| [project_id](variables.tf#L145) | Project id. | string | ✓ | |
| [billing_alert](variables.tf#L22) | Billing alert configuration. | object({…}) | | null |
| [defaults](variables.tf#L35) | Project factory default values. | object({…}) | | null |
| [dns_zones](variables.tf#L57) | DNS private zones to create as child of var.defaults.environment_dns_zone. | list(string) | | [] |
@@ -231,13 +228,13 @@ vpc:
| [iam](variables.tf#L81) | Custom IAM settings in role => [principal] format. | map(list(string)) | | {} |
| [kms_service_agents](variables.tf#L87) | KMS IAM configuration in as service => [key]. | map(list(string)) | | {} |
| [labels](variables.tf#L93) | Labels to be assigned at project level. | map(string) | | {} |
-| [org_policies](variables.tf#L99) | Org-policy overrides at project level. | object({…}) | | null |
-| [prefix](variables.tf#L113) | Prefix used for the project id. | string | | null |
-| [service_accounts](variables.tf#L124) | Service accounts to be created, and roles assigned them on the project. | map(list(string)) | | {} |
-| [service_accounts_iam](variables.tf#L130) | IAM bindings on service account resources. Format is KEY => {ROLE => [MEMBERS]} | map(map(list(string))) | | {} |
-| [service_identities_iam](variables.tf#L144) | Custom IAM settings for service identities in service => [role] format. | map(list(string)) | | {} |
-| [services](variables.tf#L137) | Services to be enabled for the project. | list(string) | | [] |
-| [vpc](variables.tf#L151) | VPC configuration for the project. | object({…}) | | null |
+| [org_policies](variables.tf#L99) | Org-policy overrides at project level. | map(object({…})) | | {} |
+| [prefix](variables.tf#L139) | Prefix used for the project id. | string | | null |
+| [service_accounts](variables.tf#L150) | Service accounts to be created, and roles assigned them on the project. | map(list(string)) | | {} |
+| [service_accounts_iam](variables.tf#L156) | IAM bindings on service account resources. Format is KEY => {ROLE => [MEMBERS]} | map(map(list(string))) | | {} |
+| [service_identities_iam](variables.tf#L164) | Custom IAM settings for service identities in service => [role] format. | map(list(string)) | | {} |
+| [services](variables.tf#L171) | Services to be enabled for the project. | list(string) | | [] |
+| [vpc](variables.tf#L178) | VPC configuration for the project. | object({…}) | | null |
## Outputs
diff --git a/blueprints/factories/project-factory/main.tf b/blueprints/factories/project-factory/main.tf
index 996b79e35..db80810b9 100644
--- a/blueprints/factories/project-factory/main.tf
+++ b/blueprints/factories/project-factory/main.tf
@@ -148,9 +148,8 @@ module "project" {
contacts = { for c in local.essential_contacts : c => ["ALL"] }
iam = local.iam
labels = local.labels
+ org_policies = try(var.org_policies, {})
parent = var.folder_id
- policy_boolean = try(var.org_policies.policy_boolean, {})
- policy_list = try(var.org_policies.policy_list, {})
service_encryption_key_ids = var.kms_service_agents
services = local.services
shared_vpc_service_config = var.vpc == null ? null : {
diff --git a/blueprints/factories/project-factory/sample-data/projects/project.yaml b/blueprints/factories/project-factory/sample-data/projects/project.yaml
index 13a8f5f52..23db3f21b 100644
--- a/blueprints/factories/project-factory/sample-data/projects/project.yaml
+++ b/blueprints/factories/project-factory/sample-data/projects/project.yaml
@@ -48,13 +48,10 @@ labels:
# [opt] Org policy overrides defined at project level
org_policies:
- policy_boolean:
- constraints/compute.disableGuestAttributesAccess: true
- policy_list:
- constraints/compute.trustedImageProjects:
- inherit_from_parent: null
- status: true
- suggested_value: null
+ constraints/compute.disableGuestAttributesAccess:
+ enforce: true
+ constraints/compute.trustedImageProjects:
+ allow:
values:
- projects/fast-dev-iac-core-0
diff --git a/blueprints/factories/project-factory/variables.tf b/blueprints/factories/project-factory/variables.tf
index 6154c032c..cf5d8fb34 100644
--- a/blueprints/factories/project-factory/variables.tf
+++ b/blueprints/factories/project-factory/variables.tf
@@ -98,16 +98,42 @@ variable "labels" {
variable "org_policies" {
description = "Org-policy overrides at project level."
- type = object({
- policy_boolean = map(bool)
- policy_list = map(object({
- inherit_from_parent = bool
- suggested_value = string
- status = bool
- values = list(string)
+ type = map(object({
+ inherit_from_parent = optional(bool) # for list policies only.
+ reset = optional(bool)
+
+ # default (unconditional) values
+ allow = optional(object({
+ all = optional(bool)
+ values = optional(list(string))
}))
- })
- default = null
+ deny = optional(object({
+ all = optional(bool)
+ values = optional(list(string))
+ }))
+ enforce = optional(bool, true) # for boolean policies only.
+
+ # conditional values
+ 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, true) # for boolean policies only.
+ condition = object({
+ description = optional(string)
+ expression = optional(string)
+ location = optional(string)
+ title = optional(string)
+ })
+ })), [])
+ }))
+ default = {}
+ nullable = false
}
variable "prefix" {
@@ -134,12 +160,6 @@ variable "service_accounts_iam" {
nullable = false
}
-variable "services" {
- description = "Services to be enabled for the project."
- type = list(string)
- default = []
- nullable = false
-}
variable "service_identities_iam" {
description = "Custom IAM settings for service identities in service => [role] format."
@@ -148,6 +168,13 @@ variable "service_identities_iam" {
nullable = false
}
+variable "services" {
+ description = "Services to be enabled for the project."
+ type = list(string)
+ default = []
+ nullable = false
+}
+
variable "vpc" {
description = "VPC configuration for the project."
type = object({
@@ -160,6 +187,3 @@ variable "vpc" {
})
default = null
}
-
-
-
diff --git a/fast/stages/03-project-factory/dev/data/projects/project.yaml.sample b/fast/stages/03-project-factory/dev/data/projects/project.yaml.sample
index 13a8f5f52..23db3f21b 100644
--- a/fast/stages/03-project-factory/dev/data/projects/project.yaml.sample
+++ b/fast/stages/03-project-factory/dev/data/projects/project.yaml.sample
@@ -48,13 +48,10 @@ labels:
# [opt] Org policy overrides defined at project level
org_policies:
- policy_boolean:
- constraints/compute.disableGuestAttributesAccess: true
- policy_list:
- constraints/compute.trustedImageProjects:
- inherit_from_parent: null
- status: true
- suggested_value: null
+ constraints/compute.disableGuestAttributesAccess:
+ enforce: true
+ constraints/compute.trustedImageProjects:
+ allow:
values:
- projects/fast-dev-iac-core-0
diff --git a/modules/organization/README.md b/modules/organization/README.md
index 2ff6b6ebb..7c5ce921e 100644
--- a/modules/organization/README.md
+++ b/modules/organization/README.md
@@ -318,7 +318,7 @@ module "org" {
| name | description | type | required | default |
|---|---|:---:|:---:|:---:|
-| [organization_id](variables.tf#L151) | Organization id in organizations/nnnnnn format. | string | ✓ | |
+| [organization_id](variables.tf#L191) | Organization id in organizations/nnnnnn format. | string | ✓ | |
| [contacts](variables.tf#L17) | List of essential contacts for this resource. Must be in the form EMAIL -> [NOTIFICATION_TYPES]. Valid notification types are ALL, SUSPENSION, SECURITY, TECHNICAL, BILLING, LEGAL, PRODUCT_UPDATES. | map(list(string)) | | {} |
| [custom_roles](variables.tf#L24) | Map of role name => list of permissions to create in this project. | map(list(string)) | | {} |
| [firewall_policies](variables.tf#L31) | Hierarchical firewall policy rules created in the organization. | map(map(object({…}))) | | {} |
@@ -333,7 +333,7 @@ module "org" {
| [iam_bindings_authoritative](variables.tf#L116) | IAM authoritative bindings, in {ROLE => [MEMBERS]} format. Roles and members not explicitly listed will be cleared. Bindings should also be authoritative when using authoritative audit config. Use with caution. | map(list(string)) | | null |
| [logging_exclusions](variables.tf#L122) | Logging exclusions for this organization in the form {NAME -> FILTER}. | map(string) | | {} |
| [logging_sinks](variables.tf#L129) | Logging sinks to create for this organization. | map(object({…})) | | {} |
-| [org_policies](variables.tf#L160) | Organization policies applied to this organization keyed by policy name. | map(object({…})) | | {} |
+| [org_policies](variables.tf#L151) | Organization policies applied to this organization keyed by policy name. | map(object({…})) | | {} |
| [tag_bindings](variables.tf#L200) | Tag bindings for this organization, in key => tag value id format. | map(string) | | null |
| [tags](variables.tf#L206) | Tags by key name. The `iam` attribute behaves like the similarly named one at module level. | map(object({…})) | | null |
@@ -346,8 +346,8 @@ module "org" {
| [firewall_policies](outputs.tf#L36) | Map of firewall policy resources created in the organization. | |
| [firewall_policy_id](outputs.tf#L41) | Map of firewall policy ids created in the organization. | |
| [organization_id](outputs.tf#L46) | Organization id dependent on module resources. | |
-| [sink_writer_identities](outputs.tf#L64) | Writer identities created for each sink. | |
-| [tag_keys](outputs.tf#L72) | Tag key resources. | |
-| [tag_values](outputs.tf#L79) | Tag value resources. | |
+| [sink_writer_identities](outputs.tf#L63) | Writer identities created for each sink. | |
+| [tag_keys](outputs.tf#L71) | Tag key resources. | |
+| [tag_values](outputs.tf#L78) | Tag value resources. | |
diff --git a/modules/organization/variables.tf b/modules/organization/variables.tf
index 2e5d87ae6..7499d6d67 100644
--- a/modules/organization/variables.tf
+++ b/modules/organization/variables.tf
@@ -148,15 +148,6 @@ variable "logging_sinks" {
nullable = false
}
-variable "organization_id" {
- description = "Organization id in organizations/nnnnnn format."
- type = string
- validation {
- condition = can(regex("^organizations/[0-9]+", var.organization_id))
- error_message = "The organization_id must in the form organizations/nnn."
- }
-}
-
variable "org_policies" {
description = "Organization policies applied to this organization keyed by policy name."
type = map(object({
@@ -197,6 +188,15 @@ variable "org_policies" {
nullable = false
}
+variable "organization_id" {
+ description = "Organization id in organizations/nnnnnn format."
+ type = string
+ validation {
+ condition = can(regex("^organizations/[0-9]+", var.organization_id))
+ 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)