From 254efdd799662ac7f5230a78368882a90147193c Mon Sep 17 00:00:00 2001 From: Julio Castillo Date: Mon, 23 Nov 2020 19:01:02 +0100 Subject: [PATCH] Hierarchical firewall support for organizations --- modules/organization/README.md | 29 ++++++++++++++++ modules/organization/main.tf | 55 +++++++++++++++++++++++++++++++ modules/organization/outputs.tf | 16 +++++++++ modules/organization/variables.tf | 24 ++++++++++++++ 4 files changed, 124 insertions(+) diff --git a/modules/organization/README.md b/modules/organization/README.md index 9547c67d..f7f68a1d 100644 --- a/modules/organization/README.md +++ b/modules/organization/README.md @@ -30,6 +30,35 @@ module "org" { # tftest:modules=1:resources=4 ``` +## Hierarchical firewall rules +```hcl +module "org" { + source = "./modules/organization" + org_id = 11223344 + 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_attachments = { + iap_policy = module.org.firewall_policy_id["iap-policy"] + } +} +# tftest:modules=1:resources=3 +``` + ## Variables diff --git a/modules/organization/main.tf b/modules/organization/main.tf index e331d6ae..d87fcab5 100644 --- a/modules/organization/main.tf +++ b/modules/organization/main.tf @@ -29,6 +29,16 @@ locals { for pair in concat(local.iam_additive_pairs, local.iam_additive_member_pairs) : "${pair.role}-${pair.member}" => pair } + extended_rules = flatten([ + for policy, rules in var.firewall_policies : [ + for rule_name, rule in rules : + merge(rule, { policy = policy, name = rule_name }) + ] + ]) + rules_map = { + for rule in local.extended_rules : + "${rule.policy}-${rule.name}" => rule + } } resource "google_organization_iam_custom_role" "roles" { @@ -144,3 +154,48 @@ resource "google_organization_policy" "list" { } } } + +resource "google_compute_organization_security_policy" "policy" { + provider = google-beta + for_each = var.firewall_policies + + display_name = each.key + parent = "organizations/${var.org_id}" +} + +resource "google_compute_organization_security_policy_rule" "rule" { + provider = google-beta + for_each = local.rules_map + + policy_id = google_compute_organization_security_policy.policy[each.value.policy].id + action = each.value.action + direction = each.value.direction + priority = each.value.priority + target_resources = each.value.target_resources + target_service_accounts = each.value.target_service_accounts + enable_logging = each.value.logging + # preview = each.value.preview + match { + description = each.value.description + config { + src_ip_ranges = each.value.direction == "INGRESS" ? each.value.ranges : null + dest_ip_ranges = each.value.direction == "EGRESS" ? each.value.ranges : null + dynamic "layer4_config" { + for_each = each.value.ports + iterator = port + content { + ip_protocol = port.key + ports = port.value + } + } + } + } +} + +resource "google_compute_organization_security_policy_association" "attachment" { + provider = google-beta + for_each = var.firewall_policy_attachments + name = "organizations/${var.org_id}-${each.key}" + attachment_id = "organizations/${var.org_id}" + policy_id = each.value +} diff --git a/modules/organization/outputs.tf b/modules/organization/outputs.tf index f33d54f1..f6e52441 100644 --- a/modules/organization/outputs.tf +++ b/modules/organization/outputs.tf @@ -26,3 +26,19 @@ output "org_id" { google_organization_policy.list ] } + +output "firewall_policies" { + description = "Map of firewall policy resources created in the organization." + value = { + for name, _ in var.firewall_policies : + name => google_compute_organization_security_policy.policy[name] + } +} + +output "firewall_policy_id" { + description = "Map of firewall policy ids created in the organization." + value = { + for name, _ in var.firewall_policies : + name => google_compute_organization_security_policy.policy[name].id + } +} diff --git a/modules/organization/variables.tf b/modules/organization/variables.tf index 8c69fcbb..1fe3f1bd 100644 --- a/modules/organization/variables.tf +++ b/modules/organization/variables.tf @@ -70,3 +70,27 @@ variable "policy_list" { })) default = {} } + +variable "firewall_policies" { + description = "Hierarchical firewall policies to *create* in the organization." + type = map(map(object({ + description = string + direction = string + action = string + priority = number + ranges = list(string) + ports = map(list(string)) + target_service_accounts = list(string) + target_resources = list(string) + logging = bool + #preview = bool + }))) + default = {} +} + +variable "firewall_policy_attachments" { + description = "List of hierarchical firewall policy IDs to *attach* to the organization" + # set to avoid manual casting with toset() + type = map(string) + default = {} +}