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"); # Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License. # you may not use this file except in compliance with the License.
@ -83,8 +83,8 @@ module "project" {
} }
org_policies = { org_policies = {
# "constraints/compute.requireOsLogin" = { # "compute.requireOsLogin" = {
# enforce = false # rules = [{ enforce = false }]
# } # }
# Example of applying a project wide policy, mainly useful for Composer 1 # 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 # sample subset of useful organization policies, edit to suit requirements
compute.disableGuestAttributesAccess: compute.disableGuestAttributesAccess:
enforce: true rules:
- enforce: true
compute.requireOsLogin: compute.requireOsLogin:
enforce: true rules:
- enforce: true
compute.restrictLoadBalancerCreationForTypes: compute.restrictLoadBalancerCreationForTypes:
allow: rules:
values: - allow:
- in:INTERNAL values:
- in:INTERNAL
compute.skipDefaultNetworkCreation: compute.skipDefaultNetworkCreation:
enforce: true rules:
- enforce: true
compute.vmExternalIpAccess: compute.vmExternalIpAccess:
deny: rules:
all: true - deny:
all: true
# compute.disableInternetNetworkEndpointGroup: # compute.disableInternetNetworkEndpointGroup:
# enforce: true # rules:
# - enforce: true
# compute.disableNestedVirtualization: # compute.disableNestedVirtualization:
# enforce: true # rules:
# - enforce: true
# compute.disableSerialPortAccess: # compute.disableSerialPortAccess:
# enforce: true # rules:
# - enforce: true
# compute.restrictCloudNATUsage: # compute.restrictCloudNATUsage:
# deny: # rules:
# all: true # - deny:
# all: true
# compute.restrictDedicatedInterconnectUsage: # compute.restrictDedicatedInterconnectUsage:
# deny: # rules:
# all: true # - deny:
# all: true
# compute.restrictPartnerInterconnectUsage: # compute.restrictPartnerInterconnectUsage:
# deny: # rules:
# all: true # - deny:
# all: true
# compute.restrictProtocolForwardingCreationForTypes: # compute.restrictProtocolForwardingCreationForTypes:
# deny: # rules:
# all: true # - deny:
# all: true
# compute.restrictSharedVpcHostProjects: # compute.restrictSharedVpcHostProjects:
# deny: # rules:
# all: true # - deny:
# all: true
# compute.restrictSharedVpcSubnetworks: # compute.restrictSharedVpcSubnetworks:
# deny: # rules:
# all: true # - deny:
# all: true
# compute.restrictVpcPeering: # compute.restrictVpcPeering:
# deny: # rules:
# all: true # - deny:
# all: true
# compute.restrictVpnPeerIPs: # compute.restrictVpnPeerIPs:
# deny: # rules:
# all: true # - deny:
# all: true
# compute.restrictXpnProjectLienRemoval: # compute.restrictXpnProjectLienRemoval:
# enforce: true # rules:
# - enforce: true
# compute.setNewProjectDefaultToZonalDNSOnly: # compute.setNewProjectDefaultToZonalDNSOnly:
# enforce: true # rules:
# - enforce: true
# compute.vmCanIpForward: # compute.vmCanIpForward:
# deny: # rules:
# all: true # - deny:
# all: true

View File

@ -3,10 +3,13 @@
# sample subset of useful organization policies, edit to suit requirements # sample subset of useful organization policies, edit to suit requirements
iam.automaticIamGrantsForDefaultServiceAccounts: iam.automaticIamGrantsForDefaultServiceAccounts:
enforce: true rules:
- enforce: true
iam.disableServiceAccountKeyCreation: iam.disableServiceAccountKeyCreation:
enforce: true rules:
- enforce: true
iam.disableServiceAccountKeyUpload: iam.disableServiceAccountKeyUpload:
enforce: true rules:
- enforce: true

View File

@ -3,24 +3,29 @@
# sample subset of useful organization policies, edit to suit requirements # sample subset of useful organization policies, edit to suit requirements
run.allowedIngress: run.allowedIngress:
allow: rules:
values: - allow:
- is:internal values:
- is:internal
# run.allowedVPCEgress: # run.allowedVPCEgress:
# allow: # rules:
# values: # - allow:
# values:
# - is:private-ranges-only # - is:private-ranges-only
# cloudfunctions.allowedIngressSettings: # cloudfunctions.allowedIngressSettings:
# allow: # rules:
# values: # - allow:
# - is:ALLOW_INTERNAL_ONLY # values:
# - is:ALLOW_INTERNAL_ONLY
# cloudfunctions.allowedVpcConnectorEgressSettings: # cloudfunctions.allowedVpcConnectorEgressSettings:
# allow: # rules:
# values: # - allow:
# - is:PRIVATE_RANGES_ONLY # values:
# - is:PRIVATE_RANGES_ONLY
# cloudfunctions.requireVPCConnector: # cloudfunctions.requireVPCConnector:
# enforce: true # rules:
# - enforce: true

View File

@ -3,7 +3,9 @@
# sample subset of useful organization policies, edit to suit requirements # sample subset of useful organization policies, edit to suit requirements
sql.restrictAuthorizedNetworks: sql.restrictAuthorizedNetworks:
enforce: true rules:
- enforce: true
sql.restrictPublicIp: sql.restrictPublicIp:
enforce: true rules:
- enforce: true

View File

@ -3,4 +3,5 @@
# sample subset of useful organization policies, edit to suit requirements # sample subset of useful organization policies, edit to suit requirements
storage.uniformBucketLevelAccess: 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"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with 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) 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 # https://stackoverflow.com/questions/53206667/cloud-build-fails-with-resource-location-constraint
module "gcs-bucket-cloudbuild" { module "gcs-bucket-cloudbuild" {
source = "../../../modules/gcs" source = "../../../modules/gcs"
@ -230,8 +230,8 @@ module "project" {
org_policies = { org_policies = {
# Example of applying a project wide policy # Example of applying a project wide policy
# "constraints/compute.requireOsLogin" = { # "compute.requireOsLogin" = {
# enforce = false # rules = [{ enforce = false }]
# } # }
} }

View File

@ -156,15 +156,18 @@ labels:
# [opt] Org policy overrides defined at project level # [opt] Org policy overrides defined at project level
org_policies: org_policies:
constraints/compute.disableGuestAttributesAccess: compute.disableGuestAttributesAccess:
enforce: true rules:
constraints/compute.trustedImageProjects: - enforce: true
allow: compute.trustedImageProjects:
values: rules:
- allow:
values:
- projects/fast-dev-iac-core-0 - projects/fast-dev-iac-core-0
constraints/compute.vmExternalIpAccess: compute.vmExternalIpAccess:
deny: rules:
all: true - deny:
all: true
# [opt] Service account to create for the project and their roles on the project # [opt] Service account to create for the project and their roles on the project
# in name => [roles] format # in name => [roles] format
@ -223,8 +226,8 @@ vpc:
| name | description | type | required | default | | name | description | type | required | default |
|---|---|:---:|:---:|:---:| |---|---|:---:|:---:|:---:|
| [billing_account_id](variables.tf#L17) | Billing account id. | <code>string</code> | ✓ | | | [billing_account_id](variables.tf#L17) | Billing account id. | <code>string</code> | ✓ | |
| [prefix](variables.tf#L157) | Prefix used for resource names. | <code>string</code> | ✓ | | | [prefix](variables.tf#L144) | Prefix used for resource names. | <code>string</code> | ✓ | |
| [project_id](variables.tf#L166) | Project id. | <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> | | [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> | | [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> | | [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> | | [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> | | [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> | | [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> | | [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#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](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#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_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#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](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#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_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#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](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#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> | | [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#L211) | Services to be enabled for the project. | <code>list&#40;string&#41;</code> | | <code>&#91;&#93;</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#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> | | [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 ## Outputs

View File

@ -48,15 +48,18 @@ labels:
# [opt] Org policy overrides defined at project level # [opt] Org policy overrides defined at project level
org_policies: org_policies:
constraints/compute.disableGuestAttributesAccess: compute.disableGuestAttributesAccess:
enforce: true rules:
constraints/compute.trustedImageProjects: - enforce: true
allow: compute.trustedImageProjects:
values: rules:
- allow:
values:
- projects/fast-dev-iac-core-0 - projects/fast-dev-iac-core-0
constraints/compute.vmExternalIpAccess: compute.vmExternalIpAccess:
deny: rules:
all: true - deny:
all: true
# [opt] Prefix - overrides default if set # [opt] Prefix - overrides default if set
prefix: test1 prefix: test1

View File

@ -119,19 +119,6 @@ variable "org_policies" {
type = map(object({ type = map(object({
inherit_from_parent = optional(bool) # for list policies only. inherit_from_parent = optional(bool) # for list policies only.
reset = optional(bool) 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({ rules = optional(list(object({
allow = optional(object({ allow = optional(object({
all = optional(bool) all = optional(bool)
@ -141,13 +128,13 @@ variable "org_policies" {
all = optional(bool) all = optional(bool)
values = optional(list(string)) values = optional(list(string))
})) }))
enforce = optional(bool, true) # for boolean policies only. enforce = optional(bool) # for boolean policies only.
condition = object({ condition = optional(object({
description = optional(string) description = optional(string)
expression = optional(string) expression = optional(string)
location = optional(string) location = optional(string)
title = optional(string) title = optional(string)
}) }), {})
})), []) })), [])
})) }))
default = {} 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"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with 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 # specify project-level org policies here if you need them
# policy_boolean = { # policy_boolean = {
# "constraints/compute.disableGuestAttributesAccess" = true # "compute.disableGuestAttributesAccess" = true
# } # }
# policy_list = { # policy_list = {
# "constraints/compute.trustedImageProjects" = { # "compute.trustedImageProjects" = {
# inherit_from_parent = null # inherit_from_parent = null
# suggested_value = null # suggested_value = null
# status = true # 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"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -227,8 +227,8 @@ module "folder-apps" {
name = "apps" name = "apps"
org_policies = { org_policies = {
# prevent VMs with public IPs in the apps folder # prevent VMs with public IPs in the apps folder
"constraints/compute.vmExternalIpAccess" = { "compute.vmExternalIpAccess" = {
deny = { all = true } rules = [{ deny = { all = true } }]
} }
} }
} }

View File

@ -28,8 +28,8 @@ module "branch-sandbox-folder" {
"roles/resourcemanager.projectCreator" = [local.automation_sas_iam.sandbox] "roles/resourcemanager.projectCreator" = [local.automation_sas_iam.sandbox]
} }
org_policies = { org_policies = {
"constraints/sql.restrictPublicIp" = { enforce = false } "sql.restrictPublicIp" = { rules = [{ enforce = false }] }
"constraints/compute.vmExternalIpAccess" = { allow = { all = true } } "compute.vmExternalIpAccess" = { rules = [{ allow = { all = true } }] }
} }
tag_bindings = { tag_bindings = {
context = var.tags.values["${var.tags.names.context}/sandbox"] 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 # sample subset of useful organization policies, edit to suit requirements
compute.disableGuestAttributesAccess: compute.disableGuestAttributesAccess:
enforce: true rules:
- enforce: true
compute.requireOsLogin: compute.requireOsLogin:
enforce: true rules:
- enforce: true
compute.restrictLoadBalancerCreationForTypes: compute.restrictLoadBalancerCreationForTypes:
allow: rules:
values: - allow:
- in:INTERNAL values:
- in:INTERNAL
compute.skipDefaultNetworkCreation: compute.skipDefaultNetworkCreation:
enforce: true rules:
- enforce: true
compute.vmExternalIpAccess: compute.vmExternalIpAccess:
deny: rules:
all: true - deny:
all: true
# compute.disableInternetNetworkEndpointGroup: # compute.disableInternetNetworkEndpointGroup:
# enforce: true # rules:
# - enforce: true
# compute.disableNestedVirtualization: # compute.disableNestedVirtualization:
# enforce: true # rules:
# - enforce: true
# compute.disableSerialPortAccess: # compute.disableSerialPortAccess:
# enforce: true # rules:
# - enforce: true
# compute.restrictCloudNATUsage: # compute.restrictCloudNATUsage:
# deny: # rules:
# all: true # - deny:
# all: true
# compute.restrictDedicatedInterconnectUsage: # compute.restrictDedicatedInterconnectUsage:
# deny: # rules:
# all: true # - deny:
# all: true
# compute.restrictPartnerInterconnectUsage: # compute.restrictPartnerInterconnectUsage:
# deny: # rules:
# all: true # - deny:
# all: true
# compute.restrictProtocolForwardingCreationForTypes: # compute.restrictProtocolForwardingCreationForTypes:
# deny: # rules:
# all: true # - deny:
# all: true
# compute.restrictSharedVpcHostProjects: # compute.restrictSharedVpcHostProjects:
# deny: # rules:
# all: true # - deny:
# all: true
# compute.restrictSharedVpcSubnetworks: # compute.restrictSharedVpcSubnetworks:
# deny: # rules:
# all: true # - deny:
# all: true
# compute.restrictVpcPeering: # compute.restrictVpcPeering:
# deny: # rules:
# all: true # - deny:
# all: true
# compute.restrictVpnPeerIPs: # compute.restrictVpnPeerIPs:
# deny: # rules:
# all: true # - deny:
# all: true
# compute.restrictXpnProjectLienRemoval: # compute.restrictXpnProjectLienRemoval:
# enforce: true # rules:
# - enforce: true
# compute.setNewProjectDefaultToZonalDNSOnly: # compute.setNewProjectDefaultToZonalDNSOnly:
# enforce: true # rules:
# - enforce: true
# compute.vmCanIpForward: # compute.vmCanIpForward:
# deny: # rules:
# all: true # - deny:
# all: true

View File

@ -3,10 +3,13 @@
# sample subset of useful organization policies, edit to suit requirements # sample subset of useful organization policies, edit to suit requirements
iam.automaticIamGrantsForDefaultServiceAccounts: iam.automaticIamGrantsForDefaultServiceAccounts:
enforce: true rules:
- enforce: true
iam.disableServiceAccountKeyCreation: iam.disableServiceAccountKeyCreation:
enforce: true rules:
- enforce: true
iam.disableServiceAccountKeyUpload: iam.disableServiceAccountKeyUpload:
enforce: true rules:
- enforce: true

View File

@ -3,24 +3,29 @@
# sample subset of useful organization policies, edit to suit requirements # sample subset of useful organization policies, edit to suit requirements
run.allowedIngress: run.allowedIngress:
allow: rules:
values: - allow:
- is:internal values:
- is:internal
# run.allowedVPCEgress: # run.allowedVPCEgress:
# allow: # rules:
# values: # - allow:
# values:
# - is:private-ranges-only # - is:private-ranges-only
# cloudfunctions.allowedIngressSettings: # cloudfunctions.allowedIngressSettings:
# allow: # rules:
# values: # - allow:
# - is:ALLOW_INTERNAL_ONLY # values:
# - is:ALLOW_INTERNAL_ONLY
# cloudfunctions.allowedVpcConnectorEgressSettings: # cloudfunctions.allowedVpcConnectorEgressSettings:
# allow: # rules:
# values: # - allow:
# - is:PRIVATE_RANGES_ONLY # values:
# - is:PRIVATE_RANGES_ONLY
# cloudfunctions.requireVPCConnector: # cloudfunctions.requireVPCConnector:
# enforce: true # rules:
# - enforce: true

View File

@ -3,7 +3,9 @@
# sample subset of useful organization policies, edit to suit requirements # sample subset of useful organization policies, edit to suit requirements
sql.restrictAuthorizedNetworks: sql.restrictAuthorizedNetworks:
enforce: true rules:
- enforce: true
sql.restrictPublicIp: sql.restrictPublicIp:
enforce: true rules:
- enforce: true

View File

@ -3,4 +3,5 @@
# sample subset of useful organization policies, edit to suit requirements # sample subset of useful organization policies, edit to suit requirements
storage.uniformBucketLevelAccess: 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"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with 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] "roles/resourcemanager.projectCreator" = [module.branch-sandbox-sa.0.iam_email]
} }
org_policies = { org_policies = {
"constraints/sql.restrictPublicIp" = { enforce = false } "sql.restrictPublicIp" = { rules = [{ enforce = false }] }
"constraints/compute.vmExternalIpAccess" = { allow = { all = true } } "compute.vmExternalIpAccess" = { rules = [{ allow = { all = true } }] }
} }
tag_bindings = { tag_bindings = {
context = try( context = try(

View File

@ -3,71 +3,90 @@
# sample subset of useful organization policies, edit to suit requirements # sample subset of useful organization policies, edit to suit requirements
compute.disableGuestAttributesAccess: compute.disableGuestAttributesAccess:
enforce: true rules:
- enforce: true
compute.requireOsLogin: compute.requireOsLogin:
enforce: true rules:
- enforce: true
compute.restrictLoadBalancerCreationForTypes: compute.restrictLoadBalancerCreationForTypes:
allow: rules:
values: - allow:
- in:INTERNAL values:
- in:INTERNAL
compute.skipDefaultNetworkCreation: compute.skipDefaultNetworkCreation:
enforce: true rules:
- enforce: true
compute.vmExternalIpAccess: compute.vmExternalIpAccess:
deny: rules:
all: true - deny:
all: true
# compute.disableInternetNetworkEndpointGroup: # compute.disableInternetNetworkEndpointGroup:
# enforce: true # rules:
# - enforce: true
# compute.disableNestedVirtualization: # compute.disableNestedVirtualization:
# enforce: true # rules:
# - enforce: true
# compute.disableSerialPortAccess: # compute.disableSerialPortAccess:
# enforce: true # rules:
# - enforce: true
# compute.restrictCloudNATUsage: # compute.restrictCloudNATUsage:
# deny: # rules:
# all: true # - deny:
# all: true
# compute.restrictDedicatedInterconnectUsage: # compute.restrictDedicatedInterconnectUsage:
# deny: # rules:
# all: true # - deny:
# all: true
# compute.restrictPartnerInterconnectUsage: # compute.restrictPartnerInterconnectUsage:
# deny: # rules:
# all: true # - deny:
# all: true
# compute.restrictProtocolForwardingCreationForTypes: # compute.restrictProtocolForwardingCreationForTypes:
# deny: # rules:
# all: true # - deny:
# all: true
# compute.restrictSharedVpcHostProjects: # compute.restrictSharedVpcHostProjects:
# deny: # rules:
# all: true # - deny:
# all: true
# compute.restrictSharedVpcSubnetworks: # compute.restrictSharedVpcSubnetworks:
# deny: # rules:
# all: true # - deny:
# all: true
# compute.restrictVpcPeering: # compute.restrictVpcPeering:
# deny: # rules:
# all: true # - deny:
# all: true
# compute.restrictVpnPeerIPs: # compute.restrictVpnPeerIPs:
# deny: # rules:
# all: true # - deny:
# all: true
# compute.restrictXpnProjectLienRemoval: # compute.restrictXpnProjectLienRemoval:
# enforce: true # rules:
# - enforce: true
# compute.setNewProjectDefaultToZonalDNSOnly: # compute.setNewProjectDefaultToZonalDNSOnly:
# enforce: true # rules:
# - enforce: true
# compute.vmCanIpForward: # compute.vmCanIpForward:
# deny: # rules:
# all: true # - deny:
# all: true

View File

@ -3,10 +3,13 @@
# sample subset of useful organization policies, edit to suit requirements # sample subset of useful organization policies, edit to suit requirements
iam.automaticIamGrantsForDefaultServiceAccounts: iam.automaticIamGrantsForDefaultServiceAccounts:
enforce: true rules:
- enforce: true
iam.disableServiceAccountKeyCreation: iam.disableServiceAccountKeyCreation:
enforce: true rules:
- enforce: true
iam.disableServiceAccountKeyUpload: iam.disableServiceAccountKeyUpload:
enforce: true rules:
- enforce: true

View File

@ -3,24 +3,29 @@
# sample subset of useful organization policies, edit to suit requirements # sample subset of useful organization policies, edit to suit requirements
run.allowedIngress: run.allowedIngress:
allow: rules:
values: - allow:
- is:internal values:
- is:internal
# run.allowedVPCEgress: # run.allowedVPCEgress:
# allow: # rules:
# values: # - allow:
# values:
# - is:private-ranges-only # - is:private-ranges-only
# cloudfunctions.allowedIngressSettings: # cloudfunctions.allowedIngressSettings:
# allow: # rules:
# values: # - allow:
# - is:ALLOW_INTERNAL_ONLY # values:
# - is:ALLOW_INTERNAL_ONLY
# cloudfunctions.allowedVpcConnectorEgressSettings: # cloudfunctions.allowedVpcConnectorEgressSettings:
# allow: # rules:
# values: # - allow:
# - is:PRIVATE_RANGES_ONLY # values:
# - is:PRIVATE_RANGES_ONLY
# cloudfunctions.requireVPCConnector: # cloudfunctions.requireVPCConnector:
# enforce: true # rules:
# - enforce: true

View File

@ -3,7 +3,9 @@
# sample subset of useful organization policies, edit to suit requirements # sample subset of useful organization policies, edit to suit requirements
sql.restrictAuthorizedNetworks: sql.restrictAuthorizedNetworks:
enforce: true rules:
- enforce: true
sql.restrictPublicIp: sql.restrictPublicIp:
enforce: true rules:
- enforce: true

View File

@ -3,4 +3,5 @@
# sample subset of useful organization policies, edit to suit requirements # sample subset of useful organization policies, edit to suit requirements
storage.uniformBucketLevelAccess: 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"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with 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 # sample subset of useful organization policies, edit to suit requirements
org_policies = { org_policies = {
"iam.allowedPolicyMemberDomains" = { allow = { values = local.all_drs_domains } } "iam.allowedPolicyMemberDomains" = {
rules = [
{ allow = { values = local.all_drs_domains } }
]
}
#"gcp.resourceLocations" = { #"gcp.resourceLocations" = {
# allow = { values = local.allowed_regions } # allow = { values = local.allowed_regions }

View File

@ -48,15 +48,18 @@ labels:
# [opt] Org policy overrides defined at project level # [opt] Org policy overrides defined at project level
org_policies: org_policies:
constraints/compute.disableGuestAttributesAccess: compute.disableGuestAttributesAccess:
enforce: true rules:
constraints/compute.trustedImageProjects: - enforce: true
allow: compute.trustedImageProjects:
values: rules:
- allow:
values:
- projects/fast-dev-iac-core-0 - projects/fast-dev-iac-core-0
constraints/compute.vmExternalIpAccess: compute.vmExternalIpAccess:
deny: rules:
all: true - deny:
all: true
# [opt] Service account to create for the project and their roles on the project # [opt] Service account to create for the project and their roles on the project
# in name => [roles] format # in name => [roles] format

View File

@ -42,40 +42,46 @@ module "folder" {
name = "Folder name" name = "Folder name"
org_policies = { org_policies = {
"compute.disableGuestAttributesAccess" = { "compute.disableGuestAttributesAccess" = {
enforce = true rules = [{ enforce = true }]
} }
"constraints/compute.skipDefaultNetworkCreation" = { "compute.skipDefaultNetworkCreation" = {
enforce = true rules = [{ enforce = true }]
} }
"iam.disableServiceAccountKeyCreation" = { "iam.disableServiceAccountKeyCreation" = {
enforce = true rules = [{ enforce = true }]
} }
"iam.disableServiceAccountKeyUpload" = { "iam.disableServiceAccountKeyUpload" = {
enforce = false
rules = [ rules = [
{ {
condition = { condition = {
expression = "resource.matchTagId(\"tagKeys/1234\", \"tagValues/1234\")" expression = "resource.matchTagId('tagKeys/1234', 'tagValues/1234')"
title = "condition" title = "condition"
description = "test condition" description = "test condition"
location = "somewhere" location = "somewhere"
} }
enforce = true enforce = true
},
{
enforce = false
} }
] ]
} }
"constraints/iam.allowedPolicyMemberDomains" = { "iam.allowedPolicyMemberDomains" = {
allow = { rules = [{
values = ["C0xxxxxxx", "C0yyyyyyy"] allow = {
} values = ["C0xxxxxxx", "C0yyyyyyy"]
}
}]
} }
"constraints/compute.trustedImageProjects" = { "compute.trustedImageProjects" = {
allow = { rules = [{
values = ["projects/my-project"] allow = {
} values = ["projects/my-project"]
}
}]
} }
"constraints/compute.vmExternalIpAccess" = { "compute.vmExternalIpAccess" = {
deny = { all = true } 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_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> | | [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> | | [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](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#L181) | Path containing org policies in YAML format. | <code>string</code> | | <code>null</code> | | [org_policies_data_path](variables.tf#L168) | 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> | | [parent](variables.tf#L174) | 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> | | [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 ## 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"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -28,16 +28,6 @@ locals {
k => { k => {
inherit_from_parent = try(v.inherit_from_parent, null) inherit_from_parent = try(v.inherit_from_parent, null)
reset = try(v.reset, 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 = [ rules = [
for r in try(v.rules, []) : { for r in try(v.rules, []) : {
allow = can(r.allow) ? { allow = can(r.allow) ? {
@ -48,7 +38,7 @@ locals {
all = try(r.deny.all, null) all = try(r.deny.all, null)
values = try(r.deny.values, null) values = try(r.deny.values, null)
} : null } : null
enforce = try(r.enforce, true) enforce = try(r.enforce, null)
condition = { condition = {
description = try(r.condition.description, null) description = try(r.condition.description, null)
expression = try(r.condition.expression, null) expression = try(r.condition.expression, null)
@ -67,8 +57,9 @@ locals {
k => merge(v, { k => merge(v, {
name = "${local.folder.name}/policies/${k}" name = "${local.folder.name}/policies/${k}"
parent = local.folder.name parent = local.folder.name
is_boolean_policy = (
is_boolean_policy = v.allow == null && v.deny == null alltrue([for r in v.rules : r.allow == null && r.deny == null])
)
has_values = ( has_values = (
length(coalesce(try(v.allow.values, []), [])) > 0 || length(coalesce(try(v.allow.values, []), [])) > 0 ||
length(coalesce(try(v.deny.values, []), [])) > 0 length(coalesce(try(v.deny.values, []), [])) > 0
@ -90,11 +81,9 @@ resource "google_org_policy_policy" "default" {
for_each = local.org_policies for_each = local.org_policies
name = each.value.name name = each.value.name
parent = each.value.parent parent = each.value.parent
spec { spec {
inherit_from_parent = each.value.inherit_from_parent inherit_from_parent = each.value.inherit_from_parent
reset = each.value.reset reset = each.value.reset
dynamic "rules" { dynamic "rules" {
for_each = each.value.rules for_each = each.value.rules
iterator = rule iterator = rule
@ -106,11 +95,14 @@ resource "google_org_policy_policy" "default" {
? upper(tostring(rule.value.enforce)) ? upper(tostring(rule.value.enforce))
: null : null
) )
condition { dynamic "condition" {
description = rule.value.condition.description for_each = rule.value.condition.expression != null ? [1] : []
expression = rule.value.condition.expression content {
location = rule.value.condition.location description = rule.value.condition.description
title = rule.value.condition.title expression = rule.value.condition.expression
location = rule.value.condition.location
title = rule.value.condition.title
}
} }
dynamic "values" { dynamic "values" {
for_each = rule.value.has_values ? [1] : [] 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"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -143,19 +143,6 @@ variable "org_policies" {
type = map(object({ type = map(object({
inherit_from_parent = optional(bool) # for list policies only. inherit_from_parent = optional(bool) # for list policies only.
reset = optional(bool) 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({ rules = optional(list(object({
allow = optional(object({ allow = optional(object({
all = optional(bool) all = optional(bool)
@ -165,13 +152,13 @@ variable "org_policies" {
all = optional(bool) all = optional(bool)
values = optional(list(string)) values = optional(list(string))
})) }))
enforce = optional(bool, true) # for boolean policies only. enforce = optional(bool) # for boolean policies only.
condition = object({ condition = optional(object({
description = optional(string) description = optional(string)
expression = optional(string) expression = optional(string)
location = optional(string) location = optional(string)
title = optional(string) title = optional(string)
}) }), {})
})), []) })), [])
})) }))
default = {} default = {}

View File

@ -25,50 +25,77 @@ module "org" {
iam_additive_members = { iam_additive_members = {
"user:compute@example.org" = ["roles/compute.admin", "roles/container.viewer"] "user:compute@example.org" = ["roles/compute.admin", "roles/container.viewer"]
} }
tags = {
allowexternal = {
description = "Allow external identities."
values = {
true = {}, false = {}
}
}
}
org_policies = { org_policies = {
"custom.gkeEnableAutoUpgrade" = { "custom.gkeEnableAutoUpgrade" = {
enforce = true rules = [{ enforce = true }]
} }
"compute.disableGuestAttributesAccess" = { "compute.disableGuestAttributesAccess" = {
enforce = true rules = [{ enforce = true }]
} }
"constraints/compute.skipDefaultNetworkCreation" = { "compute.skipDefaultNetworkCreation" = {
enforce = true rules = [{ enforce = true }]
} }
"iam.disableServiceAccountKeyCreation" = { "iam.disableServiceAccountKeyCreation" = {
enforce = true rules = [{ enforce = true }]
} }
"iam.disableServiceAccountKeyUpload" = { "iam.disableServiceAccountKeyUpload" = {
enforce = false
rules = [ rules = [
{ {
condition = { condition = {
expression = "resource.matchTagId(\"tagKeys/1234\", \"tagValues/1234\")" expression = "resource.matchTagId('tagKeys/1234', 'tagValues/1234')"
title = "condition" title = "condition"
description = "test condition" description = "test condition"
location = "somewhere" location = "somewhere"
} }
enforce = true enforce = true
},
{
enforce = false
} }
] ]
} }
"constraints/iam.allowedPolicyMemberDomains" = { "iam.allowedPolicyMemberDomains" = {
allow = { rules = [
values = ["C0xxxxxxx", "C0yyyyyyy"] {
} 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 = { "compute.trustedImageProjects" = {
values = ["projects/my-project"] rules = [{
} allow = {
values = ["projects/my-project"]
}
}]
} }
"constraints/compute.vmExternalIpAccess" = { "compute.vmExternalIpAccess" = {
deny = { all = true } rules = [{ deny = { all = true } }]
} }
} }
} }
# tftest modules=1 resources=13 inventory=basic.yaml # tftest modules=1 resources=16 inventory=basic.yaml
``` ```
## IAM ## IAM
@ -111,7 +138,7 @@ module "org" {
# not necessarily to enforce on the org level, policy may be applied on folder/project levels # not necessarily to enforce on the org level, policy may be applied on folder/project levels
org_policies = { org_policies = {
"custom.gkeEnableAutoUpgrade" = { "custom.gkeEnableAutoUpgrade" = {
enforce = true rules = [{ enforce = true }]
} }
} }
} }
@ -131,7 +158,7 @@ module "org" {
org_policy_custom_constraints_data_path = "configs/custom-constraints" org_policy_custom_constraints_data_path = "configs/custom-constraints"
org_policies = { org_policies = {
"custom.gkeEnableAutoUpgrade" = { "custom.gkeEnableAutoUpgrade" = {
enforce = true rules = [{ enforce = true }]
} }
} }
} }
@ -447,7 +474,7 @@ module "org" {
| name | description | type | required | default | | 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> | | [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> | | [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> | | [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_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> | | [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> | | [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](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#L220) | Path containing org policies in YAML format. | <code>string</code> | | <code>null</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#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](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#L240) | Path containing org policy custom constraints in YAML format. | <code>string</code> | | <code>null</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#L255) | Tag bindings for this organization, in key => tag value id format. | <code>map&#40;string&#41;</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#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> | | [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 ## 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"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -28,16 +28,6 @@ locals {
k => { k => {
inherit_from_parent = try(v.inherit_from_parent, null) inherit_from_parent = try(v.inherit_from_parent, null)
reset = try(v.reset, 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 = [ rules = [
for r in try(v.rules, []) : { for r in try(v.rules, []) : {
allow = can(r.allow) ? { allow = can(r.allow) ? {
@ -48,7 +38,7 @@ locals {
all = try(r.deny.all, null) all = try(r.deny.all, null)
values = try(r.deny.values, null) values = try(r.deny.values, null)
} : null } : null
enforce = try(r.enforce, true) enforce = try(r.enforce, null)
condition = { condition = {
description = try(r.condition.description, null) description = try(r.condition.description, null)
expression = try(r.condition.expression, null) expression = try(r.condition.expression, null)
@ -67,8 +57,9 @@ locals {
k => merge(v, { k => merge(v, {
name = "${var.organization_id}/policies/${k}" name = "${var.organization_id}/policies/${k}"
parent = var.organization_id parent = var.organization_id
is_boolean_policy = (
is_boolean_policy = v.allow == null && v.deny == null alltrue([for r in v.rules : r.allow == null && r.deny == null])
)
has_values = ( has_values = (
length(coalesce(try(v.allow.values, []), [])) > 0 || length(coalesce(try(v.allow.values, []), [])) > 0 ||
length(coalesce(try(v.deny.values, []), [])) > 0 length(coalesce(try(v.deny.values, []), [])) > 0
@ -90,11 +81,9 @@ resource "google_org_policy_policy" "default" {
for_each = local.org_policies for_each = local.org_policies
name = each.value.name name = each.value.name
parent = each.value.parent parent = each.value.parent
spec { spec {
inherit_from_parent = each.value.inherit_from_parent inherit_from_parent = each.value.inherit_from_parent
reset = each.value.reset reset = each.value.reset
dynamic "rules" { dynamic "rules" {
for_each = each.value.rules for_each = each.value.rules
iterator = rule iterator = rule
@ -106,11 +95,14 @@ resource "google_org_policy_policy" "default" {
? upper(tostring(rule.value.enforce)) ? upper(tostring(rule.value.enforce))
: null : null
) )
condition { dynamic "condition" {
description = rule.value.condition.description for_each = rule.value.condition.expression != null ? [1] : []
expression = rule.value.condition.expression content {
location = rule.value.condition.location description = rule.value.condition.description
title = rule.value.condition.title expression = rule.value.condition.expression
location = rule.value.condition.location
title = rule.value.condition.title
}
} }
dynamic "values" { dynamic "values" {
for_each = rule.value.has_values ? [1] : [] 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 = [ depends_on = [
google_organization_iam_audit_config.config, google_organization_iam_audit_config.config,
google_organization_iam_binding.authoritative, 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"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -183,18 +183,6 @@ variable "org_policies" {
type = map(object({ type = map(object({
inherit_from_parent = optional(bool) # for list policies only. inherit_from_parent = optional(bool) # for list policies only.
reset = optional(bool) 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({ rules = optional(list(object({
allow = optional(object({ allow = optional(object({
all = optional(bool) all = optional(bool)
@ -204,13 +192,13 @@ variable "org_policies" {
all = optional(bool) all = optional(bool)
values = optional(list(string)) values = optional(list(string))
})) }))
enforce = optional(bool, true) # for boolean policies only. enforce = optional(bool) # for boolean policies only.
condition = object({ condition = optional(object({
description = optional(string) description = optional(string)
expression = optional(string) expression = optional(string)
location = optional(string) location = optional(string)
title = optional(string) title = optional(string)
}) }), {})
})), []) })), [])
})) }))
default = {} default = {}

View File

@ -243,40 +243,46 @@ module "project" {
prefix = "foo" prefix = "foo"
org_policies = { org_policies = {
"compute.disableGuestAttributesAccess" = { "compute.disableGuestAttributesAccess" = {
enforce = true rules = [{ enforce = true }]
} }
"constraints/compute.skipDefaultNetworkCreation" = { "compute.skipDefaultNetworkCreation" = {
enforce = true rules = [{ enforce = true }]
} }
"iam.disableServiceAccountKeyCreation" = { "iam.disableServiceAccountKeyCreation" = {
enforce = true rules = [{ enforce = true }]
} }
"iam.disableServiceAccountKeyUpload" = { "iam.disableServiceAccountKeyUpload" = {
enforce = false
rules = [ rules = [
{ {
condition = { condition = {
expression = "resource.matchTagId(\"tagKeys/1234\", \"tagValues/1234\")" expression = "resource.matchTagId('tagKeys/1234', 'tagValues/1234')"
title = "condition" title = "condition"
description = "test condition" description = "test condition"
location = "somewhere" location = "somewhere"
} }
enforce = true enforce = true
},
{
enforce = false
} }
] ]
} }
"constraints/iam.allowedPolicyMemberDomains" = { "iam.allowedPolicyMemberDomains" = {
allow = { rules = [{
values = ["C0xxxxxxx", "C0yyyyyyy"] allow = {
} values = ["C0xxxxxxx", "C0yyyyyyy"]
}
}]
} }
"constraints/compute.trustedImageProjects" = { "compute.trustedImageProjects" = {
allow = { rules = [{
values = ["projects/my-project"] allow = {
} values = ["projects/my-project"]
}
}]
} }
"constraints/compute.vmExternalIpAccess" = { "compute.vmExternalIpAccess" = {
deny = { all = true } rules = [{ deny = { all = true } }]
} }
} }
} }
@ -306,36 +312,42 @@ module "project" {
```yaml ```yaml
# tftest-file id=boolean path=configs/org-policies/boolean.yaml # tftest-file id=boolean path=configs/org-policies/boolean.yaml
compute.disableGuestAttributesAccess: compute.disableGuestAttributesAccess:
enforce: true rules:
constraints/compute.skipDefaultNetworkCreation: - enforce: true
enforce: true compute.skipDefaultNetworkCreation:
rules:
- enforce: true
iam.disableServiceAccountKeyCreation: iam.disableServiceAccountKeyCreation:
enforce: true rules:
- enforce: true
iam.disableServiceAccountKeyUpload: iam.disableServiceAccountKeyUpload:
enforce: false
rules: rules:
- condition: - condition:
description: test condition description: test condition
expression: resource.matchTagId("tagKeys/1234", "tagValues/1234") expression: resource.matchTagId('tagKeys/1234', 'tagValues/1234')
location: somewhere location: somewhere
title: condition title: condition
enforce: true enforce: true
- enforce: false
``` ```
```yaml ```yaml
# tftest-file id=list path=configs/org-policies/list.yaml # tftest-file id=list path=configs/org-policies/list.yaml
constraints/compute.trustedImageProjects: compute.trustedImageProjects:
allow: rules:
values: - allow:
- projects/my-project values:
constraints/compute.vmExternalIpAccess: - projects/my-project
deny: compute.vmExternalIpAccess:
all: true rules:
constraints/iam.allowedPolicyMemberDomains: - deny:
allow: all: true
values: iam.allowedPolicyMemberDomains:
- C0xxxxxxx rules:
- C0yyyyyyy - 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_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> | | [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> | | [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](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#L185) | Path containing org policies in YAML format. | <code>string</code> | | <code>null</code> | | [org_policies_data_path](variables.tf#L172) | 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](variables.tf#L178) | 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_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#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> | | [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#L212) | Parent folder or organization in 'folders/folder_id' or 'organizations/org_id' format. | <code>string</code> | | <code>null</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#L222) | Optional prefix used to generate project id and name. | <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#L232) | Create project. When set to false, uses a data source to reference existing project. | <code>bool</code> | | <code>true</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#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_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#L250) | Cloud KMS encryption key in {SERVICE => [KEY_URL]} format. | <code>map&#40;list&#40;string&#41;&#41;</code> | | <code>&#123;&#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#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_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#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> | | [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#L270) | Service APIs to enable. | <code>list&#40;string&#41;</code> | | <code>&#91;&#93;</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#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_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#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> | | [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#L295) | Allows the underlying resources to be destroyed without destroying the project itself. | <code>bool</code> | | <code>false</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#L301) | Tag bindings for this project, in key => tag value id format. | <code>map&#40;string&#41;</code> | | <code>null</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 ## 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"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -28,16 +28,6 @@ locals {
k => { k => {
inherit_from_parent = try(v.inherit_from_parent, null) inherit_from_parent = try(v.inherit_from_parent, null)
reset = try(v.reset, 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 = [ rules = [
for r in try(v.rules, []) : { for r in try(v.rules, []) : {
allow = can(r.allow) ? { allow = can(r.allow) ? {
@ -48,7 +38,7 @@ locals {
all = try(r.deny.all, null) all = try(r.deny.all, null)
values = try(r.deny.values, null) values = try(r.deny.values, null)
} : null } : null
enforce = try(r.enforce, true) enforce = try(r.enforce, null)
condition = { condition = {
description = try(r.condition.description, null) description = try(r.condition.description, null)
expression = try(r.condition.expression, null) expression = try(r.condition.expression, null)
@ -67,8 +57,9 @@ locals {
k => merge(v, { k => merge(v, {
name = "projects/${local.project.project_id}/policies/${k}" name = "projects/${local.project.project_id}/policies/${k}"
parent = "projects/${local.project.project_id}" parent = "projects/${local.project.project_id}"
is_boolean_policy = (
is_boolean_policy = v.allow == null && v.deny == null alltrue([for r in v.rules : r.allow == null && r.deny == null])
)
has_values = ( has_values = (
length(coalesce(try(v.allow.values, []), [])) > 0 || length(coalesce(try(v.allow.values, []), [])) > 0 ||
length(coalesce(try(v.deny.values, []), [])) > 0 length(coalesce(try(v.deny.values, []), [])) > 0
@ -90,11 +81,9 @@ resource "google_org_policy_policy" "default" {
for_each = local.org_policies for_each = local.org_policies
name = each.value.name name = each.value.name
parent = each.value.parent parent = each.value.parent
spec { spec {
inherit_from_parent = each.value.inherit_from_parent inherit_from_parent = each.value.inherit_from_parent
reset = each.value.reset reset = each.value.reset
dynamic "rules" { dynamic "rules" {
for_each = each.value.rules for_each = each.value.rules
iterator = rule iterator = rule
@ -106,11 +95,14 @@ resource "google_org_policy_policy" "default" {
? upper(tostring(rule.value.enforce)) ? upper(tostring(rule.value.enforce))
: null : null
) )
condition { dynamic "condition" {
description = rule.value.condition.description for_each = rule.value.condition.expression != null ? [1] : []
expression = rule.value.condition.expression content {
location = rule.value.condition.location description = rule.value.condition.description
title = rule.value.condition.title expression = rule.value.condition.expression
location = rule.value.condition.location
title = rule.value.condition.title
}
} }
dynamic "values" { dynamic "values" {
for_each = rule.value.has_values ? [1] : [] 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"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -147,19 +147,6 @@ variable "org_policies" {
type = map(object({ type = map(object({
inherit_from_parent = optional(bool) # for list policies only. inherit_from_parent = optional(bool) # for list policies only.
reset = optional(bool) 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({ rules = optional(list(object({
allow = optional(object({ allow = optional(object({
all = optional(bool) all = optional(bool)
@ -169,13 +156,13 @@ variable "org_policies" {
all = optional(bool) all = optional(bool)
values = optional(list(string)) values = optional(list(string))
})) }))
enforce = optional(bool, true) # for boolean policies only. enforce = optional(bool) # for boolean policies only.
condition = object({ condition = optional(object({
description = optional(string) description = optional(string)
expression = optional(string) expression = optional(string)
location = optional(string) location = optional(string)
title = optional(string) title = optional(string)
}) }), {})
})), []) })), [])
})) }))
default = {} default = {}

View File

@ -48,15 +48,14 @@ labels:
# [opt] Org policy overrides defined at project level # [opt] Org policy overrides defined at project level
org_policies: org_policies:
policy_boolean: compute.disableGuestAttributesAccess:
constraints/compute.disableGuestAttributesAccess: true rules:
policy_list: - enforce: true
constraints/compute.trustedImageProjects: compute.trustedImageProjects:
inherit_from_parent: null rules:
status: true - allow:
suggested_value: null values:
values: - projects/fast-prod-iac-core-0
- projects/fast-prod-iac-core-0
# [opt] Prefix - overrides default if set # [opt] Prefix - overrides default if set
prefix: test1 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"); # Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with 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 # [opt] Org policy overrides defined at project level
org_policies: org_policies:
policy_boolean: compute.disableGuestAttributesAccess:
constraints/compute.disableGuestAttributesAccess: true rules:
policy_list: - enforce: true
constraints/compute.trustedImageProjects: compute.trustedImageProjects:
inherit_from_parent: null rules:
status: true - allow:
suggested_value: null values:
values: - projects/fast-prod-iac-core-0
- projects/fast-prod-iac-core-0
# [opt] Service account to create for the project and their roles on the project # [opt] Service account to create for the project and their roles on the project
# in name => [roles] format # 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"); # Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License. # you may not use this file except in compliance with the License.
@ -26,7 +26,7 @@ values:
deny_all: null deny_all: null
enforce: 'TRUE' enforce: 'TRUE'
values: [] values: []
module.folder.google_org_policy_policy.default["constraints/compute.skipDefaultNetworkCreation"]: module.folder.google_org_policy_policy.default["compute.skipDefaultNetworkCreation"]:
spec: spec:
- inherit_from_parent: null - inherit_from_parent: null
reset: null reset: null
@ -36,7 +36,7 @@ values:
deny_all: null deny_all: null
enforce: 'TRUE' enforce: 'TRUE'
values: [] values: []
module.folder.google_org_policy_policy.default["constraints/compute.trustedImageProjects"]: module.folder.google_org_policy_policy.default["compute.trustedImageProjects"]:
spec: spec:
- inherit_from_parent: null - inherit_from_parent: null
reset: null reset: null
@ -49,7 +49,7 @@ values:
- allowed_values: - allowed_values:
- projects/my-project - projects/my-project
denied_values: null denied_values: null
module.folder.google_org_policy_policy.default["constraints/compute.vmExternalIpAccess"]: module.folder.google_org_policy_policy.default["compute.vmExternalIpAccess"]:
spec: spec:
- inherit_from_parent: null - inherit_from_parent: null
reset: null reset: null
@ -59,7 +59,7 @@ values:
deny_all: 'TRUE' deny_all: 'TRUE'
enforce: null enforce: null
values: [] values: []
module.folder.google_org_policy_policy.default["constraints/iam.allowedPolicyMemberDomains"]: module.folder.google_org_policy_policy.default["iam.allowedPolicyMemberDomains"]:
spec: spec:
- inherit_from_parent: null - inherit_from_parent: null
reset: null reset: null
@ -91,7 +91,7 @@ values:
- allow_all: null - allow_all: null
condition: condition:
- description: test condition - description: test condition
expression: resource.matchTagId("tagKeys/1234", "tagValues/1234") expression: resource.matchTagId('tagKeys/1234', 'tagValues/1234')
location: somewhere location: somewhere
title: condition title: condition
deny_all: null deny_all: null

View File

@ -1,9 +1,8 @@
org_policies = { org_policies = {
"iam.disableServiceAccountKeyCreation" = { "iam.disableServiceAccountKeyCreation" = {
enforce = true rules = [{ enforce = true }]
} }
"iam.disableServiceAccountKeyUpload" = { "iam.disableServiceAccountKeyUpload" = {
enforce = false
rules = [ rules = [
{ {
condition = { condition = {
@ -13,6 +12,9 @@ org_policies = {
location = "xxx" location = "xxx"
} }
enforce = true enforce = true
},
{
enforce = false
} }
] ]
} }

View File

@ -1,14 +1,15 @@
org_policies = { org_policies = {
"compute.vmExternalIpAccess" = { "compute.vmExternalIpAccess" = {
deny = { all = true } rules = [{ deny = { all = true } }]
} }
"iam.allowedPolicyMemberDomains" = { "iam.allowedPolicyMemberDomains" = {
allow = { rules = [{
values = ["C0xxxxxxx", "C0yyyyyyy"] allow = {
} values = ["C0xxxxxxx", "C0yyyyyyy"]
}
}]
} }
"compute.restrictLoadBalancerCreationForTypes" = { "compute.restrictLoadBalancerCreationForTypes" = {
deny = { values = ["in:EXTERNAL"] }
rules = [ rules = [
{ {
condition = { condition = {
@ -31,6 +32,9 @@ org_policies = {
allow = { allow = {
all = true all = true
} }
},
{
deny = { values = ["in:EXTERNAL"] }
} }
] ]
} }

View File

@ -25,8 +25,8 @@ values:
deny_all: null deny_all: null
enforce: 'TRUE' enforce: 'TRUE'
values: [] values: []
module.org.google_org_policy_policy.default["constraints/compute.skipDefaultNetworkCreation"]: module.org.google_org_policy_policy.default["compute.skipDefaultNetworkCreation"]:
name: organizations/1234567890/policies/constraints/compute.skipDefaultNetworkCreation name: organizations/1234567890/policies/compute.skipDefaultNetworkCreation
parent: organizations/1234567890 parent: organizations/1234567890
spec: spec:
- inherit_from_parent: null - inherit_from_parent: null
@ -37,8 +37,8 @@ values:
deny_all: null deny_all: null
enforce: 'TRUE' enforce: 'TRUE'
values: [] values: []
module.org.google_org_policy_policy.default["constraints/compute.trustedImageProjects"]: module.org.google_org_policy_policy.default["compute.trustedImageProjects"]:
name: organizations/1234567890/policies/constraints/compute.trustedImageProjects name: organizations/1234567890/policies/compute.trustedImageProjects
parent: organizations/1234567890 parent: organizations/1234567890
spec: spec:
- inherit_from_parent: null - inherit_from_parent: null
@ -52,8 +52,8 @@ values:
- allowed_values: - allowed_values:
- projects/my-project - projects/my-project
denied_values: null denied_values: null
module.org.google_org_policy_policy.default["constraints/compute.vmExternalIpAccess"]: module.org.google_org_policy_policy.default["compute.vmExternalIpAccess"]:
name: organizations/1234567890/policies/constraints/compute.vmExternalIpAccess name: organizations/1234567890/policies/compute.vmExternalIpAccess
parent: organizations/1234567890 parent: organizations/1234567890
spec: spec:
- inherit_from_parent: null - inherit_from_parent: null
@ -64,15 +64,30 @@ values:
deny_all: 'TRUE' deny_all: 'TRUE'
enforce: null enforce: null
values: [] values: []
module.org.google_org_policy_policy.default["constraints/iam.allowedPolicyMemberDomains"]: module.org.google_org_policy_policy.default["iam.allowedPolicyMemberDomains"]:
name: organizations/1234567890/policies/constraints/iam.allowedPolicyMemberDomains name: organizations/1234567890/policies/iam.allowedPolicyMemberDomains
parent: organizations/1234567890 parent: organizations/1234567890
spec: spec:
- inherit_from_parent: null - inherit_from_parent: null
reset: null reset: null
rules: 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 - 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 deny_all: null
enforce: null enforce: null
values: values:
@ -102,7 +117,7 @@ values:
- allow_all: null - allow_all: null
condition: condition:
- description: test condition - description: test condition
expression: resource.matchTagId("tagKeys/1234", "tagValues/1234") expression: resource.matchTagId('tagKeys/1234', 'tagValues/1234')
location: somewhere location: somewhere
title: condition title: condition
deny_all: null deny_all: null
@ -141,6 +156,20 @@ values:
member: user:compute@example.org member: user:compute@example.org
org_id: '1234567890' org_id: '1234567890'
role: roles/container.viewer 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: counts:
google_org_policy_policy: 8 google_org_policy_policy: 8
google_organization_iam_binding: 3 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 = { org_policies = {
"iam.disableServiceAccountKeyCreation" = { "iam.disableServiceAccountKeyCreation" = {
enforce = true rules = [{ enforce = true }]
} }
"iam.disableServiceAccountKeyUpload" = { "iam.disableServiceAccountKeyUpload" = {
enforce = false
rules = [ rules = [
{ {
condition = { condition = {
@ -13,6 +12,9 @@ org_policies = {
location = "xxx" location = "xxx"
} }
enforce = true enforce = true
},
{
enforce = false
} }
] ]
} }

View File

@ -1,15 +1,17 @@
org_policies = { org_policies = {
"compute.vmExternalIpAccess" = { "compute.vmExternalIpAccess" = {
deny = { all = true } rules = [{ deny = { all = true } }]
} }
"iam.allowedPolicyMemberDomains" = { "iam.allowedPolicyMemberDomains" = {
inherit_from_parent = true inherit_from_parent = true
allow = { rules = [{
values = ["C0xxxxxxx", "C0yyyyyyy"] allow = {
} values = ["C0xxxxxxx", "C0yyyyyyy"]
}
}]
} }
"compute.restrictLoadBalancerCreationForTypes" = { "compute.restrictLoadBalancerCreationForTypes" = {
deny = { values = ["in:EXTERNAL"] }
rules = [ rules = [
{ {
condition = { condition = {
@ -32,6 +34,9 @@ org_policies = {
allow = { allow = {
all = true 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"); # Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with 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' path = modules_path / module / 'organization-policies.tf'
lines[module] = path.open().readlines() 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) == [ assert list(diff1) == [
'--- \n', '--- project\n',
'+++ \n', '+++ folder\n',
'@@ -14,7 +14,7 @@\n', '@@ -17 +17 @@\n',
' * limitations under the License.\n',
' */\n',
' \n',
'-# tfdoc:file:description Project-level organization policies.\n', '-# tfdoc:file:description Project-level organization policies.\n',
'+# tfdoc:file:description Folder-level organization policies.\n', '+# tfdoc:file:description Folder-level organization policies.\n',
' \n', '@@ -58,2 +58,2 @@\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',
'- name = "projects/${local.project.project_id}/policies/${k}"\n', '- name = "projects/${local.project.project_id}/policies/${k}"\n',
'- parent = "projects/${local.project.project_id}"\n', '- parent = "projects/${local.project.project_id}"\n',
'+ name = "${local.folder.name}/policies/${k}"\n', '+ name = "${local.folder.name}/policies/${k}"\n',
'+ parent = local.folder.name\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) == [ assert list(diff2) == [
'--- \n', '--- folder\n',
'+++ \n', '+++ organization\n',
'@@ -14,7 +14,7 @@\n', '@@ -17 +17 @@\n',
' * limitations under the License.\n',
' */\n',
' \n',
'-# tfdoc:file:description Folder-level organization policies.\n', '-# tfdoc:file:description Folder-level organization policies.\n',
'+# tfdoc:file:description Organization-level organization policies.\n', '+# tfdoc:file:description Organization-level organization policies.\n',
' \n', '@@ -58,2 +58,2 @@\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',
'- name = "${local.folder.name}/policies/${k}"\n', '- name = "${local.folder.name}/policies/${k}"\n',
'- parent = local.folder.name\n', '- parent = local.folder.name\n',
'+ name = "${var.organization_id}/policies/${k}"\n', '+ name = "${var.organization_id}/policies/${k}"\n',
'+ parent = var.organization_id\n', '+ parent = var.organization_id\n',
' \n', '@@ -116,0 +117,8 @@\n',
' is_boolean_policy = v.allow == null && v.deny == null\n',
' has_values = (\n',
'@@ -139,4 +139,13 @@\n',
' }\n',
' }\n',
' }\n',
'+\n',
'+ depends_on = [\n', '+ depends_on = [\n',
'+ google_organization_iam_audit_config.config,\n', '+ google_organization_iam_audit_config.config,\n',
'+ google_organization_iam_binding.authoritative,\n', '+ google_organization_iam_binding.authoritative,\n',
@ -89,5 +63,4 @@ def test_policy_implementation():
'+ google_organization_iam_policy.authoritative,\n', '+ google_organization_iam_policy.authoritative,\n',
'+ google_org_policy_custom_constraint.constraint,\n', '+ google_org_policy_custom_constraint.constraint,\n',
'+ ]\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"); # Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License. # you may not use this file except in compliance with the License.
@ -25,8 +25,8 @@ values:
deny_all: null deny_all: null
enforce: 'TRUE' enforce: 'TRUE'
values: [] values: []
module.project.google_org_policy_policy.default["constraints/compute.skipDefaultNetworkCreation"]: module.project.google_org_policy_policy.default["compute.skipDefaultNetworkCreation"]:
name: projects/foo-project-example/policies/constraints/compute.skipDefaultNetworkCreation name: projects/foo-project-example/policies/compute.skipDefaultNetworkCreation
parent: projects/foo-project-example parent: projects/foo-project-example
spec: spec:
- inherit_from_parent: null - inherit_from_parent: null
@ -37,8 +37,8 @@ values:
deny_all: null deny_all: null
enforce: 'TRUE' enforce: 'TRUE'
values: [] values: []
module.project.google_org_policy_policy.default["constraints/compute.trustedImageProjects"]: module.project.google_org_policy_policy.default["compute.trustedImageProjects"]:
name: projects/foo-project-example/policies/constraints/compute.trustedImageProjects name: projects/foo-project-example/policies/compute.trustedImageProjects
parent: projects/foo-project-example parent: projects/foo-project-example
spec: spec:
- inherit_from_parent: null - inherit_from_parent: null
@ -52,8 +52,8 @@ values:
- allowed_values: - allowed_values:
- projects/my-project - projects/my-project
denied_values: null denied_values: null
module.project.google_org_policy_policy.default["constraints/compute.vmExternalIpAccess"]: module.project.google_org_policy_policy.default["compute.vmExternalIpAccess"]:
name: projects/foo-project-example/policies/constraints/compute.vmExternalIpAccess name: projects/foo-project-example/policies/compute.vmExternalIpAccess
parent: projects/foo-project-example parent: projects/foo-project-example
spec: spec:
- inherit_from_parent: null - inherit_from_parent: null
@ -64,8 +64,8 @@ values:
deny_all: 'TRUE' deny_all: 'TRUE'
enforce: null enforce: null
values: [] values: []
module.project.google_org_policy_policy.default["constraints/iam.allowedPolicyMemberDomains"]: module.project.google_org_policy_policy.default["iam.allowedPolicyMemberDomains"]:
name: projects/foo-project-example/policies/constraints/iam.allowedPolicyMemberDomains name: projects/foo-project-example/policies/iam.allowedPolicyMemberDomains
parent: projects/foo-project-example parent: projects/foo-project-example
spec: spec:
- inherit_from_parent: null - inherit_from_parent: null
@ -102,7 +102,7 @@ values:
- allow_all: null - allow_all: null
condition: condition:
- description: test condition - description: test condition
expression: resource.matchTagId("tagKeys/1234", "tagValues/1234") expression: resource.matchTagId('tagKeys/1234', 'tagValues/1234')
location: somewhere location: somewhere
title: condition title: condition
deny_all: null deny_all: null

View File

@ -1,9 +1,8 @@
org_policies = { org_policies = {
"iam.disableServiceAccountKeyCreation" = { "iam.disableServiceAccountKeyCreation" = {
enforce = true rules = [{ enforce = true }]
} }
"iam.disableServiceAccountKeyUpload" = { "iam.disableServiceAccountKeyUpload" = {
enforce = false
rules = [ rules = [
{ {
condition = { condition = {
@ -13,6 +12,9 @@ org_policies = {
location = "xxx" location = "xxx"
} }
enforce = true enforce = true
},
{
enforce = false
} }
] ]
} }

View File

@ -1,15 +1,16 @@
org_policies = { org_policies = {
"compute.vmExternalIpAccess" = { "compute.vmExternalIpAccess" = {
deny = { all = true } rules = [{ deny = { all = true } }]
} }
"iam.allowedPolicyMemberDomains" = { "iam.allowedPolicyMemberDomains" = {
inherit_from_parent = true inherit_from_parent = true
allow = { rules = [{
values = ["C0xxxxxxx", "C0yyyyyyy"] allow = {
} values = ["C0xxxxxxx", "C0yyyyyyy"]
}
}]
} }
"compute.restrictLoadBalancerCreationForTypes" = { "compute.restrictLoadBalancerCreationForTypes" = {
deny = { values = ["in:EXTERNAL"] }
rules = [ rules = [
{ {
condition = { condition = {
@ -32,6 +33,9 @@ org_policies = {
allow = { allow = {
all = true all = true
} }
},
{
deny = { values = ["in:EXTERNAL"] }
} }
] ]
} }