Add support for static IPs NAT to 2-networking (#3889)
* feat(2-networking): add support for static IPs NAT * fix(linting): fix linting * fix(linting): fix linting * fix(2-networking): factory-cloudnat don't assume that the context values are present. * fix(2-networking): factory-cloudnat pass region in a try to forward the problem to the module --------- Co-authored-by: Simone Ruffilli <sruffilli@google.com> Co-authored-by: Ludovico Magnocavallo <ludomagno@google.com> Co-authored-by: Julio Castillo <jccb@google.com>
This commit is contained in:
@@ -284,6 +284,19 @@ nat_config:
|
|||||||
# [...]
|
# [...]
|
||||||
```
|
```
|
||||||
|
|
||||||
|
- **External IPs for NAT:** You can specify how many static IPs do you want, so they would be reserved and kept static. This is helpful when you need to connect to an external service that needs to whitelist the IPs. This is done by defining the number of static IP addresses in the `nat` section of a VPC's `.config.yaml` file.
|
||||||
|
|
||||||
|
For example:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
# [...]
|
||||||
|
nat_config:
|
||||||
|
nat-ew8:
|
||||||
|
num_nat_ips: 3
|
||||||
|
region: $locations:primary
|
||||||
|
# [...]
|
||||||
|
```
|
||||||
|
|
||||||
- **Cloud Routers:** The `factory-routers.tf` file manages Cloud Routers, which are used with Cloud VPN and Cloud Interconnect to exchange routes with on-premises networks. Routers are configured within each VPC's `.config.yaml` file.
|
- **Cloud Routers:** The `factory-routers.tf` file manages Cloud Routers, which are used with Cloud VPN and Cloud Interconnect to exchange routes with on-premises networks. Routers are configured within each VPC's `.config.yaml` file.
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
@@ -359,7 +372,7 @@ Internally created resources are mapped to context namespaces, and use specific
|
|||||||
|
|
||||||
| name | description | modules | resources |
|
| name | description | modules | resources |
|
||||||
|---|---|---|---|
|
|---|---|---|---|
|
||||||
| [factory-cloudnat.tf](./factory-cloudnat.tf) | Cloud NAT factory. | <code>net-cloudnat</code> | |
|
| [factory-cloudnat.tf](./factory-cloudnat.tf) | Cloud NAT factory. | <code>net-address</code> · <code>net-cloudnat</code> | |
|
||||||
| [factory-dns.tf](./factory-dns.tf) | DNS zones and RPZ factory. | <code>dns</code> · <code>dns-response-policy</code> | |
|
| [factory-dns.tf](./factory-dns.tf) | DNS zones and RPZ factory. | <code>dns</code> · <code>dns-response-policy</code> | |
|
||||||
| [factory-firewall-policies.tf](./factory-firewall-policies.tf) | Firewall policies factory. | <code>net-firewall-policy</code> | |
|
| [factory-firewall-policies.tf](./factory-firewall-policies.tf) | Firewall policies factory. | <code>net-firewall-policy</code> | |
|
||||||
| [factory-ncc.tf](./factory-ncc.tf) | NCC Hubs and Groups factory | | <code>google_network_connectivity_group</code> · <code>google_network_connectivity_hub</code> · <code>google_network_connectivity_spoke</code> |
|
| [factory-ncc.tf](./factory-ncc.tf) | NCC Hubs and Groups factory | | <code>google_network_connectivity_group</code> · <code>google_network_connectivity_hub</code> · <code>google_network_connectivity_spoke</code> |
|
||||||
|
|||||||
@@ -29,6 +29,8 @@ locals {
|
|||||||
config_timeouts = try(nat_config.config_timeouts, {})
|
config_timeouts = try(nat_config.config_timeouts, {})
|
||||||
endpoint_types = try(nat_config.endpoint_types, null)
|
endpoint_types = try(nat_config.endpoint_types, null)
|
||||||
logging_filter = try(nat_config.logging_filter, null)
|
logging_filter = try(nat_config.logging_filter, null)
|
||||||
|
num_nat_ips = try(nat_config.num_nat_ips, 0)
|
||||||
|
region = try(nat_config.region, null)
|
||||||
router_asn = try(nat_config.router_asn, null)
|
router_asn = try(nat_config.router_asn, null)
|
||||||
router_create = try(nat_config.router_create, true)
|
router_create = try(nat_config.router_create, true)
|
||||||
router_network = module.vpc-factory.vpcs[vpc_key].id
|
router_network = module.vpc-factory.vpcs[vpc_key].id
|
||||||
@@ -40,12 +42,25 @@ locals {
|
|||||||
])...)
|
])...)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
module "addresses" {
|
||||||
|
source = "../../../modules/net-address"
|
||||||
|
for_each = { for k, v in local.nat_configs : k => v if tonumber(v.num_nat_ips) > 0 }
|
||||||
|
project_id = each.value.project_id
|
||||||
|
external_addresses = {
|
||||||
|
for i in range(tonumber(each.value.num_nat_ips)) : "${each.value.name}-ip-${i}" => { region = each.value.region }
|
||||||
|
}
|
||||||
|
context = merge(local.ctx, {
|
||||||
|
project_ids = local.ctx_projects.project_ids
|
||||||
|
locations = local.ctx.locations
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
module "nat" {
|
module "nat" {
|
||||||
source = "../../../modules/net-cloudnat"
|
source = "../../../modules/net-cloudnat"
|
||||||
for_each = local.nat_configs
|
for_each = local.nat_configs
|
||||||
project_id = each.value.project_id
|
project_id = each.value.project_id
|
||||||
name = each.value.name
|
name = each.value.name
|
||||||
addresses = each.value.addresses
|
addresses = concat(each.value.addresses, [for a in try(module.addresses[each.key].external_addresses, {}) : a.self_link])
|
||||||
config_port_allocation = each.value.config_port_allocation
|
config_port_allocation = each.value.config_port_allocation
|
||||||
config_source_subnetworks = each.value.config_source_subnetworks
|
config_source_subnetworks = each.value.config_source_subnetworks
|
||||||
config_timeouts = each.value.config_timeouts
|
config_timeouts = each.value.config_timeouts
|
||||||
@@ -58,8 +73,9 @@ module "nat" {
|
|||||||
rules = each.value.rules
|
rules = each.value.rules
|
||||||
type = each.value.type
|
type = each.value.type
|
||||||
context = merge(local.ctx, {
|
context = merge(local.ctx, {
|
||||||
project_ids = local.ctx_projects.project_ids
|
project_ids = local.ctx_projects.project_ids
|
||||||
vpc_self_links = local.ctx_vpcs.self_links
|
networks = local.ctx_vpcs.self_links
|
||||||
locations = local.ctx.locations
|
locations = local.ctx.locations
|
||||||
|
subnets = local.ctx_vpcs.subnets_by_vpc
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -197,6 +197,9 @@
|
|||||||
"properties": {
|
"properties": {
|
||||||
"region": {
|
"region": {
|
||||||
"type": "string"
|
"type": "string"
|
||||||
|
},
|
||||||
|
"num_nat_ips": {
|
||||||
|
"type": "number"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -67,6 +67,7 @@
|
|||||||
- **nat_config**<a name="refs-nat_config"></a>: *object*
|
- **nat_config**<a name="refs-nat_config"></a>: *object*
|
||||||
- **`^[a-z0-9-]+$`**: *object*
|
- **`^[a-z0-9-]+$`**: *object*
|
||||||
- ⁺**region**: *string*
|
- ⁺**region**: *string*
|
||||||
|
- **num_nat_ips**: *number*
|
||||||
- **ncc_config**<a name="refs-ncc_config"></a>: *object*
|
- **ncc_config**<a name="refs-ncc_config"></a>: *object*
|
||||||
- ⁺**hub**: *string*
|
- ⁺**hub**: *string*
|
||||||
- **group**: *string*
|
- **group**: *string*
|
||||||
|
|||||||
@@ -0,0 +1,41 @@
|
|||||||
|
# Copyright 2026 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.
|
||||||
|
|
||||||
|
# yaml-language-server: $schema=../../schemas/defaults.schema.json
|
||||||
|
|
||||||
|
context:
|
||||||
|
cidr_ranges_sets:
|
||||||
|
healthchecks:
|
||||||
|
- 35.191.0.0/16
|
||||||
|
- 130.211.0.0/22
|
||||||
|
- 209.85.152.0/22
|
||||||
|
- 209.85.204.0/22
|
||||||
|
rfc1918:
|
||||||
|
- 10.0.0.0/8
|
||||||
|
- 172.16.0.0/12
|
||||||
|
- 192.168.0.0/16
|
||||||
|
locations:
|
||||||
|
primary: europe-west1
|
||||||
|
secondary: europe-west3
|
||||||
|
iam_principals: {}
|
||||||
|
projects:
|
||||||
|
defaults:
|
||||||
|
locations:
|
||||||
|
storage: eu
|
||||||
|
vpcs:
|
||||||
|
auto_create_subnetworks: false
|
||||||
|
delete_default_route_on_create: true
|
||||||
|
mtu: 1500
|
||||||
|
output_files:
|
||||||
|
storage_bucket: $storage_buckets:iac-0/iac-outputs
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
# skip boilerplate check
|
||||||
|
---
|
||||||
|
# start of document (---) avoids errors if the file only contains comments
|
||||||
|
|
||||||
|
# yaml-language-server: $schema=../../../schemas/project.schema.json
|
||||||
|
name: prod-net-core-0
|
||||||
|
parent: $folder_ids:networking
|
||||||
|
services:
|
||||||
|
- compute.googleapis.com
|
||||||
|
- container.googleapis.com
|
||||||
|
- dns.googleapis.com
|
||||||
|
- iap.googleapis.com
|
||||||
|
- logging.googleapis.com
|
||||||
|
- monitoring.googleapis.com
|
||||||
|
- networkmanagement.googleapis.com
|
||||||
|
- networksecurity.googleapis.com
|
||||||
|
- servicenetworking.googleapis.com
|
||||||
|
- vpcaccess.googleapis.com
|
||||||
|
shared_vpc_host_config:
|
||||||
|
enabled: true
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
# skip boilerplate check
|
||||||
|
---
|
||||||
|
# start of document (---) avoids errors if the file only contains comments
|
||||||
|
|
||||||
|
# yaml-language-server: $schema=../../../../schemas/vpc.schema.json
|
||||||
|
|
||||||
|
project_id: $project_ids:net-core-0
|
||||||
|
name: core-0
|
||||||
|
delete_default_routes_on_create: true
|
||||||
|
nat_config:
|
||||||
|
nat-static:
|
||||||
|
region: $locations:primary
|
||||||
|
num_nat_ips: 3
|
||||||
|
config_source_subnetworks:
|
||||||
|
all: false
|
||||||
|
subnetworks:
|
||||||
|
- self_link: $subnets:core/europe-west1/core-default
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
# skip boilerplate check
|
||||||
|
|
||||||
|
# yaml-language-server: $schema=../../../../../schemas/subnet.schema.json
|
||||||
|
|
||||||
|
name: core-default
|
||||||
|
region: $locations:primary
|
||||||
|
ip_cidr_range: 10.71.0.0/24
|
||||||
|
description: Default primary-region subnet for core
|
||||||
34
tests/fast/stages/s2_networking/static_ips_nat.tfvars
Normal file
34
tests/fast/stages/s2_networking/static_ips_nat.tfvars
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
automation = {
|
||||||
|
outputs_bucket = "test"
|
||||||
|
}
|
||||||
|
billing_account = {
|
||||||
|
id = "000000-111111-222222"
|
||||||
|
}
|
||||||
|
factories_config = {
|
||||||
|
dataset = "./data-teststatic-ips-nat"
|
||||||
|
paths = {
|
||||||
|
defaults = "defaults.yaml"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
folder_ids = {
|
||||||
|
"networking" = "folders/12345678"
|
||||||
|
"networking/prod" = "folders/23456789"
|
||||||
|
"networking/dev" = "folders/34567890"
|
||||||
|
}
|
||||||
|
organization = {
|
||||||
|
domain = "fast.example.com"
|
||||||
|
id = 123456789012
|
||||||
|
customer_id = "C00000000"
|
||||||
|
}
|
||||||
|
prefix = "fast"
|
||||||
|
service_accounts = {
|
||||||
|
"iac-0/iac-pf-rw" = "iac-pf-rw@test.iam.gserviceaccount.com"
|
||||||
|
"iac-0/iac-pf-ro" = "iac-pf-ro@test.iam.gserviceaccount.com"
|
||||||
|
}
|
||||||
|
storage_buckets = {
|
||||||
|
"iac-0/iac-outputs" = "test"
|
||||||
|
}
|
||||||
|
tag_values = {
|
||||||
|
"environment/development" = "tagValues/12345"
|
||||||
|
"environment/production" = "tagValues/12346"
|
||||||
|
}
|
||||||
78
tests/fast/stages/s2_networking/static_ips_nat.yaml
Normal file
78
tests/fast/stages/s2_networking/static_ips_nat.yaml
Normal file
@@ -0,0 +1,78 @@
|
|||||||
|
# Copyright 2026 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.
|
||||||
|
|
||||||
|
counts:
|
||||||
|
google_compute_address: 3
|
||||||
|
google_compute_network: 1
|
||||||
|
google_compute_route: 3
|
||||||
|
google_compute_router: 1
|
||||||
|
google_compute_router_nat: 1
|
||||||
|
google_compute_shared_vpc_host_project: 1
|
||||||
|
google_compute_subnetwork: 1
|
||||||
|
google_logging_project_settings: 1
|
||||||
|
google_project: 1
|
||||||
|
google_project_iam_member: 8
|
||||||
|
google_project_service: 10
|
||||||
|
google_project_service_identity: 8
|
||||||
|
google_storage_bucket_object: 2
|
||||||
|
modules: 7
|
||||||
|
resources: 43
|
||||||
|
terraform_data: 2
|
||||||
|
values:
|
||||||
|
module.addresses["core/nat-static"].google_compute_address.external["core-nat-static-ip-0"]:
|
||||||
|
address_type: EXTERNAL
|
||||||
|
description: 'Terraform managed.'
|
||||||
|
name: core-nat-static-ip-0
|
||||||
|
project: fast-prod-net-core-0
|
||||||
|
region: europe-west1
|
||||||
|
module.addresses["core/nat-static"].google_compute_address.external["core-nat-static-ip-1"]:
|
||||||
|
address_type: EXTERNAL
|
||||||
|
description: 'Terraform managed.'
|
||||||
|
name: core-nat-static-ip-1
|
||||||
|
project: fast-prod-net-core-0
|
||||||
|
region: europe-west1
|
||||||
|
module.addresses["core/nat-static"].google_compute_address.external["core-nat-static-ip-2"]:
|
||||||
|
address_type: EXTERNAL
|
||||||
|
description: 'Terraform managed.'
|
||||||
|
name: core-nat-static-ip-2
|
||||||
|
project: fast-prod-net-core-0
|
||||||
|
region: europe-west1
|
||||||
|
module.nat["core/nat-static"].google_compute_router.router[0]:
|
||||||
|
name: core-nat-static-nat
|
||||||
|
project: fast-prod-net-core-0
|
||||||
|
region: europe-west1
|
||||||
|
module.nat["core/nat-static"].google_compute_router_nat.nat:
|
||||||
|
enable_dynamic_port_allocation: False
|
||||||
|
enable_endpoint_independent_mapping: True
|
||||||
|
icmp_idle_timeout_sec: 30
|
||||||
|
log_config:
|
||||||
|
- enable: False
|
||||||
|
filter: ALL
|
||||||
|
max_ports_per_vm: 65536
|
||||||
|
name: core-nat-static
|
||||||
|
nat64_subnetwork: []
|
||||||
|
project: fast-prod-net-core-0
|
||||||
|
region: europe-west1
|
||||||
|
router: core-nat-static-nat
|
||||||
|
rules: []
|
||||||
|
source_subnetwork_ip_ranges_to_nat: LIST_OF_SUBNETWORKS
|
||||||
|
subnetwork:
|
||||||
|
- secondary_ip_range_names: []
|
||||||
|
source_ip_ranges_to_nat:
|
||||||
|
- 'ALL_IP_RANGES'
|
||||||
|
tcp_established_idle_timeout_sec: 1200
|
||||||
|
tcp_time_wait_timeout_sec: 120
|
||||||
|
tcp_transitory_idle_timeout_sec: 30
|
||||||
|
type: PUBLIC
|
||||||
|
udp_idle_timeout_sec: 30
|
||||||
@@ -22,6 +22,11 @@ tests:
|
|||||||
- dns_delegations.yaml
|
- dns_delegations.yaml
|
||||||
extra_dirs:
|
extra_dirs:
|
||||||
- ../../../tests/fast/stages/s2_networking/data-testdns-delegation
|
- ../../../tests/fast/stages/s2_networking/data-testdns-delegation
|
||||||
|
static_ips_nat:
|
||||||
|
inventory:
|
||||||
|
- static_ips_nat.yaml
|
||||||
|
extra_dirs:
|
||||||
|
- ../../../tests/fast/stages/s2_networking/data-teststatic-ips-nat
|
||||||
ncc:
|
ncc:
|
||||||
nva:
|
nva:
|
||||||
vlan_attachments:
|
vlan_attachments:
|
||||||
|
|||||||
Reference in New Issue
Block a user