/** * 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 coalesce(yamldecode(file(f)), tomap({})) : [ for name, rule in coalesce(ruleset, tomap({})) : { 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) } # TODO: deprecate once FAST does not need this anymore _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" }) } ctx = { for k, v in var.context : k => { for kk, vv in v : "${local.ctx_p}${k}:${kk}" => vv } } ctx_p = "$" network = lookup(local.ctx.networks, var.network, var.network) network_name = reverse(split("/", local.network))[0] project_id = lookup(local.ctx.project_ids, var.project_id, var.project_id) # 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 : distinct(flatten([ for range in rule.destination_ranges : try( local.ctx.cidr_ranges_sets[range], local._named_ranges[range], range ) ])) ) rules = { for k, v in rule.rules : k => v } source_ranges = ( try(rule.source_ranges, null) == null ? null : distinct(flatten([ for range in rule.source_ranges : try( local.ctx.cidr_ranges_sets[range], local._named_ranges[range], range ) ])) ) }) } } moved { from = google_compute_firewall.custom-rules to = google_compute_firewall.custom_rules } resource "google_compute_firewall" "custom_rules" { for_each = local.rules project = local.project_id network = local.network name = each.key description = each.value.description direction = each.value.direction source_ranges = ( each.value.source_ranges == null ? ( each.value.direction == "INGRESS" && each.value.sources == null ? ["0.0.0.0/0"] : null ) : [ for r in each.value.source_ranges : lookup(local.ctx.cidr_ranges, r, r) ] ) destination_ranges = ( each.value.destination_ranges == null ? ( each.value.direction == "EGRESS" ? ["0.0.0.0/0"] : null ) : [ for r in each.value.destination_ranges : lookup(local.ctx.cidr_ranges, r, r) ] ) 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 ? null : [ for s in each.value.sources : lookup(local.ctx.iam_principals, s, s) ]) : null ) target_tags = ( !each.value.use_service_accounts ? each.value.targets : null ) target_service_accounts = ( !each.value.use_service_accounts ? null : ( each.value.targets == null ? null : [ for s in each.value.targets : lookup(local.ctx.iam_principals, s, s) ]) ) 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 = try(rule.value.ports, []) } } dynamic "allow" { for_each = each.value.action == "ALLOW" ? each.value.rules : {} iterator = rule content { protocol = rule.value.protocol ports = try(rule.value.ports, []) } } }