Merge pull request #1167 from GoogleCloudPlatform/jccb/org-policies-rules-fix

Simplify org policies
This commit is contained in:
Julio Castillo 2023-02-21 16:08:43 +01:00 committed by GitHub
commit 097e905887
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
47 changed files with 629 additions and 589 deletions

View File

@ -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
}

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -3,4 +3,5 @@
# sample subset of useful organization policies, edit to suit requirements
storage.uniformBucketLevelAccess:
enforce: true
rules:
- enforce: true

View File

@ -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 }]
# }
}

View File

@ -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. | <code>string</code> | ✓ | |
| [prefix](variables.tf#L157) | Prefix used for resource names. | <code>string</code> | ✓ | |
| [project_id](variables.tf#L166) | Project id. | <code>string</code> | ✓ | |
| [prefix](variables.tf#L144) | Prefix used for resource names. | <code>string</code> | ✓ | |
| [project_id](variables.tf#L153) | Project id. | <code>string</code> | ✓ | |
| [billing_alert](variables.tf#L22) | Billing alert configuration. | <code title="object&#40;&#123;&#10; amount &#61; number&#10; thresholds &#61; object&#40;&#123;&#10; current &#61; list&#40;number&#41;&#10; forecasted &#61; list&#40;number&#41;&#10; &#125;&#41;&#10; credit_treatment &#61; string&#10;&#125;&#41;">object&#40;&#123;&#8230;&#125;&#41;</code> | | <code>null</code> |
| [defaults](variables.tf#L35) | Project factory default values. | <code title="object&#40;&#123;&#10; billing_account_id &#61; string&#10; billing_alert &#61; object&#40;&#123;&#10; amount &#61; number&#10; thresholds &#61; object&#40;&#123;&#10; current &#61; list&#40;number&#41;&#10; forecasted &#61; list&#40;number&#41;&#10; &#125;&#41;&#10; credit_treatment &#61; string&#10; &#125;&#41;&#10; environment_dns_zone &#61; string&#10; essential_contacts &#61; list&#40;string&#41;&#10; labels &#61; map&#40;string&#41;&#10; notification_channels &#61; list&#40;string&#41;&#10; shared_vpc_self_link &#61; string&#10; vpc_host_project &#61; string&#10;&#125;&#41;">object&#40;&#123;&#8230;&#125;&#41;</code> | | <code>null</code> |
| [descriptive_name](variables.tf#L57) | Name of the project name. Used for project name instead of `name` variable. | <code>string</code> | | <code>null</code> |
@ -237,15 +240,15 @@ vpc:
| [iam_additive](variables.tf#L99) | Custom additive IAM settings in role => [principal] format. | <code>map&#40;list&#40;string&#41;&#41;</code> | | <code>&#123;&#125;</code> |
| [kms_service_agents](variables.tf#L105) | KMS IAM configuration in as service => [key]. | <code>map&#40;list&#40;string&#41;&#41;</code> | | <code>&#123;&#125;</code> |
| [labels](variables.tf#L111) | Labels to be assigned at project level. | <code>map&#40;string&#41;</code> | | <code>&#123;&#125;</code> |
| [org_policies](variables.tf#L117) | Org-policy overrides at project level. | <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; 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, true&#41; &#35; for boolean policies only.&#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, true&#41; &#35; for boolean policies only.&#10; condition &#61; 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;&#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> |
| [service_accounts](variables.tf#L171) | Service accounts to be created, and roles assigned them on the project. | <code>map&#40;list&#40;string&#41;&#41;</code> | | <code>&#123;&#125;</code> |
| [service_accounts_additive](variables.tf#L177) | Service accounts to be created, and roles assigned them on the project additively. | <code>map&#40;list&#40;string&#41;&#41;</code> | | <code>&#123;&#125;</code> |
| [service_accounts_iam](variables.tf#L183) | IAM bindings on service account resources. Format is KEY => {ROLE => [MEMBERS]}. | <code>map&#40;map&#40;list&#40;string&#41;&#41;&#41;</code> | | <code>&#123;&#125;</code> |
| [service_accounts_iam_additive](variables.tf#L190) | IAM additive bindings on service account resources. Format is KEY => {ROLE => [MEMBERS]}. | <code>map&#40;map&#40;list&#40;string&#41;&#41;&#41;</code> | | <code>&#123;&#125;</code> |
| [service_identities_iam](variables.tf#L197) | Custom IAM settings for service identities in service => [role] format. | <code>map&#40;list&#40;string&#41;&#41;</code> | | <code>&#123;&#125;</code> |
| [service_identities_iam_additive](variables.tf#L204) | Custom additive IAM settings for service identities in service => [role] format. | <code>map&#40;list&#40;string&#41;&#41;</code> | | <code>&#123;&#125;</code> |
| [services](variables.tf#L211) | Services to be enabled for the project. | <code>list&#40;string&#41;</code> | | <code>&#91;&#93;</code> |
| [vpc](variables.tf#L218) | VPC configuration for the project. | <code title="object&#40;&#123;&#10; host_project &#61; string&#10; gke_setup &#61; object&#40;&#123;&#10; enable_security_admin &#61; bool&#10; enable_host_service_agent &#61; bool&#10; &#125;&#41;&#10; subnets_iam &#61; map&#40;list&#40;string&#41;&#41;&#10;&#125;&#41;">object&#40;&#123;&#8230;&#125;&#41;</code> | | <code>null</code> |
| [org_policies](variables.tf#L117) | Org-policy overrides at project level. | <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; &#125;&#41;&#41;, &#91;&#93;&#41;&#10;&#125;&#41;&#41;">map&#40;object&#40;&#123;&#8230;&#125;&#41;&#41;</code> | | <code>&#123;&#125;</code> |
| [service_accounts](variables.tf#L158) | Service accounts to be created, and roles assigned them on the project. | <code>map&#40;list&#40;string&#41;&#41;</code> | | <code>&#123;&#125;</code> |
| [service_accounts_additive](variables.tf#L164) | Service accounts to be created, and roles assigned them on the project additively. | <code>map&#40;list&#40;string&#41;&#41;</code> | | <code>&#123;&#125;</code> |
| [service_accounts_iam](variables.tf#L170) | IAM bindings on service account resources. Format is KEY => {ROLE => [MEMBERS]}. | <code>map&#40;map&#40;list&#40;string&#41;&#41;&#41;</code> | | <code>&#123;&#125;</code> |
| [service_accounts_iam_additive](variables.tf#L177) | IAM additive bindings on service account resources. Format is KEY => {ROLE => [MEMBERS]}. | <code>map&#40;map&#40;list&#40;string&#41;&#41;&#41;</code> | | <code>&#123;&#125;</code> |
| [service_identities_iam](variables.tf#L184) | Custom IAM settings for service identities in service => [role] format. | <code>map&#40;list&#40;string&#41;&#41;</code> | | <code>&#123;&#125;</code> |
| [service_identities_iam_additive](variables.tf#L191) | Custom additive IAM settings for service identities in service => [role] format. | <code>map&#40;list&#40;string&#41;&#41;</code> | | <code>&#123;&#125;</code> |
| [services](variables.tf#L198) | Services to be enabled for the project. | <code>list&#40;string&#41;</code> | | <code>&#91;&#93;</code> |
| [vpc](variables.tf#L205) | VPC configuration for the project. | <code title="object&#40;&#123;&#10; host_project &#61; string&#10; gke_setup &#61; object&#40;&#123;&#10; enable_security_admin &#61; bool&#10; enable_host_service_agent &#61; bool&#10; &#125;&#41;&#10; subnets_iam &#61; map&#40;list&#40;string&#41;&#41;&#10;&#125;&#41;">object&#40;&#123;&#8230;&#125;&#41;</code> | | <code>null</code> |
## Outputs

View File

@ -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

View File

@ -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 = {}

View File

@ -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

View File

@ -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 } }]
}
}
}

View File

@ -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"]

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -3,4 +3,5 @@
# sample subset of useful organization policies, edit to suit requirements
storage.uniformBucketLevelAccess:
enforce: true
rules:
- enforce: true

View File

@ -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(

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -3,4 +3,5 @@
# sample subset of useful organization policies, edit to suit requirements
storage.uniformBucketLevelAccess:
enforce: true
rules:
- enforce: true

View File

@ -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 }

View File

@ -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

View File

@ -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}. | <code>map&#40;string&#41;</code> | | <code>&#123;&#125;</code> |
| [logging_sinks](variables.tf#L105) | Logging sinks to create for the organization. | <code title="map&#40;object&#40;&#123;&#10; bq_partitioned_table &#61; optional&#40;bool&#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; string&#10; include_children &#61; optional&#40;bool, true&#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#L135) | Folder name. | <code>string</code> | | <code>null</code> |
| [org_policies](variables.tf#L141) | 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; 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, true&#41; &#35; for boolean policies only.&#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, true&#41; &#35; for boolean policies only.&#10; condition &#61; 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;&#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_policies_data_path](variables.tf#L181) | Path containing org policies in YAML format. | <code>string</code> | | <code>null</code> |
| [parent](variables.tf#L187) | Parent in folders/folder_id or organizations/org_id format. | <code>string</code> | | <code>null</code> |
| [tag_bindings](variables.tf#L197) | Tag bindings for this folder, in key => tag value id format. | <code>map&#40;string&#41;</code> | | <code>null</code> |
| [org_policies](variables.tf#L141) | 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; &#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_policies_data_path](variables.tf#L168) | Path containing org policies in YAML format. | <code>string</code> | | <code>null</code> |
| [parent](variables.tf#L174) | Parent in folders/folder_id or organizations/org_id format. | <code>string</code> | | <code>null</code> |
| [tag_bindings](variables.tf#L184) | Tag bindings for this folder, in key => tag value id format. | <code>map&#40;string&#41;</code> | | <code>null</code> |
## Outputs

View File

@ -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)
}
}
}
}
}

View File

@ -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 = {}

View File

@ -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. | <code>string</code> | ✓ | |
| [organization_id](variables.tf#L234) | 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> |
| [firewall_policies](variables.tf#L31) | Hierarchical firewall policy rules created in the organization. | <code title="map&#40;map&#40;object&#40;&#123;&#10; action &#61; string&#10; description &#61; string&#10; direction &#61; string&#10; logging &#61; bool&#10; ports &#61; map&#40;list&#40;string&#41;&#41;&#10; priority &#61; number&#10; ranges &#61; list&#40;string&#41;&#10; target_resources &#61; list&#40;string&#41;&#10; target_service_accounts &#61; list&#40;string&#41;&#10;&#125;&#41;&#41;&#41;">map&#40;map&#40;object&#40;&#123;&#8230;&#125;&#41;&#41;&#41;</code> | | <code>&#123;&#125;</code> |
@ -463,12 +490,12 @@ module "org" {
| [logging_exclusions](variables.tf#L122) | Logging exclusions for this organization in the form {NAME -> FILTER}. | <code>map&#40;string&#41;</code> | | <code>&#123;&#125;</code> |
| [logging_sinks](variables.tf#L129) | Logging sinks to create for the organization. | <code title="map&#40;object&#40;&#123;&#10; bq_partitioned_table &#61; optional&#40;bool&#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; string&#10; include_children &#61; optional&#40;bool, true&#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.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. | <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; 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; &#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#L181) | 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; 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, true&#41; &#35; for boolean policies only.&#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, true&#41; &#35; for boolean policies only.&#10; condition &#61; 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;&#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_policies_data_path](variables.tf#L220) | Path containing org policies in YAML format. | <code>string</code> | | <code>null</code> |
| [org_policy_custom_constraints](variables.tf#L226) | Organization policiy 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_policy_custom_constraints_data_path](variables.tf#L240) | Path containing org policy custom constraints in YAML format. | <code>string</code> | | <code>null</code> |
| [tag_bindings](variables.tf#L255) | Tag bindings for this organization, in key => tag value id format. | <code>map&#40;string&#41;</code> | | <code>null</code> |
| [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. | <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; 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; 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> |
| [org_policies](variables.tf#L181) | 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; &#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_policies_data_path](variables.tf#L208) | Path containing org policies in YAML format. | <code>string</code> | | <code>null</code> |
| [org_policy_custom_constraints](variables.tf#L214) | Organization policiy 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_policy_custom_constraints_data_path](variables.tf#L228) | Path containing org policy custom constraints in YAML format. | <code>string</code> | | <code>null</code> |
| [tag_bindings](variables.tf#L243) | Tag bindings for this organization, in key => tag value id format. | <code>map&#40;string&#41;</code> | | <code>null</code> |
| [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. | <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; 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; 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> |
## Outputs

View File

@ -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,

View File

@ -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 = {}

View File

@ -243,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 } }]
}
}
}
@ -306,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
```
@ -522,23 +534,23 @@ output "compute_robot" {
| [logging_exclusions](variables.tf#L95) | Logging exclusions for this project in the form {NAME -> FILTER}. | <code>map&#40;string&#41;</code> | | <code>&#123;&#125;</code> |
| [logging_sinks](variables.tf#L102) | Logging sinks to create for this project. | <code title="map&#40;object&#40;&#123;&#10; bq_partitioned_table &#61; optional&#40;bool&#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; string&#10; iam &#61; optional&#40;bool, true&#41;&#10; type &#61; string&#10; unique_writer &#61; optional&#40;bool&#41;&#10;&#125;&#41;&#41;">map&#40;object&#40;&#123;&#8230;&#125;&#41;&#41;</code> | | <code>&#123;&#125;</code> |
| [metric_scopes](variables.tf#L133) | List of projects that will act as metric scopes for this project. | <code>list&#40;string&#41;</code> | | <code>&#91;&#93;</code> |
| [org_policies](variables.tf#L145) | Organization policies applied to this project 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; 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, true&#41; &#35; for boolean policies only.&#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, true&#41; &#35; for boolean policies only.&#10; condition &#61; 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;&#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_policies_data_path](variables.tf#L185) | Path containing org policies in YAML format. | <code>string</code> | | <code>null</code> |
| [oslogin](variables.tf#L191) | Enable OS Login. | <code>bool</code> | | <code>false</code> |
| [oslogin_admins](variables.tf#L197) | List of IAM-style identities that will be granted roles necessary for OS Login administrators. | <code>list&#40;string&#41;</code> | | <code>&#91;&#93;</code> |
| [oslogin_users](variables.tf#L205) | List of IAM-style identities that will be granted roles necessary for OS Login users. | <code>list&#40;string&#41;</code> | | <code>&#91;&#93;</code> |
| [parent](variables.tf#L212) | Parent folder or organization in 'folders/folder_id' or 'organizations/org_id' format. | <code>string</code> | | <code>null</code> |
| [prefix](variables.tf#L222) | Optional prefix used to generate project id and name. | <code>string</code> | | <code>null</code> |
| [project_create](variables.tf#L232) | Create project. When set to false, uses a data source to reference existing project. | <code>bool</code> | | <code>true</code> |
| [service_config](variables.tf#L238) | Configure service API activation. | <code title="object&#40;&#123;&#10; disable_on_destroy &#61; bool&#10; disable_dependent_services &#61; bool&#10;&#125;&#41;">object&#40;&#123;&#8230;&#125;&#41;</code> | | <code title="&#123;&#10; disable_on_destroy &#61; false&#10; disable_dependent_services &#61; false&#10;&#125;">&#123;&#8230;&#125;</code> |
| [service_encryption_key_ids](variables.tf#L250) | Cloud KMS encryption key in {SERVICE => [KEY_URL]} format. | <code>map&#40;list&#40;string&#41;&#41;</code> | | <code>&#123;&#125;</code> |
| [service_perimeter_bridges](variables.tf#L257) | Name of VPC-SC Bridge perimeters to add project into. See comment in the variables file for format. | <code>list&#40;string&#41;</code> | | <code>null</code> |
| [service_perimeter_standard](variables.tf#L264) | Name of VPC-SC Standard perimeter to add project into. See comment in the variables file for format. | <code>string</code> | | <code>null</code> |
| [services](variables.tf#L270) | Service APIs to enable. | <code>list&#40;string&#41;</code> | | <code>&#91;&#93;</code> |
| [shared_vpc_host_config](variables.tf#L276) | Configures this project as a Shared VPC host project (mutually exclusive with shared_vpc_service_project). | <code title="object&#40;&#123;&#10; enabled &#61; bool&#10; service_projects &#61; optional&#40;list&#40;string&#41;, &#91;&#93;&#41;&#10;&#125;&#41;">object&#40;&#123;&#8230;&#125;&#41;</code> | | <code>null</code> |
| [shared_vpc_service_config](variables.tf#L285) | Configures this project as a Shared VPC service project (mutually exclusive with shared_vpc_host_config). | <code title="object&#40;&#123;&#10; host_project &#61; string&#10; service_identity_iam &#61; optional&#40;map&#40;list&#40;string&#41;&#41;&#41;&#10;&#125;&#41;">object&#40;&#123;&#8230;&#125;&#41;</code> | | <code>null</code> |
| [skip_delete](variables.tf#L295) | Allows the underlying resources to be destroyed without destroying the project itself. | <code>bool</code> | | <code>false</code> |
| [tag_bindings](variables.tf#L301) | Tag bindings for this project, in key => tag value id format. | <code>map&#40;string&#41;</code> | | <code>null</code> |
| [org_policies](variables.tf#L145) | Organization policies applied to this project 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; &#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_policies_data_path](variables.tf#L172) | Path containing org policies in YAML format. | <code>string</code> | | <code>null</code> |
| [oslogin](variables.tf#L178) | Enable OS Login. | <code>bool</code> | | <code>false</code> |
| [oslogin_admins](variables.tf#L184) | List of IAM-style identities that will be granted roles necessary for OS Login administrators. | <code>list&#40;string&#41;</code> | | <code>&#91;&#93;</code> |
| [oslogin_users](variables.tf#L192) | List of IAM-style identities that will be granted roles necessary for OS Login users. | <code>list&#40;string&#41;</code> | | <code>&#91;&#93;</code> |
| [parent](variables.tf#L199) | Parent folder or organization in 'folders/folder_id' or 'organizations/org_id' format. | <code>string</code> | | <code>null</code> |
| [prefix](variables.tf#L209) | Optional prefix used to generate project id and name. | <code>string</code> | | <code>null</code> |
| [project_create](variables.tf#L219) | Create project. When set to false, uses a data source to reference existing project. | <code>bool</code> | | <code>true</code> |
| [service_config](variables.tf#L225) | Configure service API activation. | <code title="object&#40;&#123;&#10; disable_on_destroy &#61; bool&#10; disable_dependent_services &#61; bool&#10;&#125;&#41;">object&#40;&#123;&#8230;&#125;&#41;</code> | | <code title="&#123;&#10; disable_on_destroy &#61; false&#10; disable_dependent_services &#61; false&#10;&#125;">&#123;&#8230;&#125;</code> |
| [service_encryption_key_ids](variables.tf#L237) | Cloud KMS encryption key in {SERVICE => [KEY_URL]} format. | <code>map&#40;list&#40;string&#41;&#41;</code> | | <code>&#123;&#125;</code> |
| [service_perimeter_bridges](variables.tf#L244) | Name of VPC-SC Bridge perimeters to add project into. See comment in the variables file for format. | <code>list&#40;string&#41;</code> | | <code>null</code> |
| [service_perimeter_standard](variables.tf#L251) | Name of VPC-SC Standard perimeter to add project into. See comment in the variables file for format. | <code>string</code> | | <code>null</code> |
| [services](variables.tf#L257) | Service APIs to enable. | <code>list&#40;string&#41;</code> | | <code>&#91;&#93;</code> |
| [shared_vpc_host_config](variables.tf#L263) | Configures this project as a Shared VPC host project (mutually exclusive with shared_vpc_service_project). | <code title="object&#40;&#123;&#10; enabled &#61; bool&#10; service_projects &#61; optional&#40;list&#40;string&#41;, &#91;&#93;&#41;&#10;&#125;&#41;">object&#40;&#123;&#8230;&#125;&#41;</code> | | <code>null</code> |
| [shared_vpc_service_config](variables.tf#L272) | Configures this project as a Shared VPC service project (mutually exclusive with shared_vpc_host_config). | <code title="object&#40;&#123;&#10; host_project &#61; string&#10; service_identity_iam &#61; optional&#40;map&#40;list&#40;string&#41;&#41;&#41;&#10;&#125;&#41;">object&#40;&#123;&#8230;&#125;&#41;</code> | | <code>null</code> |
| [skip_delete](variables.tf#L282) | Allows the underlying resources to be destroyed without destroying the project itself. | <code>bool</code> | | <code>false</code> |
| [tag_bindings](variables.tf#L288) | Tag bindings for this project, in key => tag value id format. | <code>map&#40;string&#41;</code> | | <code>null</code> |
## Outputs

View File

@ -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)
}
}
}
}
}

View File

@ -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 = {}

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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
}
]
}

View File

@ -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"] }
}
]
}

View File

@ -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

View File

@ -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
}
]
}

View File

@ -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"] }
}
]
}

View File

@ -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',
]

View File

@ -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

View File

@ -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
}
]
}

View File

@ -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"] }
}
]
}