diff --git a/modules/net-cloudnat/README.md b/modules/net-cloudnat/README.md
index b8b8b614e..dd1e88922 100644
--- a/modules/net-cloudnat/README.md
+++ b/modules/net-cloudnat/README.md
@@ -189,21 +189,22 @@ module "nat" {
| name | description | type | required | default |
|---|---|:---:|:---:|:---:|
-| [name](variables.tf#L107) | Name of the Cloud NAT resource. | string | ✓ | |
-| [project_id](variables.tf#L112) | Project where resources will be created. | string | ✓ | |
-| [region](variables.tf#L117) | Region where resources will be created. | string | ✓ | |
+| [name](variables.tf#L121) | Name of the Cloud NAT resource. | string | ✓ | |
+| [project_id](variables.tf#L126) | Project where resources will be created. | string | ✓ | |
+| [region](variables.tf#L131) | Region where resources will be created. | string | ✓ | |
| [addresses](variables.tf#L17) | Optional list of external address self links. | list(string) | | [] |
-| [config_port_allocation](variables.tf#L23) | Configuration for how to assign ports to virtual machines. min_ports_per_vm and max_ports_per_vm have no effect unless enable_dynamic_port_allocation is set to 'true'. | object({…}) | | {} |
-| [config_source_subnetworks](variables.tf#L39) | Subnetwork configuration. | object({…}) | | {} |
-| [config_timeouts](variables.tf#L69) | Timeout configurations. | object({…}) | | {} |
-| [endpoint_types](variables.tf#L82) | Specifies the endpoint Types supported by the NAT Gateway. Supported values include: ENDPOINT_TYPE_VM, ENDPOINT_TYPE_SWG, ENDPOINT_TYPE_MANAGED_PROXY_LB. | list(string) | | null |
-| [logging_filter](variables.tf#L101) | Enables logging if not null, value is one of 'ERRORS_ONLY', 'TRANSLATIONS_ONLY', 'ALL'. | string | | null |
-| [router_asn](variables.tf#L122) | Router ASN used for auto-created router. | number | | null |
-| [router_create](variables.tf#L128) | Create router. | bool | | true |
-| [router_name](variables.tf#L134) | Router name, leave blank if router will be created to use auto generated name. | string | | null |
-| [router_network](variables.tf#L140) | Name of the VPC used for auto-created router. | string | | null |
-| [rules](variables.tf#L146) | List of rules associated with this NAT. | list(object({…})) | | [] |
-| [type](variables.tf#L166) | Whether this Cloud NAT is used for public or private IP translation. One of 'PUBLIC' or 'PRIVATE'. | string | | "PUBLIC" |
+| [config_port_allocation](variables.tf#L24) | Configuration for how to assign ports to virtual machines. min_ports_per_vm and max_ports_per_vm have no effect unless enable_dynamic_port_allocation is set to 'true'. | object({…}) | | {} |
+| [config_source_subnetworks](variables.tf#L40) | Subnetwork configuration. | object({…}) | | {} |
+| [config_timeouts](variables.tf#L70) | Timeout configurations. | object({…}) | | {} |
+| [context](variables.tf#L83) | Context-specific interpolations. | object({…}) | | {} |
+| [endpoint_types](variables.tf#L96) | Specifies the endpoint Types supported by the NAT Gateway. Supported values include: ENDPOINT_TYPE_VM, ENDPOINT_TYPE_SWG, ENDPOINT_TYPE_MANAGED_PROXY_LB. | list(string) | | null |
+| [logging_filter](variables.tf#L115) | Enables logging if not null, value is one of 'ERRORS_ONLY', 'TRANSLATIONS_ONLY', 'ALL'. | string | | null |
+| [router_asn](variables.tf#L136) | Router ASN used for auto-created router. | number | | null |
+| [router_create](variables.tf#L142) | Create router. | bool | | true |
+| [router_name](variables.tf#L148) | Router name, leave blank if router will be created to use auto generated name. | string | | null |
+| [router_network](variables.tf#L154) | Name of the VPC used for auto-created router. | string | | null |
+| [rules](variables.tf#L160) | List of rules associated with this NAT. | list(object({…})) | | [] |
+| [type](variables.tf#L180) | Whether this Cloud NAT is used for public or private IP translation. One of 'PUBLIC' or 'PRIVATE'. | string | | "PUBLIC" |
## Outputs
diff --git a/modules/net-cloudnat/main.tf b/modules/net-cloudnat/main.tf
index 2c6d8eb67..60a4f72d0 100644
--- a/modules/net-cloudnat/main.tf
+++ b/modules/net-cloudnat/main.tf
@@ -15,11 +15,19 @@
*/
locals {
+ ctx = {
+ for k, v in var.context : k => {
+ for kk, vv in v : "${local.ctx_p}${k}:${kk}" => vv
+ }
+ }
+ ctx_p = "$"
router_name = (
var.router_create
? try(google_compute_router.router[0].name, null)
: var.router_name
)
+ project_id = lookup(local.ctx.project_ids, var.project_id, var.project_id)
+ region = lookup(local.ctx.locations, var.region, var.region)
subnet_config = (
var.config_source_subnetworks.all != true
? "LIST_OF_SUBNETWORKS"
@@ -34,10 +42,9 @@ locals {
resource "google_compute_router" "router" {
count = var.router_create ? 1 : 0
name = var.router_name == null ? "${var.name}-nat" : var.router_name
- project = var.project_id
- region = var.region
- network = var.router_network
-
+ project = local.project_id
+ region = local.region
+ network = lookup(local.ctx.networks, var.router_network, var.router_network)
dynamic "bgp" {
for_each = var.router_asn == null ? [] : [1]
content {
@@ -48,13 +55,15 @@ resource "google_compute_router" "router" {
resource "google_compute_router_nat" "nat" {
provider = google-beta
- project = var.project_id
- region = var.region
+ project = local.project_id
+ region = local.region
name = var.name
endpoint_types = var.endpoint_types
type = var.type
router = local.router_name
- nat_ips = var.addresses
+ nat_ips = [
+ for a in var.addresses : lookup(local.ctx.addresses, a, a)
+ ]
nat_ip_allocate_option = (
var.type == "PRIVATE"
? null
@@ -64,30 +73,28 @@ resource "google_compute_router_nat" "nat" {
: "AUTO_ONLY"
)
)
- source_subnetwork_ip_ranges_to_nat = local.subnet_config
icmp_idle_timeout_sec = var.config_timeouts.icmp
- udp_idle_timeout_sec = var.config_timeouts.udp
+ source_subnetwork_ip_ranges_to_nat = local.subnet_config
tcp_established_idle_timeout_sec = var.config_timeouts.tcp_established
tcp_time_wait_timeout_sec = var.config_timeouts.tcp_time_wait
tcp_transitory_idle_timeout_sec = var.config_timeouts.tcp_transitory
+ udp_idle_timeout_sec = var.config_timeouts.udp
enable_endpoint_independent_mapping = (
var.config_port_allocation.enable_endpoint_independent_mapping
)
enable_dynamic_port_allocation = (
var.config_port_allocation.enable_dynamic_port_allocation
)
+ log_config {
+ enable = var.logging_filter == null ? false : true
+ filter = var.logging_filter == null ? "ALL" : var.logging_filter
+ }
min_ports_per_vm = (
var.config_port_allocation.min_ports_per_vm
)
max_ports_per_vm = (
var.config_port_allocation.max_ports_per_vm
)
-
- log_config {
- enable = var.logging_filter == null ? false : true
- filter = var.logging_filter == null ? "ALL" : var.logging_filter
- }
-
dynamic "subnetwork" {
for_each = toset(
local.subnet_config == "LIST_OF_SUBNETWORKS"
@@ -95,7 +102,9 @@ resource "google_compute_router_nat" "nat" {
: []
)
content {
- name = subnetwork.value.self_link
+ name = lookup(
+ local.ctx.subnets, subnetwork.value.self_link, subnetwork.value.self_link
+ )
source_ip_ranges_to_nat = (
subnetwork.value.all_ranges == true
? ["ALL_IP_RANGES"]
@@ -120,7 +129,6 @@ resource "google_compute_router_nat" "nat" {
)
}
}
-
dynamic "rules" {
for_each = { for i, r in var.rules : i => r }
content {
diff --git a/modules/net-cloudnat/variables.tf b/modules/net-cloudnat/variables.tf
index 88fe1cb83..369a3d94f 100644
--- a/modules/net-cloudnat/variables.tf
+++ b/modules/net-cloudnat/variables.tf
@@ -17,6 +17,7 @@
variable "addresses" {
description = "Optional list of external address self links."
type = list(string)
+ nullable = false
default = []
}
@@ -79,6 +80,19 @@ variable "config_timeouts" {
nullable = false
}
+variable "context" {
+ description = "Context-specific interpolations."
+ type = object({
+ addresses = optional(map(string), {})
+ locations = optional(map(string), {})
+ networks = optional(map(string), {})
+ project_ids = optional(map(string), {})
+ subnets = optional(map(string), {})
+ })
+ default = {}
+ nullable = false
+}
+
variable "endpoint_types" {
description = "Specifies the endpoint Types supported by the NAT Gateway. Supported values include: ENDPOINT_TYPE_VM, ENDPOINT_TYPE_SWG, ENDPOINT_TYPE_MANAGED_PROXY_LB."
type = list(string)
diff --git a/modules/net-firewall-policy/README.md b/modules/net-firewall-policy/README.md
index ca3aecf2f..fe899cc03 100644
--- a/modules/net-firewall-policy/README.md
+++ b/modules/net-firewall-policy/README.md
@@ -17,8 +17,8 @@ The module also makes fewer assumptions about implicit defaults, only using one
- [Factory](#factory)
- [Firewall Rule Factory Schema](#firewall-rule-factory-schema)
- [Dynamic Rule Matching](#dynamic-rule-matching)
- - [Ingress Rules (](#ingress-rules-)
- - [Egress Rules (](#egress-rules-)
+ - [Ingress Rules](#ingress-rules)
+ - [Egress Rules](#egress-rules)
- [Rule-Level Mappings](#rule-level-mappings)
- [Variables](#variables)
- [Outputs](#outputs)
@@ -351,7 +351,9 @@ This module simplifies firewall rule creation by using generic, context-aware va
The tables below provide a complete reference for these dynamic mappings.
-#### Ingress Rules (`direction = "INGRESS"`)
+#### Ingress Rules
+
+`direction = "INGRESS"`
| Module Variable (`match.*`) | Mapped Resource Attribute |
| :--- | :--- |
@@ -361,7 +363,9 @@ The tables below provide a complete reference for these dynamic mappings.
| `source_tags` | `src_secure_tags` |
| `threat_intelligences` | `src_threat_intelligences` |
-#### Egress Rules (`direction = "EGRESS"`)
+#### Egress Rules
+
+`direction = "EGRESS"`
| Module Variable (`match.*`) | Mapped Resource Attribute |
| :--- | :--- |
@@ -377,22 +381,21 @@ The following variable is defined at the top level of the rule (not within the `
| Module Variable | Mapped Resource Attribute |
| :--- | :--- |
| `target_tags` | `target_secure_tags` |
-
-
## Variables
| name | description | type | required | default |
|---|---|:---:|:---:|:---:|
-| [name](variables.tf#L117) | Policy name. | string | ✓ | |
-| [parent_id](variables.tf#L123) | Parent node where the policy will be created, `folders/nnn` or `organizations/nnn` for hierarchical policy, project id for a network policy. | string | ✓ | |
+| [name](variables.tf#L132) | Policy name. | string | ✓ | |
+| [parent_id](variables.tf#L138) | Parent node where the policy will be created, `folders/nnn` or `organizations/nnn` for hierarchical policy, project id for a network policy. | string | ✓ | |
| [attachments](variables.tf#L17) | Ids of the resources to which this policy will be attached, in descriptive name => self link format. Specify folders or organization for hierarchical policy, VPCs for network policy. | map(string) | | {} |
-| [description](variables.tf#L24) | Policy description. | string | | null |
-| [egress_rules](variables.tf#L30) | List of egress rule definitions, action can be 'allow', 'deny', 'goto_next' or 'apply_security_profile_group'. The match.layer4configs map is in protocol => optional [ports] format. | map(object({…})) | | {} |
-| [factories_config](variables.tf#L68) | Paths to folders for the optional factories. | object({…}) | | {} |
-| [ingress_rules](variables.tf#L79) | List of ingress rule definitions, action can be 'allow', 'deny', 'goto_next' or 'apply_security_profile_group'. | map(object({…})) | | {} |
-| [region](variables.tf#L129) | Policy region. Leave null for hierarchical policy, set to 'global' for a global network policy. | string | | null |
-| [security_profile_group_ids](variables.tf#L135) | The optional security groups ids to be referenced in factories. | map(string) | | {} |
+| [context](variables.tf#L24) | Context-specific interpolations. | object({…}) | | {} |
+| [description](variables.tf#L39) | Policy description. | string | | null |
+| [egress_rules](variables.tf#L45) | List of egress rule definitions, action can be 'allow', 'deny', 'goto_next' or 'apply_security_profile_group'. The match.layer4configs map is in protocol => optional [ports] format. | map(object({…})) | | {} |
+| [factories_config](variables.tf#L83) | Paths to folders for the optional factories. | object({…}) | | {} |
+| [ingress_rules](variables.tf#L94) | List of ingress rule definitions, action can be 'allow', 'deny', 'goto_next' or 'apply_security_profile_group'. | map(object({…})) | | {} |
+| [region](variables.tf#L144) | Policy region. Leave null for hierarchical policy, set to 'global' for a global network policy. | string | | null |
+| [security_profile_group_ids](variables.tf#L150) | The optional security groups ids to be referenced in factories. | map(string) | | {} |
## Outputs
diff --git a/modules/net-firewall-policy/hierarchical.tf b/modules/net-firewall-policy/hierarchical.tf
index 7969a559d..dffbb7805 100644
--- a/modules/net-firewall-policy/hierarchical.tf
+++ b/modules/net-firewall-policy/hierarchical.tf
@@ -16,7 +16,7 @@
resource "google_compute_firewall_policy" "hierarchical" {
count = local.use_hierarchical ? 1 : 0
- parent = var.parent_id
+ parent = lookup(local.ctx.folder_ids, var.parent_id, var.parent_id)
short_name = var.name
description = var.description
}
@@ -24,7 +24,7 @@ resource "google_compute_firewall_policy" "hierarchical" {
resource "google_compute_firewall_policy_association" "hierarchical" {
for_each = local.use_hierarchical ? var.attachments : {}
name = "${var.name}-${each.key}"
- attachment_target = each.value
+ attachment_target = lookup(local.ctx.folder_ids, each.value, each.value)
firewall_policy = google_compute_firewall_policy.hierarchical[0].name
}
@@ -33,23 +33,43 @@ resource "google_compute_firewall_policy_rule" "hierarchical" {
for_each = toset(
local.use_hierarchical ? keys(local.rules) : []
)
- firewall_policy = google_compute_firewall_policy.hierarchical[0].name
- action = local.rules[each.key].action
- description = local.rules[each.key].description
- direction = local.rules[each.key].direction
- disabled = local.rules[each.key].disabled
- enable_logging = local.rules[each.key].enable_logging
- priority = local.rules[each.key].priority
- target_resources = local.rules[each.key].target_resources
- target_service_accounts = local.rules[each.key].target_service_accounts
- tls_inspect = local.rules[each.key].tls_inspect
+ firewall_policy = google_compute_firewall_policy.hierarchical[0].name
+ action = local.rules[each.key].action
+ description = local.rules[each.key].description
+ direction = local.rules[each.key].direction
+ disabled = local.rules[each.key].disabled
+ enable_logging = local.rules[each.key].enable_logging
+ priority = local.rules[each.key].priority
+ target_resources = (
+ local.rules[each.key].target_resources == null ? null : [
+ for n in local.rules[each.key].target_resources :
+ lookup(local.ctx.networks, n, n)
+ ]
+ )
+ target_service_accounts = (
+ local.rules[each.key].target_service_accounts == null ? null : [
+ for n in local.rules[each.key].target_service_accounts :
+ lookup(local.ctx.iam_principals, n, n)
+ ]
+ )
+ tls_inspect = local.rules[each.key].tls_inspect
security_profile_group = try(
var.security_profile_group_ids[local.rules[each.key].security_profile_group],
local.rules[each.key].security_profile_group
)
match {
- dest_ip_ranges = local.rules[each.key].match.destination_ranges
- src_ip_ranges = local.rules[each.key].match.source_ranges
+ dest_ip_ranges = (
+ local.rules[each.key].match.destination_ranges == null ? null : [
+ for r in local.rules[each.key].match.destination_ranges :
+ lookup(local.ctx.cidr_ranges, r, r)
+ ]
+ )
+ src_ip_ranges = (
+ local.rules[each.key].match.source_ranges == null ? null : [
+ for r in local.rules[each.key].match.source_ranges :
+ lookup(local.ctx.cidr_ranges, r, r)
+ ]
+ )
dest_address_groups = (
local.rules[each.key].direction == "EGRESS"
? local.rules[each.key].match.address_groups
diff --git a/modules/net-firewall-policy/main.tf b/modules/net-firewall-policy/main.tf
index 093c8bf23..b59a92126 100644
--- a/modules/net-firewall-policy/main.tf
+++ b/modules/net-firewall-policy/main.tf
@@ -23,6 +23,12 @@ locals {
for name, rule in merge(var.ingress_rules) :
"ingress/${name}" => merge(rule, { name = name, direction = "INGRESS" })
}
+ ctx = {
+ for k, v in var.context : k => {
+ for kk, vv in v : "${local.ctx_p}${k}:${kk}" => vv
+ }
+ }
+ ctx_p = "$"
rules = merge(
local.factory_egress_rules, local.factory_ingress_rules,
local._rules_egress, local._rules_ingress
diff --git a/modules/net-firewall-policy/net-global.tf b/modules/net-firewall-policy/net-global.tf
index cf837c861..8d9bc4049 100644
--- a/modules/net-firewall-policy/net-global.tf
+++ b/modules/net-firewall-policy/net-global.tf
@@ -16,7 +16,7 @@
resource "google_compute_network_firewall_policy" "net-global" {
count = !local.use_hierarchical && !local.use_regional ? 1 : 0
- project = var.parent_id
+ project = lookup(local.ctx.project_ids, var.parent_id, var.parent_id)
name = var.name
description = var.description
}
@@ -25,9 +25,9 @@ resource "google_compute_network_firewall_policy_association" "net-global" {
for_each = (
!local.use_hierarchical && !local.use_regional ? var.attachments : {}
)
- project = var.parent_id
+ project = lookup(local.ctx.project_ids, var.parent_id, var.parent_id)
name = "${var.name}-${each.key}"
- attachment_target = each.value
+ attachment_target = lookup(local.ctx.networks, each.value, each.value)
firewall_policy = google_compute_network_firewall_policy.net-global[0].name
}
@@ -38,24 +38,39 @@ resource "google_compute_network_firewall_policy_rule" "net-global" {
? keys(local.rules)
: []
)
- project = var.parent_id
- firewall_policy = google_compute_network_firewall_policy.net-global[0].name
- rule_name = local.rules[each.key].name
- action = local.rules[each.key].action
- description = local.rules[each.key].description
- direction = local.rules[each.key].direction
- disabled = local.rules[each.key].disabled
- enable_logging = local.rules[each.key].enable_logging
- priority = local.rules[each.key].priority
- target_service_accounts = local.rules[each.key].target_service_accounts
- tls_inspect = local.rules[each.key].tls_inspect
+ project = lookup(local.ctx.project_ids, var.parent_id, var.parent_id)
+ firewall_policy = google_compute_network_firewall_policy.net-global[0].name
+ rule_name = local.rules[each.key].name
+ action = local.rules[each.key].action
+ description = local.rules[each.key].description
+ direction = local.rules[each.key].direction
+ disabled = local.rules[each.key].disabled
+ enable_logging = local.rules[each.key].enable_logging
+ priority = local.rules[each.key].priority
+ target_service_accounts = (
+ local.rules[each.key].target_service_accounts == null ? null : [
+ for n in local.rules[each.key].target_service_accounts :
+ lookup(local.ctx.iam_principals, n, n)
+ ]
+ )
+ tls_inspect = local.rules[each.key].tls_inspect
security_profile_group = try(
var.security_profile_group_ids[local.rules[each.key].security_profile_group],
local.rules[each.key].security_profile_group
)
match {
- dest_ip_ranges = local.rules[each.key].match.destination_ranges
- src_ip_ranges = local.rules[each.key].match.source_ranges
+ dest_ip_ranges = (
+ local.rules[each.key].match.destination_ranges == null ? null : [
+ for r in local.rules[each.key].match.destination_ranges :
+ lookup(local.ctx.cidr_ranges, r, r)
+ ]
+ )
+ src_ip_ranges = (
+ local.rules[each.key].match.source_ranges == null ? null : [
+ for r in local.rules[each.key].match.source_ranges :
+ lookup(local.ctx.cidr_ranges, r, r)
+ ]
+ )
dest_address_groups = (
local.rules[each.key].direction == "EGRESS"
? local.rules[each.key].match.address_groups
@@ -106,7 +121,9 @@ resource "google_compute_network_firewall_policy_rule" "net-global" {
dynamic "src_secure_tags" {
for_each = toset(coalesce(local.rules[each.key].match.source_tags, []))
content {
- name = src_secure_tags.key
+ name = lookup(
+ local.ctx.tag_values, src_secure_tags.key, src_secure_tags.key
+ )
}
}
}
@@ -117,7 +134,9 @@ resource "google_compute_network_firewall_policy_rule" "net-global" {
: local.rules[each.key].target_tags
)
content {
- name = target_secure_tags.value
+ name = lookup(
+ local.ctx.tag_values, target_secure_tags.value, target_secure_tags.value
+ )
}
}
}
diff --git a/modules/net-firewall-policy/net-regional.tf b/modules/net-firewall-policy/net-regional.tf
index 281cbc4f9..9a83a5ef6 100644
--- a/modules/net-firewall-policy/net-regional.tf
+++ b/modules/net-firewall-policy/net-regional.tf
@@ -16,20 +16,20 @@
resource "google_compute_region_network_firewall_policy" "net-regional" {
count = !local.use_hierarchical && local.use_regional ? 1 : 0
- project = var.parent_id
+ project = lookup(local.ctx.project_ids, var.parent_id, var.parent_id)
name = var.name
description = var.description
- region = var.region
+ region = lookup(local.ctx.locations, var.region, var.region)
}
resource "google_compute_region_network_firewall_policy_association" "net-regional" {
for_each = (
!local.use_hierarchical && local.use_regional ? var.attachments : {}
)
- project = var.parent_id
- region = var.region
+ project = lookup(local.ctx.project_ids, var.parent_id, var.parent_id)
+ region = lookup(local.ctx.locations, var.region, var.region)
name = "${var.name}-${each.key}"
- attachment_target = each.value
+ attachment_target = lookup(local.ctx.networks, each.value, each.value)
firewall_policy = google_compute_region_network_firewall_policy.net-regional[0].name
}
@@ -40,20 +40,35 @@ resource "google_compute_region_network_firewall_policy_rule" "net-regional" {
? keys(local.rules)
: []
)
- project = var.parent_id
- region = var.region
- firewall_policy = google_compute_region_network_firewall_policy.net-regional[0].name
- rule_name = local.rules[each.key].name
- action = local.rules[each.key].action
- description = local.rules[each.key].description
- direction = local.rules[each.key].direction
- disabled = local.rules[each.key].disabled
- enable_logging = local.rules[each.key].enable_logging
- priority = local.rules[each.key].priority
- target_service_accounts = local.rules[each.key].target_service_accounts
+ project = lookup(local.ctx.project_ids, var.parent_id, var.parent_id)
+ region = lookup(local.ctx.locations, var.region, var.region)
+ firewall_policy = google_compute_region_network_firewall_policy.net-regional[0].name
+ rule_name = local.rules[each.key].name
+ action = local.rules[each.key].action
+ description = local.rules[each.key].description
+ direction = local.rules[each.key].direction
+ disabled = local.rules[each.key].disabled
+ enable_logging = local.rules[each.key].enable_logging
+ priority = local.rules[each.key].priority
+ target_service_accounts = (
+ local.rules[each.key].target_service_accounts == null ? null : [
+ for n in local.rules[each.key].target_service_accounts :
+ lookup(local.ctx.iam_principals, n, n)
+ ]
+ )
match {
- dest_ip_ranges = local.rules[each.key].match.destination_ranges
- src_ip_ranges = local.rules[each.key].match.source_ranges
+ dest_ip_ranges = (
+ local.rules[each.key].match.destination_ranges == null ? null : [
+ for r in local.rules[each.key].match.destination_ranges :
+ lookup(local.ctx.cidr_ranges, r, r)
+ ]
+ )
+ src_ip_ranges = (
+ local.rules[each.key].match.source_ranges == null ? null : [
+ for r in local.rules[each.key].match.source_ranges :
+ lookup(local.ctx.cidr_ranges, r, r)
+ ]
+ )
dest_address_groups = (
local.rules[each.key].direction == "EGRESS"
? local.rules[each.key].match.address_groups
@@ -104,7 +119,9 @@ resource "google_compute_region_network_firewall_policy_rule" "net-regional" {
dynamic "src_secure_tags" {
for_each = toset(coalesce(local.rules[each.key].match.source_tags, []))
content {
- name = src_secure_tags.key
+ name = lookup(
+ local.ctx.tag_values, src_secure_tags.key, src_secure_tags.key
+ )
}
}
}
@@ -115,7 +132,9 @@ resource "google_compute_region_network_firewall_policy_rule" "net-regional" {
: local.rules[each.key].target_tags
)
content {
- name = target_secure_tags.value
+ name = lookup(
+ local.ctx.tag_values, target_secure_tags.value, target_secure_tags.value
+ )
}
}
}
diff --git a/modules/net-firewall-policy/variables.tf b/modules/net-firewall-policy/variables.tf
index bab3ee853..9ccc91783 100644
--- a/modules/net-firewall-policy/variables.tf
+++ b/modules/net-firewall-policy/variables.tf
@@ -21,6 +21,21 @@ variable "attachments" {
nullable = false
}
+variable "context" {
+ description = "Context-specific interpolations."
+ type = object({
+ cidr_ranges = optional(map(string), {})
+ folder_ids = optional(map(string), {})
+ iam_principals = optional(map(string), {})
+ locations = optional(map(string), {})
+ networks = optional(map(string), {})
+ project_ids = optional(map(string), {})
+ tag_values = optional(map(string), {})
+ })
+ default = {}
+ nullable = false
+}
+
variable "description" {
description = "Policy description."
type = string
diff --git a/tests/modules/net_cloudnat/context.tfvars b/tests/modules/net_cloudnat/context.tfvars
new file mode 100644
index 000000000..78b8af838
--- /dev/null
+++ b/tests/modules/net_cloudnat/context.tfvars
@@ -0,0 +1,28 @@
+context = {
+ addresses = {
+ test = "35.10.10.10"
+ }
+ locations = {
+ ew8 = "europe-west8"
+ }
+ networks = {
+ test = "projects/foo-dev-net-spoke-0/global/networks/dev-spoke-0"
+ }
+ project_ids = {
+ test = "foo-test-0"
+ }
+ subnets = {
+ test = "projects/foo-dev-net-spoke-0/regions/europe-west1/subnetworks/gce"
+ }
+}
+addresses = ["$addresses:test"]
+config_source_subnetworks = {
+ all = false
+ subnetworks = [{
+ self_link = "$subnets:test"
+ }]
+}
+name = "test"
+project_id = "$project_ids:test"
+region = "$locations:ew8"
+router_network = "$networks:test"
diff --git a/tests/modules/net_cloudnat/context.yaml b/tests/modules/net_cloudnat/context.yaml
new file mode 100644
index 000000000..3faec0cad
--- /dev/null
+++ b/tests/modules/net_cloudnat/context.yaml
@@ -0,0 +1,61 @@
+# Copyright 2025 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.
+
+values:
+ google_compute_router.router[0]:
+ bgp: []
+ description: null
+ encrypted_interconnect_router: null
+ md5_authentication_keys: []
+ name: test-nat
+ network: projects/foo-dev-net-spoke-0/global/networks/dev-spoke-0
+ project: foo-test-0
+ region: europe-west8
+ timeouts: null
+ google_compute_router_nat.nat:
+ enable_dynamic_port_allocation: false
+ enable_endpoint_independent_mapping: true
+ icmp_idle_timeout_sec: 30
+ initial_nat_ips: null
+ log_config:
+ - enable: false
+ filter: ALL
+ max_ports_per_vm: 65536
+ name: test
+ nat64_subnetwork: []
+ nat_ip_allocate_option: MANUAL_ONLY
+ nat_ips:
+ - 35.10.10.10
+ project: foo-test-0
+ region: europe-west8
+ router: test-nat
+ rules: []
+ source_subnetwork_ip_ranges_to_nat: LIST_OF_SUBNETWORKS
+ source_subnetwork_ip_ranges_to_nat64: null
+ subnetwork:
+ - name: projects/foo-dev-net-spoke-0/regions/europe-west1/subnetworks/gce
+ secondary_ip_range_names: []
+ source_ip_ranges_to_nat:
+ - ALL_IP_RANGES
+ tcp_established_idle_timeout_sec: 1200
+ tcp_time_wait_timeout_sec: 120
+ tcp_transitory_idle_timeout_sec: 30
+ timeouts: null
+ type: PUBLIC
+ udp_idle_timeout_sec: 30
+counts:
+ google_compute_router: 1
+ google_compute_router_nat: 1
+ modules: 0
+ resources: 2
diff --git a/tests/modules/net_cloudnat/tftest.yaml b/tests/modules/net_cloudnat/tftest.yaml
new file mode 100644
index 000000000..8f75c0ecf
--- /dev/null
+++ b/tests/modules/net_cloudnat/tftest.yaml
@@ -0,0 +1,17 @@
+# Copyright 2025 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.
+
+module: modules/net-cloudnat
+tests:
+ context:
diff --git a/tests/modules/net_firewall_policy/context-g.tfvars b/tests/modules/net_firewall_policy/context-g.tfvars
new file mode 100644
index 000000000..7acda3c67
--- /dev/null
+++ b/tests/modules/net_firewall_policy/context-g.tfvars
@@ -0,0 +1,52 @@
+context = {
+ cidr_ranges = {
+ rfc1918-10 = "10.0.0.0/8"
+ }
+ folder_ids = {
+ test = "folders/1234567890"
+ }
+ iam_principals = {
+ test = "serviceAccount:test@test-project.iam.gserviceaccount.com"
+ }
+ locations = {
+ ew8 = "europe-west8"
+ }
+ networks = {
+ test = "projects/foo-dev-net-spoke-0/global/networks/dev-spoke-0"
+ }
+ project_ids = {
+ test = "foo-test-0"
+ }
+ tag_values = {
+ "test" = "tagValues/1234567890"
+ }
+}
+name = "test-1"
+parent_id = "$project_ids:test"
+region = "global"
+attachments = {
+ test = "$networks:test"
+}
+egress_rules = {
+ smtp = {
+ priority = 900
+ target_service_accounts = ["$iam_principals:test"]
+ match = {
+ destination_ranges = ["$cidr_ranges:rfc1918-10"]
+ layer4_configs = [{ protocol = "tcp", ports = ["25"] }]
+ source_tags = ["$tag_values:test"]
+ }
+ }
+}
+ingress_rules = {
+ icmp = {
+ priority = 1000
+ enable_logging = true
+ target_resources = ["$networks:test"]
+ target_tags = ["$tag_values:test"]
+ match = {
+ source_ranges = ["$cidr_ranges:rfc1918-10"]
+ layer4_configs = [{ protocol = "icmp" }]
+ }
+ }
+}
diff --git a/tests/modules/net_firewall_policy/context-g.yaml b/tests/modules/net_firewall_policy/context-g.yaml
new file mode 100644
index 000000000..2a7569356
--- /dev/null
+++ b/tests/modules/net_firewall_policy/context-g.yaml
@@ -0,0 +1,99 @@
+# Copyright 2025 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.
+
+values:
+ google_compute_network_firewall_policy.net-global[0]:
+ description: null
+ name: test-1
+ project: foo-test-0
+ timeouts: null
+ google_compute_network_firewall_policy_association.net-global["test"]:
+ attachment_target: projects/foo-dev-net-spoke-0/global/networks/dev-spoke-0
+ firewall_policy: test-1
+ name: test-1-test
+ project: foo-test-0
+ timeouts: null
+ google_compute_network_firewall_policy_rule.net-global["egress/smtp"]:
+ action: deny
+ description: null
+ direction: EGRESS
+ disabled: false
+ enable_logging: null
+ firewall_policy: test-1
+ match:
+ - dest_address_groups: null
+ dest_fqdns: null
+ dest_ip_ranges:
+ - 10.0.0.0/8
+ dest_region_codes: null
+ dest_threat_intelligences: null
+ layer4_configs:
+ - ip_protocol: tcp
+ ports:
+ - '25'
+ src_address_groups: null
+ src_fqdns: null
+ src_ip_ranges: null
+ src_region_codes: null
+ src_secure_tags:
+ - name: tagValues/1234567890
+ src_threat_intelligences: null
+ priority: 900
+ project: foo-test-0
+ rule_name: smtp
+ security_profile_group: null
+ target_secure_tags: []
+ target_service_accounts:
+ - serviceAccount:test@test-project.iam.gserviceaccount.com
+ timeouts: null
+ tls_inspect: null
+ google_compute_network_firewall_policy_rule.net-global["ingress/icmp"]:
+ action: allow
+ description: null
+ direction: INGRESS
+ disabled: false
+ enable_logging: true
+ firewall_policy: test-1
+ match:
+ - dest_address_groups: null
+ dest_fqdns: null
+ dest_ip_ranges: null
+ dest_region_codes: null
+ dest_threat_intelligences: null
+ layer4_configs:
+ - ip_protocol: icmp
+ ports: null
+ src_address_groups: null
+ src_fqdns: null
+ src_ip_ranges:
+ - 10.0.0.0/8
+ src_region_codes: null
+ src_secure_tags: []
+ src_threat_intelligences: null
+ priority: 1000
+ project: foo-test-0
+ rule_name: icmp
+ security_profile_group: null
+ target_secure_tags:
+ - name: tagValues/1234567890
+ target_service_accounts: null
+ timeouts: null
+ tls_inspect: null
+
+counts:
+ google_compute_network_firewall_policy: 1
+ google_compute_network_firewall_policy_association: 1
+ google_compute_network_firewall_policy_rule: 2
+ modules: 0
+ resources: 4
diff --git a/tests/modules/net_firewall_policy/context-h.tfvars b/tests/modules/net_firewall_policy/context-h.tfvars
new file mode 100644
index 000000000..80eb44543
--- /dev/null
+++ b/tests/modules/net_firewall_policy/context-h.tfvars
@@ -0,0 +1,49 @@
+context = {
+ cidr_ranges = {
+ rfc1918-10 = "10.0.0.0/8"
+ }
+ folder_ids = {
+ test = "folders/1234567890"
+ }
+ iam_principals = {
+ test = "serviceAccount:test@test-project.iam.gserviceaccount.com"
+ }
+ locations = {
+ ew8 = "europe-west8"
+ }
+ networks = {
+ test = "projects/foo-dev-net-spoke-0/global/networks/dev-spoke-0"
+ }
+ project_ids = {
+ test = "foo-test-0"
+ }
+ tag_values = {
+ "test/one" = "tagValues/1234567890"
+ }
+}
+name = "test-1"
+parent_id = "$folder_ids:test"
+attachments = {
+ test = "$folder_ids:test"
+}
+egress_rules = {
+ smtp = {
+ priority = 900
+ match = {
+ destination_ranges = ["$cidr_ranges:rfc1918-10"]
+ layer4_configs = [{ protocol = "tcp", ports = ["25"] }]
+ }
+ }
+}
+ingress_rules = {
+ icmp = {
+ priority = 1000
+ enable_logging = true
+ target_resources = ["$networks:test"]
+ target_service_accounts = ["$iam_principals:test"]
+ match = {
+ source_ranges = ["$cidr_ranges:rfc1918-10"]
+ layer4_configs = [{ protocol = "icmp" }]
+ }
+ }
+}
diff --git a/tests/modules/net_firewall_policy/context-h.yaml b/tests/modules/net_firewall_policy/context-h.yaml
new file mode 100644
index 000000000..ebcbcc539
--- /dev/null
+++ b/tests/modules/net_firewall_policy/context-h.yaml
@@ -0,0 +1,92 @@
+# Copyright 2025 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.
+
+values:
+ google_compute_firewall_policy.hierarchical[0]:
+ description: null
+ parent: folders/1234567890
+ short_name: test-1
+ timeouts: null
+ google_compute_firewall_policy_association.hierarchical["test"]:
+ attachment_target: folders/1234567890
+ name: test-1-test
+ timeouts: null
+ google_compute_firewall_policy_rule.hierarchical["egress/smtp"]:
+ action: deny
+ description: null
+ direction: EGRESS
+ disabled: false
+ enable_logging: null
+ match:
+ - dest_address_groups: null
+ dest_fqdns: null
+ dest_ip_ranges:
+ - 10.0.0.0/8
+ dest_region_codes: null
+ dest_threat_intelligences: null
+ layer4_configs:
+ - ip_protocol: tcp
+ ports:
+ - '25'
+ src_address_groups: null
+ src_fqdns: null
+ src_ip_ranges: null
+ src_region_codes: null
+ src_secure_tags: []
+ src_threat_intelligences: null
+ priority: 900
+ security_profile_group: null
+ target_resources: null
+ target_secure_tags: []
+ target_service_accounts: null
+ timeouts: null
+ tls_inspect: null
+ google_compute_firewall_policy_rule.hierarchical["ingress/icmp"]:
+ action: allow
+ description: null
+ direction: INGRESS
+ disabled: false
+ enable_logging: true
+ match:
+ - dest_address_groups: null
+ dest_fqdns: null
+ dest_ip_ranges: null
+ dest_region_codes: null
+ dest_threat_intelligences: null
+ layer4_configs:
+ - ip_protocol: icmp
+ ports: null
+ src_address_groups: null
+ src_fqdns: null
+ src_ip_ranges:
+ - 10.0.0.0/8
+ src_region_codes: null
+ src_secure_tags: []
+ src_threat_intelligences: null
+ priority: 1000
+ security_profile_group: null
+ target_resources:
+ - projects/foo-dev-net-spoke-0/global/networks/dev-spoke-0
+ target_secure_tags: []
+ target_service_accounts:
+ - serviceAccount:test@test-project.iam.gserviceaccount.com
+ timeouts: null
+ tls_inspect: null
+
+counts:
+ google_compute_firewall_policy: 1
+ google_compute_firewall_policy_association: 1
+ google_compute_firewall_policy_rule: 2
+ modules: 0
+ resources: 4
diff --git a/tests/modules/net_firewall_policy/context-r.tfvars b/tests/modules/net_firewall_policy/context-r.tfvars
new file mode 100644
index 000000000..9630d37be
--- /dev/null
+++ b/tests/modules/net_firewall_policy/context-r.tfvars
@@ -0,0 +1,52 @@
+context = {
+ cidr_ranges = {
+ rfc1918-10 = "10.0.0.0/8"
+ }
+ folder_ids = {
+ test = "folders/1234567890"
+ }
+ iam_principals = {
+ test = "serviceAccount:test@test-project.iam.gserviceaccount.com"
+ }
+ locations = {
+ ew8 = "europe-west8"
+ }
+ networks = {
+ test = "projects/foo-dev-net-spoke-0/global/networks/dev-spoke-0"
+ }
+ project_ids = {
+ test = "foo-test-0"
+ }
+ tag_values = {
+ "test" = "tagValues/1234567890"
+ }
+}
+name = "test-1"
+parent_id = "$project_ids:test"
+region = "$locations:ew8"
+attachments = {
+ test = "$networks:test"
+}
+egress_rules = {
+ smtp = {
+ priority = 900
+ target_service_accounts = ["$iam_principals:test"]
+ match = {
+ destination_ranges = ["$cidr_ranges:rfc1918-10"]
+ layer4_configs = [{ protocol = "tcp", ports = ["25"] }]
+ source_tags = ["$tag_values:test"]
+ }
+ }
+}
+ingress_rules = {
+ icmp = {
+ priority = 1000
+ enable_logging = true
+ target_resources = ["$networks:test"]
+ target_tags = ["$tag_values:test"]
+ match = {
+ source_ranges = ["$cidr_ranges:rfc1918-10"]
+ layer4_configs = [{ protocol = "icmp" }]
+ }
+ }
+}
diff --git a/tests/modules/net_firewall_policy/context-r.yaml b/tests/modules/net_firewall_policy/context-r.yaml
new file mode 100644
index 000000000..d68a05777
--- /dev/null
+++ b/tests/modules/net_firewall_policy/context-r.yaml
@@ -0,0 +1,103 @@
+# Copyright 2025 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.
+
+values:
+ google_compute_region_network_firewall_policy.net-regional[0]:
+ description: null
+ name: test-1
+ project: foo-test-0
+ region: europe-west8
+ timeouts: null
+ google_compute_region_network_firewall_policy_association.net-regional["test"]:
+ attachment_target: projects/foo-dev-net-spoke-0/global/networks/dev-spoke-0
+ firewall_policy: test-1
+ name: test-1-test
+ project: foo-test-0
+ region: europe-west8
+ timeouts: null
+ google_compute_region_network_firewall_policy_rule.net-regional["egress/smtp"]:
+ action: deny
+ description: null
+ direction: EGRESS
+ disabled: false
+ enable_logging: null
+ firewall_policy: test-1
+ match:
+ - dest_address_groups: null
+ dest_fqdns: null
+ dest_ip_ranges:
+ - 10.0.0.0/8
+ dest_region_codes: null
+ dest_threat_intelligences: null
+ layer4_configs:
+ - ip_protocol: tcp
+ ports:
+ - '25'
+ src_address_groups: null
+ src_fqdns: null
+ src_ip_ranges: null
+ src_region_codes: null
+ src_secure_tags:
+ - name: tagValues/1234567890
+ src_threat_intelligences: null
+ priority: 900
+ project: foo-test-0
+ region: europe-west8
+ rule_name: smtp
+ security_profile_group: null
+ target_secure_tags: []
+ target_service_accounts:
+ - serviceAccount:test@test-project.iam.gserviceaccount.com
+ timeouts: null
+ tls_inspect: null
+ google_compute_region_network_firewall_policy_rule.net-regional["ingress/icmp"]:
+ action: allow
+ description: null
+ direction: INGRESS
+ disabled: false
+ enable_logging: true
+ firewall_policy: test-1
+ match:
+ - dest_address_groups: null
+ dest_fqdns: null
+ dest_ip_ranges: null
+ dest_region_codes: null
+ dest_threat_intelligences: null
+ layer4_configs:
+ - ip_protocol: icmp
+ ports: null
+ src_address_groups: null
+ src_fqdns: null
+ src_ip_ranges:
+ - 10.0.0.0/8
+ src_region_codes: null
+ src_secure_tags: []
+ src_threat_intelligences: null
+ priority: 1000
+ project: foo-test-0
+ region: europe-west8
+ rule_name: icmp
+ security_profile_group: null
+ target_secure_tags:
+ - name: tagValues/1234567890
+ target_service_accounts: null
+ timeouts: null
+ tls_inspect: null
+
+counts:
+ google_compute_region_network_firewall_policy: 1
+ google_compute_region_network_firewall_policy_association: 1
+ google_compute_region_network_firewall_policy_rule: 2
+ modules: 0
+ resources: 4
diff --git a/tests/modules/net_firewall_policy/tftest.yaml b/tests/modules/net_firewall_policy/tftest.yaml
new file mode 100644
index 000000000..192932f44
--- /dev/null
+++ b/tests/modules/net_firewall_policy/tftest.yaml
@@ -0,0 +1,19 @@
+# Copyright 2025 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.
+
+module: modules/net-firewall-policy
+tests:
+ context-g:
+ context-h:
+ context-r: