Google Cloud Folder Module
This module allows the creation and management of folders, including support for IAM bindings, organization policies, and hierarchical firewall rules.
Examples
IAM bindings
module "folder" {
source = "./modules/folder"
parent = "organizations/1234567890"
name = "Folder name"
group_iam = {
"cloud-owners@example.org" = [
"roles/owner",
"roles/resourcemanager.projectCreator"
]
}
iam = {
"roles/owner" = ["user:one@example.com"]
}
}
# tftest modules=1 resources=3
Organization policies
module "folder" {
source = "./modules/folder"
parent = "organizations/1234567890"
name = "Folder name"
policy_boolean = {
"constraints/compute.disableGuestAttributesAccess" = true
"constraints/compute.skipDefaultNetworkCreation" = true
}
policy_list = {
"constraints/compute.trustedImageProjects" = {
inherit_from_parent = null
suggested_value = null
status = true
values = ["projects/my-project"]
}
}
}
# tftest modules=1 resources=4
Firewall policy factory
In the same way as for the organization module, the in-built factory allows you to define a single policy, using one file for rules, and an optional file for CIDR range substitution variables. Remember that non-absolute paths are relative to the root module (the folder where you run terraform
).
module "folder" {
source = "./modules/folder"
parent = "organizations/1234567890"
name = "Folder name"
firewall_policy_factory = {
cidr_file = "data/cidrs.yaml"
policy_name = null
rules_file = "data/rules.yaml"
}
firewall_policy_association = {
factory-policy = module.folder.firewall_policy_id["factory"]
}
}
# tftest skip
# cidrs.yaml
rfc1918:
- 10.0.0.0/8
- 172.16.0.0/12
- 192.168.0.0/16
# rules.yaml
allow-admins:
description: Access from the admin subnet to all subnets
direction: INGRESS
action: allow
priority: 1000
ranges:
- $rfc1918
ports:
all: []
target_resources: null
enable_logging: false
allow-ssh-from-iap:
description: Enable SSH from IAP
direction: INGRESS
action: allow
priority: 1002
ranges:
- 35.235.240.0/20
ports:
tcp: ["22"]
target_resources: null
enable_logging: false
Logging Sinks
module "gcs" {
source = "./modules/gcs"
project_id = "my-project"
name = "gcs_sink"
force_destroy = true
}
module "dataset" {
source = "./modules/bigquery-dataset"
project_id = "my-project"
id = "bq_sink"
}
module "pubsub" {
source = "./modules/pubsub"
project_id = "my-project"
name = "pubsub_sink"
}
module "bucket" {
source = "./modules/logging-bucket"
parent_type = "project"
parent = "my-project"
id = "bucket"
}
module "folder-sink" {
source = "./modules/folder"
parent = "folders/657104291943"
name = "my-folder"
logging_sinks = {
warnings = {
type = "storage"
destination = module.gcs.id
filter = "severity=WARNING"
include_children = true
exclusions = {}
}
info = {
type = "bigquery"
destination = module.dataset.id
filter = "severity=INFO"
include_children = true
exclusions = {}
}
notice = {
type = "pubsub"
destination = module.pubsub.id
filter = "severity=NOTICE"
include_children = true
exclusions = {}
}
debug = {
type = "logging"
destination = module.bucket.id
filter = "severity=DEBUG"
include_children = true
exclusions = {
no-compute = "logName:compute"
}
}
}
logging_exclusions = {
no-gce-instances = "resource.type=gce_instance"
}
}
# tftest modules=5 resources=14
Hierarchical firewall policies
module "folder1" {
source = "./modules/folder"
parent = var.organization_id
name = "policy-container"
firewall_policies = {
iap-policy = {
allow-iap-ssh = {
description = "Always allow ssh from IAP"
direction = "INGRESS"
action = "allow"
priority = 100
ranges = ["35.235.240.0/20"]
ports = { tcp = ["22"] }
target_service_accounts = null
target_resources = null
logging = false
}
}
}
firewall_policy_association = {
iap-policy = "iap-policy"
}
}
module "folder2" {
source = "./modules/folder"
parent = var.organization_id
name = "hf2"
firewall_policy_association = {
iap-policy = module.folder1.firewall_policy_id["iap-policy"]
}
}
# tftest modules=2 resources=6
Tags
Refer to the Creating and managing tags documentation for details on usage.
module "org" {
source = "./modules/organization"
organization_id = var.organization_id
tags = {
environment = {
description = "Environment specification."
iam = null
values = {
dev = null
prod = null
}
}
}
}
module "folder" {
source = "./modules/folder"
name = "Test"
parent = module.org.organization_id
tag_bindings = {
env-prod = module.org.tag_values["environment/prod"].id
foo = "tagValues/12345678"
}
}
# tftest modules=2 resources=6
Files
name |
description |
resources |
firewall-policies.tf |
None |
google_compute_firewall_policy · google_compute_firewall_policy_association · google_compute_firewall_policy_rule |
iam.tf |
IAM bindings, roles and audit logging resources. |
google_folder_iam_binding · google_folder_iam_member |
logging.tf |
Log sinks and supporting resources. |
google_bigquery_dataset_iam_member · google_logging_folder_exclusion · google_logging_folder_sink · google_project_iam_member · google_pubsub_topic_iam_member · google_storage_bucket_iam_member |
main.tf |
Module-level locals and resources. |
google_essential_contacts_contact · google_folder |
organization-policies.tf |
Folder-level organization policies. |
google_folder_organization_policy |
outputs.tf |
Module outputs. |
|
tags.tf |
None |
google_tags_tag_binding |
variables.tf |
Module variables. |
|
versions.tf |
Version pins. |
|
Variables
name |
description |
type |
required |
default |
contacts |
List of essential contacts for this resource. Must be in the form EMAIL -> [NOTIFICATION_TYPES]. Valid notification types are ALL, SUSPENSION, SECURITY, TECHNICAL, BILLING, LEGAL, PRODUCT_UPDATES. |
map(list(string)) |
|
{} |
firewall_policies |
Hierarchical firewall policies created in this folder. |
map(map(object({…}))) |
|
{} |
firewall_policy_association |
The hierarchical firewall policy to associate to this folder. Must be either a key in the firewall_policies map or the id of a policy defined somewhere else. |
map(string) |
|
{} |
firewall_policy_factory |
Configuration for the firewall policy factory. |
object({…}) |
|
null |
folder_create |
Create folder. When set to false, uses id to reference an existing folder. |
bool |
|
true |
group_iam |
Authoritative IAM binding for organization groups, in {GROUP_EMAIL => [ROLES]} format. Group emails need to be static. Can be used in combination with the iam variable. |
map(list(string)) |
|
{} |
iam |
IAM bindings in {ROLE => [MEMBERS]} format. |
map(list(string)) |
|
{} |
iam_additive |
Non authoritative IAM bindings, in {ROLE => [MEMBERS]} format. |
map(list(string)) |
|
{} |
iam_additive_members |
IAM additive bindings in {MEMBERS => [ROLE]} format. This might break if members are dynamic values. |
map(list(string)) |
|
{} |
id |
Folder ID in case you use folder_create=false. |
string |
|
null |
logging_exclusions |
Logging exclusions for this folder in the form {NAME -> FILTER}. |
map(string) |
|
{} |
logging_sinks |
Logging sinks to create for this folder. |
map(object({…})) |
|
{} |
name |
Folder name. |
string |
|
null |
parent |
Parent in folders/folder_id or organizations/org_id format. |
string |
|
null |
policy_boolean |
Map of boolean org policies and enforcement value, set value to null for policy restore. |
map(bool) |
|
{} |
policy_list |
Map of list org policies, status is true for allow, false for deny, null for restore. Values can only be used for allow or deny. |
map(object({…})) |
|
{} |
tag_bindings |
Tag bindings for this folder, in key => tag value id format. |
map(string) |
|
null |
Outputs