diff --git a/blueprints/data-solutions/data-playground/main.tf b/blueprints/data-solutions/data-playground/main.tf
index 548bee37..a3cfd54e 100644
--- a/blueprints/data-solutions/data-playground/main.tf
+++ b/blueprints/data-solutions/data-playground/main.tf
@@ -1,4 +1,4 @@
-# Copyright 2022 Google LLC
+# 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.
@@ -83,8 +83,8 @@ module "project" {
}
org_policies = {
- # "constraints/compute.requireOsLogin" = {
- # enforce = false
+ # "compute.requireOsLogin" = {
+ # rules = [{ enforce = false }]
# }
# Example of applying a project wide policy, mainly useful for Composer 1
}
diff --git a/blueprints/data-solutions/shielded-folder/data/org-policies/compute.yaml b/blueprints/data-solutions/shielded-folder/data/org-policies/compute.yaml
index 0d27ac42..a3f96b1b 100644
--- a/blueprints/data-solutions/shielded-folder/data/org-policies/compute.yaml
+++ b/blueprints/data-solutions/shielded-folder/data/org-policies/compute.yaml
@@ -3,71 +3,90 @@
# sample subset of useful organization policies, edit to suit requirements
compute.disableGuestAttributesAccess:
- enforce: true
+ rules:
+ - enforce: true
compute.requireOsLogin:
- enforce: true
+ rules:
+ - enforce: true
compute.restrictLoadBalancerCreationForTypes:
- allow:
- values:
- - in:INTERNAL
+ rules:
+ - allow:
+ values:
+ - in:INTERNAL
compute.skipDefaultNetworkCreation:
- enforce: true
+ rules:
+ - enforce: true
compute.vmExternalIpAccess:
- deny:
- all: true
+ rules:
+ - deny:
+ all: true
# compute.disableInternetNetworkEndpointGroup:
-# enforce: true
+# rules:
+# - enforce: true
# compute.disableNestedVirtualization:
-# enforce: true
+# rules:
+# - enforce: true
# compute.disableSerialPortAccess:
-# enforce: true
+# rules:
+# - enforce: true
# compute.restrictCloudNATUsage:
-# deny:
-# all: true
+# rules:
+# - deny:
+# all: true
# compute.restrictDedicatedInterconnectUsage:
-# deny:
-# all: true
+# rules:
+# - deny:
+# all: true
# compute.restrictPartnerInterconnectUsage:
-# deny:
-# all: true
+# rules:
+# - deny:
+# all: true
# compute.restrictProtocolForwardingCreationForTypes:
-# deny:
-# all: true
+# rules:
+# - deny:
+# all: true
# compute.restrictSharedVpcHostProjects:
-# deny:
-# all: true
+# rules:
+# - deny:
+# all: true
# compute.restrictSharedVpcSubnetworks:
-# deny:
-# all: true
+# rules:
+# - deny:
+# all: true
# compute.restrictVpcPeering:
-# deny:
-# all: true
+# rules:
+# - deny:
+# all: true
# compute.restrictVpnPeerIPs:
-# deny:
-# all: true
+# rules:
+# - deny:
+# all: true
# compute.restrictXpnProjectLienRemoval:
-# enforce: true
+# rules:
+# - enforce: true
# compute.setNewProjectDefaultToZonalDNSOnly:
-# enforce: true
+# rules:
+# - enforce: true
# compute.vmCanIpForward:
-# deny:
-# all: true
+# rules:
+# - deny:
+# all: true
diff --git a/blueprints/data-solutions/shielded-folder/data/org-policies/iam.yaml b/blueprints/data-solutions/shielded-folder/data/org-policies/iam.yaml
index 4d83f827..58e0032c 100644
--- a/blueprints/data-solutions/shielded-folder/data/org-policies/iam.yaml
+++ b/blueprints/data-solutions/shielded-folder/data/org-policies/iam.yaml
@@ -3,10 +3,13 @@
# sample subset of useful organization policies, edit to suit requirements
iam.automaticIamGrantsForDefaultServiceAccounts:
- enforce: true
+ rules:
+ - enforce: true
iam.disableServiceAccountKeyCreation:
- enforce: true
+ rules:
+ - enforce: true
iam.disableServiceAccountKeyUpload:
- enforce: true
+ rules:
+ - enforce: true
diff --git a/blueprints/data-solutions/shielded-folder/data/org-policies/serverless.yaml b/blueprints/data-solutions/shielded-folder/data/org-policies/serverless.yaml
index de62e6c7..3efb23cd 100644
--- a/blueprints/data-solutions/shielded-folder/data/org-policies/serverless.yaml
+++ b/blueprints/data-solutions/shielded-folder/data/org-policies/serverless.yaml
@@ -3,24 +3,29 @@
# sample subset of useful organization policies, edit to suit requirements
run.allowedIngress:
- allow:
- values:
- - is:internal
+ rules:
+ - allow:
+ values:
+ - is:internal
# run.allowedVPCEgress:
-# allow:
-# values:
+# rules:
+# - allow:
+# values:
# - is:private-ranges-only
# cloudfunctions.allowedIngressSettings:
-# allow:
-# values:
-# - is:ALLOW_INTERNAL_ONLY
+# rules:
+# - allow:
+# values:
+# - is:ALLOW_INTERNAL_ONLY
# cloudfunctions.allowedVpcConnectorEgressSettings:
-# allow:
-# values:
-# - is:PRIVATE_RANGES_ONLY
+# rules:
+# - allow:
+# values:
+# - is:PRIVATE_RANGES_ONLY
# cloudfunctions.requireVPCConnector:
-# enforce: true
+# rules:
+# - enforce: true
diff --git a/blueprints/data-solutions/shielded-folder/data/org-policies/sql.yaml b/blueprints/data-solutions/shielded-folder/data/org-policies/sql.yaml
index 88b84d9d..0eee8045 100644
--- a/blueprints/data-solutions/shielded-folder/data/org-policies/sql.yaml
+++ b/blueprints/data-solutions/shielded-folder/data/org-policies/sql.yaml
@@ -3,7 +3,9 @@
# sample subset of useful organization policies, edit to suit requirements
sql.restrictAuthorizedNetworks:
- enforce: true
+ rules:
+ - enforce: true
sql.restrictPublicIp:
- enforce: true
+ rules:
+ - enforce: true
diff --git a/blueprints/data-solutions/shielded-folder/data/org-policies/storage.yaml b/blueprints/data-solutions/shielded-folder/data/org-policies/storage.yaml
index 6c0a673f..448357b8 100644
--- a/blueprints/data-solutions/shielded-folder/data/org-policies/storage.yaml
+++ b/blueprints/data-solutions/shielded-folder/data/org-policies/storage.yaml
@@ -3,4 +3,5 @@
# sample subset of useful organization policies, edit to suit requirements
storage.uniformBucketLevelAccess:
- enforce: true
+ rules:
+ - enforce: true
diff --git a/blueprints/data-solutions/vertex-mlops/main.tf b/blueprints/data-solutions/vertex-mlops/main.tf
index 5f7fbc0c..27129298 100644
--- a/blueprints/data-solutions/vertex-mlops/main.tf
+++ b/blueprints/data-solutions/vertex-mlops/main.tf
@@ -1,5 +1,5 @@
/**
- * Copyright 2022 Google LLC
+ * 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.
@@ -112,7 +112,7 @@ module "gcs-bucket" {
encryption_key = try(local.service_encryption_keys.storage, null)
}
-# Default bucket for Cloud Build to prevent error: "'us' violates constraint ‘constraints/gcp.resourceLocations’"
+# Default bucket for Cloud Build to prevent error: "'us' violates constraint ‘gcp.resourceLocations’"
# https://stackoverflow.com/questions/53206667/cloud-build-fails-with-resource-location-constraint
module "gcs-bucket-cloudbuild" {
source = "../../../modules/gcs"
@@ -230,8 +230,8 @@ module "project" {
org_policies = {
# Example of applying a project wide policy
- # "constraints/compute.requireOsLogin" = {
- # enforce = false
+ # "compute.requireOsLogin" = {
+ # rules = [{ enforce = false }]
# }
}
diff --git a/blueprints/factories/project-factory/README.md b/blueprints/factories/project-factory/README.md
index 2b8c3874..68e2e1d0 100644
--- a/blueprints/factories/project-factory/README.md
+++ b/blueprints/factories/project-factory/README.md
@@ -156,15 +156,18 @@ labels:
# [opt] Org policy overrides defined at project level
org_policies:
- constraints/compute.disableGuestAttributesAccess:
- enforce: true
- constraints/compute.trustedImageProjects:
- allow:
- values:
+ compute.disableGuestAttributesAccess:
+ rules:
+ - enforce: true
+ compute.trustedImageProjects:
+ rules:
+ - allow:
+ values:
- projects/fast-dev-iac-core-0
- constraints/compute.vmExternalIpAccess:
- deny:
- all: true
+ compute.vmExternalIpAccess:
+ rules:
+ - deny:
+ all: true
# [opt] Service account to create for the project and their roles on the project
# in name => [roles] format
@@ -223,8 +226,8 @@ vpc:
| name | description | type | required | default |
|---|---|:---:|:---:|:---:|
| [billing_account_id](variables.tf#L17) | Billing account id. | string
| ✓ | |
-| [prefix](variables.tf#L157) | Prefix used for resource names. | string
| ✓ | |
-| [project_id](variables.tf#L166) | Project id. | string
| ✓ | |
+| [prefix](variables.tf#L144) | Prefix used for resource names. | string
| ✓ | |
+| [project_id](variables.tf#L153) | Project id. | string
| ✓ | |
| [billing_alert](variables.tf#L22) | Billing alert configuration. | object({…})
| | null
|
| [defaults](variables.tf#L35) | Project factory default values. | object({…})
| | null
|
| [descriptive_name](variables.tf#L57) | Name of the project name. Used for project name instead of `name` variable. | string
| | null
|
@@ -237,15 +240,15 @@ vpc:
| [iam_additive](variables.tf#L99) | Custom additive IAM settings in role => [principal] format. | map(list(string))
| | {}
|
| [kms_service_agents](variables.tf#L105) | KMS IAM configuration in as service => [key]. | map(list(string))
| | {}
|
| [labels](variables.tf#L111) | Labels to be assigned at project level. | map(string)
| | {}
|
-| [org_policies](variables.tf#L117) | Org-policy overrides at project level. | map(object({…}))
| | {}
|
-| [service_accounts](variables.tf#L171) | Service accounts to be created, and roles assigned them on the project. | map(list(string))
| | {}
|
-| [service_accounts_additive](variables.tf#L177) | Service accounts to be created, and roles assigned them on the project additively. | map(list(string))
| | {}
|
-| [service_accounts_iam](variables.tf#L183) | IAM bindings on service account resources. Format is KEY => {ROLE => [MEMBERS]}. | map(map(list(string)))
| | {}
|
-| [service_accounts_iam_additive](variables.tf#L190) | IAM additive bindings on service account resources. Format is KEY => {ROLE => [MEMBERS]}. | map(map(list(string)))
| | {}
|
-| [service_identities_iam](variables.tf#L197) | Custom IAM settings for service identities in service => [role] format. | map(list(string))
| | {}
|
-| [service_identities_iam_additive](variables.tf#L204) | Custom additive IAM settings for service identities in service => [role] format. | map(list(string))
| | {}
|
-| [services](variables.tf#L211) | Services to be enabled for the project. | list(string)
| | []
|
-| [vpc](variables.tf#L218) | VPC configuration for the project. | object({…})
| | null
|
+| [org_policies](variables.tf#L117) | Org-policy overrides at project level. | map(object({…}))
| | {}
|
+| [service_accounts](variables.tf#L158) | Service accounts to be created, and roles assigned them on the project. | map(list(string))
| | {}
|
+| [service_accounts_additive](variables.tf#L164) | Service accounts to be created, and roles assigned them on the project additively. | map(list(string))
| | {}
|
+| [service_accounts_iam](variables.tf#L170) | IAM bindings on service account resources. Format is KEY => {ROLE => [MEMBERS]}. | map(map(list(string)))
| | {}
|
+| [service_accounts_iam_additive](variables.tf#L177) | IAM additive bindings on service account resources. Format is KEY => {ROLE => [MEMBERS]}. | map(map(list(string)))
| | {}
|
+| [service_identities_iam](variables.tf#L184) | Custom IAM settings for service identities in service => [role] format. | map(list(string))
| | {}
|
+| [service_identities_iam_additive](variables.tf#L191) | Custom additive IAM settings for service identities in service => [role] format. | map(list(string))
| | {}
|
+| [services](variables.tf#L198) | Services to be enabled for the project. | list(string)
| | []
|
+| [vpc](variables.tf#L205) | VPC configuration for the project. | object({…})
| | null
|
## Outputs
diff --git a/blueprints/factories/project-factory/sample-data/projects/project.yaml b/blueprints/factories/project-factory/sample-data/projects/project.yaml
index 03449913..cd7b1837 100644
--- a/blueprints/factories/project-factory/sample-data/projects/project.yaml
+++ b/blueprints/factories/project-factory/sample-data/projects/project.yaml
@@ -48,15 +48,18 @@ labels:
# [opt] Org policy overrides defined at project level
org_policies:
- constraints/compute.disableGuestAttributesAccess:
- enforce: true
- constraints/compute.trustedImageProjects:
- allow:
- values:
+ compute.disableGuestAttributesAccess:
+ rules:
+ - enforce: true
+ compute.trustedImageProjects:
+ rules:
+ - allow:
+ values:
- projects/fast-dev-iac-core-0
- constraints/compute.vmExternalIpAccess:
- deny:
- all: true
+ compute.vmExternalIpAccess:
+ rules:
+ - deny:
+ all: true
# [opt] Prefix - overrides default if set
prefix: test1
diff --git a/blueprints/factories/project-factory/variables.tf b/blueprints/factories/project-factory/variables.tf
index 3aa3fa36..a2089bcf 100644
--- a/blueprints/factories/project-factory/variables.tf
+++ b/blueprints/factories/project-factory/variables.tf
@@ -119,19 +119,6 @@ variable "org_policies" {
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))
- }))
- 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)
@@ -141,13 +128,13 @@ variable "org_policies" {
all = optional(bool)
values = optional(list(string))
}))
- enforce = optional(bool, true) # for boolean policies only.
- condition = object({
+ enforce = optional(bool) # for boolean policies only.
+ condition = optional(object({
description = optional(string)
expression = optional(string)
location = optional(string)
title = optional(string)
- })
+ }), {})
})), [])
}))
default = {}
diff --git a/blueprints/gke/multitenant-fleet/main.tf b/blueprints/gke/multitenant-fleet/main.tf
index 588d6c5b..4079db99 100644
--- a/blueprints/gke/multitenant-fleet/main.tf
+++ b/blueprints/gke/multitenant-fleet/main.tf
@@ -1,5 +1,5 @@
/**
- * Copyright 2022 Google LLC
+ * 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.
@@ -64,10 +64,10 @@ module "gke-project-0" {
}
# specify project-level org policies here if you need them
# policy_boolean = {
- # "constraints/compute.disableGuestAttributesAccess" = true
+ # "compute.disableGuestAttributesAccess" = true
# }
# policy_list = {
- # "constraints/compute.trustedImageProjects" = {
+ # "compute.trustedImageProjects" = {
# inherit_from_parent = null
# suggested_value = null
# status = true
diff --git a/blueprints/networking/filtering-proxy/main.tf b/blueprints/networking/filtering-proxy/main.tf
index 06efa814..b36f0140 100644
--- a/blueprints/networking/filtering-proxy/main.tf
+++ b/blueprints/networking/filtering-proxy/main.tf
@@ -1,5 +1,5 @@
/**
- * Copyright 2022 Google LLC
+ * 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.
@@ -227,8 +227,8 @@ module "folder-apps" {
name = "apps"
org_policies = {
# prevent VMs with public IPs in the apps folder
- "constraints/compute.vmExternalIpAccess" = {
- deny = { all = true }
+ "compute.vmExternalIpAccess" = {
+ rules = [{ deny = { all = true } }]
}
}
}
diff --git a/fast/stages-multitenant/1-resman-tenant/branch-sandbox.tf b/fast/stages-multitenant/1-resman-tenant/branch-sandbox.tf
index 6f3d526c..39ab03ed 100644
--- a/fast/stages-multitenant/1-resman-tenant/branch-sandbox.tf
+++ b/fast/stages-multitenant/1-resman-tenant/branch-sandbox.tf
@@ -28,8 +28,8 @@ module "branch-sandbox-folder" {
"roles/resourcemanager.projectCreator" = [local.automation_sas_iam.sandbox]
}
org_policies = {
- "constraints/sql.restrictPublicIp" = { enforce = false }
- "constraints/compute.vmExternalIpAccess" = { allow = { all = true } }
+ "sql.restrictPublicIp" = { rules = [{ enforce = false }] }
+ "compute.vmExternalIpAccess" = { rules = [{ allow = { all = true } }] }
}
tag_bindings = {
context = var.tags.values["${var.tags.names.context}/sandbox"]
diff --git a/fast/stages-multitenant/1-resman-tenant/data/org-policies/compute.yaml b/fast/stages-multitenant/1-resman-tenant/data/org-policies/compute.yaml
index 0d27ac42..a3f96b1b 100644
--- a/fast/stages-multitenant/1-resman-tenant/data/org-policies/compute.yaml
+++ b/fast/stages-multitenant/1-resman-tenant/data/org-policies/compute.yaml
@@ -3,71 +3,90 @@
# sample subset of useful organization policies, edit to suit requirements
compute.disableGuestAttributesAccess:
- enforce: true
+ rules:
+ - enforce: true
compute.requireOsLogin:
- enforce: true
+ rules:
+ - enforce: true
compute.restrictLoadBalancerCreationForTypes:
- allow:
- values:
- - in:INTERNAL
+ rules:
+ - allow:
+ values:
+ - in:INTERNAL
compute.skipDefaultNetworkCreation:
- enforce: true
+ rules:
+ - enforce: true
compute.vmExternalIpAccess:
- deny:
- all: true
+ rules:
+ - deny:
+ all: true
# compute.disableInternetNetworkEndpointGroup:
-# enforce: true
+# rules:
+# - enforce: true
# compute.disableNestedVirtualization:
-# enforce: true
+# rules:
+# - enforce: true
# compute.disableSerialPortAccess:
-# enforce: true
+# rules:
+# - enforce: true
# compute.restrictCloudNATUsage:
-# deny:
-# all: true
+# rules:
+# - deny:
+# all: true
# compute.restrictDedicatedInterconnectUsage:
-# deny:
-# all: true
+# rules:
+# - deny:
+# all: true
# compute.restrictPartnerInterconnectUsage:
-# deny:
-# all: true
+# rules:
+# - deny:
+# all: true
# compute.restrictProtocolForwardingCreationForTypes:
-# deny:
-# all: true
+# rules:
+# - deny:
+# all: true
# compute.restrictSharedVpcHostProjects:
-# deny:
-# all: true
+# rules:
+# - deny:
+# all: true
# compute.restrictSharedVpcSubnetworks:
-# deny:
-# all: true
+# rules:
+# - deny:
+# all: true
# compute.restrictVpcPeering:
-# deny:
-# all: true
+# rules:
+# - deny:
+# all: true
# compute.restrictVpnPeerIPs:
-# deny:
-# all: true
+# rules:
+# - deny:
+# all: true
# compute.restrictXpnProjectLienRemoval:
-# enforce: true
+# rules:
+# - enforce: true
# compute.setNewProjectDefaultToZonalDNSOnly:
-# enforce: true
+# rules:
+# - enforce: true
# compute.vmCanIpForward:
-# deny:
-# all: true
+# rules:
+# - deny:
+# all: true
diff --git a/fast/stages-multitenant/1-resman-tenant/data/org-policies/iam.yaml b/fast/stages-multitenant/1-resman-tenant/data/org-policies/iam.yaml
index 4d83f827..58e0032c 100644
--- a/fast/stages-multitenant/1-resman-tenant/data/org-policies/iam.yaml
+++ b/fast/stages-multitenant/1-resman-tenant/data/org-policies/iam.yaml
@@ -3,10 +3,13 @@
# sample subset of useful organization policies, edit to suit requirements
iam.automaticIamGrantsForDefaultServiceAccounts:
- enforce: true
+ rules:
+ - enforce: true
iam.disableServiceAccountKeyCreation:
- enforce: true
+ rules:
+ - enforce: true
iam.disableServiceAccountKeyUpload:
- enforce: true
+ rules:
+ - enforce: true
diff --git a/fast/stages-multitenant/1-resman-tenant/data/org-policies/serverless.yaml b/fast/stages-multitenant/1-resman-tenant/data/org-policies/serverless.yaml
index de62e6c7..3efb23cd 100644
--- a/fast/stages-multitenant/1-resman-tenant/data/org-policies/serverless.yaml
+++ b/fast/stages-multitenant/1-resman-tenant/data/org-policies/serverless.yaml
@@ -3,24 +3,29 @@
# sample subset of useful organization policies, edit to suit requirements
run.allowedIngress:
- allow:
- values:
- - is:internal
+ rules:
+ - allow:
+ values:
+ - is:internal
# run.allowedVPCEgress:
-# allow:
-# values:
+# rules:
+# - allow:
+# values:
# - is:private-ranges-only
# cloudfunctions.allowedIngressSettings:
-# allow:
-# values:
-# - is:ALLOW_INTERNAL_ONLY
+# rules:
+# - allow:
+# values:
+# - is:ALLOW_INTERNAL_ONLY
# cloudfunctions.allowedVpcConnectorEgressSettings:
-# allow:
-# values:
-# - is:PRIVATE_RANGES_ONLY
+# rules:
+# - allow:
+# values:
+# - is:PRIVATE_RANGES_ONLY
# cloudfunctions.requireVPCConnector:
-# enforce: true
+# rules:
+# - enforce: true
diff --git a/fast/stages-multitenant/1-resman-tenant/data/org-policies/sql.yaml b/fast/stages-multitenant/1-resman-tenant/data/org-policies/sql.yaml
index 88b84d9d..0eee8045 100644
--- a/fast/stages-multitenant/1-resman-tenant/data/org-policies/sql.yaml
+++ b/fast/stages-multitenant/1-resman-tenant/data/org-policies/sql.yaml
@@ -3,7 +3,9 @@
# sample subset of useful organization policies, edit to suit requirements
sql.restrictAuthorizedNetworks:
- enforce: true
+ rules:
+ - enforce: true
sql.restrictPublicIp:
- enforce: true
+ rules:
+ - enforce: true
diff --git a/fast/stages-multitenant/1-resman-tenant/data/org-policies/storage.yaml b/fast/stages-multitenant/1-resman-tenant/data/org-policies/storage.yaml
index 6c0a673f..448357b8 100644
--- a/fast/stages-multitenant/1-resman-tenant/data/org-policies/storage.yaml
+++ b/fast/stages-multitenant/1-resman-tenant/data/org-policies/storage.yaml
@@ -3,4 +3,5 @@
# sample subset of useful organization policies, edit to suit requirements
storage.uniformBucketLevelAccess:
- enforce: true
+ rules:
+ - enforce: true
diff --git a/fast/stages/0-bootstrap/README.md b/fast/stages/0-bootstrap/README.md
index e1bb2948..88bdceb3 100644
--- a/fast/stages/0-bootstrap/README.md
+++ b/fast/stages/0-bootstrap/README.md
@@ -452,7 +452,10 @@ The remaining configuration is manual, as it regards the repositories themselves
- edit the modules source to match your modules repository
- a simple way is using the "Replace in files" function of your editor
- search for `source\s*= "../../../modules/([^"]+)"`
- - replace with `source = "git@github.com:my-org/fast-modules.git//$1?ref=v1.0"`
+ - replace with:
+ - modules stored on GitHub: `source = "git@github.com:my-org/fast-modules.git//$1?ref=v1.0"`
+ - modules stored on Gitlab: `source = "git::ssh://git@gitlab.com/my-org/fast-modules.git//$1?ref=v1.0"`
+ - modules stored on Source Repositories: `source = git::https://source.developers.google.com/p/my-project/r/my-repository//$1?ref=v1.0"`. You may need to run `git config --global credential.'https://source.developers.google.com'.helper gcloud.sh` first as documented [here](https://cloud.google.com/source-repositories/docs/adding-repositories-as-remotes#add_the_repository_as_a_remote)
- copy the generated workflow file for the stage from the GCS output files bucket or from the local clone if enabled
- for GitHub, place it in a `.github/workflows` folder in the repository root
- for Gitlab, rename it to `.gitlab-ci.yml` and place it in the repository root
diff --git a/fast/stages/1-resman/branch-sandbox.tf b/fast/stages/1-resman/branch-sandbox.tf
index 8b54e749..72221bc0 100644
--- a/fast/stages/1-resman/branch-sandbox.tf
+++ b/fast/stages/1-resman/branch-sandbox.tf
@@ -1,5 +1,5 @@
/**
- * Copyright 2022 Google LLC
+ * 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.
@@ -33,8 +33,8 @@ module "branch-sandbox-folder" {
"roles/resourcemanager.projectCreator" = [module.branch-sandbox-sa.0.iam_email]
}
org_policies = {
- "constraints/sql.restrictPublicIp" = { enforce = false }
- "constraints/compute.vmExternalIpAccess" = { allow = { all = true } }
+ "sql.restrictPublicIp" = { rules = [{ enforce = false }] }
+ "compute.vmExternalIpAccess" = { rules = [{ allow = { all = true } }] }
}
tag_bindings = {
context = try(
diff --git a/fast/stages/1-resman/data/org-policies/compute.yaml b/fast/stages/1-resman/data/org-policies/compute.yaml
index 0d27ac42..a3f96b1b 100644
--- a/fast/stages/1-resman/data/org-policies/compute.yaml
+++ b/fast/stages/1-resman/data/org-policies/compute.yaml
@@ -3,71 +3,90 @@
# sample subset of useful organization policies, edit to suit requirements
compute.disableGuestAttributesAccess:
- enforce: true
+ rules:
+ - enforce: true
compute.requireOsLogin:
- enforce: true
+ rules:
+ - enforce: true
compute.restrictLoadBalancerCreationForTypes:
- allow:
- values:
- - in:INTERNAL
+ rules:
+ - allow:
+ values:
+ - in:INTERNAL
compute.skipDefaultNetworkCreation:
- enforce: true
+ rules:
+ - enforce: true
compute.vmExternalIpAccess:
- deny:
- all: true
+ rules:
+ - deny:
+ all: true
# compute.disableInternetNetworkEndpointGroup:
-# enforce: true
+# rules:
+# - enforce: true
# compute.disableNestedVirtualization:
-# enforce: true
+# rules:
+# - enforce: true
# compute.disableSerialPortAccess:
-# enforce: true
+# rules:
+# - enforce: true
# compute.restrictCloudNATUsage:
-# deny:
-# all: true
+# rules:
+# - deny:
+# all: true
# compute.restrictDedicatedInterconnectUsage:
-# deny:
-# all: true
+# rules:
+# - deny:
+# all: true
# compute.restrictPartnerInterconnectUsage:
-# deny:
-# all: true
+# rules:
+# - deny:
+# all: true
# compute.restrictProtocolForwardingCreationForTypes:
-# deny:
-# all: true
+# rules:
+# - deny:
+# all: true
# compute.restrictSharedVpcHostProjects:
-# deny:
-# all: true
+# rules:
+# - deny:
+# all: true
# compute.restrictSharedVpcSubnetworks:
-# deny:
-# all: true
+# rules:
+# - deny:
+# all: true
# compute.restrictVpcPeering:
-# deny:
-# all: true
+# rules:
+# - deny:
+# all: true
# compute.restrictVpnPeerIPs:
-# deny:
-# all: true
+# rules:
+# - deny:
+# all: true
# compute.restrictXpnProjectLienRemoval:
-# enforce: true
+# rules:
+# - enforce: true
# compute.setNewProjectDefaultToZonalDNSOnly:
-# enforce: true
+# rules:
+# - enforce: true
# compute.vmCanIpForward:
-# deny:
-# all: true
+# rules:
+# - deny:
+# all: true
diff --git a/fast/stages/1-resman/data/org-policies/iam.yaml b/fast/stages/1-resman/data/org-policies/iam.yaml
index 4d83f827..58e0032c 100644
--- a/fast/stages/1-resman/data/org-policies/iam.yaml
+++ b/fast/stages/1-resman/data/org-policies/iam.yaml
@@ -3,10 +3,13 @@
# sample subset of useful organization policies, edit to suit requirements
iam.automaticIamGrantsForDefaultServiceAccounts:
- enforce: true
+ rules:
+ - enforce: true
iam.disableServiceAccountKeyCreation:
- enforce: true
+ rules:
+ - enforce: true
iam.disableServiceAccountKeyUpload:
- enforce: true
+ rules:
+ - enforce: true
diff --git a/fast/stages/1-resman/data/org-policies/serverless.yaml b/fast/stages/1-resman/data/org-policies/serverless.yaml
index de62e6c7..3efb23cd 100644
--- a/fast/stages/1-resman/data/org-policies/serverless.yaml
+++ b/fast/stages/1-resman/data/org-policies/serverless.yaml
@@ -3,24 +3,29 @@
# sample subset of useful organization policies, edit to suit requirements
run.allowedIngress:
- allow:
- values:
- - is:internal
+ rules:
+ - allow:
+ values:
+ - is:internal
# run.allowedVPCEgress:
-# allow:
-# values:
+# rules:
+# - allow:
+# values:
# - is:private-ranges-only
# cloudfunctions.allowedIngressSettings:
-# allow:
-# values:
-# - is:ALLOW_INTERNAL_ONLY
+# rules:
+# - allow:
+# values:
+# - is:ALLOW_INTERNAL_ONLY
# cloudfunctions.allowedVpcConnectorEgressSettings:
-# allow:
-# values:
-# - is:PRIVATE_RANGES_ONLY
+# rules:
+# - allow:
+# values:
+# - is:PRIVATE_RANGES_ONLY
# cloudfunctions.requireVPCConnector:
-# enforce: true
+# rules:
+# - enforce: true
diff --git a/fast/stages/1-resman/data/org-policies/sql.yaml b/fast/stages/1-resman/data/org-policies/sql.yaml
index 88b84d9d..0eee8045 100644
--- a/fast/stages/1-resman/data/org-policies/sql.yaml
+++ b/fast/stages/1-resman/data/org-policies/sql.yaml
@@ -3,7 +3,9 @@
# sample subset of useful organization policies, edit to suit requirements
sql.restrictAuthorizedNetworks:
- enforce: true
+ rules:
+ - enforce: true
sql.restrictPublicIp:
- enforce: true
+ rules:
+ - enforce: true
diff --git a/fast/stages/1-resman/data/org-policies/storage.yaml b/fast/stages/1-resman/data/org-policies/storage.yaml
index 6c0a673f..448357b8 100644
--- a/fast/stages/1-resman/data/org-policies/storage.yaml
+++ b/fast/stages/1-resman/data/org-policies/storage.yaml
@@ -3,4 +3,5 @@
# sample subset of useful organization policies, edit to suit requirements
storage.uniformBucketLevelAccess:
- enforce: true
+ rules:
+ - enforce: true
diff --git a/fast/stages/1-resman/organization.tf b/fast/stages/1-resman/organization.tf
index 3d7db46d..a3bc2f0d 100644
--- a/fast/stages/1-resman/organization.tf
+++ b/fast/stages/1-resman/organization.tf
@@ -1,5 +1,5 @@
/**
- * Copyright 2022 Google LLC
+ * 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.
@@ -68,7 +68,11 @@ module "organization" {
# sample subset of useful organization policies, edit to suit requirements
org_policies = {
- "iam.allowedPolicyMemberDomains" = { allow = { values = local.all_drs_domains } }
+ "iam.allowedPolicyMemberDomains" = {
+ rules = [
+ { allow = { values = local.all_drs_domains } }
+ ]
+ }
#"gcp.resourceLocations" = {
# allow = { values = local.allowed_regions }
diff --git a/fast/stages/3-project-factory/dev/data/projects/project.yaml.sample b/fast/stages/3-project-factory/dev/data/projects/project.yaml.sample
index 88ba0bf5..5311019d 100644
--- a/fast/stages/3-project-factory/dev/data/projects/project.yaml.sample
+++ b/fast/stages/3-project-factory/dev/data/projects/project.yaml.sample
@@ -48,15 +48,18 @@ labels:
# [opt] Org policy overrides defined at project level
org_policies:
- constraints/compute.disableGuestAttributesAccess:
- enforce: true
- constraints/compute.trustedImageProjects:
- allow:
- values:
+ compute.disableGuestAttributesAccess:
+ rules:
+ - enforce: true
+ compute.trustedImageProjects:
+ rules:
+ - allow:
+ values:
- projects/fast-dev-iac-core-0
- constraints/compute.vmExternalIpAccess:
- deny:
- all: true
+ compute.vmExternalIpAccess:
+ rules:
+ - deny:
+ all: true
# [opt] Service account to create for the project and their roles on the project
# in name => [roles] format
diff --git a/modules/folder/README.md b/modules/folder/README.md
index e1ad6809..8addd48e 100644
--- a/modules/folder/README.md
+++ b/modules/folder/README.md
@@ -42,40 +42,46 @@ module "folder" {
name = "Folder name"
org_policies = {
"compute.disableGuestAttributesAccess" = {
- enforce = true
+ rules = [{ enforce = true }]
}
- "constraints/compute.skipDefaultNetworkCreation" = {
- enforce = true
+ "compute.skipDefaultNetworkCreation" = {
+ rules = [{ enforce = true }]
}
"iam.disableServiceAccountKeyCreation" = {
- enforce = true
+ rules = [{ enforce = true }]
}
"iam.disableServiceAccountKeyUpload" = {
- enforce = false
rules = [
{
condition = {
- expression = "resource.matchTagId(\"tagKeys/1234\", \"tagValues/1234\")"
+ expression = "resource.matchTagId('tagKeys/1234', 'tagValues/1234')"
title = "condition"
description = "test condition"
location = "somewhere"
}
enforce = true
+ },
+ {
+ enforce = false
}
]
}
- "constraints/iam.allowedPolicyMemberDomains" = {
- allow = {
- values = ["C0xxxxxxx", "C0yyyyyyy"]
- }
+ "iam.allowedPolicyMemberDomains" = {
+ rules = [{
+ allow = {
+ values = ["C0xxxxxxx", "C0yyyyyyy"]
+ }
+ }]
}
- "constraints/compute.trustedImageProjects" = {
- allow = {
- values = ["projects/my-project"]
- }
+ "compute.trustedImageProjects" = {
+ rules = [{
+ allow = {
+ values = ["projects/my-project"]
+ }
+ }]
}
- "constraints/compute.vmExternalIpAccess" = {
- deny = { all = true }
+ "compute.vmExternalIpAccess" = {
+ rules = [{ deny = { all = true } }]
}
}
}
@@ -340,10 +346,10 @@ module "folder" {
| [logging_exclusions](variables.tf#L98) | Logging exclusions for this folder in the form {NAME -> FILTER}. | map(string)
| | {}
|
| [logging_sinks](variables.tf#L105) | Logging sinks to create for the organization. | map(object({…}))
| | {}
|
| [name](variables.tf#L135) | Folder name. | string
| | null
|
-| [org_policies](variables.tf#L141) | Organization policies applied to this folder keyed by policy name. | map(object({…}))
| | {}
|
-| [org_policies_data_path](variables.tf#L181) | Path containing org policies in YAML format. | string
| | null
|
-| [parent](variables.tf#L187) | Parent in folders/folder_id or organizations/org_id format. | string
| | null
|
-| [tag_bindings](variables.tf#L197) | Tag bindings for this folder, in key => tag value id format. | map(string)
| | null
|
+| [org_policies](variables.tf#L141) | Organization policies applied to this folder keyed by policy name. | map(object({…}))
| | {}
|
+| [org_policies_data_path](variables.tf#L168) | Path containing org policies in YAML format. | string
| | null
|
+| [parent](variables.tf#L174) | Parent in folders/folder_id or organizations/org_id format. | string
| | null
|
+| [tag_bindings](variables.tf#L184) | Tag bindings for this folder, in key => tag value id format. | map(string)
| | null
|
## Outputs
diff --git a/modules/folder/organization-policies.tf b/modules/folder/organization-policies.tf
index 47532f21..2bf79c4a 100644
--- a/modules/folder/organization-policies.tf
+++ b/modules/folder/organization-policies.tf
@@ -1,5 +1,5 @@
/**
- * Copyright 2022 Google LLC
+ * 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.
@@ -28,16 +28,6 @@ locals {
k => {
inherit_from_parent = try(v.inherit_from_parent, null)
reset = try(v.reset, null)
- allow = can(v.allow) ? {
- all = try(v.allow.all, null)
- values = try(v.allow.values, null)
- } : null
- deny = can(v.deny) ? {
- all = try(v.deny.all, null)
- values = try(v.deny.values, null)
- } : null
- enforce = try(v.enforce, true)
-
rules = [
for r in try(v.rules, []) : {
allow = can(r.allow) ? {
@@ -48,7 +38,7 @@ locals {
all = try(r.deny.all, null)
values = try(r.deny.values, null)
} : null
- enforce = try(r.enforce, true)
+ enforce = try(r.enforce, null)
condition = {
description = try(r.condition.description, null)
expression = try(r.condition.expression, null)
@@ -67,8 +57,9 @@ locals {
k => merge(v, {
name = "${local.folder.name}/policies/${k}"
parent = local.folder.name
-
- is_boolean_policy = v.allow == null && v.deny == null
+ is_boolean_policy = (
+ alltrue([for r in v.rules : r.allow == null && r.deny == null])
+ )
has_values = (
length(coalesce(try(v.allow.values, []), [])) > 0 ||
length(coalesce(try(v.deny.values, []), [])) > 0
@@ -90,11 +81,9 @@ resource "google_org_policy_policy" "default" {
for_each = local.org_policies
name = each.value.name
parent = each.value.parent
-
spec {
inherit_from_parent = each.value.inherit_from_parent
reset = each.value.reset
-
dynamic "rules" {
for_each = each.value.rules
iterator = rule
@@ -106,11 +95,14 @@ resource "google_org_policy_policy" "default" {
? upper(tostring(rule.value.enforce))
: null
)
- condition {
- description = rule.value.condition.description
- expression = rule.value.condition.expression
- location = rule.value.condition.location
- title = rule.value.condition.title
+ dynamic "condition" {
+ for_each = rule.value.condition.expression != null ? [1] : []
+ content {
+ description = rule.value.condition.description
+ expression = rule.value.condition.expression
+ location = rule.value.condition.location
+ title = rule.value.condition.title
+ }
}
dynamic "values" {
for_each = rule.value.has_values ? [1] : []
@@ -121,22 +113,5 @@ resource "google_org_policy_policy" "default" {
}
}
}
-
- rules {
- allow_all = try(each.value.allow.all, null) == true ? "TRUE" : null
- deny_all = try(each.value.deny.all, null) == true ? "TRUE" : null
- enforce = (
- each.value.is_boolean_policy && each.value.enforce != null
- ? upper(tostring(each.value.enforce))
- : null
- )
- dynamic "values" {
- for_each = each.value.has_values ? [1] : []
- content {
- allowed_values = try(each.value.allow.values, null)
- denied_values = try(each.value.deny.values, null)
- }
- }
- }
}
}
diff --git a/modules/folder/variables.tf b/modules/folder/variables.tf
index a93ea1aa..e0abc612 100644
--- a/modules/folder/variables.tf
+++ b/modules/folder/variables.tf
@@ -1,5 +1,5 @@
/**
- * Copyright 2022 Google LLC
+ * 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.
@@ -143,19 +143,6 @@ variable "org_policies" {
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))
- }))
- 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)
@@ -165,13 +152,13 @@ variable "org_policies" {
all = optional(bool)
values = optional(list(string))
}))
- enforce = optional(bool, true) # for boolean policies only.
- condition = object({
+ enforce = optional(bool) # for boolean policies only.
+ condition = optional(object({
description = optional(string)
expression = optional(string)
location = optional(string)
title = optional(string)
- })
+ }), {})
})), [])
}))
default = {}
diff --git a/modules/net-vpc/README.md b/modules/net-vpc/README.md
index dbd85502..bd5675d2 100644
--- a/modules/net-vpc/README.md
+++ b/modules/net-vpc/README.md
@@ -314,7 +314,7 @@ module "vpc" {
name = "my-network"
data_folder = "config/subnets"
}
-# tftest modules=1 resources=3 files=subnet-simple,subnet-detailed inventory=factory.yaml
+# tftest modules=1 resources=4 files=subnet-simple,subnet-detailed inventory=factory.yaml
```
```yaml
diff --git a/modules/net-vpc/subnets.tf b/modules/net-vpc/subnets.tf
index ae094ecf..7c03bfca 100644
--- a/modules/net-vpc/subnets.tf
+++ b/modules/net-vpc/subnets.tf
@@ -31,6 +31,9 @@ locals {
flow_logs_config = try(v.flow_logs, null)
ipv6 = try(v.ipv6, null)
secondary_ip_ranges = try(v.secondary_ip_ranges, null)
+ iam_groups = try(v.iam_groups, [])
+ iam_users = try(v.iam_users, [])
+ iam_service_accounts = try(v.iam_service_accounts, [])
}
}
_factory_subnets_iam = [
diff --git a/modules/organization/README.md b/modules/organization/README.md
index b6caa3cd..39b5ff29 100644
--- a/modules/organization/README.md
+++ b/modules/organization/README.md
@@ -25,50 +25,77 @@ module "org" {
iam_additive_members = {
"user:compute@example.org" = ["roles/compute.admin", "roles/container.viewer"]
}
-
+ tags = {
+ allowexternal = {
+ description = "Allow external identities."
+ values = {
+ true = {}, false = {}
+ }
+ }
+ }
org_policies = {
"custom.gkeEnableAutoUpgrade" = {
- enforce = true
+ rules = [{ enforce = true }]
}
"compute.disableGuestAttributesAccess" = {
- enforce = true
+ rules = [{ enforce = true }]
}
- "constraints/compute.skipDefaultNetworkCreation" = {
- enforce = true
+ "compute.skipDefaultNetworkCreation" = {
+ rules = [{ enforce = true }]
}
"iam.disableServiceAccountKeyCreation" = {
- enforce = true
+ rules = [{ enforce = true }]
}
"iam.disableServiceAccountKeyUpload" = {
- enforce = false
rules = [
{
condition = {
- expression = "resource.matchTagId(\"tagKeys/1234\", \"tagValues/1234\")"
+ expression = "resource.matchTagId('tagKeys/1234', 'tagValues/1234')"
title = "condition"
description = "test condition"
location = "somewhere"
}
enforce = true
+ },
+ {
+ enforce = false
}
]
}
- "constraints/iam.allowedPolicyMemberDomains" = {
- allow = {
- values = ["C0xxxxxxx", "C0yyyyyyy"]
- }
+ "iam.allowedPolicyMemberDomains" = {
+ rules = [
+ {
+ allow = { all = true }
+ condition = {
+ expression = "resource.matchTag('1234567890/allowexternal', 'true')"
+ title = "Allow external identities"
+ description = "Allow external identities when resource has the `allowexternal` tag set to true."
+ }
+ },
+ {
+ allow = { values = ["C0xxxxxxx", "C0yyyyyyy"] }
+ condition = {
+ expression = "!resource.matchTag('1234567890/allowexternal', 'true')"
+ title = ""
+ description = "For any resource without allowexternal=true, only allow identities from restricted domains."
+ }
+ }
+ ]
}
- "constraints/compute.trustedImageProjects" = {
- allow = {
- values = ["projects/my-project"]
- }
+
+ "compute.trustedImageProjects" = {
+ rules = [{
+ allow = {
+ values = ["projects/my-project"]
+ }
+ }]
}
- "constraints/compute.vmExternalIpAccess" = {
- deny = { all = true }
+ "compute.vmExternalIpAccess" = {
+ rules = [{ deny = { all = true } }]
}
}
}
-# tftest modules=1 resources=13 inventory=basic.yaml
+# tftest modules=1 resources=16 inventory=basic.yaml
```
## IAM
@@ -111,7 +138,7 @@ module "org" {
# not necessarily to enforce on the org level, policy may be applied on folder/project levels
org_policies = {
"custom.gkeEnableAutoUpgrade" = {
- enforce = true
+ rules = [{ enforce = true }]
}
}
}
@@ -131,7 +158,7 @@ module "org" {
org_policy_custom_constraints_data_path = "configs/custom-constraints"
org_policies = {
"custom.gkeEnableAutoUpgrade" = {
- enforce = true
+ rules = [{ enforce = true }]
}
}
}
@@ -447,7 +474,7 @@ module "org" {
| name | description | type | required | default |
|---|---|:---:|:---:|:---:|
-| [organization_id](variables.tf#L246) | Organization id in organizations/nnnnnn format. | string
| ✓ | |
+| [organization_id](variables.tf#L234) | 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({…})))
| | {}
|
@@ -463,12 +490,12 @@ module "org" {
| [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 the organization. | map(object({…}))
| | {}
|
| [network_tags](variables.tf#L159) | 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. | map(object({…}))
| | {}
|
-| [org_policies](variables.tf#L181) | Organization policies applied to this organization keyed by policy name. | map(object({…}))
| | {}
|
-| [org_policies_data_path](variables.tf#L220) | Path containing org policies in YAML format. | string
| | null
|
-| [org_policy_custom_constraints](variables.tf#L226) | Organization policiy custom constraints keyed by constraint name. | map(object({…}))
| | {}
|
-| [org_policy_custom_constraints_data_path](variables.tf#L240) | Path containing org policy custom constraints in YAML format. | string
| | null
|
-| [tag_bindings](variables.tf#L255) | Tag bindings for this organization, in key => tag value id format. | map(string)
| | null
|
-| [tags](variables.tf#L261) | 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. | map(object({…}))
| | {}
|
+| [org_policies](variables.tf#L181) | Organization policies applied to this organization keyed by policy name. | map(object({…}))
| | {}
|
+| [org_policies_data_path](variables.tf#L208) | Path containing org policies in YAML format. | string
| | null
|
+| [org_policy_custom_constraints](variables.tf#L214) | Organization policiy custom constraints keyed by constraint name. | map(object({…}))
| | {}
|
+| [org_policy_custom_constraints_data_path](variables.tf#L228) | Path containing org policy custom constraints in YAML format. | string
| | null
|
+| [tag_bindings](variables.tf#L243) | Tag bindings for this organization, in key => tag value id format. | map(string)
| | null
|
+| [tags](variables.tf#L249) | 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. | map(object({…}))
| | {}
|
## Outputs
diff --git a/modules/organization/organization-policies.tf b/modules/organization/organization-policies.tf
index 1a99ef9a..b43c5955 100644
--- a/modules/organization/organization-policies.tf
+++ b/modules/organization/organization-policies.tf
@@ -1,5 +1,5 @@
/**
- * Copyright 2022 Google LLC
+ * 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.
@@ -28,16 +28,6 @@ locals {
k => {
inherit_from_parent = try(v.inherit_from_parent, null)
reset = try(v.reset, null)
- allow = can(v.allow) ? {
- all = try(v.allow.all, null)
- values = try(v.allow.values, null)
- } : null
- deny = can(v.deny) ? {
- all = try(v.deny.all, null)
- values = try(v.deny.values, null)
- } : null
- enforce = try(v.enforce, true)
-
rules = [
for r in try(v.rules, []) : {
allow = can(r.allow) ? {
@@ -48,7 +38,7 @@ locals {
all = try(r.deny.all, null)
values = try(r.deny.values, null)
} : null
- enforce = try(r.enforce, true)
+ enforce = try(r.enforce, null)
condition = {
description = try(r.condition.description, null)
expression = try(r.condition.expression, null)
@@ -67,8 +57,9 @@ locals {
k => merge(v, {
name = "${var.organization_id}/policies/${k}"
parent = var.organization_id
-
- is_boolean_policy = v.allow == null && v.deny == null
+ is_boolean_policy = (
+ alltrue([for r in v.rules : r.allow == null && r.deny == null])
+ )
has_values = (
length(coalesce(try(v.allow.values, []), [])) > 0 ||
length(coalesce(try(v.deny.values, []), [])) > 0
@@ -90,11 +81,9 @@ resource "google_org_policy_policy" "default" {
for_each = local.org_policies
name = each.value.name
parent = each.value.parent
-
spec {
inherit_from_parent = each.value.inherit_from_parent
reset = each.value.reset
-
dynamic "rules" {
for_each = each.value.rules
iterator = rule
@@ -106,11 +95,14 @@ resource "google_org_policy_policy" "default" {
? upper(tostring(rule.value.enforce))
: null
)
- condition {
- description = rule.value.condition.description
- expression = rule.value.condition.expression
- location = rule.value.condition.location
- title = rule.value.condition.title
+ dynamic "condition" {
+ for_each = rule.value.condition.expression != null ? [1] : []
+ content {
+ description = rule.value.condition.description
+ expression = rule.value.condition.expression
+ location = rule.value.condition.location
+ title = rule.value.condition.title
+ }
}
dynamic "values" {
for_each = rule.value.has_values ? [1] : []
@@ -121,25 +113,7 @@ resource "google_org_policy_policy" "default" {
}
}
}
-
- rules {
- allow_all = try(each.value.allow.all, null) == true ? "TRUE" : null
- deny_all = try(each.value.deny.all, null) == true ? "TRUE" : null
- enforce = (
- each.value.is_boolean_policy && each.value.enforce != null
- ? upper(tostring(each.value.enforce))
- : null
- )
- dynamic "values" {
- for_each = each.value.has_values ? [1] : []
- content {
- allowed_values = try(each.value.allow.values, null)
- denied_values = try(each.value.deny.values, null)
- }
- }
- }
}
-
depends_on = [
google_organization_iam_audit_config.config,
google_organization_iam_binding.authoritative,
diff --git a/modules/organization/variables.tf b/modules/organization/variables.tf
index ced5cad3..619056a0 100644
--- a/modules/organization/variables.tf
+++ b/modules/organization/variables.tf
@@ -1,5 +1,5 @@
/**
- * Copyright 2022 Google LLC
+ * 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.
@@ -183,18 +183,6 @@ variable "org_policies" {
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))
- }))
- 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)
@@ -204,13 +192,13 @@ variable "org_policies" {
all = optional(bool)
values = optional(list(string))
}))
- enforce = optional(bool, true) # for boolean policies only.
- condition = object({
+ enforce = optional(bool) # for boolean policies only.
+ condition = optional(object({
description = optional(string)
expression = optional(string)
location = optional(string)
title = optional(string)
- })
+ }), {})
})), [])
}))
default = {}
diff --git a/modules/project/README.md b/modules/project/README.md
index e7a645fe..730fe190 100644
--- a/modules/project/README.md
+++ b/modules/project/README.md
@@ -213,7 +213,6 @@ module "service-project" {
source = "./fabric/modules/project"
name = "my-service-project"
shared_vpc_service_config = {
- attach = true
host_project = module.host-project.project_id
service_identity_iam = {
"roles/compute.networkUser" = [
@@ -244,40 +243,46 @@ module "project" {
prefix = "foo"
org_policies = {
"compute.disableGuestAttributesAccess" = {
- enforce = true
+ rules = [{ enforce = true }]
}
- "constraints/compute.skipDefaultNetworkCreation" = {
- enforce = true
+ "compute.skipDefaultNetworkCreation" = {
+ rules = [{ enforce = true }]
}
"iam.disableServiceAccountKeyCreation" = {
- enforce = true
+ rules = [{ enforce = true }]
}
"iam.disableServiceAccountKeyUpload" = {
- enforce = false
rules = [
{
condition = {
- expression = "resource.matchTagId(\"tagKeys/1234\", \"tagValues/1234\")"
+ expression = "resource.matchTagId('tagKeys/1234', 'tagValues/1234')"
title = "condition"
description = "test condition"
location = "somewhere"
}
enforce = true
+ },
+ {
+ enforce = false
}
]
}
- "constraints/iam.allowedPolicyMemberDomains" = {
- allow = {
- values = ["C0xxxxxxx", "C0yyyyyyy"]
- }
+ "iam.allowedPolicyMemberDomains" = {
+ rules = [{
+ allow = {
+ values = ["C0xxxxxxx", "C0yyyyyyy"]
+ }
+ }]
}
- "constraints/compute.trustedImageProjects" = {
- allow = {
- values = ["projects/my-project"]
- }
+ "compute.trustedImageProjects" = {
+ rules = [{
+ allow = {
+ values = ["projects/my-project"]
+ }
+ }]
}
- "constraints/compute.vmExternalIpAccess" = {
- deny = { all = true }
+ "compute.vmExternalIpAccess" = {
+ rules = [{ deny = { all = true } }]
}
}
}
@@ -307,36 +312,42 @@ module "project" {
```yaml
# tftest-file id=boolean path=configs/org-policies/boolean.yaml
compute.disableGuestAttributesAccess:
- enforce: true
-constraints/compute.skipDefaultNetworkCreation:
- enforce: true
+ rules:
+ - enforce: true
+compute.skipDefaultNetworkCreation:
+ rules:
+ - enforce: true
iam.disableServiceAccountKeyCreation:
- enforce: true
+ rules:
+ - enforce: true
iam.disableServiceAccountKeyUpload:
- enforce: false
rules:
- condition:
description: test condition
- expression: resource.matchTagId("tagKeys/1234", "tagValues/1234")
+ expression: resource.matchTagId('tagKeys/1234', 'tagValues/1234')
location: somewhere
title: condition
enforce: true
+ - enforce: false
```
```yaml
# tftest-file id=list path=configs/org-policies/list.yaml
-constraints/compute.trustedImageProjects:
- allow:
- values:
- - projects/my-project
-constraints/compute.vmExternalIpAccess:
- deny:
- all: true
-constraints/iam.allowedPolicyMemberDomains:
- allow:
- values:
- - C0xxxxxxx
- - C0yyyyyyy
+compute.trustedImageProjects:
+ rules:
+ - allow:
+ values:
+ - projects/my-project
+compute.vmExternalIpAccess:
+ rules:
+ - deny:
+ all: true
+iam.allowedPolicyMemberDomains:
+ rules:
+ - allow:
+ values:
+ - C0xxxxxxx
+ - C0yyyyyyy
```
@@ -523,23 +534,23 @@ output "compute_robot" {
| [logging_exclusions](variables.tf#L95) | Logging exclusions for this project in the form {NAME -> FILTER}. | map(string)
| | {}
|
| [logging_sinks](variables.tf#L102) | Logging sinks to create for this project. | map(object({…}))
| | {}
|
| [metric_scopes](variables.tf#L133) | List of projects that will act as metric scopes for this project. | list(string)
| | []
|
-| [org_policies](variables.tf#L145) | Organization policies applied to this project keyed by policy name. | map(object({…}))
| | {}
|
-| [org_policies_data_path](variables.tf#L185) | Path containing org policies in YAML format. | string
| | null
|
-| [oslogin](variables.tf#L191) | Enable OS Login. | bool
| | false
|
-| [oslogin_admins](variables.tf#L197) | List of IAM-style identities that will be granted roles necessary for OS Login administrators. | list(string)
| | []
|
-| [oslogin_users](variables.tf#L205) | List of IAM-style identities that will be granted roles necessary for OS Login users. | list(string)
| | []
|
-| [parent](variables.tf#L212) | Parent folder or organization in 'folders/folder_id' or 'organizations/org_id' format. | string
| | null
|
-| [prefix](variables.tf#L222) | Optional prefix used to generate project id and name. | string
| | null
|
-| [project_create](variables.tf#L232) | Create project. When set to false, uses a data source to reference existing project. | bool
| | true
|
-| [service_config](variables.tf#L238) | Configure service API activation. | object({…})
| | {…}
|
-| [service_encryption_key_ids](variables.tf#L250) | Cloud KMS encryption key in {SERVICE => [KEY_URL]} format. | map(list(string))
| | {}
|
-| [service_perimeter_bridges](variables.tf#L257) | Name of VPC-SC Bridge perimeters to add project into. See comment in the variables file for format. | list(string)
| | null
|
-| [service_perimeter_standard](variables.tf#L264) | Name of VPC-SC Standard perimeter to add project into. See comment in the variables file for format. | string
| | null
|
-| [services](variables.tf#L270) | Service APIs to enable. | list(string)
| | []
|
-| [shared_vpc_host_config](variables.tf#L276) | Configures this project as a Shared VPC host project (mutually exclusive with shared_vpc_service_project). | object({…})
| | null
|
-| [shared_vpc_service_config](variables.tf#L285) | Configures this project as a Shared VPC service project (mutually exclusive with shared_vpc_host_config). | object({…})
| | null
|
-| [skip_delete](variables.tf#L295) | Allows the underlying resources to be destroyed without destroying the project itself. | bool
| | false
|
-| [tag_bindings](variables.tf#L301) | Tag bindings for this project, in key => tag value id format. | map(string)
| | null
|
+| [org_policies](variables.tf#L145) | Organization policies applied to this project keyed by policy name. | map(object({…}))
| | {}
|
+| [org_policies_data_path](variables.tf#L172) | Path containing org policies in YAML format. | string
| | null
|
+| [oslogin](variables.tf#L178) | Enable OS Login. | bool
| | false
|
+| [oslogin_admins](variables.tf#L184) | List of IAM-style identities that will be granted roles necessary for OS Login administrators. | list(string)
| | []
|
+| [oslogin_users](variables.tf#L192) | List of IAM-style identities that will be granted roles necessary for OS Login users. | list(string)
| | []
|
+| [parent](variables.tf#L199) | Parent folder or organization in 'folders/folder_id' or 'organizations/org_id' format. | string
| | null
|
+| [prefix](variables.tf#L209) | Optional prefix used to generate project id and name. | string
| | null
|
+| [project_create](variables.tf#L219) | Create project. When set to false, uses a data source to reference existing project. | bool
| | true
|
+| [service_config](variables.tf#L225) | Configure service API activation. | object({…})
| | {…}
|
+| [service_encryption_key_ids](variables.tf#L237) | Cloud KMS encryption key in {SERVICE => [KEY_URL]} format. | map(list(string))
| | {}
|
+| [service_perimeter_bridges](variables.tf#L244) | Name of VPC-SC Bridge perimeters to add project into. See comment in the variables file for format. | list(string)
| | null
|
+| [service_perimeter_standard](variables.tf#L251) | Name of VPC-SC Standard perimeter to add project into. See comment in the variables file for format. | string
| | null
|
+| [services](variables.tf#L257) | Service APIs to enable. | list(string)
| | []
|
+| [shared_vpc_host_config](variables.tf#L263) | Configures this project as a Shared VPC host project (mutually exclusive with shared_vpc_service_project). | object({…})
| | null
|
+| [shared_vpc_service_config](variables.tf#L272) | Configures this project as a Shared VPC service project (mutually exclusive with shared_vpc_host_config). | object({…})
| | null
|
+| [skip_delete](variables.tf#L282) | Allows the underlying resources to be destroyed without destroying the project itself. | bool
| | false
|
+| [tag_bindings](variables.tf#L288) | Tag bindings for this project, in key => tag value id format. | map(string)
| | null
|
## Outputs
diff --git a/modules/project/organization-policies.tf b/modules/project/organization-policies.tf
index 4ff5bb99..37e6f253 100644
--- a/modules/project/organization-policies.tf
+++ b/modules/project/organization-policies.tf
@@ -1,5 +1,5 @@
/**
- * Copyright 2022 Google LLC
+ * 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.
@@ -28,16 +28,6 @@ locals {
k => {
inherit_from_parent = try(v.inherit_from_parent, null)
reset = try(v.reset, null)
- allow = can(v.allow) ? {
- all = try(v.allow.all, null)
- values = try(v.allow.values, null)
- } : null
- deny = can(v.deny) ? {
- all = try(v.deny.all, null)
- values = try(v.deny.values, null)
- } : null
- enforce = try(v.enforce, true)
-
rules = [
for r in try(v.rules, []) : {
allow = can(r.allow) ? {
@@ -48,7 +38,7 @@ locals {
all = try(r.deny.all, null)
values = try(r.deny.values, null)
} : null
- enforce = try(r.enforce, true)
+ enforce = try(r.enforce, null)
condition = {
description = try(r.condition.description, null)
expression = try(r.condition.expression, null)
@@ -67,8 +57,9 @@ locals {
k => merge(v, {
name = "projects/${local.project.project_id}/policies/${k}"
parent = "projects/${local.project.project_id}"
-
- is_boolean_policy = v.allow == null && v.deny == null
+ is_boolean_policy = (
+ alltrue([for r in v.rules : r.allow == null && r.deny == null])
+ )
has_values = (
length(coalesce(try(v.allow.values, []), [])) > 0 ||
length(coalesce(try(v.deny.values, []), [])) > 0
@@ -90,11 +81,9 @@ resource "google_org_policy_policy" "default" {
for_each = local.org_policies
name = each.value.name
parent = each.value.parent
-
spec {
inherit_from_parent = each.value.inherit_from_parent
reset = each.value.reset
-
dynamic "rules" {
for_each = each.value.rules
iterator = rule
@@ -106,11 +95,14 @@ resource "google_org_policy_policy" "default" {
? upper(tostring(rule.value.enforce))
: null
)
- condition {
- description = rule.value.condition.description
- expression = rule.value.condition.expression
- location = rule.value.condition.location
- title = rule.value.condition.title
+ dynamic "condition" {
+ for_each = rule.value.condition.expression != null ? [1] : []
+ content {
+ description = rule.value.condition.description
+ expression = rule.value.condition.expression
+ location = rule.value.condition.location
+ title = rule.value.condition.title
+ }
}
dynamic "values" {
for_each = rule.value.has_values ? [1] : []
@@ -121,22 +113,5 @@ resource "google_org_policy_policy" "default" {
}
}
}
-
- rules {
- allow_all = try(each.value.allow.all, null) == true ? "TRUE" : null
- deny_all = try(each.value.deny.all, null) == true ? "TRUE" : null
- enforce = (
- each.value.is_boolean_policy && each.value.enforce != null
- ? upper(tostring(each.value.enforce))
- : null
- )
- dynamic "values" {
- for_each = each.value.has_values ? [1] : []
- content {
- allowed_values = try(each.value.allow.values, null)
- denied_values = try(each.value.deny.values, null)
- }
- }
- }
}
}
diff --git a/modules/project/variables.tf b/modules/project/variables.tf
index 3769a1fb..ede3a8c6 100644
--- a/modules/project/variables.tf
+++ b/modules/project/variables.tf
@@ -1,5 +1,5 @@
/**
- * Copyright 2022 Google LLC
+ * 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.
@@ -147,19 +147,6 @@ variable "org_policies" {
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))
- }))
- 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)
@@ -169,13 +156,13 @@ variable "org_policies" {
all = optional(bool)
values = optional(list(string))
}))
- enforce = optional(bool, true) # for boolean policies only.
- condition = object({
+ enforce = optional(bool) # for boolean policies only.
+ condition = optional(object({
description = optional(string)
expression = optional(string)
location = optional(string)
title = optional(string)
- })
+ }), {})
})), [])
}))
default = {}
diff --git a/modules/vpc-sc/README.md b/modules/vpc-sc/README.md
index 8e412bcf..7ad0cba5 100644
--- a/modules/vpc-sc/README.md
+++ b/modules/vpc-sc/README.md
@@ -147,8 +147,8 @@ module "test" {
from = {
identities = [
"serviceAccount:test-tf@myproject.iam.gserviceaccount.com",
- ],
- source_access_levels = ["*"]
+ ]
+ access_levels = ["*"]
}
to = {
operations = [{ service_name = "*" }]
diff --git a/tests/blueprints/factories/project_factory/fixture/projects/project.yaml b/tests/blueprints/factories/project_factory/fixture/projects/project.yaml
index a1581984..b8d6e663 100644
--- a/tests/blueprints/factories/project_factory/fixture/projects/project.yaml
+++ b/tests/blueprints/factories/project_factory/fixture/projects/project.yaml
@@ -48,15 +48,14 @@ 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
- values:
- - projects/fast-prod-iac-core-0
+ compute.disableGuestAttributesAccess:
+ rules:
+ - enforce: true
+ compute.trustedImageProjects:
+ rules:
+ - allow:
+ values:
+ - projects/fast-prod-iac-core-0
# [opt] Prefix - overrides default if set
prefix: test1
diff --git a/tests/fast/stages/s3_project_factory/data/projects/project.yaml b/tests/fast/stages/s3_project_factory/data/projects/project.yaml
index d988d9d5..90354a2a 100644
--- a/tests/fast/stages/s3_project_factory/data/projects/project.yaml
+++ b/tests/fast/stages/s3_project_factory/data/projects/project.yaml
@@ -1,4 +1,4 @@
-# Copyright 2022 Google LLC
+# 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.
@@ -60,15 +60,14 @@ 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
- values:
- - projects/fast-prod-iac-core-0
+ compute.disableGuestAttributesAccess:
+ rules:
+ - enforce: true
+ compute.trustedImageProjects:
+ rules:
+ - allow:
+ values:
+ - projects/fast-prod-iac-core-0
# [opt] Service account to create for the project and their roles on the project
# in name => [roles] format
diff --git a/tests/modules/folder/examples/org-policies.yaml b/tests/modules/folder/examples/org-policies.yaml
index f8bf4187..c7bee123 100644
--- a/tests/modules/folder/examples/org-policies.yaml
+++ b/tests/modules/folder/examples/org-policies.yaml
@@ -1,4 +1,4 @@
-# Copyright 2022 Google LLC
+# 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.
@@ -26,7 +26,7 @@ values:
deny_all: null
enforce: 'TRUE'
values: []
- module.folder.google_org_policy_policy.default["constraints/compute.skipDefaultNetworkCreation"]:
+ module.folder.google_org_policy_policy.default["compute.skipDefaultNetworkCreation"]:
spec:
- inherit_from_parent: null
reset: null
@@ -36,7 +36,7 @@ values:
deny_all: null
enforce: 'TRUE'
values: []
- module.folder.google_org_policy_policy.default["constraints/compute.trustedImageProjects"]:
+ module.folder.google_org_policy_policy.default["compute.trustedImageProjects"]:
spec:
- inherit_from_parent: null
reset: null
@@ -49,7 +49,7 @@ values:
- allowed_values:
- projects/my-project
denied_values: null
- module.folder.google_org_policy_policy.default["constraints/compute.vmExternalIpAccess"]:
+ module.folder.google_org_policy_policy.default["compute.vmExternalIpAccess"]:
spec:
- inherit_from_parent: null
reset: null
@@ -59,7 +59,7 @@ values:
deny_all: 'TRUE'
enforce: null
values: []
- module.folder.google_org_policy_policy.default["constraints/iam.allowedPolicyMemberDomains"]:
+ module.folder.google_org_policy_policy.default["iam.allowedPolicyMemberDomains"]:
spec:
- inherit_from_parent: null
reset: null
@@ -91,7 +91,7 @@ values:
- allow_all: null
condition:
- description: test condition
- expression: resource.matchTagId("tagKeys/1234", "tagValues/1234")
+ expression: resource.matchTagId('tagKeys/1234', 'tagValues/1234')
location: somewhere
title: condition
deny_all: null
diff --git a/tests/modules/folder/org_policies_boolean.tfvars b/tests/modules/folder/org_policies_boolean.tfvars
index eceafe6d..cf5047a2 100644
--- a/tests/modules/folder/org_policies_boolean.tfvars
+++ b/tests/modules/folder/org_policies_boolean.tfvars
@@ -1,9 +1,8 @@
org_policies = {
"iam.disableServiceAccountKeyCreation" = {
- enforce = true
+ rules = [{ enforce = true }]
}
"iam.disableServiceAccountKeyUpload" = {
- enforce = false
rules = [
{
condition = {
@@ -13,6 +12,9 @@ org_policies = {
location = "xxx"
}
enforce = true
+ },
+ {
+ enforce = false
}
]
}
diff --git a/tests/modules/folder/org_policies_list.tfvars b/tests/modules/folder/org_policies_list.tfvars
index 73807173..2c83de47 100644
--- a/tests/modules/folder/org_policies_list.tfvars
+++ b/tests/modules/folder/org_policies_list.tfvars
@@ -1,14 +1,15 @@
org_policies = {
"compute.vmExternalIpAccess" = {
- deny = { all = true }
+ rules = [{ deny = { all = true } }]
}
"iam.allowedPolicyMemberDomains" = {
- allow = {
- values = ["C0xxxxxxx", "C0yyyyyyy"]
- }
+ rules = [{
+ allow = {
+ values = ["C0xxxxxxx", "C0yyyyyyy"]
+ }
+ }]
}
"compute.restrictLoadBalancerCreationForTypes" = {
- deny = { values = ["in:EXTERNAL"] }
rules = [
{
condition = {
@@ -31,6 +32,9 @@ org_policies = {
allow = {
all = true
}
+ },
+ {
+ deny = { values = ["in:EXTERNAL"] }
}
]
}
diff --git a/tests/modules/net_vpc/examples/factory.yaml b/tests/modules/net_vpc/examples/factory.yaml
index 48671c29..0724b597 100644
--- a/tests/modules/net_vpc/examples/factory.yaml
+++ b/tests/modules/net_vpc/examples/factory.yaml
@@ -44,7 +44,18 @@ values:
region: europe-west4
role: null
secondary_ip_range: []
+ module.vpc.google_compute_subnetwork_iam_binding.binding["europe-west1/subnet-detailed.roles/compute.networkUser"]:
+ condition: []
+ members:
+ - group:lorem@example.com
+ - serviceAccount:fbz@prj.iam.gserviceaccount.com
+ - user:foobar@example.com
+ project: my-project
+ region: europe-west1
+ role: roles/compute.networkUser
+ subnetwork: subnet-detailed
counts:
google_compute_network: 1
google_compute_subnetwork: 2
+ google_compute_subnetwork_iam_binding: 1
diff --git a/tests/modules/organization/examples/basic.yaml b/tests/modules/organization/examples/basic.yaml
index f7b63a1d..9960a712 100644
--- a/tests/modules/organization/examples/basic.yaml
+++ b/tests/modules/organization/examples/basic.yaml
@@ -25,8 +25,8 @@ values:
deny_all: null
enforce: 'TRUE'
values: []
- module.org.google_org_policy_policy.default["constraints/compute.skipDefaultNetworkCreation"]:
- name: organizations/1234567890/policies/constraints/compute.skipDefaultNetworkCreation
+ module.org.google_org_policy_policy.default["compute.skipDefaultNetworkCreation"]:
+ name: organizations/1234567890/policies/compute.skipDefaultNetworkCreation
parent: organizations/1234567890
spec:
- inherit_from_parent: null
@@ -37,8 +37,8 @@ values:
deny_all: null
enforce: 'TRUE'
values: []
- module.org.google_org_policy_policy.default["constraints/compute.trustedImageProjects"]:
- name: organizations/1234567890/policies/constraints/compute.trustedImageProjects
+ module.org.google_org_policy_policy.default["compute.trustedImageProjects"]:
+ name: organizations/1234567890/policies/compute.trustedImageProjects
parent: organizations/1234567890
spec:
- inherit_from_parent: null
@@ -52,8 +52,8 @@ values:
- allowed_values:
- projects/my-project
denied_values: null
- module.org.google_org_policy_policy.default["constraints/compute.vmExternalIpAccess"]:
- name: organizations/1234567890/policies/constraints/compute.vmExternalIpAccess
+ module.org.google_org_policy_policy.default["compute.vmExternalIpAccess"]:
+ name: organizations/1234567890/policies/compute.vmExternalIpAccess
parent: organizations/1234567890
spec:
- inherit_from_parent: null
@@ -64,15 +64,30 @@ values:
deny_all: 'TRUE'
enforce: null
values: []
- module.org.google_org_policy_policy.default["constraints/iam.allowedPolicyMemberDomains"]:
- name: organizations/1234567890/policies/constraints/iam.allowedPolicyMemberDomains
+ module.org.google_org_policy_policy.default["iam.allowedPolicyMemberDomains"]:
+ name: organizations/1234567890/policies/iam.allowedPolicyMemberDomains
parent: organizations/1234567890
spec:
- inherit_from_parent: null
reset: null
rules:
+ - allow_all: 'TRUE'
+ condition:
+ - description: Allow external identities when resource has the `allowexternal`
+ tag set to true.
+ expression: resource.matchTag('1234567890/allowexternal', 'true')
+ location: null
+ title: Allow external identities
+ deny_all: null
+ enforce: null
+ values: []
- allow_all: null
- condition: []
+ condition:
+ - description: For any resource without allowexternal=true, only allow identities
+ from restricted domains.
+ expression: '!resource.matchTag(''1234567890/allowexternal'', ''true'')'
+ location: null
+ title: ''
deny_all: null
enforce: null
values:
@@ -102,7 +117,7 @@ values:
- allow_all: null
condition:
- description: test condition
- expression: resource.matchTagId("tagKeys/1234", "tagValues/1234")
+ expression: resource.matchTagId('tagKeys/1234', 'tagValues/1234')
location: somewhere
title: condition
deny_all: null
@@ -141,6 +156,20 @@ values:
member: user:compute@example.org
org_id: '1234567890'
role: roles/container.viewer
+ module.org.google_tags_tag_key.default["allowexternal"]:
+ description: Allow external identities.
+ parent: organizations/1234567890
+ purpose: null
+ purpose_data: null
+ short_name: allowexternal
+ module.org.google_tags_tag_value.default["allowexternal/false"]:
+ short_name: 'false'
+ module.org.google_tags_tag_value.default["allowexternal/true"]:
+ short_name: 'true'
+
counts:
google_org_policy_policy: 8
google_organization_iam_binding: 3
+ google_organization_iam_member: 2
+ google_tags_tag_key: 1
+ google_tags_tag_value: 2
diff --git a/tests/modules/organization/org_policies_boolean.tfvars b/tests/modules/organization/org_policies_boolean.tfvars
index eceafe6d..cf5047a2 100644
--- a/tests/modules/organization/org_policies_boolean.tfvars
+++ b/tests/modules/organization/org_policies_boolean.tfvars
@@ -1,9 +1,8 @@
org_policies = {
"iam.disableServiceAccountKeyCreation" = {
- enforce = true
+ rules = [{ enforce = true }]
}
"iam.disableServiceAccountKeyUpload" = {
- enforce = false
rules = [
{
condition = {
@@ -13,6 +12,9 @@ org_policies = {
location = "xxx"
}
enforce = true
+ },
+ {
+ enforce = false
}
]
}
diff --git a/tests/modules/organization/org_policies_list.tfvars b/tests/modules/organization/org_policies_list.tfvars
index f9de8dba..d03f8530 100644
--- a/tests/modules/organization/org_policies_list.tfvars
+++ b/tests/modules/organization/org_policies_list.tfvars
@@ -1,15 +1,17 @@
org_policies = {
"compute.vmExternalIpAccess" = {
- deny = { all = true }
+ rules = [{ deny = { all = true } }]
}
"iam.allowedPolicyMemberDomains" = {
inherit_from_parent = true
- allow = {
- values = ["C0xxxxxxx", "C0yyyyyyy"]
- }
+ rules = [{
+ allow = {
+ values = ["C0xxxxxxx", "C0yyyyyyy"]
+ }
+ }]
+
}
"compute.restrictLoadBalancerCreationForTypes" = {
- deny = { values = ["in:EXTERNAL"] }
rules = [
{
condition = {
@@ -32,6 +34,9 @@ org_policies = {
allow = {
all = true
}
+ },
+ {
+ deny = { values = ["in:EXTERNAL"] }
}
]
}
diff --git a/tests/modules/organization/test_plan_org_policies_modules.py b/tests/modules/organization/test_plan_org_policies_modules.py
index 1d19ee1e..30881d99 100644
--- a/tests/modules/organization/test_plan_org_policies_modules.py
+++ b/tests/modules/organization/test_plan_org_policies_modules.py
@@ -1,4 +1,4 @@
-# Copyright 2022 Google LLC
+# 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.
@@ -26,61 +26,35 @@ def test_policy_implementation():
path = modules_path / module / 'organization-policies.tf'
lines[module] = path.open().readlines()
- diff1 = difflib.unified_diff(lines['project'], lines['folder'])
+ diff1 = difflib.unified_diff(lines['project'], lines['folder'], 'project',
+ 'folder', n=0)
assert list(diff1) == [
- '--- \n',
- '+++ \n',
- '@@ -14,7 +14,7 @@\n',
- ' * limitations under the License.\n',
- ' */\n',
- ' \n',
+ '--- project\n',
+ '+++ folder\n',
+ '@@ -17 +17 @@\n',
'-# tfdoc:file:description Project-level organization policies.\n',
'+# tfdoc:file:description Folder-level organization policies.\n',
- ' \n',
- ' locals {\n',
- ' _factory_data_raw = merge([\n',
- '@@ -65,8 +65,8 @@\n',
- ' org_policies = {\n',
- ' for k, v in local._org_policies :\n',
- ' k => merge(v, {\n',
+ '@@ -58,2 +58,2 @@\n',
'- name = "projects/${local.project.project_id}/policies/${k}"\n',
'- parent = "projects/${local.project.project_id}"\n',
'+ name = "${local.folder.name}/policies/${k}"\n',
'+ parent = local.folder.name\n',
- ' \n',
- ' is_boolean_policy = v.allow == null && v.deny == null\n',
- ' has_values = (\n',
]
- diff2 = difflib.unified_diff(lines['folder'], lines['organization'])
+ diff2 = difflib.unified_diff(lines['folder'], lines['organization'], 'folder',
+ 'organization', n=0)
assert list(diff2) == [
- '--- \n',
- '+++ \n',
- '@@ -14,7 +14,7 @@\n',
- ' * limitations under the License.\n',
- ' */\n',
- ' \n',
+ '--- folder\n',
+ '+++ organization\n',
+ '@@ -17 +17 @@\n',
'-# tfdoc:file:description Folder-level organization policies.\n',
'+# tfdoc:file:description Organization-level organization policies.\n',
- ' \n',
- ' locals {\n',
- ' _factory_data_raw = merge([\n',
- '@@ -65,8 +65,8 @@\n',
- ' org_policies = {\n',
- ' for k, v in local._org_policies :\n',
- ' k => merge(v, {\n',
+ '@@ -58,2 +58,2 @@\n',
'- name = "${local.folder.name}/policies/${k}"\n',
'- parent = local.folder.name\n',
'+ name = "${var.organization_id}/policies/${k}"\n',
'+ parent = var.organization_id\n',
- ' \n',
- ' is_boolean_policy = v.allow == null && v.deny == null\n',
- ' has_values = (\n',
- '@@ -139,4 +139,13 @@\n',
- ' }\n',
- ' }\n',
- ' }\n',
- '+\n',
+ '@@ -116,0 +117,8 @@\n',
'+ depends_on = [\n',
'+ google_organization_iam_audit_config.config,\n',
'+ google_organization_iam_binding.authoritative,\n',
@@ -89,5 +63,4 @@ def test_policy_implementation():
'+ google_organization_iam_policy.authoritative,\n',
'+ google_org_policy_custom_constraint.constraint,\n',
'+ ]\n',
- ' }\n',
]
diff --git a/tests/modules/project/examples/org-policies.yaml b/tests/modules/project/examples/org-policies.yaml
index 8841dede..d4dddc75 100644
--- a/tests/modules/project/examples/org-policies.yaml
+++ b/tests/modules/project/examples/org-policies.yaml
@@ -1,4 +1,4 @@
-# Copyright 2022 Google LLC
+# 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.
@@ -25,8 +25,8 @@ values:
deny_all: null
enforce: 'TRUE'
values: []
- module.project.google_org_policy_policy.default["constraints/compute.skipDefaultNetworkCreation"]:
- name: projects/foo-project-example/policies/constraints/compute.skipDefaultNetworkCreation
+ module.project.google_org_policy_policy.default["compute.skipDefaultNetworkCreation"]:
+ name: projects/foo-project-example/policies/compute.skipDefaultNetworkCreation
parent: projects/foo-project-example
spec:
- inherit_from_parent: null
@@ -37,8 +37,8 @@ values:
deny_all: null
enforce: 'TRUE'
values: []
- module.project.google_org_policy_policy.default["constraints/compute.trustedImageProjects"]:
- name: projects/foo-project-example/policies/constraints/compute.trustedImageProjects
+ module.project.google_org_policy_policy.default["compute.trustedImageProjects"]:
+ name: projects/foo-project-example/policies/compute.trustedImageProjects
parent: projects/foo-project-example
spec:
- inherit_from_parent: null
@@ -52,8 +52,8 @@ values:
- allowed_values:
- projects/my-project
denied_values: null
- module.project.google_org_policy_policy.default["constraints/compute.vmExternalIpAccess"]:
- name: projects/foo-project-example/policies/constraints/compute.vmExternalIpAccess
+ module.project.google_org_policy_policy.default["compute.vmExternalIpAccess"]:
+ name: projects/foo-project-example/policies/compute.vmExternalIpAccess
parent: projects/foo-project-example
spec:
- inherit_from_parent: null
@@ -64,8 +64,8 @@ values:
deny_all: 'TRUE'
enforce: null
values: []
- module.project.google_org_policy_policy.default["constraints/iam.allowedPolicyMemberDomains"]:
- name: projects/foo-project-example/policies/constraints/iam.allowedPolicyMemberDomains
+ module.project.google_org_policy_policy.default["iam.allowedPolicyMemberDomains"]:
+ name: projects/foo-project-example/policies/iam.allowedPolicyMemberDomains
parent: projects/foo-project-example
spec:
- inherit_from_parent: null
@@ -102,7 +102,7 @@ values:
- allow_all: null
condition:
- description: test condition
- expression: resource.matchTagId("tagKeys/1234", "tagValues/1234")
+ expression: resource.matchTagId('tagKeys/1234', 'tagValues/1234')
location: somewhere
title: condition
deny_all: null
diff --git a/tests/modules/project/org_policies_boolean.tfvars b/tests/modules/project/org_policies_boolean.tfvars
index eceafe6d..cf5047a2 100644
--- a/tests/modules/project/org_policies_boolean.tfvars
+++ b/tests/modules/project/org_policies_boolean.tfvars
@@ -1,9 +1,8 @@
org_policies = {
"iam.disableServiceAccountKeyCreation" = {
- enforce = true
+ rules = [{ enforce = true }]
}
"iam.disableServiceAccountKeyUpload" = {
- enforce = false
rules = [
{
condition = {
@@ -13,6 +12,9 @@ org_policies = {
location = "xxx"
}
enforce = true
+ },
+ {
+ enforce = false
}
]
}
diff --git a/tests/modules/project/org_policies_list.tfvars b/tests/modules/project/org_policies_list.tfvars
index f9de8dba..4889547d 100644
--- a/tests/modules/project/org_policies_list.tfvars
+++ b/tests/modules/project/org_policies_list.tfvars
@@ -1,15 +1,16 @@
org_policies = {
"compute.vmExternalIpAccess" = {
- deny = { all = true }
+ rules = [{ deny = { all = true } }]
}
"iam.allowedPolicyMemberDomains" = {
inherit_from_parent = true
- allow = {
- values = ["C0xxxxxxx", "C0yyyyyyy"]
- }
+ rules = [{
+ allow = {
+ values = ["C0xxxxxxx", "C0yyyyyyy"]
+ }
+ }]
}
"compute.restrictLoadBalancerCreationForTypes" = {
- deny = { values = ["in:EXTERNAL"] }
rules = [
{
condition = {
@@ -32,6 +33,9 @@ org_policies = {
allow = {
all = true
}
+ },
+ {
+ deny = { values = ["in:EXTERNAL"] }
}
]
}