cloud-foundation-fabric/modules/net-vpc-firewall/main.tf

170 lines
5.3 KiB
HCL

/**
* Copyright 2024 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
locals {
_factory_rules_folder = try(pathexpand(var.factories_config.rules_folder), null)
# define list of rule files
_factory_rule_files = local._factory_rules_folder == null ? [] : [
for f in try(fileset(local._factory_rules_folder, "**/*.yaml"), []) :
"${local._factory_rules_folder}/${f}"
]
# decode rule files and account for optional attributes
_factory_rule_list = flatten([
for f in local._factory_rule_files : [
for direction, ruleset in yamldecode(file(f)) : [
for name, rule in ruleset : {
name = name
deny = try(rule.deny, false)
rules = try(rule.rules, [{ protocol = "all", ports = null }])
description = try(rule.description, null)
destination_ranges = try(rule.destination_ranges, null)
direction = upper(direction)
disabled = try(rule.disabled, null)
enable_logging = try(rule.enable_logging, null)
priority = try(rule.priority, 1000)
source_ranges = try(rule.source_ranges, null)
sources = try(rule.sources, null)
targets = try(rule.targets, null)
use_service_accounts = try(rule.use_service_accounts, false)
}
]
]
])
_factory_rules = {
for r in local._factory_rule_list : r.name => r
if contains(["EGRESS", "INGRESS"], r.direction)
}
_named_ranges = merge(
(
var.factories_config.cidr_tpl_file != null
? yamldecode(pathexpand(file(var.factories_config.cidr_tpl_file)))
: {}
),
var.named_ranges
)
_rules = merge(
local._factory_rules, local._rules_egress, local._rules_ingress
)
_rules_egress = {
for name, rule in merge(var.egress_rules) :
name => merge(rule, { direction = "EGRESS" })
}
_rules_ingress = {
for name, rule in merge(var.ingress_rules) :
name => merge(rule, { direction = "INGRESS" })
}
# convert rules data to resource format and replace range template variables
rules = {
for name, rule in local._rules :
name => merge(rule, {
action = rule.deny == true ? "DENY" : "ALLOW"
destination_ranges = (
try(rule.destination_ranges, null) == null
? null
: flatten([
for range in rule.destination_ranges :
try(local._named_ranges[range], range)
])
)
rules = { for k, v in rule.rules : k => v }
source_ranges = (
try(rule.source_ranges, null) == null
? null
: flatten([
for range in rule.source_ranges :
try(local._named_ranges[range], range)
])
)
})
}
}
resource "google_compute_firewall" "custom-rules" {
for_each = local.rules
project = var.project_id
network = var.network
name = each.key
description = each.value.description
direction = each.value.direction
source_ranges = (
each.value.direction == "INGRESS"
? (
each.value.source_ranges == null && each.value.sources == null
? ["0.0.0.0/0"]
: each.value.source_ranges
)
#for egress, we will include the source_ranges when provided. Previously, null was forced
: each.value.source_ranges
)
destination_ranges = (
each.value.direction == "EGRESS"
? (
each.value.destination_ranges == null
? ["0.0.0.0/0"]
: each.value.destination_ranges
)
#for ingress, we will include the destination_ranges when provided. Previously, null was forced
: each.value.destination_ranges
)
source_tags = (
each.value.use_service_accounts || each.value.direction == "EGRESS"
? null
: each.value.sources
)
source_service_accounts = (
each.value.use_service_accounts && each.value.direction == "INGRESS"
? each.value.sources
: null
)
target_tags = (
each.value.use_service_accounts ? null : each.value.targets
)
target_service_accounts = (
each.value.use_service_accounts ? each.value.targets : null
)
disabled = each.value.disabled == true
priority = each.value.priority
dynamic "log_config" {
for_each = each.value.enable_logging == null ? [] : [""]
content {
metadata = (
try(each.value.enable_logging.include_metadata, null) == true
? "INCLUDE_ALL_METADATA"
: "EXCLUDE_ALL_METADATA"
)
}
}
dynamic "deny" {
for_each = each.value.action == "DENY" ? each.value.rules : {}
iterator = rule
content {
protocol = rule.value.protocol
ports = rule.value.ports
}
}
dynamic "allow" {
for_each = each.value.action == "ALLOW" ? each.value.rules : {}
iterator = rule
content {
protocol = rule.value.protocol
ports = rule.value.ports
}
}
}