Add support for context to net-lb-int net-vpc-firewall and net-vpc module (#3419)

* net-lb-int

* net-vpc-firewall

* net-vpc

* net-vpc
This commit is contained in:
Ludovico Magnocavallo
2025-10-16 07:54:14 +02:00
committed by GitHub
parent ecdc248f3f
commit 7c920d7d35
25 changed files with 1044 additions and 221 deletions

View File

@@ -374,20 +374,21 @@ One other issue is a `Provider produced inconsistent final plan` error which is
| name | description | type | required | default |
|---|---|:---:|:---:|:---:|
| [name](variables.tf#L188) | Name used for all resources. | <code>string</code> | ✓ | |
| [project_id](variables.tf#L193) | Project id where resources will be created. | <code>string</code> | ✓ | |
| [region](variables.tf#L198) | GCP region. | <code>string</code> | ✓ | |
| [vpc_config](variables.tf#L224) | VPC-level configuration. | <code title="object&#40;&#123;&#10; network &#61; string&#10; subnetwork &#61; string&#10;&#125;&#41;">object&#40;&#123;&#8230;&#125;&#41;</code> | ✓ | |
| [name](variables.tf#L201) | Name used for all resources. | <code>string</code> | ✓ | |
| [project_id](variables.tf#L206) | Project id where resources will be created. | <code>string</code> | ✓ | |
| [region](variables.tf#L211) | GCP region. | <code>string</code> | ✓ | |
| [vpc_config](variables.tf#L237) | VPC-level configuration. | <code title="object&#40;&#123;&#10; network &#61; string&#10; subnetwork &#61; string&#10;&#125;&#41;">object&#40;&#123;&#8230;&#125;&#41;</code> | ✓ | |
| [backend_service_config](variables.tf#L17) | Backend service level configuration. | <code title="object&#40;&#123;&#10; connection_draining_timeout_sec &#61; optional&#40;number&#41;&#10; connection_tracking &#61; optional&#40;object&#40;&#123;&#10; idle_timeout_sec &#61; optional&#40;number&#41;&#10; persist_conn_on_unhealthy &#61; optional&#40;string&#41;&#10; track_per_session &#61; optional&#40;bool&#41;&#10; &#125;&#41;&#41;&#10; enable_subsetting &#61; optional&#40;bool&#41;&#10; failover_config &#61; optional&#40;object&#40;&#123;&#10; disable_conn_drain &#61; optional&#40;bool&#41;&#10; drop_traffic_if_unhealthy &#61; optional&#40;bool&#41;&#10; ratio &#61; optional&#40;number&#41;&#10; &#125;&#41;&#41;&#10; log_sample_rate &#61; optional&#40;number&#41;&#10; name &#61; optional&#40;string&#41;&#10; description &#61; optional&#40;string, &#34;Terraform managed.&#34;&#41;&#10; protocol &#61; optional&#40;string, &#34;UNSPECIFIED&#34;&#41;&#10; session_affinity &#61; optional&#40;string&#41;&#10; timeout_sec &#61; optional&#40;number&#41;&#10;&#125;&#41;">object&#40;&#123;&#8230;&#125;&#41;</code> | | <code>&#123;&#125;</code> |
| [backends](variables.tf#L53) | Load balancer backends. | <code title="list&#40;object&#40;&#123;&#10; group &#61; string&#10; description &#61; optional&#40;string, &#34;Terraform managed.&#34;&#41;&#10; failover &#61; optional&#40;bool, false&#41;&#10;&#125;&#41;&#41;">list&#40;object&#40;&#123;&#8230;&#125;&#41;&#41;</code> | | <code>&#91;&#93;</code> |
| [description](variables.tf#L64) | Optional description used for resources. | <code>string</code> | | <code>&#34;Terraform managed.&#34;</code> |
| [forwarding_rules_config](variables.tf#L70) | The optional forwarding rules configuration. | <code title="map&#40;object&#40;&#123;&#10; address &#61; optional&#40;string&#41;&#10; description &#61; optional&#40;string&#41;&#10; global_access &#61; optional&#40;bool, true&#41;&#10; ipv6 &#61; optional&#40;bool, false&#41;&#10; name &#61; optional&#40;string&#41;&#10; ports &#61; optional&#40;list&#40;string&#41;, null&#41;&#10; protocol &#61; optional&#40;string, &#34;TCP&#34;&#41;&#10;&#125;&#41;&#41;">map&#40;object&#40;&#123;&#8230;&#125;&#41;&#41;</code> | | <code title="&#123;&#10; &#34;&#34; &#61; &#123;&#125;&#10;&#125;">&#123;&#8230;&#125;</code> |
| [group_configs](variables.tf#L86) | Optional unmanaged groups to create. Can be referenced in backends via outputs. | <code title="map&#40;object&#40;&#123;&#10; zone &#61; string&#10; description &#61; optional&#40;string, &#34;Terraform managed.&#34;&#41;&#10; instances &#61; optional&#40;list&#40;string&#41;&#41;&#10; named_ports &#61; optional&#40;map&#40;number&#41;, &#123;&#125;&#41;&#10;&#125;&#41;&#41;">map&#40;object&#40;&#123;&#8230;&#125;&#41;&#41;</code> | | <code>&#123;&#125;</code> |
| [health_check](variables.tf#L98) | Name of existing health check to use, disables auto-created health check. Also set `health_check_config = null` when cross-referencing an health check from another load balancer module to avoid a Terraform error. | <code>string</code> | | <code>null</code> |
| [health_check_config](variables.tf#L104) | Optional auto-created health check configuration, use the output self-link to set it in the auto healing policy. Refer to examples for usage. | <code title="object&#40;&#123;&#10; check_interval_sec &#61; optional&#40;number&#41;&#10; description &#61; optional&#40;string, &#34;Terraform managed.&#34;&#41;&#10; enable_logging &#61; optional&#40;bool, false&#41;&#10; healthy_threshold &#61; optional&#40;number&#41;&#10; name &#61; optional&#40;string&#41;&#10; timeout_sec &#61; optional&#40;number&#41;&#10; unhealthy_threshold &#61; optional&#40;number&#41;&#10; grpc &#61; optional&#40;object&#40;&#123;&#10; port &#61; optional&#40;number&#41;&#10; port_name &#61; optional&#40;string&#41;&#10; port_specification &#61; optional&#40;string&#41; &#35; USE_FIXED_PORT USE_NAMED_PORT USE_SERVING_PORT&#10; service_name &#61; optional&#40;string&#41;&#10; &#125;&#41;&#41;&#10; http &#61; optional&#40;object&#40;&#123;&#10; host &#61; optional&#40;string&#41;&#10; port &#61; optional&#40;number&#41;&#10; port_name &#61; optional&#40;string&#41;&#10; port_specification &#61; optional&#40;string&#41; &#35; USE_FIXED_PORT USE_NAMED_PORT USE_SERVING_PORT&#10; proxy_header &#61; optional&#40;string&#41;&#10; request_path &#61; optional&#40;string&#41;&#10; response &#61; optional&#40;string&#41;&#10; &#125;&#41;&#41;&#10; http2 &#61; optional&#40;object&#40;&#123;&#10; host &#61; optional&#40;string&#41;&#10; port &#61; optional&#40;number&#41;&#10; port_name &#61; optional&#40;string&#41;&#10; port_specification &#61; optional&#40;string&#41; &#35; USE_FIXED_PORT USE_NAMED_PORT USE_SERVING_PORT&#10; proxy_header &#61; optional&#40;string&#41;&#10; request_path &#61; optional&#40;string&#41;&#10; response &#61; optional&#40;string&#41;&#10; &#125;&#41;&#41;&#10; https &#61; optional&#40;object&#40;&#123;&#10; host &#61; optional&#40;string&#41;&#10; port &#61; optional&#40;number&#41;&#10; port_name &#61; optional&#40;string&#41;&#10; port_specification &#61; optional&#40;string&#41; &#35; USE_FIXED_PORT USE_NAMED_PORT USE_SERVING_PORT&#10; proxy_header &#61; optional&#40;string&#41;&#10; request_path &#61; optional&#40;string&#41;&#10; response &#61; optional&#40;string&#41;&#10; &#125;&#41;&#41;&#10; tcp &#61; optional&#40;object&#40;&#123;&#10; port &#61; optional&#40;number&#41;&#10; port_name &#61; optional&#40;string&#41;&#10; port_specification &#61; optional&#40;string&#41; &#35; USE_FIXED_PORT USE_NAMED_PORT USE_SERVING_PORT&#10; proxy_header &#61; optional&#40;string&#41;&#10; request &#61; optional&#40;string&#41;&#10; response &#61; optional&#40;string&#41;&#10; &#125;&#41;&#41;&#10; ssl &#61; optional&#40;object&#40;&#123;&#10; port &#61; optional&#40;number&#41;&#10; port_name &#61; optional&#40;string&#41;&#10; port_specification &#61; optional&#40;string&#41; &#35; USE_FIXED_PORT USE_NAMED_PORT USE_SERVING_PORT&#10; proxy_header &#61; optional&#40;string&#41;&#10; request &#61; optional&#40;string&#41;&#10; response &#61; optional&#40;string&#41;&#10; &#125;&#41;&#41;&#10;&#125;&#41;">object&#40;&#123;&#8230;&#125;&#41;</code> | | <code title="&#123;&#10; tcp &#61; &#123;&#10; port_specification &#61; &#34;USE_SERVING_PORT&#34;&#10; &#125;&#10;&#125;">&#123;&#8230;&#125;</code> |
| [labels](variables.tf#L182) | Labels set on resources. | <code>map&#40;string&#41;</code> | | <code>&#123;&#125;</code> |
| [service_attachments](variables.tf#L203) | PSC service attachments, keyed by forwarding rule. | <code title="map&#40;object&#40;&#123;&#10; nat_subnets &#61; list&#40;string&#41;&#10; automatic_connection &#61; optional&#40;bool, false&#41;&#10; consumer_accept_lists &#61; optional&#40;map&#40;string&#41;, &#123;&#125;&#41;&#10; consumer_reject_lists &#61; optional&#40;list&#40;string&#41;&#41;&#10; description &#61; optional&#40;string&#41;&#10; domain_name &#61; optional&#40;string&#41;&#10; enable_proxy_protocol &#61; optional&#40;bool, false&#41;&#10; reconcile_connections &#61; optional&#40;bool&#41;&#10;&#125;&#41;&#41;">map&#40;object&#40;&#123;&#8230;&#125;&#41;&#41;</code> | | <code>null</code> |
| [service_label](variables.tf#L218) | Optional prefix of the fully qualified forwarding rule name. | <code>string</code> | | <code>null</code> |
| [context](variables.tf#L64) | Context-specific interpolations. | <code title="object&#40;&#123;&#10; addresses &#61; optional&#40;map&#40;string&#41;, &#123;&#125;&#41;&#10; locations &#61; optional&#40;map&#40;string&#41;, &#123;&#125;&#41;&#10; networks &#61; optional&#40;map&#40;string&#41;, &#123;&#125;&#41;&#10; project_ids &#61; optional&#40;map&#40;string&#41;, &#123;&#125;&#41;&#10; subnets &#61; optional&#40;map&#40;string&#41;, &#123;&#125;&#41;&#10;&#125;&#41;">object&#40;&#123;&#8230;&#125;&#41;</code> | | <code>&#123;&#125;</code> |
| [description](variables.tf#L77) | Optional description used for resources. | <code>string</code> | | <code>&#34;Terraform managed.&#34;</code> |
| [forwarding_rules_config](variables.tf#L83) | The optional forwarding rules configuration. | <code title="map&#40;object&#40;&#123;&#10; address &#61; optional&#40;string&#41;&#10; description &#61; optional&#40;string&#41;&#10; global_access &#61; optional&#40;bool, true&#41;&#10; ipv6 &#61; optional&#40;bool, false&#41;&#10; name &#61; optional&#40;string&#41;&#10; ports &#61; optional&#40;list&#40;string&#41;, null&#41;&#10; protocol &#61; optional&#40;string, &#34;TCP&#34;&#41;&#10;&#125;&#41;&#41;">map&#40;object&#40;&#123;&#8230;&#125;&#41;&#41;</code> | | <code title="&#123;&#10; &#34;&#34; &#61; &#123;&#125;&#10;&#125;">&#123;&#8230;&#125;</code> |
| [group_configs](variables.tf#L99) | Optional unmanaged groups to create. Can be referenced in backends via outputs. | <code title="map&#40;object&#40;&#123;&#10; zone &#61; string&#10; description &#61; optional&#40;string, &#34;Terraform managed.&#34;&#41;&#10; instances &#61; optional&#40;list&#40;string&#41;&#41;&#10; named_ports &#61; optional&#40;map&#40;number&#41;, &#123;&#125;&#41;&#10;&#125;&#41;&#41;">map&#40;object&#40;&#123;&#8230;&#125;&#41;&#41;</code> | | <code>&#123;&#125;</code> |
| [health_check](variables.tf#L111) | Name of existing health check to use, disables auto-created health check. Also set `health_check_config = null` when cross-referencing an health check from another load balancer module to avoid a Terraform error. | <code>string</code> | | <code>null</code> |
| [health_check_config](variables.tf#L117) | Optional auto-created health check configuration, use the output self-link to set it in the auto healing policy. Refer to examples for usage. | <code title="object&#40;&#123;&#10; check_interval_sec &#61; optional&#40;number&#41;&#10; description &#61; optional&#40;string, &#34;Terraform managed.&#34;&#41;&#10; enable_logging &#61; optional&#40;bool, false&#41;&#10; healthy_threshold &#61; optional&#40;number&#41;&#10; name &#61; optional&#40;string&#41;&#10; timeout_sec &#61; optional&#40;number&#41;&#10; unhealthy_threshold &#61; optional&#40;number&#41;&#10; grpc &#61; optional&#40;object&#40;&#123;&#10; port &#61; optional&#40;number&#41;&#10; port_name &#61; optional&#40;string&#41;&#10; port_specification &#61; optional&#40;string&#41; &#35; USE_FIXED_PORT USE_NAMED_PORT USE_SERVING_PORT&#10; service_name &#61; optional&#40;string&#41;&#10; &#125;&#41;&#41;&#10; http &#61; optional&#40;object&#40;&#123;&#10; host &#61; optional&#40;string&#41;&#10; port &#61; optional&#40;number&#41;&#10; port_name &#61; optional&#40;string&#41;&#10; port_specification &#61; optional&#40;string&#41; &#35; USE_FIXED_PORT USE_NAMED_PORT USE_SERVING_PORT&#10; proxy_header &#61; optional&#40;string&#41;&#10; request_path &#61; optional&#40;string&#41;&#10; response &#61; optional&#40;string&#41;&#10; &#125;&#41;&#41;&#10; http2 &#61; optional&#40;object&#40;&#123;&#10; host &#61; optional&#40;string&#41;&#10; port &#61; optional&#40;number&#41;&#10; port_name &#61; optional&#40;string&#41;&#10; port_specification &#61; optional&#40;string&#41; &#35; USE_FIXED_PORT USE_NAMED_PORT USE_SERVING_PORT&#10; proxy_header &#61; optional&#40;string&#41;&#10; request_path &#61; optional&#40;string&#41;&#10; response &#61; optional&#40;string&#41;&#10; &#125;&#41;&#41;&#10; https &#61; optional&#40;object&#40;&#123;&#10; host &#61; optional&#40;string&#41;&#10; port &#61; optional&#40;number&#41;&#10; port_name &#61; optional&#40;string&#41;&#10; port_specification &#61; optional&#40;string&#41; &#35; USE_FIXED_PORT USE_NAMED_PORT USE_SERVING_PORT&#10; proxy_header &#61; optional&#40;string&#41;&#10; request_path &#61; optional&#40;string&#41;&#10; response &#61; optional&#40;string&#41;&#10; &#125;&#41;&#41;&#10; tcp &#61; optional&#40;object&#40;&#123;&#10; port &#61; optional&#40;number&#41;&#10; port_name &#61; optional&#40;string&#41;&#10; port_specification &#61; optional&#40;string&#41; &#35; USE_FIXED_PORT USE_NAMED_PORT USE_SERVING_PORT&#10; proxy_header &#61; optional&#40;string&#41;&#10; request &#61; optional&#40;string&#41;&#10; response &#61; optional&#40;string&#41;&#10; &#125;&#41;&#41;&#10; ssl &#61; optional&#40;object&#40;&#123;&#10; port &#61; optional&#40;number&#41;&#10; port_name &#61; optional&#40;string&#41;&#10; port_specification &#61; optional&#40;string&#41; &#35; USE_FIXED_PORT USE_NAMED_PORT USE_SERVING_PORT&#10; proxy_header &#61; optional&#40;string&#41;&#10; request &#61; optional&#40;string&#41;&#10; response &#61; optional&#40;string&#41;&#10; &#125;&#41;&#41;&#10;&#125;&#41;">object&#40;&#123;&#8230;&#125;&#41;</code> | | <code title="&#123;&#10; tcp &#61; &#123;&#10; port_specification &#61; &#34;USE_SERVING_PORT&#34;&#10; &#125;&#10;&#125;">&#123;&#8230;&#125;</code> |
| [labels](variables.tf#L195) | Labels set on resources. | <code>map&#40;string&#41;</code> | | <code>&#123;&#125;</code> |
| [service_attachments](variables.tf#L216) | PSC service attachments, keyed by forwarding rule. | <code title="map&#40;object&#40;&#123;&#10; nat_subnets &#61; list&#40;string&#41;&#10; automatic_connection &#61; optional&#40;bool, false&#41;&#10; consumer_accept_lists &#61; optional&#40;map&#40;string&#41;, &#123;&#125;&#41;&#10; consumer_reject_lists &#61; optional&#40;list&#40;string&#41;&#41;&#10; description &#61; optional&#40;string&#41;&#10; domain_name &#61; optional&#40;string&#41;&#10; enable_proxy_protocol &#61; optional&#40;bool, false&#41;&#10; reconcile_connections &#61; optional&#40;bool&#41;&#10;&#125;&#41;&#41;">map&#40;object&#40;&#123;&#8230;&#125;&#41;&#41;</code> | | <code>null</code> |
| [service_label](variables.tf#L231) | Optional prefix of the fully qualified forwarding rule name. | <code>string</code> | | <code>null</code> |
## Outputs

View File

@@ -18,8 +18,8 @@
resource "google_compute_instance_group" "default" {
for_each = var.group_configs
project = var.project_id
zone = each.value.zone
project = local.project_id
zone = lookup(local.ctx.locations, each.value.zone, each.value.zone)
name = "${var.name}-${each.key}"
description = each.value.description
instances = each.value.instances

View File

@@ -31,7 +31,7 @@ locals {
resource "google_compute_health_check" "default" {
provider = google-beta
count = local.hc != null ? 1 : 0
project = var.project_id
project = local.project_id
name = coalesce(local.hc.name, var.name)
description = local.hc.description
check_interval_sec = local.hc.check_interval_sec

View File

@@ -16,19 +16,34 @@
locals {
_service_attachments = (
var.service_attachments == null ? {} : var.service_attachments
)
bs_conntrack = var.backend_service_config.connection_tracking
bs_failover = var.backend_service_config.failover_config
forwarding_rule_names = {
for k, v in var.forwarding_rules_config :
k => k == "" ? var.name : "${var.name}-${k}"
}
ctx = {
for k, v in var.context : k => {
for kk, vv in v : "${local.ctx_p}${k}:${kk}" => vv
}
}
ctx_p = "$"
health_check = (
var.health_check != null
? var.health_check
: google_compute_health_check.default[0].self_link
)
_service_attachments = (
var.service_attachments == null ? {} : var.service_attachments
network = lookup(
local.ctx.networks, var.vpc_config.network, var.vpc_config.network
)
project_id = lookup(
local.ctx.project_ids, var.project_id, var.project_id
)
region = lookup(
local.ctx.locations, var.region, var.region
)
service_attachments = {
for k, v in local._service_attachments :
@@ -44,36 +59,38 @@ moved {
resource "google_compute_forwarding_rule" "default" {
for_each = var.forwarding_rules_config
provider = google-beta
project = var.project_id
project = local.project_id
name = coalesce(each.value.name, local.forwarding_rule_names[each.key])
region = var.region
region = local.region
description = each.value.description
ip_address = each.value.address
ip_address = try(local.ctx.addresses[each.value.address], each.value.address)
ip_protocol = each.value.protocol
ip_version = each.value.address != null ? null : each.value.ipv6 == true ? "IPV6" : "IPV4" # do not set if address is provided
backend_service = (
google_compute_region_backend_service.default.self_link
)
load_balancing_scheme = "INTERNAL"
network = var.vpc_config.network
network = local.network
ports = each.value.ports # "nnnnn" or "nnnnn,nnnnn,nnnnn" max 5
subnetwork = var.vpc_config.subnetwork
allow_global_access = each.value.global_access
labels = var.labels
all_ports = each.value.ports == null ? true : null
service_label = var.service_label
subnetwork = lookup(
local.ctx.subnets, var.vpc_config.subnetwork, var.vpc_config.subnetwork
)
allow_global_access = each.value.global_access
labels = var.labels
all_ports = each.value.ports == null ? true : null
service_label = var.service_label
# is_mirroring_collector = false
}
resource "google_compute_region_backend_service" "default" {
provider = google-beta
project = var.project_id
region = var.region
project = local.project_id
region = local.region
name = coalesce(var.backend_service_config.name, var.name)
description = var.backend_service_config.description
load_balancing_scheme = "INTERNAL"
protocol = var.backend_service_config.protocol
network = var.vpc_config.network
network = local.network
health_checks = [local.health_check]
connection_draining_timeout_sec = var.backend_service_config.connection_draining_timeout_sec
session_affinity = var.backend_service_config.session_affinity
@@ -135,12 +152,14 @@ resource "google_compute_region_backend_service" "default" {
resource "google_compute_service_attachment" "default" {
for_each = local.service_attachments
project = var.project_id
region = var.region
project = local.project_id
region = local.region
name = local.forwarding_rule_names[each.key]
description = var.description
target_service = google_compute_forwarding_rule.default[each.key].id
nat_subnets = each.value.nat_subnets
nat_subnets = each.value.nat_subnets == null ? null : [
for s in each.value.nat_subnets : lookup(local.ctx.subnets, s, s)
]
connection_preference = (
each.value.automatic_connection ? "ACCEPT_AUTOMATIC" : "ACCEPT_MANUAL"
)

View File

@@ -61,6 +61,19 @@ variable "backends" {
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 "description" {
description = "Optional description used for resources."
type = string

View File

@@ -269,13 +269,14 @@ module "firewall" {
| name | description | type | required | default |
|---|---|:---:|:---:|:---:|
| [network](variables.tf#L111) | Name of the network this set of firewall rules applies to. | <code>string</code> | ✓ | |
| [project_id](variables.tf#L116) | Project id of the project that holds the network. | <code>string</code> | ✓ | |
| [default_rules_config](variables.tf#L17) | Optionally created convenience rules. Set the 'disabled' attribute to true, or individual rule attributes to empty lists to disable. | <code title="object&#40;&#123;&#10; admin_ranges &#61; optional&#40;list&#40;string&#41;&#41;&#10; disabled &#61; optional&#40;bool, false&#41;&#10; http_ranges &#61; optional&#40;list&#40;string&#41;, &#91;&#10; &#34;35.191.0.0&#47;16&#34;, &#34;130.211.0.0&#47;22&#34;, &#34;209.85.152.0&#47;22&#34;, &#34;209.85.204.0&#47;22&#34;&#93;&#10; &#41;&#10; http_tags &#61; optional&#40;list&#40;string&#41;, &#91;&#34;http-server&#34;&#93;&#41;&#10; https_ranges &#61; optional&#40;list&#40;string&#41;, &#91;&#10; &#34;35.191.0.0&#47;16&#34;, &#34;130.211.0.0&#47;22&#34;, &#34;209.85.152.0&#47;22&#34;, &#34;209.85.204.0&#47;22&#34;&#93;&#10; &#41;&#10; https_tags &#61; optional&#40;list&#40;string&#41;, &#91;&#34;https-server&#34;&#93;&#41;&#10; ssh_ranges &#61; optional&#40;list&#40;string&#41;, &#91;&#34;35.235.240.0&#47;20&#34;&#93;&#41;&#10; ssh_tags &#61; optional&#40;list&#40;string&#41;, &#91;&#34;ssh&#34;&#93;&#41;&#10;&#125;&#41;">object&#40;&#123;&#8230;&#125;&#41;</code> | | <code>&#123;&#125;</code> |
| [egress_rules](variables.tf#L37) | List of egress rule definitions, default to deny action. Null destination ranges will be replaced with 0/0. | <code title="map&#40;object&#40;&#123;&#10; deny &#61; optional&#40;bool, true&#41;&#10; description &#61; optional&#40;string&#41;&#10; destination_ranges &#61; optional&#40;list&#40;string&#41;&#41;&#10; disabled &#61; optional&#40;bool, false&#41;&#10; enable_logging &#61; optional&#40;object&#40;&#123;&#10; include_metadata &#61; optional&#40;bool&#41;&#10; &#125;&#41;&#41;&#10; priority &#61; optional&#40;number, 1000&#41;&#10; source_ranges &#61; optional&#40;list&#40;string&#41;&#41;&#10; targets &#61; optional&#40;list&#40;string&#41;&#41;&#10; use_service_accounts &#61; optional&#40;bool, false&#41;&#10; rules &#61; optional&#40;list&#40;object&#40;&#123;&#10; protocol &#61; string&#10; ports &#61; optional&#40;list&#40;string&#41;&#41;&#10; &#125;&#41;&#41;, &#91;&#123; protocol &#61; &#34;all&#34; &#125;&#93;&#41;&#10;&#125;&#41;&#41;">map&#40;object&#40;&#123;&#8230;&#125;&#41;&#41;</code> | | <code>&#123;&#125;</code> |
| [factories_config](variables.tf#L60) | Paths to data files and folders that enable factory functionality. | <code title="object&#40;&#123;&#10; cidr_tpl_file &#61; optional&#40;string&#41;&#10; rules_folder &#61; optional&#40;string&#41;&#10;&#125;&#41;">object&#40;&#123;&#8230;&#125;&#41;</code> | | <code>&#123;&#125;</code> |
| [ingress_rules](variables.tf#L70) | List of ingress rule definitions, default to allow action. Null source ranges will be replaced with 0/0. | <code title="map&#40;object&#40;&#123;&#10; deny &#61; optional&#40;bool, false&#41;&#10; description &#61; optional&#40;string&#41;&#10; destination_ranges &#61; optional&#40;list&#40;string&#41;, &#91;&#93;&#41; &#35; empty list is needed as default to allow deletion after initial creation with a value. See https:&#47;&#47;github.com&#47;hashicorp&#47;terraform-provider-google&#47;issues&#47;14270&#10; disabled &#61; optional&#40;bool, false&#41;&#10; enable_logging &#61; optional&#40;object&#40;&#123;&#10; include_metadata &#61; optional&#40;bool&#41;&#10; &#125;&#41;&#41;&#10; priority &#61; optional&#40;number, 1000&#41;&#10; source_ranges &#61; optional&#40;list&#40;string&#41;&#41;&#10; sources &#61; optional&#40;list&#40;string&#41;&#41;&#10; targets &#61; optional&#40;list&#40;string&#41;&#41;&#10; use_service_accounts &#61; optional&#40;bool, false&#41;&#10; rules &#61; optional&#40;list&#40;object&#40;&#123;&#10; protocol &#61; string&#10; ports &#61; optional&#40;list&#40;string&#41;&#41;&#10; &#125;&#41;&#41;, &#91;&#123; protocol &#61; &#34;all&#34; &#125;&#93;&#41;&#10;&#125;&#41;&#41;">map&#40;object&#40;&#123;&#8230;&#125;&#41;&#41;</code> | | <code>&#123;&#125;</code> |
| [named_ranges](variables.tf#L94) | Define mapping of names to ranges that can be used in custom rules. | <code>map&#40;list&#40;string&#41;&#41;</code> | | <code title="&#123;&#10; any &#61; &#91;&#34;0.0.0.0&#47;0&#34;&#93;&#10; dns-forwarders &#61; &#91;&#34;35.199.192.0&#47;19&#34;&#93;&#10; health-checkers &#61; &#91;&#10; &#34;35.191.0.0&#47;16&#34;, &#34;130.211.0.0&#47;22&#34;, &#34;209.85.152.0&#47;22&#34;, &#34;209.85.204.0&#47;22&#34;&#10; &#93;&#10; iap-forwarders &#61; &#91;&#34;35.235.240.0&#47;20&#34;&#93;&#10; private-googleapis &#61; &#91;&#34;199.36.153.8&#47;30&#34;&#93;&#10; restricted-googleapis &#61; &#91;&#34;199.36.153.4&#47;30&#34;&#93;&#10; rfc1918 &#61; &#91;&#34;10.0.0.0&#47;8&#34;, &#34;172.16.0.0&#47;12&#34;, &#34;192.168.0.0&#47;16&#34;&#93;&#10;&#125;">&#123;&#8230;&#125;</code> |
| [network](variables.tf#L123) | Name of the network this set of firewall rules applies to. | <code>string</code> | ✓ | |
| [project_id](variables.tf#L128) | Project id of the project that holds the network. | <code>string</code> | ✓ | |
| [context](variables.tf#L17) | Context-specific interpolations. | <code title="object&#40;&#123;&#10; cidr_ranges &#61; optional&#40;map&#40;string&#41;, &#123;&#125;&#41;&#10; iam_principals &#61; optional&#40;map&#40;string&#41;, &#123;&#125;&#41;&#10; networks &#61; optional&#40;map&#40;string&#41;, &#123;&#125;&#41;&#10; project_ids &#61; optional&#40;map&#40;string&#41;, &#123;&#125;&#41;&#10;&#125;&#41;">object&#40;&#123;&#8230;&#125;&#41;</code> | | <code>&#123;&#125;</code> |
| [default_rules_config](variables.tf#L29) | Optionally created convenience rules. Set the 'disabled' attribute to true, or individual rule attributes to empty lists to disable. | <code title="object&#40;&#123;&#10; admin_ranges &#61; optional&#40;list&#40;string&#41;&#41;&#10; disabled &#61; optional&#40;bool, false&#41;&#10; http_ranges &#61; optional&#40;list&#40;string&#41;, &#91;&#10; &#34;35.191.0.0&#47;16&#34;, &#34;130.211.0.0&#47;22&#34;, &#34;209.85.152.0&#47;22&#34;, &#34;209.85.204.0&#47;22&#34;&#93;&#10; &#41;&#10; http_tags &#61; optional&#40;list&#40;string&#41;, &#91;&#34;http-server&#34;&#93;&#41;&#10; https_ranges &#61; optional&#40;list&#40;string&#41;, &#91;&#10; &#34;35.191.0.0&#47;16&#34;, &#34;130.211.0.0&#47;22&#34;, &#34;209.85.152.0&#47;22&#34;, &#34;209.85.204.0&#47;22&#34;&#93;&#10; &#41;&#10; https_tags &#61; optional&#40;list&#40;string&#41;, &#91;&#34;https-server&#34;&#93;&#41;&#10; ssh_ranges &#61; optional&#40;list&#40;string&#41;, &#91;&#34;35.235.240.0&#47;20&#34;&#93;&#41;&#10; ssh_tags &#61; optional&#40;list&#40;string&#41;, &#91;&#34;ssh&#34;&#93;&#41;&#10;&#125;&#41;">object&#40;&#123;&#8230;&#125;&#41;</code> | | <code>&#123;&#125;</code> |
| [egress_rules](variables.tf#L49) | List of egress rule definitions, default to deny action. Null destination ranges will be replaced with 0/0. | <code title="map&#40;object&#40;&#123;&#10; deny &#61; optional&#40;bool, true&#41;&#10; description &#61; optional&#40;string&#41;&#10; destination_ranges &#61; optional&#40;list&#40;string&#41;&#41;&#10; disabled &#61; optional&#40;bool, false&#41;&#10; enable_logging &#61; optional&#40;object&#40;&#123;&#10; include_metadata &#61; optional&#40;bool&#41;&#10; &#125;&#41;&#41;&#10; priority &#61; optional&#40;number, 1000&#41;&#10; source_ranges &#61; optional&#40;list&#40;string&#41;&#41;&#10; targets &#61; optional&#40;list&#40;string&#41;&#41;&#10; use_service_accounts &#61; optional&#40;bool, false&#41;&#10; rules &#61; optional&#40;list&#40;object&#40;&#123;&#10; protocol &#61; string&#10; ports &#61; optional&#40;list&#40;string&#41;&#41;&#10; &#125;&#41;&#41;, &#91;&#123; protocol &#61; &#34;all&#34; &#125;&#93;&#41;&#10;&#125;&#41;&#41;">map&#40;object&#40;&#123;&#8230;&#125;&#41;&#41;</code> | | <code>&#123;&#125;</code> |
| [factories_config](variables.tf#L72) | Paths to data files and folders that enable factory functionality. | <code title="object&#40;&#123;&#10; cidr_tpl_file &#61; optional&#40;string&#41;&#10; rules_folder &#61; optional&#40;string&#41;&#10;&#125;&#41;">object&#40;&#123;&#8230;&#125;&#41;</code> | | <code>&#123;&#125;</code> |
| [ingress_rules](variables.tf#L82) | List of ingress rule definitions, default to allow action. Null source ranges will be replaced with 0/0. | <code title="map&#40;object&#40;&#123;&#10; deny &#61; optional&#40;bool, false&#41;&#10; description &#61; optional&#40;string&#41;&#10; destination_ranges &#61; optional&#40;list&#40;string&#41;, &#91;&#93;&#41; &#35; empty list is needed as default to allow deletion after initial creation with a value. See https:&#47;&#47;github.com&#47;hashicorp&#47;terraform-provider-google&#47;issues&#47;14270&#10; disabled &#61; optional&#40;bool, false&#41;&#10; enable_logging &#61; optional&#40;object&#40;&#123;&#10; include_metadata &#61; optional&#40;bool&#41;&#10; &#125;&#41;&#41;&#10; priority &#61; optional&#40;number, 1000&#41;&#10; source_ranges &#61; optional&#40;list&#40;string&#41;&#41;&#10; sources &#61; optional&#40;list&#40;string&#41;&#41;&#10; targets &#61; optional&#40;list&#40;string&#41;&#41;&#10; use_service_accounts &#61; optional&#40;bool, false&#41;&#10; rules &#61; optional&#40;list&#40;object&#40;&#123;&#10; protocol &#61; string&#10; ports &#61; optional&#40;list&#40;string&#41;&#41;&#10; &#125;&#41;&#41;, &#91;&#123; protocol &#61; &#34;all&#34; &#125;&#93;&#41;&#10;&#125;&#41;&#41;">map&#40;object&#40;&#123;&#8230;&#125;&#41;&#41;</code> | | <code>&#123;&#125;</code> |
| [named_ranges](variables.tf#L106) | Define mapping of names to ranges that can be used in custom rules. | <code>map&#40;list&#40;string&#41;&#41;</code> | | <code title="&#123;&#10; any &#61; &#91;&#34;0.0.0.0&#47;0&#34;&#93;&#10; dns-forwarders &#61; &#91;&#34;35.199.192.0&#47;19&#34;&#93;&#10; health-checkers &#61; &#91;&#10; &#34;35.191.0.0&#47;16&#34;, &#34;130.211.0.0&#47;22&#34;, &#34;209.85.152.0&#47;22&#34;, &#34;209.85.204.0&#47;22&#34;&#10; &#93;&#10; iap-forwarders &#61; &#91;&#34;35.235.240.0&#47;20&#34;&#93;&#10; private-googleapis &#61; &#91;&#34;199.36.153.8&#47;30&#34;&#93;&#10; restricted-googleapis &#61; &#91;&#34;199.36.153.4&#47;30&#34;&#93;&#10; rfc1918 &#61; &#91;&#34;10.0.0.0&#47;8&#34;, &#34;172.16.0.0&#47;12&#34;, &#34;192.168.0.0&#47;16&#34;&#93;&#10;&#125;">&#123;&#8230;&#125;</code> |
## Outputs

View File

@@ -25,23 +25,27 @@ locals {
}
resource "google_compute_firewall" "allow-admins" {
count = length(local.default_rules.admin_ranges) > 0 ? 1 : 0
name = "${var.network}-ingress-admins"
description = "Access from the admin subnet to all subnets."
network = var.network
project = var.project_id
source_ranges = local.default_rules.admin_ranges
count = length(local.default_rules.admin_ranges) > 0 ? 1 : 0
project = local.project_id
network = local.network
name = "${local.network_name}-ingress-admins"
description = "Access from the admin subnet to all subnets."
source_ranges = [
for r in local.default_rules.admin_ranges : lookup(local.ctx.cidr_ranges, r, r)
]
allow { protocol = "all" }
}
resource "google_compute_firewall" "allow-tag-http" {
count = length(local.default_rules.http_ranges) > 0 ? 1 : 0
name = "${var.network}-ingress-tag-http"
description = "Allow http to machines with matching tags."
network = var.network
project = var.project_id
source_ranges = local.default_rules.http_ranges
target_tags = local.default_rules.http_tags
count = length(local.default_rules.http_ranges) > 0 ? 1 : 0
project = local.project_id
network = local.network
name = "${local.network_name}-ingress-tag-http"
description = "Allow http to machines with matching tags."
source_ranges = [
for r in local.default_rules.http_ranges : lookup(local.ctx.cidr_ranges, r, r)
]
target_tags = local.default_rules.http_tags
allow {
protocol = "tcp"
ports = ["80"]
@@ -49,13 +53,15 @@ resource "google_compute_firewall" "allow-tag-http" {
}
resource "google_compute_firewall" "allow-tag-https" {
count = length(local.default_rules.https_ranges) > 0 ? 1 : 0
name = "${var.network}-ingress-tag-https"
description = "Allow http to machines with matching tags."
network = var.network
project = var.project_id
source_ranges = local.default_rules.https_ranges
target_tags = local.default_rules.https_tags
count = length(local.default_rules.https_ranges) > 0 ? 1 : 0
project = local.project_id
network = local.network
name = "${local.network_name}-ingress-tag-https"
description = "Allow http to machines with matching tags."
source_ranges = [
for r in local.default_rules.https_ranges : lookup(local.ctx.cidr_ranges, r, r)
]
target_tags = local.default_rules.https_tags
allow {
protocol = "tcp"
ports = ["443"]
@@ -63,13 +69,15 @@ resource "google_compute_firewall" "allow-tag-https" {
}
resource "google_compute_firewall" "allow-tag-ssh" {
count = length(local.default_rules.ssh_ranges) > 0 ? 1 : 0
name = "${var.network}-ingress-tag-ssh"
description = "Allow SSH to machines with matching tags."
network = var.network
project = var.project_id
source_ranges = local.default_rules.ssh_ranges
target_tags = local.default_rules.ssh_tags
count = length(local.default_rules.ssh_ranges) > 0 ? 1 : 0
project = local.project_id
network = local.network
name = "${local.network_name}-ingress-tag-ssh"
description = "Allow SSH to machines with matching tags."
source_ranges = [
for r in local.default_rules.ssh_ranges : lookup(local.ctx.cidr_ranges, r, r)
]
target_tags = local.default_rules.ssh_tags
allow {
protocol = "tcp"
ports = ["22"]

View File

@@ -66,6 +66,15 @@ locals {
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 :
@@ -94,30 +103,32 @@ locals {
resource "google_compute_firewall" "custom-rules" {
for_each = local.rules
project = var.project_id
network = var.network
project = local.project_id
network = local.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.source_ranges == null && each.value.sources == null
each.value.direction == "INGRESS" && each.value.sources == null
? ["0.0.0.0/0"]
: each.value.source_ranges
: null
)
#for egress, we will include the source_ranges when provided. Previously, null was forced
: each.value.source_ranges
: [
for r in each.value.source_ranges : lookup(local.ctx.cidr_ranges, r, r)
]
)
destination_ranges = (
each.value.direction == "EGRESS"
each.value.destination_ranges == null
? (
each.value.destination_ranges == null
each.value.direction == "EGRESS"
? ["0.0.0.0/0"]
: each.value.destination_ranges
: null
)
#for ingress, we will include the destination_ranges when provided. Previously, null was forced
: each.value.destination_ranges
: [
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"
@@ -126,14 +137,19 @@ resource "google_compute_firewall" "custom-rules" {
)
source_service_accounts = (
each.value.use_service_accounts && each.value.direction == "INGRESS"
? each.value.sources
? (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 ? null : each.value.targets
!each.value.use_service_accounts ? each.value.targets : null
)
target_service_accounts = (
each.value.use_service_accounts ? each.value.targets : null
!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

View File

@@ -14,6 +14,18 @@
* limitations under the License.
*/
variable "context" {
description = "Context-specific interpolations."
type = object({
cidr_ranges = optional(map(string), {})
iam_principals = optional(map(string), {})
networks = optional(map(string), {})
project_ids = optional(map(string), {})
})
default = {}
nullable = false
}
variable "default_rules_config" {
description = "Optionally created convenience rules. Set the 'disabled' attribute to true, or individual rule attributes to empty lists to disable."
type = object({

View File

@@ -486,7 +486,7 @@ module "vpc" {
project_id = var.project_id
name = "my-network"
context = {
regions = {
locations = {
primary = "europe-west4"
secondary = "europe-west8"
}
@@ -500,7 +500,7 @@ module "vpc" {
```yaml
name: simple
region: $regions:primary
region: $locations:primary
ip_cidr_range: 10.0.1.0/24
# tftest-file id=subnet-simple path=config/subnets/subnet-simple.yaml schema=subnet.schema.json
@@ -899,32 +899,32 @@ secondary_ip_ranges:
| name | description | type | required | default |
|---|---|:---:|:---:|:---:|
| [name](variables.tf#L171) | The name of the network being created. | <code>string</code> | ✓ | |
| [project_id](variables.tf#L248) | The ID of the project where this VPC will be created. | <code>string</code> | ✓ | |
| [name](variables.tf#L184) | The name of the network being created. | <code>string</code> | ✓ | |
| [project_id](variables.tf#L261) | The ID of the project where this VPC will be created. | <code>string</code> | ✓ | |
| [auto_create_subnetworks](variables.tf#L17) | Set to true to create an auto mode subnet, defaults to custom mode. | <code>bool</code> | | <code>false</code> |
| [context](variables.tf#L23) | Context-specific interpolations. | <code title="object&#40;&#123;&#10; regions &#61; optional&#40;map&#40;string&#41;, &#123;&#125;&#41;&#10;&#125;&#41;">object&#40;&#123;&#8230;&#125;&#41;</code> | | <code>&#123;&#125;</code> |
| [create_googleapis_routes](variables.tf#L32) | Toggle creation of googleapis private/restricted routes. Disabled when vpc creation is turned off, or when set to null. | <code title="object&#40;&#123;&#10; directpath &#61; optional&#40;bool, true&#41;&#10; directpath-6 &#61; optional&#40;bool, false&#41;&#10; private &#61; optional&#40;bool, true&#41;&#10; private-6 &#61; optional&#40;bool, false&#41;&#10; restricted &#61; optional&#40;bool, true&#41;&#10; restricted-6 &#61; optional&#40;bool, false&#41;&#10;&#125;&#41;">object&#40;&#123;&#8230;&#125;&#41;</code> | | <code>&#123;&#125;</code> |
| [delete_default_routes_on_create](variables.tf#L45) | Set to true to delete the default routes at creation time. | <code>bool</code> | | <code>false</code> |
| [description](variables.tf#L51) | An optional description of this resource (triggers recreation on change). | <code>string</code> | | <code>&#34;Terraform-managed.&#34;</code> |
| [dns_policy](variables.tf#L57) | DNS policy setup for the VPC. | <code title="object&#40;&#123;&#10; inbound &#61; optional&#40;bool&#41;&#10; logging &#61; optional&#40;bool&#41;&#10; outbound &#61; optional&#40;object&#40;&#123;&#10; private_ns &#61; list&#40;string&#41;&#10; public_ns &#61; list&#40;string&#41;&#10; &#125;&#41;&#41;&#10;&#125;&#41;">object&#40;&#123;&#8230;&#125;&#41;</code> | | <code>null</code> |
| [factories_config](variables.tf#L70) | Paths to data files and folders that enable factory functionality. | <code title="object&#40;&#123;&#10; subnets_folder &#61; optional&#40;string&#41;&#10; internal_ranges_folder &#61; optional&#40;string&#41;&#10;&#125;&#41;">object&#40;&#123;&#8230;&#125;&#41;</code> | | <code>&#123;&#125;</code> |
| [firewall_policy_enforcement_order](variables.tf#L79) | Order that Firewall Rules and Firewall Policies are evaluated. Can be either 'BEFORE_CLASSIC_FIREWALL' or 'AFTER_CLASSIC_FIREWALL'. | <code>string</code> | | <code>&#34;AFTER_CLASSIC_FIREWALL&#34;</code> |
| [internal_ranges](variables.tf#L91) | Internal range configuration for IPAM operations within the VPC network. | <code title="list&#40;object&#40;&#123;&#10; name &#61; string&#10; description &#61; optional&#40;string&#41;&#10; ip_cidr_range &#61; optional&#40;string&#41;&#10; labels &#61; optional&#40;map&#40;string&#41;, &#123;&#125;&#41;&#10; usage &#61; string&#10; peering &#61; string&#10; prefix_length &#61; optional&#40;number&#41;&#10; target_cidr_range &#61; optional&#40;list&#40;string&#41;&#41;&#10; exclude_cidr_ranges &#61; optional&#40;list&#40;string&#41;&#41;&#10; overlaps &#61; optional&#40;list&#40;string&#41;&#41;&#10; immutable &#61; optional&#40;bool&#41;&#10; allocation_options &#61; optional&#40;object&#40;&#123;&#10; allocation_strategy &#61; optional&#40;string&#41;&#10; first_available_ranges_lookup_size &#61; optional&#40;number&#41;&#10; &#125;&#41;&#41;&#10; migration &#61; optional&#40;object&#40;&#123;&#10; source &#61; string&#10; target &#61; string&#10; &#125;&#41;&#41;&#10;&#125;&#41;&#41;">list&#40;object&#40;&#123;&#8230;&#125;&#41;&#41;</code> | | <code>&#91;&#93;</code> |
| [ipv6_config](variables.tf#L155) | Optional IPv6 configuration for this network. | <code title="object&#40;&#123;&#10; enable_ula_internal &#61; optional&#40;bool&#41;&#10; internal_range &#61; optional&#40;string&#41;&#10;&#125;&#41;">object&#40;&#123;&#8230;&#125;&#41;</code> | | <code>&#123;&#125;</code> |
| [mtu](variables.tf#L165) | Maximum Transmission Unit in bytes. The minimum value for this field is 1460 (the default) and the maximum value is 1500 bytes. | <code>number</code> | | <code>null</code> |
| [network_attachments](variables.tf#L176) | PSC network attachments, names as keys. | <code title="map&#40;object&#40;&#123;&#10; subnet &#61; string&#10; automatic_connection &#61; optional&#40;bool, false&#41;&#10; description &#61; optional&#40;string, &#34;Terraform-managed.&#34;&#41;&#10; producer_accept_lists &#61; optional&#40;list&#40;string&#41;&#41;&#10; producer_reject_lists &#61; optional&#40;list&#40;string&#41;&#41;&#10;&#125;&#41;&#41;">map&#40;object&#40;&#123;&#8230;&#125;&#41;&#41;</code> | | <code>&#123;&#125;</code> |
| [peering_config](variables.tf#L189) | VPC peering configuration. | <code title="object&#40;&#123;&#10; peer_vpc_self_link &#61; string&#10; create_remote_peer &#61; optional&#40;bool, true&#41;&#10; export_routes &#61; optional&#40;bool&#41;&#10; import_routes &#61; optional&#40;bool&#41;&#10;&#125;&#41;">object&#40;&#123;&#8230;&#125;&#41;</code> | | <code>null</code> |
| [policy_based_routes](variables.tf#L200) | Policy based routes, keyed by name. | <code title="map&#40;object&#40;&#123;&#10; description &#61; optional&#40;string, &#34;Terraform-managed.&#34;&#41;&#10; labels &#61; optional&#40;map&#40;string&#41;&#41;&#10; priority &#61; optional&#40;number&#41;&#10; next_hop_ilb_ip &#61; optional&#40;string&#41;&#10; use_default_routing &#61; optional&#40;bool, false&#41;&#10; filter &#61; optional&#40;object&#40;&#123;&#10; ip_protocol &#61; optional&#40;string&#41;&#10; dest_range &#61; optional&#40;string&#41;&#10; src_range &#61; optional&#40;string&#41;&#10; &#125;&#41;, &#123;&#125;&#41;&#10; target &#61; optional&#40;object&#40;&#123;&#10; interconnect_attachment &#61; optional&#40;string&#41;&#10; tags &#61; optional&#40;list&#40;string&#41;&#41;&#10; &#125;&#41;, &#123;&#125;&#41;&#10;&#125;&#41;&#41;">map&#40;object&#40;&#123;&#8230;&#125;&#41;&#41;</code> | | <code>&#123;&#125;</code> |
| [psa_configs](variables.tf#L253) | The Private Service Access configuration. | <code title="list&#40;object&#40;&#123;&#10; deletion_policy &#61; optional&#40;string, null&#41;&#10; ranges &#61; map&#40;string&#41;&#10; export_routes &#61; optional&#40;bool, false&#41;&#10; import_routes &#61; optional&#40;bool, false&#41;&#10; peered_domains &#61; optional&#40;list&#40;string&#41;, &#91;&#93;&#41;&#10; range_prefix &#61; optional&#40;string&#41;&#10; service_producer &#61; optional&#40;string, &#34;servicenetworking.googleapis.com&#34;&#41;&#10;&#125;&#41;&#41;">list&#40;object&#40;&#123;&#8230;&#125;&#41;&#41;</code> | | <code>&#91;&#93;</code> |
| [routes](variables.tf#L284) | Network routes, keyed by name. | <code title="map&#40;object&#40;&#123;&#10; description &#61; optional&#40;string, &#34;Terraform-managed.&#34;&#41;&#10; dest_range &#61; string&#10; next_hop_type &#61; string &#35; gateway, instance, ip, vpn_tunnel, ilb&#10; next_hop &#61; string&#10; priority &#61; optional&#40;number&#41;&#10; tags &#61; optional&#40;list&#40;string&#41;&#41;&#10;&#125;&#41;&#41;">map&#40;object&#40;&#123;&#8230;&#125;&#41;&#41;</code> | | <code>&#123;&#125;</code> |
| [routing_mode](variables.tf#L305) | The network routing mode (default 'GLOBAL'). | <code>string</code> | | <code>&#34;GLOBAL&#34;</code> |
| [shared_vpc_host](variables.tf#L315) | Enable shared VPC for this project. | <code>bool</code> | | <code>false</code> |
| [shared_vpc_service_projects](variables.tf#L321) | Shared VPC service projects to register with this host. | <code>list&#40;string&#41;</code> | | <code>&#91;&#93;</code> |
| [subnets](variables.tf#L327) | Subnet configuration. | <code title="list&#40;object&#40;&#123;&#10; name &#61; string&#10; ip_cidr_range &#61; optional&#40;string&#41;&#10; region &#61; string&#10; description &#61; optional&#40;string&#41;&#10; enable_private_access &#61; optional&#40;bool, true&#41;&#10; allow_subnet_cidr_routes_overlap &#61; optional&#40;bool, null&#41;&#10; reserved_internal_range &#61; optional&#40;string&#41;&#10; flow_logs_config &#61; optional&#40;object&#40;&#123;&#10; aggregation_interval &#61; optional&#40;string&#41;&#10; filter_expression &#61; optional&#40;string&#41;&#10; flow_sampling &#61; optional&#40;number&#41;&#10; metadata &#61; optional&#40;string&#41;&#10; metadata_fields &#61; optional&#40;list&#40;string&#41;&#41;&#10; &#125;&#41;&#41;&#10; ipv6 &#61; optional&#40;object&#40;&#123;&#10; access_type &#61; optional&#40;string, &#34;INTERNAL&#34;&#41;&#10; ipv6_only &#61; optional&#40;bool, false&#41;&#10; &#125;&#41;&#41;&#10; ip_collection &#61; optional&#40;string, null&#41;&#10; secondary_ip_ranges &#61; optional&#40;map&#40;object&#40;&#123;&#10; ip_cidr_range &#61; optional&#40;string&#41;&#10; reserved_internal_range &#61; optional&#40;string&#41;&#10; &#125;&#41;&#41;&#41;&#10; iam &#61; optional&#40;map&#40;list&#40;string&#41;&#41;, &#123;&#125;&#41;&#10; iam_bindings &#61; optional&#40;map&#40;object&#40;&#123;&#10; role &#61; string&#10; members &#61; list&#40;string&#41;&#10; condition &#61; optional&#40;object&#40;&#123;&#10; expression &#61; string&#10; title &#61; string&#10; description &#61; optional&#40;string&#41;&#10; &#125;&#41;&#41;&#10; &#125;&#41;&#41;, &#123;&#125;&#41;&#10; iam_bindings_additive &#61; optional&#40;map&#40;object&#40;&#123;&#10; member &#61; string&#10; role &#61; string&#10; condition &#61; optional&#40;object&#40;&#123;&#10; expression &#61; string&#10; title &#61; string&#10; description &#61; optional&#40;string&#41;&#10; &#125;&#41;&#41;&#10; &#125;&#41;&#41;, &#123;&#125;&#41;&#10;&#125;&#41;&#41;">list&#40;object&#40;&#123;&#8230;&#125;&#41;&#41;</code> | | <code>&#91;&#93;</code> |
| [subnets_private_nat](variables.tf#L407) | List of private NAT subnets. | <code title="list&#40;object&#40;&#123;&#10; name &#61; string&#10; ip_cidr_range &#61; string&#10; region &#61; string&#10; description &#61; optional&#40;string&#41;&#10;&#125;&#41;&#41;">list&#40;object&#40;&#123;&#8230;&#125;&#41;&#41;</code> | | <code>&#91;&#93;</code> |
| [subnets_proxy_only](variables.tf#L419) | List of proxy-only subnets for Regional HTTPS or Internal HTTPS load balancers. Note: Only one proxy-only subnet for each VPC network in each region can be active. | <code title="list&#40;object&#40;&#123;&#10; name &#61; string&#10; ip_cidr_range &#61; string&#10; region &#61; string&#10; description &#61; optional&#40;string&#41;&#10; active &#61; optional&#40;bool, true&#41;&#10; global &#61; optional&#40;bool, false&#41;&#10;&#10;&#10; iam &#61; optional&#40;map&#40;list&#40;string&#41;&#41;, &#123;&#125;&#41;&#10; iam_bindings &#61; optional&#40;map&#40;object&#40;&#123;&#10; role &#61; string&#10; members &#61; list&#40;string&#41;&#10; condition &#61; optional&#40;object&#40;&#123;&#10; expression &#61; string&#10; title &#61; string&#10; description &#61; optional&#40;string&#41;&#10; &#125;&#41;&#41;&#10; &#125;&#41;&#41;, &#123;&#125;&#41;&#10; iam_bindings_additive &#61; optional&#40;map&#40;object&#40;&#123;&#10; member &#61; string&#10; role &#61; string&#10; condition &#61; optional&#40;object&#40;&#123;&#10; expression &#61; string&#10; title &#61; string&#10; description &#61; optional&#40;string&#41;&#10; &#125;&#41;&#41;&#10; &#125;&#41;&#41;, &#123;&#125;&#41;&#10;&#125;&#41;&#41;">list&#40;object&#40;&#123;&#8230;&#125;&#41;&#41;</code> | | <code>&#91;&#93;</code> |
| [subnets_psc](variables.tf#L453) | List of subnets for Private Service Connect service producers. | <code title="list&#40;object&#40;&#123;&#10; name &#61; string&#10; ip_cidr_range &#61; string&#10; region &#61; string&#10; description &#61; optional&#40;string&#41;&#10;&#10;&#10; iam &#61; optional&#40;map&#40;list&#40;string&#41;&#41;, &#123;&#125;&#41;&#10; iam_bindings &#61; optional&#40;map&#40;object&#40;&#123;&#10; role &#61; string&#10; members &#61; list&#40;string&#41;&#10; condition &#61; optional&#40;object&#40;&#123;&#10; expression &#61; string&#10; title &#61; string&#10; description &#61; optional&#40;string&#41;&#10; &#125;&#41;&#41;&#10; &#125;&#41;&#41;, &#123;&#125;&#41;&#10; iam_bindings_additive &#61; optional&#40;map&#40;object&#40;&#123;&#10; member &#61; string&#10; role &#61; string&#10; condition &#61; optional&#40;object&#40;&#123;&#10; expression &#61; string&#10; title &#61; string&#10; description &#61; optional&#40;string&#41;&#10; &#125;&#41;&#41;&#10; &#125;&#41;&#41;, &#123;&#125;&#41;&#10;&#125;&#41;&#41;">list&#40;object&#40;&#123;&#8230;&#125;&#41;&#41;</code> | | <code>&#91;&#93;</code> |
| [vpc_reuse](variables.tf#L485) | Reuse existing VPC if not null. If the network_id number is not passed in, a data source is used. | <code title="object&#40;&#123;&#10; use_data_source &#61; optional&#40;bool, true&#41;&#10; attributes &#61; optional&#40;object&#40;&#123;&#10; network_id &#61; number&#10; &#125;&#41;&#41;&#10;&#125;&#41;">object&#40;&#123;&#8230;&#125;&#41;</code> | | <code>null</code> |
| [context](variables.tf#L23) | Context-specific interpolations. | <code title="object&#40;&#123;&#10; addresses &#61; optional&#40;map&#40;string&#41;, &#123;&#125;&#41;&#10; cidr_ranges &#61; optional&#40;map&#40;string&#41;, &#123;&#125;&#41;&#10; condition_vars &#61; optional&#40;map&#40;map&#40;string&#41;&#41;, &#123;&#125;&#41;&#10; custom_roles &#61; optional&#40;map&#40;string&#41;, &#123;&#125;&#41;&#10; iam_principals &#61; optional&#40;map&#40;string&#41;, &#123;&#125;&#41;&#10; locations &#61; optional&#40;map&#40;string&#41;, &#123;&#125;&#41;&#10; networks &#61; optional&#40;map&#40;string&#41;, &#123;&#125;&#41;&#10; regions &#61; optional&#40;map&#40;string&#41;, &#123;&#125;&#41;&#10; project_ids &#61; optional&#40;map&#40;string&#41;, &#123;&#125;&#41;&#10;&#125;&#41;">object&#40;&#123;&#8230;&#125;&#41;</code> | | <code>&#123;&#125;</code> |
| [create_googleapis_routes](variables.tf#L45) | Toggle creation of googleapis private/restricted routes. Disabled when vpc creation is turned off, or when set to null. | <code title="object&#40;&#123;&#10; directpath &#61; optional&#40;bool, true&#41;&#10; directpath-6 &#61; optional&#40;bool, false&#41;&#10; private &#61; optional&#40;bool, true&#41;&#10; private-6 &#61; optional&#40;bool, false&#41;&#10; restricted &#61; optional&#40;bool, true&#41;&#10; restricted-6 &#61; optional&#40;bool, false&#41;&#10;&#125;&#41;">object&#40;&#123;&#8230;&#125;&#41;</code> | | <code>&#123;&#125;</code> |
| [delete_default_routes_on_create](variables.tf#L58) | Set to true to delete the default routes at creation time. | <code>bool</code> | | <code>false</code> |
| [description](variables.tf#L64) | An optional description of this resource (triggers recreation on change). | <code>string</code> | | <code>&#34;Terraform-managed.&#34;</code> |
| [dns_policy](variables.tf#L70) | DNS policy setup for the VPC. | <code title="object&#40;&#123;&#10; inbound &#61; optional&#40;bool&#41;&#10; logging &#61; optional&#40;bool&#41;&#10; outbound &#61; optional&#40;object&#40;&#123;&#10; private_ns &#61; list&#40;string&#41;&#10; public_ns &#61; list&#40;string&#41;&#10; &#125;&#41;&#41;&#10;&#125;&#41;">object&#40;&#123;&#8230;&#125;&#41;</code> | | <code>null</code> |
| [factories_config](variables.tf#L83) | Paths to data files and folders that enable factory functionality. | <code title="object&#40;&#123;&#10; subnets_folder &#61; optional&#40;string&#41;&#10; internal_ranges_folder &#61; optional&#40;string&#41;&#10;&#125;&#41;">object&#40;&#123;&#8230;&#125;&#41;</code> | | <code>&#123;&#125;</code> |
| [firewall_policy_enforcement_order](variables.tf#L92) | Order that Firewall Rules and Firewall Policies are evaluated. Can be either 'BEFORE_CLASSIC_FIREWALL' or 'AFTER_CLASSIC_FIREWALL'. | <code>string</code> | | <code>&#34;AFTER_CLASSIC_FIREWALL&#34;</code> |
| [internal_ranges](variables.tf#L104) | Internal range configuration for IPAM operations within the VPC network. | <code title="list&#40;object&#40;&#123;&#10; name &#61; string&#10; description &#61; optional&#40;string&#41;&#10; ip_cidr_range &#61; optional&#40;string&#41;&#10; labels &#61; optional&#40;map&#40;string&#41;, &#123;&#125;&#41;&#10; usage &#61; string&#10; peering &#61; string&#10; prefix_length &#61; optional&#40;number&#41;&#10; target_cidr_range &#61; optional&#40;list&#40;string&#41;&#41;&#10; exclude_cidr_ranges &#61; optional&#40;list&#40;string&#41;&#41;&#10; overlaps &#61; optional&#40;list&#40;string&#41;&#41;&#10; immutable &#61; optional&#40;bool&#41;&#10; allocation_options &#61; optional&#40;object&#40;&#123;&#10; allocation_strategy &#61; optional&#40;string&#41;&#10; first_available_ranges_lookup_size &#61; optional&#40;number&#41;&#10; &#125;&#41;&#41;&#10; migration &#61; optional&#40;object&#40;&#123;&#10; source &#61; string&#10; target &#61; string&#10; &#125;&#41;&#41;&#10;&#125;&#41;&#41;">list&#40;object&#40;&#123;&#8230;&#125;&#41;&#41;</code> | | <code>&#91;&#93;</code> |
| [ipv6_config](variables.tf#L168) | Optional IPv6 configuration for this network. | <code title="object&#40;&#123;&#10; enable_ula_internal &#61; optional&#40;bool&#41;&#10; internal_range &#61; optional&#40;string&#41;&#10;&#125;&#41;">object&#40;&#123;&#8230;&#125;&#41;</code> | | <code>&#123;&#125;</code> |
| [mtu](variables.tf#L178) | Maximum Transmission Unit in bytes. The minimum value for this field is 1460 (the default) and the maximum value is 1500 bytes. | <code>number</code> | | <code>null</code> |
| [network_attachments](variables.tf#L189) | PSC network attachments, names as keys. | <code title="map&#40;object&#40;&#123;&#10; subnet &#61; string&#10; automatic_connection &#61; optional&#40;bool, false&#41;&#10; description &#61; optional&#40;string, &#34;Terraform-managed.&#34;&#41;&#10; producer_accept_lists &#61; optional&#40;list&#40;string&#41;&#41;&#10; producer_reject_lists &#61; optional&#40;list&#40;string&#41;&#41;&#10;&#125;&#41;&#41;">map&#40;object&#40;&#123;&#8230;&#125;&#41;&#41;</code> | | <code>&#123;&#125;</code> |
| [peering_config](variables.tf#L202) | VPC peering configuration. | <code title="object&#40;&#123;&#10; peer_vpc_self_link &#61; string&#10; create_remote_peer &#61; optional&#40;bool, true&#41;&#10; export_routes &#61; optional&#40;bool&#41;&#10; import_routes &#61; optional&#40;bool&#41;&#10;&#125;&#41;">object&#40;&#123;&#8230;&#125;&#41;</code> | | <code>null</code> |
| [policy_based_routes](variables.tf#L213) | Policy based routes, keyed by name. | <code title="map&#40;object&#40;&#123;&#10; description &#61; optional&#40;string, &#34;Terraform-managed.&#34;&#41;&#10; labels &#61; optional&#40;map&#40;string&#41;&#41;&#10; priority &#61; optional&#40;number&#41;&#10; next_hop_ilb_ip &#61; optional&#40;string&#41;&#10; use_default_routing &#61; optional&#40;bool, false&#41;&#10; filter &#61; optional&#40;object&#40;&#123;&#10; ip_protocol &#61; optional&#40;string&#41;&#10; dest_range &#61; optional&#40;string&#41;&#10; src_range &#61; optional&#40;string&#41;&#10; &#125;&#41;, &#123;&#125;&#41;&#10; target &#61; optional&#40;object&#40;&#123;&#10; interconnect_attachment &#61; optional&#40;string&#41;&#10; tags &#61; optional&#40;list&#40;string&#41;&#41;&#10; &#125;&#41;, &#123;&#125;&#41;&#10;&#125;&#41;&#41;">map&#40;object&#40;&#123;&#8230;&#125;&#41;&#41;</code> | | <code>&#123;&#125;</code> |
| [psa_configs](variables.tf#L266) | The Private Service Access configuration. | <code title="list&#40;object&#40;&#123;&#10; deletion_policy &#61; optional&#40;string, null&#41;&#10; ranges &#61; map&#40;string&#41;&#10; export_routes &#61; optional&#40;bool, false&#41;&#10; import_routes &#61; optional&#40;bool, false&#41;&#10; peered_domains &#61; optional&#40;list&#40;string&#41;, &#91;&#93;&#41;&#10; range_prefix &#61; optional&#40;string&#41;&#10; service_producer &#61; optional&#40;string, &#34;servicenetworking.googleapis.com&#34;&#41;&#10;&#125;&#41;&#41;">list&#40;object&#40;&#123;&#8230;&#125;&#41;&#41;</code> | | <code>&#91;&#93;</code> |
| [routes](variables.tf#L297) | Network routes, keyed by name. | <code title="map&#40;object&#40;&#123;&#10; description &#61; optional&#40;string, &#34;Terraform-managed.&#34;&#41;&#10; dest_range &#61; string&#10; next_hop_type &#61; string &#35; gateway, instance, ip, vpn_tunnel, ilb&#10; next_hop &#61; string&#10; priority &#61; optional&#40;number&#41;&#10; tags &#61; optional&#40;list&#40;string&#41;&#41;&#10;&#125;&#41;&#41;">map&#40;object&#40;&#123;&#8230;&#125;&#41;&#41;</code> | | <code>&#123;&#125;</code> |
| [routing_mode](variables.tf#L318) | The network routing mode (default 'GLOBAL'). | <code>string</code> | | <code>&#34;GLOBAL&#34;</code> |
| [shared_vpc_host](variables.tf#L328) | Enable shared VPC for this project. | <code>bool</code> | | <code>false</code> |
| [shared_vpc_service_projects](variables.tf#L334) | Shared VPC service projects to register with this host. | <code>list&#40;string&#41;</code> | | <code>&#91;&#93;</code> |
| [subnets](variables.tf#L340) | Subnet configuration. | <code title="list&#40;object&#40;&#123;&#10; name &#61; string&#10; ip_cidr_range &#61; optional&#40;string&#41;&#10; region &#61; string&#10; description &#61; optional&#40;string&#41;&#10; enable_private_access &#61; optional&#40;bool, true&#41;&#10; allow_subnet_cidr_routes_overlap &#61; optional&#40;bool, null&#41;&#10; reserved_internal_range &#61; optional&#40;string&#41;&#10; flow_logs_config &#61; optional&#40;object&#40;&#123;&#10; aggregation_interval &#61; optional&#40;string&#41;&#10; filter_expression &#61; optional&#40;string&#41;&#10; flow_sampling &#61; optional&#40;number&#41;&#10; metadata &#61; optional&#40;string&#41;&#10; metadata_fields &#61; optional&#40;list&#40;string&#41;&#41;&#10; &#125;&#41;&#41;&#10; ipv6 &#61; optional&#40;object&#40;&#123;&#10; access_type &#61; optional&#40;string, &#34;INTERNAL&#34;&#41;&#10; ipv6_only &#61; optional&#40;bool, false&#41;&#10; &#125;&#41;&#41;&#10; ip_collection &#61; optional&#40;string, null&#41;&#10; secondary_ip_ranges &#61; optional&#40;map&#40;object&#40;&#123;&#10; ip_cidr_range &#61; optional&#40;string&#41;&#10; reserved_internal_range &#61; optional&#40;string&#41;&#10; &#125;&#41;&#41;&#41;&#10; iam &#61; optional&#40;map&#40;list&#40;string&#41;&#41;, &#123;&#125;&#41;&#10; iam_bindings &#61; optional&#40;map&#40;object&#40;&#123;&#10; role &#61; string&#10; members &#61; list&#40;string&#41;&#10; condition &#61; optional&#40;object&#40;&#123;&#10; expression &#61; string&#10; title &#61; string&#10; description &#61; optional&#40;string&#41;&#10; &#125;&#41;&#41;&#10; &#125;&#41;&#41;, &#123;&#125;&#41;&#10; iam_bindings_additive &#61; optional&#40;map&#40;object&#40;&#123;&#10; member &#61; string&#10; role &#61; string&#10; condition &#61; optional&#40;object&#40;&#123;&#10; expression &#61; string&#10; title &#61; string&#10; description &#61; optional&#40;string&#41;&#10; &#125;&#41;&#41;&#10; &#125;&#41;&#41;, &#123;&#125;&#41;&#10;&#125;&#41;&#41;">list&#40;object&#40;&#123;&#8230;&#125;&#41;&#41;</code> | | <code>&#91;&#93;</code> |
| [subnets_private_nat](variables.tf#L420) | List of private NAT subnets. | <code title="list&#40;object&#40;&#123;&#10; name &#61; string&#10; ip_cidr_range &#61; string&#10; region &#61; string&#10; description &#61; optional&#40;string&#41;&#10;&#125;&#41;&#41;">list&#40;object&#40;&#123;&#8230;&#125;&#41;&#41;</code> | | <code>&#91;&#93;</code> |
| [subnets_proxy_only](variables.tf#L432) | List of proxy-only subnets for Regional HTTPS or Internal HTTPS load balancers. Note: Only one proxy-only subnet for each VPC network in each region can be active. | <code title="list&#40;object&#40;&#123;&#10; name &#61; string&#10; ip_cidr_range &#61; string&#10; region &#61; string&#10; description &#61; optional&#40;string&#41;&#10; active &#61; optional&#40;bool, true&#41;&#10; global &#61; optional&#40;bool, false&#41;&#10;&#10;&#10; iam &#61; optional&#40;map&#40;list&#40;string&#41;&#41;, &#123;&#125;&#41;&#10; iam_bindings &#61; optional&#40;map&#40;object&#40;&#123;&#10; role &#61; string&#10; members &#61; list&#40;string&#41;&#10; condition &#61; optional&#40;object&#40;&#123;&#10; expression &#61; string&#10; title &#61; string&#10; description &#61; optional&#40;string&#41;&#10; &#125;&#41;&#41;&#10; &#125;&#41;&#41;, &#123;&#125;&#41;&#10; iam_bindings_additive &#61; optional&#40;map&#40;object&#40;&#123;&#10; member &#61; string&#10; role &#61; string&#10; condition &#61; optional&#40;object&#40;&#123;&#10; expression &#61; string&#10; title &#61; string&#10; description &#61; optional&#40;string&#41;&#10; &#125;&#41;&#41;&#10; &#125;&#41;&#41;, &#123;&#125;&#41;&#10;&#125;&#41;&#41;">list&#40;object&#40;&#123;&#8230;&#125;&#41;&#41;</code> | | <code>&#91;&#93;</code> |
| [subnets_psc](variables.tf#L466) | List of subnets for Private Service Connect service producers. | <code title="list&#40;object&#40;&#123;&#10; name &#61; string&#10; ip_cidr_range &#61; string&#10; region &#61; string&#10; description &#61; optional&#40;string&#41;&#10;&#10;&#10; iam &#61; optional&#40;map&#40;list&#40;string&#41;&#41;, &#123;&#125;&#41;&#10; iam_bindings &#61; optional&#40;map&#40;object&#40;&#123;&#10; role &#61; string&#10; members &#61; list&#40;string&#41;&#10; condition &#61; optional&#40;object&#40;&#123;&#10; expression &#61; string&#10; title &#61; string&#10; description &#61; optional&#40;string&#41;&#10; &#125;&#41;&#41;&#10; &#125;&#41;&#41;, &#123;&#125;&#41;&#10; iam_bindings_additive &#61; optional&#40;map&#40;object&#40;&#123;&#10; member &#61; string&#10; role &#61; string&#10; condition &#61; optional&#40;object&#40;&#123;&#10; expression &#61; string&#10; title &#61; string&#10; description &#61; optional&#40;string&#41;&#10; &#125;&#41;&#41;&#10; &#125;&#41;&#41;, &#123;&#125;&#41;&#10;&#125;&#41;&#41;">list&#40;object&#40;&#123;&#8230;&#125;&#41;&#41;</code> | | <code>&#91;&#93;</code> |
| [vpc_reuse](variables.tf#L498) | Reuse existing VPC if not null. If the network_id number is not passed in, a data source is used. | <code title="object&#40;&#123;&#10; use_data_source &#61; optional&#40;bool, true&#41;&#10; attributes &#61; optional&#40;object&#40;&#123;&#10; network_id &#61; number&#10; &#125;&#41;&#41;&#10;&#125;&#41;">object&#40;&#123;&#8230;&#125;&#41;</code> | | <code>null</code> |
## Outputs

View File

@@ -52,12 +52,10 @@ locals {
}
}
}
internal_ranges = merge(
{ for r in var.internal_ranges : r.name => r },
local._factory_internal_ranges
)
internal_ranges_ids = {
for k, v in google_network_connectivity_internal_range.internal_range :
k => v.id
@@ -65,14 +63,15 @@ locals {
}
resource "google_network_connectivity_internal_range" "internal_range" {
provider = google-beta
for_each = local.internal_ranges
project = var.project_id
name = each.value.name
network = local.network.id
description = each.value.description
ip_cidr_range = each.value.ip_cidr_range
provider = google-beta
for_each = local.internal_ranges
project = local.project_id
name = each.value.name
network = local.network.id
description = each.value.description
ip_cidr_range = try(
local.ctx.cidr_ranges[each.value.ip_cidr_range], each.value.ip_cidr_range
)
labels = each.value.labels
usage = each.value.usage
peering = each.value.peering

View File

@@ -15,11 +15,14 @@
*/
locals {
ctx = {
_ctx = {
for k, v in var.context : k => {
for kk, vv in v : "${local.ctx_p}${k}:${kk}" => vv
}
}
ctx = merge(local._ctx, {
locations = merge(local._ctx.regions, local._ctx.locations)
})
ctx_p = "$"
network = (
var.vpc_reuse == null
@@ -56,19 +59,28 @@ locals {
peer_network = (
var.peering_config == null
? null
: element(reverse(split("/", var.peering_config.peer_vpc_self_link)), 0)
: (
startswith(var.peering_config.peer_vpc_self_link, "$networks:")
? lookup(
local.ctx.networks,
var.peering_config.peer_vpc_self_link,
var.peering_config.peer_vpc_self_link
)
: element(reverse(split("/", var.peering_config.peer_vpc_self_link)), 0)
)
)
project_id = lookup(local.ctx.project_ids, var.project_id, var.project_id)
}
data "google_compute_network" "network" {
count = try(var.vpc_reuse.use_data_source, null) == true ? 1 : 0
name = var.name
project = var.project_id
project = local.project_id
}
resource "google_compute_network" "network" {
count = var.vpc_reuse == null ? 1 : 0
project = var.project_id
project = local.project_id
name = var.name
description = var.description
auto_create_subnetworks = var.auto_create_subnetworks
@@ -81,11 +93,15 @@ resource "google_compute_network" "network" {
}
resource "google_compute_network_peering" "local" {
provider = google-beta
count = var.peering_config == null ? 0 : 1
name = "${var.name}-${local.peer_network}"
network = local.network.self_link
peer_network = var.peering_config.peer_vpc_self_link
provider = google-beta
count = var.peering_config == null ? 0 : 1
name = "${var.name}-${local.peer_network}"
network = local.network.self_link
peer_network = lookup(
local.ctx.networks,
var.peering_config.peer_vpc_self_link,
var.peering_config.peer_vpc_self_link
)
export_custom_routes = var.peering_config.export_routes
import_custom_routes = var.peering_config.import_routes
}
@@ -97,8 +113,12 @@ resource "google_compute_network_peering" "remote" {
? 1
: 0
)
name = "${local.peer_network}-${var.name}"
network = var.peering_config.peer_vpc_self_link
name = "${local.peer_network}-${var.name}"
network = lookup(
local.ctx.networks,
var.peering_config.peer_vpc_self_link,
var.peering_config.peer_vpc_self_link
)
peer_network = local.network.self_link
export_custom_routes = var.peering_config.import_routes
import_custom_routes = var.peering_config.export_routes
@@ -108,7 +128,7 @@ resource "google_compute_network_peering" "remote" {
resource "google_compute_shared_vpc_host_project" "shared_vpc_host" {
provider = google-beta
count = var.shared_vpc_host ? 1 : 0
project = var.project_id
project = local.project_id
depends_on = [local.network]
}
@@ -119,14 +139,14 @@ resource "google_compute_shared_vpc_service_project" "service_projects" {
? var.shared_vpc_service_projects
: []
)
host_project = var.project_id
service_project = each.value
host_project = local.project_id
service_project = lookup(local.ctx.project_ids, each.value, each.value)
depends_on = [google_compute_shared_vpc_host_project.shared_vpc_host]
}
resource "google_dns_policy" "default" {
count = var.dns_policy == null ? 0 : 1
project = var.project_id
project = local.project_id
name = var.name
enable_inbound_forwarding = try(var.dns_policy.inbound, null)
enable_logging = try(var.dns_policy.logging, null)
@@ -145,7 +165,7 @@ resource "google_dns_policy" "default" {
)
iterator = ns
content {
ipv4_address = ns.value
ipv4_address = lookup(local.ctx.addresses, ns.value, ns.value)
forwarding_path = "private"
}
}
@@ -157,7 +177,7 @@ resource "google_dns_policy" "default" {
)
iterator = ns
content {
ipv4_address = ns.value
ipv4_address = lookup(local.ctx.addresses, ns.value, ns.value)
}
}
}

View File

@@ -44,7 +44,8 @@ locals {
})
}
psa_configs_ranges = {
for v in local._psa_configs_ranges : v.key => v.value
for v in local._psa_configs_ranges :
v.key => lookup(local.ctx.cidr_ranges, v.value, v.value)
}
psa_peered_domains = {
for v in local._psa_peered_domains : v.key => v
@@ -53,7 +54,7 @@ locals {
resource "google_compute_global_address" "psa_ranges" {
for_each = local.psa_configs_ranges
project = var.project_id
project = local.project_id
network = local.network.id
name = each.key
purpose = "VPC_PEERING"

View File

@@ -50,36 +50,42 @@ locals {
}
resource "google_compute_route" "gateway" {
for_each = local.routes.gateway
project = var.project_id
network = local.network.name
name = "${var.name}-${each.key}"
description = each.value.description
dest_range = each.value.dest_range
for_each = local.routes.gateway
project = local.project_id
network = local.network.name
name = "${var.name}-${each.key}"
description = each.value.description
dest_range = lookup(
local.ctx.cidr_ranges, each.value.dest_range, each.value.dest_range
)
priority = each.value.priority
tags = each.value.tags
next_hop_gateway = each.value.next_hop
}
resource "google_compute_route" "ilb" {
for_each = local.routes.ilb
project = var.project_id
network = local.network.name
name = "${var.name}-${each.key}"
description = each.value.description
dest_range = each.value.dest_range
for_each = local.routes.ilb
project = local.project_id
network = local.network.name
name = "${var.name}-${each.key}"
description = each.value.description
dest_range = lookup(
local.ctx.cidr_ranges, each.value.dest_range, each.value.dest_range
)
priority = each.value.priority
tags = each.value.tags
next_hop_ilb = each.value.next_hop
}
resource "google_compute_route" "instance" {
for_each = local.routes.instance
project = var.project_id
network = local.network.name
name = "${var.name}-${each.key}"
description = each.value.description
dest_range = each.value.dest_range
for_each = local.routes.instance
project = local.project_id
network = local.network.name
name = "${var.name}-${each.key}"
description = each.value.description
dest_range = lookup(
local.ctx.cidr_ranges, each.value.dest_range, each.value.dest_range
)
priority = each.value.priority
tags = each.value.tags
next_hop_instance = each.value.next_hop
@@ -89,23 +95,29 @@ resource "google_compute_route" "instance" {
resource "google_compute_route" "ip" {
for_each = local.routes.ip
project = var.project_id
project = local.project_id
network = local.network.name
name = "${var.name}-${each.key}"
description = each.value.description
dest_range = each.value.dest_range
priority = each.value.priority
tags = each.value.tags
next_hop_ip = each.value.next_hop
dest_range = lookup(
local.ctx.cidr_ranges, each.value.dest_range, each.value.dest_range
)
priority = each.value.priority
tags = each.value.tags
next_hop_ip = lookup(
local.ctx.addresses, each.value.next_hop, each.value.next_hop
)
}
resource "google_compute_route" "vpn_tunnel" {
for_each = local.routes.vpn_tunnel
project = var.project_id
network = local.network.name
name = "${var.name}-${each.key}"
description = each.value.description
dest_range = each.value.dest_range
for_each = local.routes.vpn_tunnel
project = local.project_id
network = local.network.name
name = "${var.name}-${each.key}"
description = each.value.description
dest_range = lookup(
local.ctx.cidr_ranges, each.value.dest_range, each.value.dest_range
)
priority = each.value.priority
tags = each.value.tags
next_hop_vpn_tunnel = each.value.next_hop
@@ -113,7 +125,7 @@ resource "google_compute_route" "vpn_tunnel" {
resource "google_network_connectivity_policy_based_route" "default" {
for_each = var.policy_based_routes
project = var.project_id
project = local.project_id
network = local.network.id
name = "${var.name}-${each.key}"
description = each.value.description

View File

@@ -23,7 +23,7 @@ locals {
}
_factory_data = {
for k, v in local._factory_data_raw : k => merge(v, {
region_computed = lookup(local.ctx.regions, v.region, v.region)
region_computed = lookup(local.ctx.locations, v.region, v.region)
})
}
_factory_path = try(pathexpand(var.factories_config.subnets_folder), null)
@@ -88,7 +88,9 @@ locals {
_is_proxy_only = try(v.proxy_only == true, false)
}
}
_iam_subnets = concat(
var.subnets, var.subnets_psc, var.subnets_proxy_only, values(local._factory_subnets)
)
all_subnets = merge(
{ for k, v in google_compute_subnetwork.subnetwork : k => v },
{ for k, v in google_compute_subnetwork.proxy_only : k => v },
@@ -96,22 +98,21 @@ locals {
)
subnet_iam = flatten(concat(
[
for s in concat(var.subnets, var.subnets_psc, var.subnets_proxy_only, values(local._factory_subnets)) : [
for role, members in s.iam :
{
role = role
for s in local._iam_subnets : [
for role, members in s.iam : {
role = lookup(local.ctx.custom_roles, role, role)
members = members
subnet = "${s.region}/${s.name}"
subnet = "${lookup(local.ctx.locations, s.region, s.region)}/${s.name}"
}
]
],
))
subnet_iam_bindings = merge([
for s in concat(var.subnets, var.subnets_psc, var.subnets_proxy_only, values(local._factory_subnets)) : {
for s in local._iam_subnets : {
for key, data in s.iam_bindings :
key => {
role = data.role
subnet = "${s.region}/${s.name}"
role = lookup(local.ctx.custom_roles, data.role, data.role)
subnet = "${lookup(local.ctx.locations, s.region, s.region)}/${s.name}"
members = data.members
condition = data.condition
}
@@ -121,42 +122,60 @@ locals {
# In other words, if you have multiple additive bindings with the
# same name, only one will be used
subnet_iam_bindings_additive = merge([
for s in concat(var.subnets, var.subnets_psc, var.subnets_proxy_only, values(local._factory_subnets)) : {
for s in local._iam_subnets : {
for key, data in s.iam_bindings_additive :
key => {
role = data.role
subnet = "${s.region}/${s.name}"
role = lookup(local.ctx.custom_roles, data.role, data.role)
subnet = "${lookup(local.ctx.locations, s.region, s.region)}/${s.name}"
member = data.member
condition = data.condition
}
}
]...)
subnets = merge(
{ for s in var.subnets : "${s.region}/${s.name}" => s },
{
for s in var.subnets :
"${lookup(local.ctx.locations, s.region, s.region)}/${s.name}" => s
},
{ for k, v in local._factory_subnets : k => v if v._is_regular }
)
subnets_proxy_only = merge(
{ for s in var.subnets_proxy_only : "${s.region}/${s.name}" => s },
{
for s in var.subnets_proxy_only :
"${lookup(local.ctx.locations, s.region, s.region)}/${s.name}" => s
},
{ for k, v in local._factory_subnets : k => v if v._is_proxy_only },
)
subnets_private_nat = merge(
{ for s in var.subnets_private_nat : "${s.region}/${s.name}" => s },
{
for s in var.subnets_private_nat :
"${lookup(local.ctx.locations, s.region, s.region)}/${s.name}" => s
},
# { for k, v in local._factory_subnets : k => v if v._is_proxy_only },
)
subnets_psc = merge(
{ for s in var.subnets_psc : "${s.region}/${s.name}" => s },
{
for s in var.subnets_psc :
"${lookup(local.ctx.locations, s.region, s.region)}/${s.name}" => s
},
{ for k, v in local._factory_subnets : k => v if v._is_psc }
)
}
resource "google_compute_subnetwork" "subnetwork" {
provider = google-beta
for_each = local.subnets
project = var.project_id
network = local.network.name
name = each.value.name
region = each.value.region
ip_cidr_range = try(each.value.ipv6.ipv6_only, false) ? null : each.value.ip_cidr_range
provider = google-beta
for_each = local.subnets
project = local.project_id
network = local.network.name
name = each.value.name
region = lookup(
local.ctx.locations, each.value.region, each.value.region
)
ip_cidr_range = (
try(each.value.ipv6.ipv6_only, false)
? null
: try(local.ctx.cidr_ranges[each.value.ip_cidr_range], each.value.ip_cidr_range)
)
allow_subnet_cidr_routes_overlap = each.value.allow_subnet_cidr_routes_overlap
reserved_internal_range = (
each.value.reserved_internal_range != null
@@ -189,8 +208,13 @@ resource "google_compute_subnetwork" "subnetwork" {
dynamic "secondary_ip_range" {
for_each = each.value.secondary_ip_ranges == null ? {} : each.value.secondary_ip_ranges
content {
range_name = secondary_ip_range.key
ip_cidr_range = try(secondary_ip_range.value.ip_cidr_range, secondary_ip_range.value)
range_name = secondary_ip_range.key
ip_cidr_range = try(
local.ctx.cidr_ranges[secondary_ip_range.value.ip_cidr_range],
secondary_ip_range.value.ip_cidr_range,
local.ctx.cidr_ranges[secondary_ip_range.value],
secondary_ip_range.value
)
reserved_internal_range = (
try(secondary_ip_range.value.reserved_internal_range, null) != null
? "networkconnectivity.googleapis.com/${try(local.internal_ranges_ids[secondary_ip_range.value.reserved_internal_range], secondary_ip_range.value.reserved_internal_range)}"
@@ -215,12 +239,16 @@ resource "google_compute_subnetwork" "subnetwork" {
}
resource "google_compute_subnetwork" "proxy_only" {
for_each = local.subnets_proxy_only
project = var.project_id
network = local.network.name
name = each.value.name
region = each.value.region
ip_cidr_range = each.value.ip_cidr_range
for_each = local.subnets_proxy_only
project = local.project_id
network = local.network.name
name = each.value.name
region = lookup(
local.ctx.locations, each.value.region, each.value.region
)
ip_cidr_range = lookup(
local.ctx.cidr_ranges, each.value.ip_cidr_range, each.value.ip_cidr_range
)
description = (
# Set description to an empty string (eg "") to create subnet without a description.
each.value.description == null
@@ -232,12 +260,16 @@ resource "google_compute_subnetwork" "proxy_only" {
}
resource "google_compute_subnetwork" "private_nat" {
for_each = local.subnets_private_nat
project = var.project_id
network = local.network.name
name = each.value.name
region = each.value.region
ip_cidr_range = each.value.ip_cidr_range
for_each = local.subnets_private_nat
project = local.project_id
network = local.network.name
name = each.value.name
region = lookup(
local.ctx.locations, each.value.region, each.value.region
)
ip_cidr_range = lookup(
local.ctx.cidr_ranges, each.value.ip_cidr_range, each.value.ip_cidr_range
)
description = (
# Set description to an empty string (eg "") to create subnet without a description.
each.value.description == null
@@ -248,12 +280,16 @@ resource "google_compute_subnetwork" "private_nat" {
}
resource "google_compute_subnetwork" "psc" {
for_each = local.subnets_psc
project = var.project_id
network = local.network.name
name = each.value.name
region = each.value.region
ip_cidr_range = each.value.ip_cidr_range
for_each = local.subnets_psc
project = local.project_id
network = local.network.name
name = each.value.name
region = lookup(
local.ctx.locations, each.value.region, each.value.region
)
ip_cidr_range = lookup(
local.ctx.cidr_ranges, each.value.ip_cidr_range, each.value.ip_cidr_range
)
description = (
# Set description to an empty string (eg "") to create subnet without a description.
each.value.description == null
@@ -269,24 +305,30 @@ resource "google_compute_subnetwork_iam_binding" "authoritative" {
for binding in local.subnet_iam :
"${binding.subnet}.${binding.role}" => binding
}
project = var.project_id
project = local.project_id
subnetwork = local.all_subnets[each.value.subnet].name
region = local.all_subnets[each.value.subnet].region
role = each.value.role
members = each.value.members
members = [
for m in each.value.members : lookup(local.ctx.iam_principals, m, m)
]
}
resource "google_compute_subnetwork_iam_binding" "bindings" {
for_each = local.subnet_iam_bindings
project = var.project_id
project = local.project_id
subnetwork = local.all_subnets[each.value.subnet].name
region = local.all_subnets[each.value.subnet].region
role = each.value.role
members = each.value.members
members = [
for m in each.value.members : lookup(local.ctx.iam_principals, m, m)
]
dynamic "condition" {
for_each = each.value.condition == null ? [] : [""]
content {
expression = each.value.condition.expression
expression = templatestring(
each.value.condition.expression, var.context.condition_vars
)
title = each.value.condition.title
description = each.value.condition.description
}
@@ -295,15 +337,19 @@ resource "google_compute_subnetwork_iam_binding" "bindings" {
resource "google_compute_subnetwork_iam_member" "bindings" {
for_each = local.subnet_iam_bindings_additive
project = var.project_id
project = local.project_id
subnetwork = local.all_subnets[each.value.subnet].name
region = local.all_subnets[each.value.subnet].region
role = each.value.role
member = each.value.member
member = lookup(
local.ctx.iam_principals, each.value.member, each.value.member
)
dynamic "condition" {
for_each = each.value.condition == null ? [] : [""]
content {
expression = each.value.condition.expression
expression = templatestring(
each.value.condition.expression, var.context.condition_vars
)
title = each.value.condition.title
description = each.value.condition.description
}
@@ -313,7 +359,7 @@ resource "google_compute_subnetwork_iam_member" "bindings" {
resource "google_compute_network_attachment" "default" {
provider = google-beta
for_each = var.network_attachments
project = var.project_id
project = local.project_id
region = google_compute_subnetwork.subnetwork[each.value.subnet].region
name = each.key
description = each.value.description

View File

@@ -23,10 +23,23 @@ variable "auto_create_subnetworks" {
variable "context" {
description = "Context-specific interpolations."
type = object({
regions = optional(map(string), {})
addresses = optional(map(string), {})
cidr_ranges = optional(map(string), {})
condition_vars = optional(map(map(string)), {})
custom_roles = optional(map(string), {})
iam_principals = optional(map(string), {})
locations = optional(map(string), {})
networks = optional(map(string), {})
# legacy context
regions = optional(map(string), {})
project_ids = optional(map(string), {})
})
default = {}
nullable = false
validation {
condition = length(var.context.regions) == 0 || length(var.context.locations) == 0
error_message = "Only one of locations, regions can be used."
}
}
variable "create_googleapis_routes" {

View File

@@ -0,0 +1,42 @@
context = {
addresses = {
test = "10.0.0.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-west8/subnetworks/gce"
test-nat = "projects/foo-dev-net-spoke-0/regions/europe-west8/subnetworks/test-nat"
}
project_ids = {
test = "foo-test-0"
}
}
project_id = "$project_ids:test"
region = "$locations:ew8"
name = "test"
vpc_config = {
network = "$networks:test"
subnetwork = "$subnets:test"
}
backends = [{
group = "foo"
failover = false
}]
forwarding_rules_config = {
"" = {
address = "$addresses:test"
}
}
service_attachments = {
"" = {
nat_subnets = ["$subnets:test-nat"]
}
}

View File

@@ -0,0 +1,126 @@
# 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_forwarding_rule.default[""]:
all_ports: true
allow_global_access: true
allow_psc_global_access: null
description: null
ip_address: 10.0.0.10
ip_collection: null
ip_protocol: TCP
is_mirroring_collector: null
labels: null
load_balancing_scheme: INTERNAL
name: test
network: projects/foo-dev-net-spoke-0/global/networks/dev-spoke-0
no_automate_dns_zone: null
ports: null
project: foo-test-0
recreate_closed_psc: false
region: europe-west8
service_label: null
source_ip_ranges: null
subnetwork: projects/foo-dev-net-spoke-0/regions/europe-west8/subnetworks/gce
target: null
timeouts: null
google_compute_health_check.default[0]:
check_interval_sec: 5
description: Terraform managed.
grpc_health_check: []
grpc_tls_health_check: []
healthy_threshold: 2
http2_health_check: []
http_health_check: []
https_health_check: []
name: test
project: foo-test-0
source_regions: null
ssl_health_check: []
tcp_health_check:
- port: null
port_name: null
port_specification: USE_SERVING_PORT
proxy_header: NONE
request: null
response: null
timeout_sec: 5
timeouts: null
unhealthy_threshold: 2
google_compute_region_backend_service.default:
affinity_cookie_ttl_sec: null
backend:
- balancing_mode: CONNECTION
capacity_scaler: null
custom_metrics: []
description: Terraform managed.
failover: false
group: foo
max_connections: null
max_connections_per_endpoint: null
max_connections_per_instance: null
max_rate: null
max_rate_per_endpoint: null
max_rate_per_instance: null
max_utilization: null
circuit_breakers: []
connection_draining_timeout_sec: 300
connection_tracking_policy: []
consistent_hash: []
custom_metrics: []
description: Terraform managed.
dynamic_forwarding: []
enable_cdn: null
failover_policy: []
ha_policy: []
iap:
- enabled: false
oauth2_client_id: null
oauth2_client_secret: null
ip_address_selection_policy: null
load_balancing_scheme: INTERNAL
locality_lb_policy: null
name: test
network: projects/foo-dev-net-spoke-0/global/networks/dev-spoke-0
outlier_detection: []
project: foo-test-0
protocol: UNSPECIFIED
region: europe-west8
security_policy: null
strong_session_affinity_cookie: []
subsetting: []
timeouts: null
google_compute_service_attachment.default[""]:
connection_preference: ACCEPT_MANUAL
consumer_accept_lists: []
consumer_reject_lists: null
description: Terraform managed.
domain_names: null
enable_proxy_protocol: false
name: test
nat_subnets:
- projects/foo-dev-net-spoke-0/regions/europe-west8/subnetworks/test-nat
project: foo-test-0
region: europe-west8
send_propagated_connection_limit_if_zero: false
timeouts: null
counts:
google_compute_forwarding_rule: 1
google_compute_health_check: 1
google_compute_region_backend_service: 1
google_compute_service_attachment: 1
modules: 0
resources: 4

View File

@@ -15,5 +15,6 @@
module: modules/net-lb-int
tests:
context:
defaults:
forwarding-rule:

View File

@@ -0,0 +1,96 @@
context = {
addresses = {
dns-external = "8.8.8.8"
dns-internal = "10.10.10.10"
test = "10.20.20.20"
}
cidr_ranges = {
rfc1918-10 = "10.0.0.0/8"
rfc1918-172 = "172.16.10.0/12"
rfc1918-192 = "192.168.0.0/16"
test = "8.8.8.8/32"
}
condition_vars = {
organization = {
id = 1234567890
}
}
custom_roles = {
myrole = "organizations/366118655033/roles/myRoleOne"
}
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"
}
}
dns_policy = {
inbound = true
outbound = {
private_ns = ["$addresses:dns-internal"]
public_ns = ["$addresses:dns-external"]
}
}
internal_ranges = [
{
name = "pods-range"
usage = "FOR_VPC"
peering = "FOR_SELF"
ip_cidr_range = "$cidr_ranges:rfc1918-172"
}
]
project_id = "$project_ids:test"
routes = {
next-hop = {
description = "Route to internal range."
dest_range = "$cidr_ranges:test"
next_hop_type = "ip"
next_hop = "$addresses:test"
}
}
subnets = [
{
name = "production"
region = "$locations:ew8"
reserved_internal_range = "pods-range"
iam = {
"$custom_roles:myrole" = [
"iam_principals:test"
]
}
iam_bindings = {
myrole_two = {
role = "$custom_roles:myrole"
members = [
"$iam_principals:test"
]
condition = {
title = "Test"
expression = "resource.matchTag('$${organization.id}/environment', 'development')"
}
}
}
iam_bindings_additive = {
myrole_two = {
role = "$custom_roles:myrole"
member = "$iam_principals:test"
}
}
secondary_ip_ranges = {
pods = {
reserved_internal_range = "pods-range"
}
# Mixed configuration: some ranges use internal ranges, others use CIDR
traditional = {
ip_cidr_range = "$cidr_ranges:rfc1918-192"
}
}
}
]

View File

@@ -0,0 +1,175 @@
# 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.network[0]:
auto_create_subnetworks: false
delete_default_routes_on_create: false
description: Terraform-managed.
enable_ula_internal_ipv6: null
name: test
network_firewall_policy_enforcement_order: AFTER_CLASSIC_FIREWALL
network_profile: null
params: []
project: foo-test-0
routing_mode: GLOBAL
timeouts: null
google_compute_route.gateway["directpath-googleapis"]:
description: Terraform-managed.
dest_range: 34.126.0.0/18
name: test-directpath-googleapis
network: test
next_hop_gateway: default-internet-gateway
next_hop_ilb: null
next_hop_instance: null
next_hop_vpn_tunnel: null
params: []
priority: 1000
project: foo-test-0
tags: null
timeouts: null
google_compute_route.gateway["private-googleapis"]:
description: Terraform-managed.
dest_range: 199.36.153.8/30
name: test-private-googleapis
network: test
next_hop_gateway: default-internet-gateway
next_hop_ilb: null
next_hop_instance: null
next_hop_vpn_tunnel: null
params: []
priority: 1000
project: foo-test-0
tags: null
timeouts: null
google_compute_route.gateway["restricted-googleapis"]:
description: Terraform-managed.
dest_range: 199.36.153.4/30
name: test-restricted-googleapis
network: test
next_hop_gateway: default-internet-gateway
next_hop_ilb: null
next_hop_instance: null
next_hop_vpn_tunnel: null
params: []
priority: 1000
project: foo-test-0
tags: null
timeouts: null
google_compute_route.ip["next-hop"]:
description: Route to internal range.
dest_range: 8.8.8.8/32
name: test-next-hop
network: test
next_hop_gateway: null
next_hop_ilb: null
next_hop_instance: null
next_hop_ip: 10.20.20.20
next_hop_vpn_tunnel: null
params: []
priority: 1000
project: foo-test-0
tags: null
timeouts: null
google_compute_subnetwork.subnetwork["europe-west8/production"]:
description: Terraform-managed.
ip_collection: null
ipv6_access_type: null
log_config: []
name: production
network: test
params: []
private_ip_google_access: true
project: foo-test-0
region: europe-west8
role: null
secondary_ip_range:
- range_name: pods
- ip_cidr_range: 192.168.0.0/16
range_name: traditional
reserved_internal_range: null
send_secondary_ip_range_if_empty: true
timeouts: null
google_compute_subnetwork_iam_binding.authoritative["europe-west8/production.organizations/366118655033/roles/myRoleOne"]:
condition: []
members:
- iam_principals:test
project: foo-test-0
region: europe-west8
role: organizations/366118655033/roles/myRoleOne
subnetwork: production
google_compute_subnetwork_iam_binding.bindings["myrole_two"]:
condition:
- description: null
expression: resource.matchTag('1234567890/environment', 'development')
title: Test
members:
- serviceAccount:test@test-project.iam.gserviceaccount.com
project: foo-test-0
region: europe-west8
role: organizations/366118655033/roles/myRoleOne
subnetwork: production
google_compute_subnetwork_iam_member.bindings["myrole_two"]:
condition: []
member: serviceAccount:test@test-project.iam.gserviceaccount.com
project: foo-test-0
region: europe-west8
role: organizations/366118655033/roles/myRoleOne
subnetwork: production
google_dns_policy.default[0]:
alternative_name_server_config:
- target_name_servers:
- forwarding_path: ''
ipv4_address: 8.8.8.8
- forwarding_path: private
ipv4_address: 10.10.10.10
description: Managed by Terraform
enable_inbound_forwarding: true
enable_logging: null
name: test
networks:
- {}
project: foo-test-0
timeouts: null
google_network_connectivity_internal_range.internal_range["pods-range"]:
allocation_options: []
description: null
effective_labels:
goog-terraform-provisioned: 'true'
exclude_cidr_ranges: null
immutable: null
ip_cidr_range: 172.16.10.0/12
labels: null
migration: []
name: pods-range
overlaps: null
peering: FOR_SELF
prefix_length: null
project: foo-test-0
target_cidr_range: null
terraform_labels:
goog-terraform-provisioned: 'true'
timeouts: null
usage: FOR_VPC
counts:
google_compute_network: 1
google_compute_route: 4
google_compute_subnetwork: 1
google_compute_subnetwork_iam_binding: 2
google_compute_subnetwork_iam_member: 1
google_dns_policy: 1
google_network_connectivity_internal_range: 1
modules: 0
resources: 11

View File

@@ -17,6 +17,7 @@ common_tfvars:
- common.tfvars
tests:
context:
shared_vpc:
psa_routes_export:
psa_routes_import:

View File

@@ -0,0 +1,47 @@
context = {
cidr_ranges = {
rfc1918-10 = "10.0.0.0/8"
}
iam_principals = {
test = "serviceAccount:test@test-project.iam.gserviceaccount.com"
}
networks = {
test = "projects/foo-dev-net-spoke-0/global/networks/dev-spoke-0"
}
project_ids = {
test = "foo-test-0"
}
}
project_id = "$project_ids:test"
network = "$networks:test"
attachments = {
test = "$networks:test"
}
default_rules_config = {
admin_ranges = ["$cidr_ranges:rfc1918-10"]
http_ranges = ["$cidr_ranges:rfc1918-10"]
https_ranges = ["$cidr_ranges:rfc1918-10"]
ssh_ranges = ["$cidr_ranges:rfc1918-10"]
}
egress_rules = {
allow-egress-rfc1918 = {
deny = false
description = "Allow egress."
destination_ranges = [
"$cidr_ranges:rfc1918-10", "172.16.0.0/12", "192.168.0.0/16"
]
source_ranges = ["$cidr_ranges:rfc1918-10"]
targets = ["$iam_principals:test"]
use_service_accounts = true
}
}
ingress_rules = {
allow-ingress-tag = {
description = "Allow ingress."
destination_ranges = ["$cidr_ranges:rfc1918-10"]
source_ranges = ["$cidr_ranges:rfc1918-10"]
sources = ["$iam_principals:test"]
targets = ["$iam_principals:test"]
use_service_accounts = true
}
}

View File

@@ -0,0 +1,157 @@
# 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.allow-admins[0]:
allow:
- ports: []
protocol: all
deny: []
description: Access from the admin subnet to all subnets.
disabled: null
log_config: []
name: dev-spoke-0-ingress-admins
network: projects/foo-dev-net-spoke-0/global/networks/dev-spoke-0
params: []
priority: 1000
project: foo-test-0
source_ranges:
- 10.0.0.0/8
source_service_accounts: null
source_tags: null
target_service_accounts: null
target_tags: null
timeouts: null
google_compute_firewall.allow-tag-http[0]:
allow:
- ports:
- '80'
protocol: tcp
deny: []
description: Allow http to machines with matching tags.
disabled: null
log_config: []
name: dev-spoke-0-ingress-tag-http
network: projects/foo-dev-net-spoke-0/global/networks/dev-spoke-0
params: []
priority: 1000
project: foo-test-0
source_ranges:
- 10.0.0.0/8
source_service_accounts: null
source_tags: null
target_service_accounts: null
target_tags:
- http-server
timeouts: null
google_compute_firewall.allow-tag-https[0]:
allow:
- ports:
- '443'
protocol: tcp
deny: []
description: Allow http to machines with matching tags.
disabled: null
log_config: []
name: dev-spoke-0-ingress-tag-https
network: projects/foo-dev-net-spoke-0/global/networks/dev-spoke-0
params: []
priority: 1000
project: foo-test-0
source_ranges:
- 10.0.0.0/8
source_service_accounts: null
source_tags: null
target_service_accounts: null
target_tags:
- https-server
timeouts: null
google_compute_firewall.allow-tag-ssh[0]:
allow:
- ports:
- '22'
protocol: tcp
deny: []
description: Allow SSH to machines with matching tags.
disabled: null
log_config: []
name: dev-spoke-0-ingress-tag-ssh
network: projects/foo-dev-net-spoke-0/global/networks/dev-spoke-0
params: []
priority: 1000
project: foo-test-0
source_ranges:
- 10.0.0.0/8
source_service_accounts: null
source_tags: null
target_service_accounts: null
target_tags:
- ssh
timeouts: null
google_compute_firewall.custom-rules["allow-egress-rfc1918"]:
allow:
- ports: []
protocol: all
deny: []
description: Allow egress.
destination_ranges:
- 10.0.0.0/8
- 172.16.0.0/12
- 192.168.0.0/16
direction: EGRESS
disabled: false
log_config: []
name: allow-egress-rfc1918
network: projects/foo-dev-net-spoke-0/global/networks/dev-spoke-0
params: []
priority: 1000
project: foo-test-0
source_ranges:
- 10.0.0.0/8
source_service_accounts: null
source_tags: null
target_service_accounts:
- serviceAccount:test@test-project.iam.gserviceaccount.com
target_tags: null
timeouts: null
google_compute_firewall.custom-rules["allow-ingress-tag"]:
allow:
- ports: []
protocol: all
deny: []
description: Allow ingress.
destination_ranges:
- 10.0.0.0/8
direction: INGRESS
disabled: false
log_config: []
name: allow-ingress-tag
network: projects/foo-dev-net-spoke-0/global/networks/dev-spoke-0
params: []
priority: 1000
project: foo-test-0
source_ranges:
- 10.0.0.0/8
source_service_accounts:
- serviceAccount:test@test-project.iam.gserviceaccount.com
source_tags: null
target_service_accounts:
- serviceAccount:test@test-project.iam.gserviceaccount.com
target_tags: null
timeouts: null
counts:
google_compute_firewall: 6
modules: 0
resources: 6

View File

@@ -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-vpc-firewall
tests:
context: