From 13636ba07b1154fe1727a3affb82190e30135273 Mon Sep 17 00:00:00 2001 From: Julio Castillo Date: Fri, 2 Feb 2024 10:58:16 +0100 Subject: [PATCH] Make Cloud NAT creation optional in FAST net stages. (#2038) * Make Cloud NAT creation optional in FAST net stages. Fixes #2021 * Update READMEs --- fast/stages/2-networking-a-peering/README.md | 23 ++++++------ fast/stages/2-networking-a-peering/net-dev.tf | 4 +-- .../2-networking-a-peering/net-landing.tf | 3 +- .../stages/2-networking-a-peering/net-prod.tf | 4 +-- .../2-networking-a-peering/variables.tf | 7 ++++ fast/stages/2-networking-b-vpn/README.md | 23 ++++++------ fast/stages/2-networking-b-vpn/net-dev.tf | 4 +-- fast/stages/2-networking-b-vpn/net-landing.tf | 3 +- fast/stages/2-networking-b-vpn/net-prod.tf | 4 +-- fast/stages/2-networking-b-vpn/variables.tf | 7 ++++ fast/stages/2-networking-c-nva/README.md | 31 ++++++++-------- fast/stages/2-networking-c-nva/net-landing.tf | 4 ++- fast/stages/2-networking-c-nva/variables.tf | 7 ++++ .../2-networking-d-separate-envs/README.md | 25 ++++++------- .../2-networking-d-separate-envs/net-dev.tf | 4 +-- .../2-networking-d-separate-envs/net-prod.tf | 4 +-- .../2-networking-d-separate-envs/variables.tf | 7 ++++ fast/stages/2-networking-e-nva-bgp/README.md | 35 ++++++++++--------- .../2-networking-e-nva-bgp/net-landing.tf | 4 ++- .../2-networking-e-nva-bgp/variables.tf | 7 ++++ .../s2_networking_a_peering/common.tfvars | 1 + .../stages/s2_networking_b_vpn/common.tfvars | 1 + .../stages/s2_networking_c_nva/common.tfvars | 1 + .../common.tfvars | 1 + .../s2_networking_e_nva_bgp/common.tfvars | 1 + 25 files changed, 133 insertions(+), 82 deletions(-) diff --git a/fast/stages/2-networking-a-peering/README.md b/fast/stages/2-networking-a-peering/README.md index be27cabd..84208067 100644 --- a/fast/stages/2-networking-a-peering/README.md +++ b/fast/stages/2-networking-a-peering/README.md @@ -101,7 +101,7 @@ In this setup: ### Internet egress -The path of least resistance for Internet egress is using Cloud NAT, and that is what's implemented in this setup, with a NAT gateway configured for each VPC. +Cloud NAT provides the simplest path for internet egress. This setup uses Cloud NAT, with optional per-VPC NAT gateways. Cloud NAT is disabled by default; enable it by setting the `enable_cloud_nat` variable. Several other scenarios are possible of course, with varying degrees of complexity: @@ -389,20 +389,21 @@ DNS configurations are centralised in the `dns-*.tf` files. Spokes delegate DNS |---|---|:---:|:---:|:---:|:---:| | [automation](variables.tf#L42) | Automation resources created by the bootstrap stage. | object({…}) | ✓ | | 0-bootstrap | | [billing_account](variables.tf#L50) | Billing account id. If billing account is not part of the same org set `is_org_level` to false. | object({…}) | ✓ | | 0-bootstrap | -| [folder_ids](variables.tf#L103) | Folders to be used for the networking resources in folders/nnnnnnnnnnn format. If null, folder will be created. | object({…}) | ✓ | | 1-resman | -| [organization](variables.tf#L123) | Organization details. | object({…}) | ✓ | | 0-bootstrap | -| [prefix](variables.tf#L139) | Prefix used for resources that need unique names. Use 9 characters or less. | string | ✓ | | 0-bootstrap | +| [folder_ids](variables.tf#L110) | Folders to be used for the networking resources in folders/nnnnnnnnnnn format. If null, folder will be created. | object({…}) | ✓ | | 1-resman | +| [organization](variables.tf#L130) | Organization details. | object({…}) | ✓ | | 0-bootstrap | +| [prefix](variables.tf#L146) | Prefix used for resources that need unique names. Use 9 characters or less. | string | ✓ | | 0-bootstrap | | [alert_config](variables.tf#L17) | Configuration for monitoring alerts. | object({…}) | | {…} | | | [custom_roles](variables.tf#L63) | Custom roles defined at the org level, in key => id format. | object({…}) | | null | 0-bootstrap | | [dns](variables.tf#L72) | DNS configuration. | object({…}) | | {} | | -| [factories_config](variables.tf#L82) | Configuration for network resource factories. | object({…}) | | {…} | | -| [groups](variables.tf#L113) | Group names or emails to grant organization-level permissions. If just the name is provided, the default organization domain is assumed. | object({…}) | | {} | 0-bootstrap | -| [outputs_location](variables.tf#L133) | Path where providers and tfvars files for the following stages are written. Leave empty to disable. | string | | null | | +| [enable_cloud_nat](variables.tf#L82) | Deploy Cloud NAT. | bool | | false | | +| [factories_config](variables.tf#L89) | Configuration for network resource factories. | object({…}) | | {…} | | +| [groups](variables.tf#L120) | Group names or emails to grant organization-level permissions. If just the name is provided, the default organization domain is assumed. | object({…}) | | {} | 0-bootstrap | +| [outputs_location](variables.tf#L140) | Path where providers and tfvars files for the following stages are written. Leave empty to disable. | string | | null | | | [peering_configs](variables-peerings.tf#L19) | Peering configurations. | object({…}) | | {} | | -| [psa_ranges](variables.tf#L150) | IP ranges used for Private Service Access (CloudSQL, etc.). | object({…}) | | null | | -| [regions](variables.tf#L169) | Region definitions. | object({…}) | | {…} | | -| [service_accounts](variables.tf#L181) | Automation service accounts in name => email format. | object({…}) | | null | 1-resman | -| [vpn_onprem_primary_config](variables.tf#L195) | VPN gateway configuration for onprem interconnection in the primary region. | object({…}) | | null | | +| [psa_ranges](variables.tf#L157) | IP ranges used for Private Service Access (CloudSQL, etc.). | object({…}) | | null | | +| [regions](variables.tf#L176) | Region definitions. | object({…}) | | {…} | | +| [service_accounts](variables.tf#L188) | Automation service accounts in name => email format. | object({…}) | | null | 1-resman | +| [vpn_onprem_primary_config](variables.tf#L202) | VPN gateway configuration for onprem interconnection in the primary region. | object({…}) | | null | | ## Outputs diff --git a/fast/stages/2-networking-a-peering/net-dev.tf b/fast/stages/2-networking-a-peering/net-dev.tf index 898bb850..c9e1d09d 100644 --- a/fast/stages/2-networking-a-peering/net-dev.tf +++ b/fast/stages/2-networking-a-peering/net-dev.tf @@ -1,5 +1,5 @@ /** - * Copyright 2023 Google LLC + * Copyright 2024 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -95,8 +95,8 @@ module "dev-spoke-firewall" { } module "dev-spoke-cloudnat" { - for_each = toset(values(module.dev-spoke-vpc.subnet_regions)) source = "../../../modules/net-cloudnat" + for_each = toset(var.enable_cloud_nat ? values(module.dev-spoke-vpc.subnet_regions) : []) project_id = module.dev-spoke-project.project_id region = each.value name = "dev-nat-${local.region_shortnames[each.value]}" diff --git a/fast/stages/2-networking-a-peering/net-landing.tf b/fast/stages/2-networking-a-peering/net-landing.tf index e2309f1b..c8239e4c 100644 --- a/fast/stages/2-networking-a-peering/net-landing.tf +++ b/fast/stages/2-networking-a-peering/net-landing.tf @@ -1,5 +1,5 @@ /** - * Copyright 2023 Google LLC + * Copyright 2024 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -80,6 +80,7 @@ moved { module "landing-nat-primary" { source = "../../../modules/net-cloudnat" + count = var.enable_cloud_nat ? 1 : 0 project_id = module.landing-project.project_id region = var.regions.primary name = local.region_shortnames[var.regions.primary] diff --git a/fast/stages/2-networking-a-peering/net-prod.tf b/fast/stages/2-networking-a-peering/net-prod.tf index 3226af61..72937b44 100644 --- a/fast/stages/2-networking-a-peering/net-prod.tf +++ b/fast/stages/2-networking-a-peering/net-prod.tf @@ -1,5 +1,5 @@ /** - * Copyright 2023 Google LLC + * Copyright 2024 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -93,8 +93,8 @@ module "prod-spoke-firewall" { } module "prod-spoke-cloudnat" { - for_each = toset(values(module.prod-spoke-vpc.subnet_regions)) source = "../../../modules/net-cloudnat" + for_each = toset(var.enable_cloud_nat ? values(module.prod-spoke-vpc.subnet_regions) : []) project_id = module.prod-spoke-project.project_id region = each.value name = "prod-nat-${local.region_shortnames[each.value]}" diff --git a/fast/stages/2-networking-a-peering/variables.tf b/fast/stages/2-networking-a-peering/variables.tf index 6eaa2d45..b1f51b4c 100644 --- a/fast/stages/2-networking-a-peering/variables.tf +++ b/fast/stages/2-networking-a-peering/variables.tf @@ -79,6 +79,13 @@ variable "dns" { nullable = false } +variable "enable_cloud_nat" { + description = "Deploy Cloud NAT." + type = bool + default = false + nullable = false +} + variable "factories_config" { description = "Configuration for network resource factories." type = object({ diff --git a/fast/stages/2-networking-b-vpn/README.md b/fast/stages/2-networking-b-vpn/README.md index 4a440474..19251ad2 100644 --- a/fast/stages/2-networking-b-vpn/README.md +++ b/fast/stages/2-networking-b-vpn/README.md @@ -107,7 +107,7 @@ As is evident from the table above, the hub/landing VPC acts as the route concen ### Internet egress -The path of least resistance for Internet egress is using Cloud NAT, and that is what's implemented in this setup, with a NAT gateway configured for each VPC. +Cloud NAT provides the simplest path for internet egress. This setup uses Cloud NAT, with optional per-VPC NAT gateways. Cloud NAT is disabled by default; enable it by setting the `enable_cloud_nat` variable. Several other scenarios are possible of course, with varying degrees of complexity: @@ -413,20 +413,21 @@ DNS configurations are centralised in the `dns-*.tf` files. Spokes delegate DNS |---|---|:---:|:---:|:---:|:---:| | [automation](variables.tf#L42) | Automation resources created by the bootstrap stage. | object({…}) | ✓ | | 0-bootstrap | | [billing_account](variables.tf#L50) | Billing account id. If billing account is not part of the same org set `is_org_level` to false. | object({…}) | ✓ | | 0-bootstrap | -| [folder_ids](variables.tf#L103) | Folders to be used for the networking resources in folders/nnnnnnnnnnn format. If null, folder will be created. | object({…}) | ✓ | | 1-resman | -| [organization](variables.tf#L123) | Organization details. | object({…}) | ✓ | | 0-bootstrap | -| [prefix](variables.tf#L139) | Prefix used for resources that need unique names. Use 9 characters or less. | string | ✓ | | 0-bootstrap | +| [folder_ids](variables.tf#L110) | Folders to be used for the networking resources in folders/nnnnnnnnnnn format. If null, folder will be created. | object({…}) | ✓ | | 1-resman | +| [organization](variables.tf#L130) | Organization details. | object({…}) | ✓ | | 0-bootstrap | +| [prefix](variables.tf#L146) | Prefix used for resources that need unique names. Use 9 characters or less. | string | ✓ | | 0-bootstrap | | [alert_config](variables.tf#L17) | Configuration for monitoring alerts. | object({…}) | | {…} | | | [custom_roles](variables.tf#L63) | Custom roles defined at the org level, in key => id format. | object({…}) | | null | 0-bootstrap | | [dns](variables.tf#L72) | DNS configuration. | object({…}) | | {} | | -| [factories_config](variables.tf#L82) | Configuration for network resource factories. | object({…}) | | {…} | | -| [groups](variables.tf#L113) | Group names or emails to grant organization-level permissions. If just the name is provided, the default organization domain is assumed. | object({…}) | | {} | 0-bootstrap | -| [outputs_location](variables.tf#L133) | Path where providers and tfvars files for the following stages are written. Leave empty to disable. | string | | null | | -| [psa_ranges](variables.tf#L150) | IP ranges used for Private Service Access (CloudSQL, etc.). | object({…}) | | null | | -| [regions](variables.tf#L169) | Region definitions. | object({…}) | | {…} | | -| [service_accounts](variables.tf#L181) | Automation service accounts in name => email format. | object({…}) | | null | 1-resman | +| [enable_cloud_nat](variables.tf#L82) | Deploy Cloud NAT. | bool | | false | | +| [factories_config](variables.tf#L89) | Configuration for network resource factories. | object({…}) | | {…} | | +| [groups](variables.tf#L120) | Group names or emails to grant organization-level permissions. If just the name is provided, the default organization domain is assumed. | object({…}) | | {} | 0-bootstrap | +| [outputs_location](variables.tf#L140) | Path where providers and tfvars files for the following stages are written. Leave empty to disable. | string | | null | | +| [psa_ranges](variables.tf#L157) | IP ranges used for Private Service Access (CloudSQL, etc.). | object({…}) | | null | | +| [regions](variables.tf#L176) | Region definitions. | object({…}) | | {…} | | +| [service_accounts](variables.tf#L188) | Automation service accounts in name => email format. | object({…}) | | null | 1-resman | | [vpn_configs](variables-vpn.tf#L17) | Hub to spokes VPN configurations. | object({…}) | | {} | | -| [vpn_onprem_primary_config](variables.tf#L195) | VPN gateway configuration for onprem interconnection in the primary region. | object({…}) | | null | | +| [vpn_onprem_primary_config](variables.tf#L202) | VPN gateway configuration for onprem interconnection in the primary region. | object({…}) | | null | | ## Outputs diff --git a/fast/stages/2-networking-b-vpn/net-dev.tf b/fast/stages/2-networking-b-vpn/net-dev.tf index 898bb850..c9e1d09d 100644 --- a/fast/stages/2-networking-b-vpn/net-dev.tf +++ b/fast/stages/2-networking-b-vpn/net-dev.tf @@ -1,5 +1,5 @@ /** - * Copyright 2023 Google LLC + * Copyright 2024 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -95,8 +95,8 @@ module "dev-spoke-firewall" { } module "dev-spoke-cloudnat" { - for_each = toset(values(module.dev-spoke-vpc.subnet_regions)) source = "../../../modules/net-cloudnat" + for_each = toset(var.enable_cloud_nat ? values(module.dev-spoke-vpc.subnet_regions) : []) project_id = module.dev-spoke-project.project_id region = each.value name = "dev-nat-${local.region_shortnames[each.value]}" diff --git a/fast/stages/2-networking-b-vpn/net-landing.tf b/fast/stages/2-networking-b-vpn/net-landing.tf index e2309f1b..c8239e4c 100644 --- a/fast/stages/2-networking-b-vpn/net-landing.tf +++ b/fast/stages/2-networking-b-vpn/net-landing.tf @@ -1,5 +1,5 @@ /** - * Copyright 2023 Google LLC + * Copyright 2024 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -80,6 +80,7 @@ moved { module "landing-nat-primary" { source = "../../../modules/net-cloudnat" + count = var.enable_cloud_nat ? 1 : 0 project_id = module.landing-project.project_id region = var.regions.primary name = local.region_shortnames[var.regions.primary] diff --git a/fast/stages/2-networking-b-vpn/net-prod.tf b/fast/stages/2-networking-b-vpn/net-prod.tf index 3226af61..72937b44 100644 --- a/fast/stages/2-networking-b-vpn/net-prod.tf +++ b/fast/stages/2-networking-b-vpn/net-prod.tf @@ -1,5 +1,5 @@ /** - * Copyright 2023 Google LLC + * Copyright 2024 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -93,8 +93,8 @@ module "prod-spoke-firewall" { } module "prod-spoke-cloudnat" { - for_each = toset(values(module.prod-spoke-vpc.subnet_regions)) source = "../../../modules/net-cloudnat" + for_each = toset(var.enable_cloud_nat ? values(module.prod-spoke-vpc.subnet_regions) : []) project_id = module.prod-spoke-project.project_id region = each.value name = "prod-nat-${local.region_shortnames[each.value]}" diff --git a/fast/stages/2-networking-b-vpn/variables.tf b/fast/stages/2-networking-b-vpn/variables.tf index 6eaa2d45..b1f51b4c 100644 --- a/fast/stages/2-networking-b-vpn/variables.tf +++ b/fast/stages/2-networking-b-vpn/variables.tf @@ -79,6 +79,13 @@ variable "dns" { nullable = false } +variable "enable_cloud_nat" { + description = "Deploy Cloud NAT." + type = bool + default = false + nullable = false +} + variable "factories_config" { description = "Configuration for network resource factories." type = object({ diff --git a/fast/stages/2-networking-c-nva/README.md b/fast/stages/2-networking-c-nva/README.md index 79019c0e..60ecf02c 100644 --- a/fast/stages/2-networking-c-nva/README.md +++ b/fast/stages/2-networking-c-nva/README.md @@ -79,7 +79,7 @@ The traffic destined to the VMs in each MIG is mediated through regional interna By default, the design assumes the following: - on-premise networks (and related resources) are considered trusted. As such, the VPNs connecting with on-premises are terminated in GCP, in the trusted VPC -- the public Internet is considered untrusted. As such [Cloud NAT](https://cloud.google.com/nat/docs/overview) has been deployed in the untrusted landing VPC only +- the public Internet is considered untrusted. As such [Cloud NAT](https://cloud.google.com/nat/docs/overview) is deployed in the untrusted landing VPC only - cross-environment traffic and traffic from any untrusted network to any trusted network (and vice versa) pass through the NVAs. For demo purposes, the current NVA performs simple routing/natting only - any traffic from a trusted network to an untrusted network (e.g. Internet) is natted by the NVAs. Users can configure further exclusions @@ -169,7 +169,7 @@ The Cloud Routers (connected to the VPN gateways in the trusted VPC) are configu ### Internet egress -In this setup, Internet egress is realized through [Cloud NAT](https://cloud.google.com/nat/docs/overview), deployed in the untrusted landing VPC. This allows instances in all other VPCs to reach the Internet, passing through the NVAs (being the public Internet considered untrusted). +In this setup, Internet egress is realized through [Cloud NAT](https://cloud.google.com/nat/docs/overview), deployed in the untrusted landing VPC. This allows instances in all other VPCs to reach the Internet, passing through the NVAs (being the public Internet considered untrusted). Cloud NAT is disabled by default; enable it by setting the `enable_cloud_nat` variable Several other scenarios are possible, with various degrees of complexity: @@ -458,22 +458,23 @@ DNS configurations are centralised in the `dns-*.tf` files. Spokes delegate DNS |---|---|:---:|:---:|:---:|:---:| | [automation](variables.tf#L42) | Automation resources created by the bootstrap stage. | object({…}) | ✓ | | 0-bootstrap | | [billing_account](variables.tf#L50) | Billing account id. If billing account is not part of the same org set `is_org_level` to false. | object({…}) | ✓ | | 0-bootstrap | -| [folder_ids](variables.tf#L103) | Folders to be used for the networking resources in folders/nnnnnnnnnnn format. If null, folder will be created. | object({…}) | ✓ | | 1-resman | -| [organization](variables.tf#L146) | Organization details. | object({…}) | ✓ | | 0-bootstrap | -| [prefix](variables.tf#L162) | Prefix used for resources that need unique names. Use 9 characters or less. | string | ✓ | | 0-bootstrap | +| [folder_ids](variables.tf#L110) | Folders to be used for the networking resources in folders/nnnnnnnnnnn format. If null, folder will be created. | object({…}) | ✓ | | 1-resman | +| [organization](variables.tf#L153) | Organization details. | object({…}) | ✓ | | 0-bootstrap | +| [prefix](variables.tf#L169) | Prefix used for resources that need unique names. Use 9 characters or less. | string | ✓ | | 0-bootstrap | | [alert_config](variables.tf#L17) | Configuration for monitoring alerts. | object({…}) | | {…} | | | [custom_roles](variables.tf#L63) | Custom roles defined at the org level, in key => id format. | object({…}) | | null | 0-bootstrap | | [dns](variables.tf#L72) | DNS configuration. | object({…}) | | {} | | -| [factories_config](variables.tf#L82) | Configuration for network resource factories. | object({…}) | | {…} | | -| [gcp_ranges](variables.tf#L113) | GCP address ranges in name => range format. | map(string) | | {…} | | -| [groups](variables.tf#L128) | Group names or emails to grant organization-level permissions. If just the name is provided, the default organization domain is assumed. | object({…}) | | {} | 0-bootstrap | -| [onprem_cidr](variables.tf#L138) | Onprem addresses in name => range format. | map(string) | | {…} | | -| [outputs_location](variables.tf#L156) | Path where providers and tfvars files for the following stages are written. Leave empty to disable. | string | | null | | -| [psa_ranges](variables.tf#L173) | IP ranges used for Private Service Access (e.g. CloudSQL). Ranges is in name => range format. | object({…}) | | null | | -| [regions](variables.tf#L192) | Region definitions. | object({…}) | | {…} | | -| [service_accounts](variables.tf#L204) | Automation service accounts in name => email format. | object({…}) | | null | 1-resman | -| [vpn_onprem_primary_config](variables.tf#L218) | VPN gateway configuration for onprem interconnection in the primary region. | object({…}) | | null | | -| [vpn_onprem_secondary_config](variables.tf#L261) | VPN gateway configuration for onprem interconnection in the secondary region. | object({…}) | | null | | +| [enable_cloud_nat](variables.tf#L82) | Deploy Cloud NAT. | bool | | false | | +| [factories_config](variables.tf#L89) | Configuration for network resource factories. | object({…}) | | {…} | | +| [gcp_ranges](variables.tf#L120) | GCP address ranges in name => range format. | map(string) | | {…} | | +| [groups](variables.tf#L135) | Group names or emails to grant organization-level permissions. If just the name is provided, the default organization domain is assumed. | object({…}) | | {} | 0-bootstrap | +| [onprem_cidr](variables.tf#L145) | Onprem addresses in name => range format. | map(string) | | {…} | | +| [outputs_location](variables.tf#L163) | Path where providers and tfvars files for the following stages are written. Leave empty to disable. | string | | null | | +| [psa_ranges](variables.tf#L180) | IP ranges used for Private Service Access (e.g. CloudSQL). Ranges is in name => range format. | object({…}) | | null | | +| [regions](variables.tf#L199) | Region definitions. | object({…}) | | {…} | | +| [service_accounts](variables.tf#L211) | Automation service accounts in name => email format. | object({…}) | | null | 1-resman | +| [vpn_onprem_primary_config](variables.tf#L225) | VPN gateway configuration for onprem interconnection in the primary region. | object({…}) | | null | | +| [vpn_onprem_secondary_config](variables.tf#L268) | VPN gateway configuration for onprem interconnection in the secondary region. | object({…}) | | null | | ## Outputs diff --git a/fast/stages/2-networking-c-nva/net-landing.tf b/fast/stages/2-networking-c-nva/net-landing.tf index fb19c31b..86230a0b 100644 --- a/fast/stages/2-networking-c-nva/net-landing.tf +++ b/fast/stages/2-networking-c-nva/net-landing.tf @@ -1,5 +1,5 @@ /** - * Copyright 2023 Google LLC + * Copyright 2024 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -81,6 +81,7 @@ moved { module "landing-nat-primary" { source = "../../../modules/net-cloudnat" + count = var.enable_cloud_nat ? 1 : 0 project_id = module.landing-project.project_id region = var.regions.primary name = local.region_shortnames[var.regions.primary] @@ -96,6 +97,7 @@ moved { module "landing-nat-secondary" { source = "../../../modules/net-cloudnat" + count = var.enable_cloud_nat ? 1 : 0 project_id = module.landing-project.project_id region = var.regions.secondary name = local.region_shortnames[var.regions.secondary] diff --git a/fast/stages/2-networking-c-nva/variables.tf b/fast/stages/2-networking-c-nva/variables.tf index a376ce42..9d100143 100644 --- a/fast/stages/2-networking-c-nva/variables.tf +++ b/fast/stages/2-networking-c-nva/variables.tf @@ -79,6 +79,13 @@ variable "dns" { nullable = false } +variable "enable_cloud_nat" { + description = "Deploy Cloud NAT." + type = bool + default = false + nullable = false +} + variable "factories_config" { description = "Configuration for network resource factories." type = object({ diff --git a/fast/stages/2-networking-d-separate-envs/README.md b/fast/stages/2-networking-d-separate-envs/README.md index 5922ce61..0febb156 100644 --- a/fast/stages/2-networking-d-separate-envs/README.md +++ b/fast/stages/2-networking-d-separate-envs/README.md @@ -71,7 +71,7 @@ In this setup: ### Internet egress -The path of least resistance for Internet egress is using Cloud NAT, and that is what's implemented in this setup, with a NAT gateway configured for each VPC. +Cloud NAT provides the simplest path for internet egress. This setup uses Cloud NAT, with optional per-VPC NAT gateways. Cloud NAT is disabled by default; enable it by setting the `enable_cloud_nat` variable. Several other scenarios are possible of course, with varying degrees of complexity: @@ -332,20 +332,21 @@ Regions are defined via the `regions` variable which sets up a mapping between t |---|---|:---:|:---:|:---:|:---:| | [automation](variables.tf#L42) | Automation resources created by the bootstrap stage. | object({…}) | ✓ | | 0-bootstrap | | [billing_account](variables.tf#L50) | Billing account id. If billing account is not part of the same org set `is_org_level` to false. | object({…}) | ✓ | | 0-bootstrap | -| [folder_ids](variables.tf#L104) | Folders to be used for the networking resources in folders/nnnnnnnnnnn format. If null, folder will be created. | object({…}) | ✓ | | 1-resman | -| [organization](variables.tf#L124) | Organization details. | object({…}) | ✓ | | 0-bootstrap | -| [prefix](variables.tf#L140) | Prefix used for resources that need unique names. Use 9 characters or less. | string | ✓ | | 0-bootstrap | +| [folder_ids](variables.tf#L111) | Folders to be used for the networking resources in folders/nnnnnnnnnnn format. If null, folder will be created. | object({…}) | ✓ | | 1-resman | +| [organization](variables.tf#L131) | Organization details. | object({…}) | ✓ | | 0-bootstrap | +| [prefix](variables.tf#L147) | Prefix used for resources that need unique names. Use 9 characters or less. | string | ✓ | | 0-bootstrap | | [alert_config](variables.tf#L17) | Configuration for monitoring alerts. | object({…}) | | {…} | | | [custom_roles](variables.tf#L63) | Custom roles defined at the org level, in key => id format. | object({…}) | | null | 0-bootstrap | | [dns](variables.tf#L72) | DNS configuration. | object({…}) | | {} | | -| [factories_config](variables.tf#L83) | Configuration for network resource factories. | object({…}) | | {…} | | -| [groups](variables.tf#L114) | Group names or emails to grant organization-level permissions. If just the name is provided, the default organization domain is assumed. | object({…}) | | {} | 0-bootstrap | -| [outputs_location](variables.tf#L134) | Path where providers and tfvars files for the following stages are written. Leave empty to disable. | string | | null | | -| [psa_ranges](variables.tf#L151) | IP ranges used for Private Service Access (e.g. CloudSQL). | object({…}) | | null | | -| [regions](variables.tf#L170) | Region definitions. | object({…}) | | {…} | | -| [service_accounts](variables.tf#L180) | Automation service accounts in name => email format. | object({…}) | | null | 1-resman | -| [vpn_onprem_dev_primary_config](variables.tf#L194) | VPN gateway configuration for onprem interconnection from dev in the primary region. | object({…}) | | null | | -| [vpn_onprem_prod_primary_config](variables.tf#L237) | VPN gateway configuration for onprem interconnection from prod in the primary region. | object({…}) | | null | | +| [enable_cloud_nat](variables.tf#L83) | Deploy Cloud NAT. | bool | | false | | +| [factories_config](variables.tf#L90) | Configuration for network resource factories. | object({…}) | | {…} | | +| [groups](variables.tf#L121) | Group names or emails to grant organization-level permissions. If just the name is provided, the default organization domain is assumed. | object({…}) | | {} | 0-bootstrap | +| [outputs_location](variables.tf#L141) | Path where providers and tfvars files for the following stages are written. Leave empty to disable. | string | | null | | +| [psa_ranges](variables.tf#L158) | IP ranges used for Private Service Access (e.g. CloudSQL). | object({…}) | | null | | +| [regions](variables.tf#L177) | Region definitions. | object({…}) | | {…} | | +| [service_accounts](variables.tf#L187) | Automation service accounts in name => email format. | object({…}) | | null | 1-resman | +| [vpn_onprem_dev_primary_config](variables.tf#L201) | VPN gateway configuration for onprem interconnection from dev in the primary region. | object({…}) | | null | | +| [vpn_onprem_prod_primary_config](variables.tf#L244) | VPN gateway configuration for onprem interconnection from prod in the primary region. | object({…}) | | null | | ## Outputs diff --git a/fast/stages/2-networking-d-separate-envs/net-dev.tf b/fast/stages/2-networking-d-separate-envs/net-dev.tf index 5cd8c355..753a6a4e 100644 --- a/fast/stages/2-networking-d-separate-envs/net-dev.tf +++ b/fast/stages/2-networking-d-separate-envs/net-dev.tf @@ -1,5 +1,5 @@ /** - * Copyright 2023 Google LLC + * Copyright 2024 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -95,8 +95,8 @@ module "dev-spoke-firewall" { } module "dev-spoke-cloudnat" { - for_each = toset(values(module.dev-spoke-vpc.subnet_regions)) source = "../../../modules/net-cloudnat" + for_each = toset(var.enable_cloud_nat ? values(module.dev-spoke-vpc.subnet_regions) : []) project_id = module.dev-spoke-project.project_id region = each.value name = "dev-nat-${local.region_shortnames[each.value]}" diff --git a/fast/stages/2-networking-d-separate-envs/net-prod.tf b/fast/stages/2-networking-d-separate-envs/net-prod.tf index 6889bb96..920d3fce 100644 --- a/fast/stages/2-networking-d-separate-envs/net-prod.tf +++ b/fast/stages/2-networking-d-separate-envs/net-prod.tf @@ -1,5 +1,5 @@ /** - * Copyright 2023 Google LLC + * Copyright 2024 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -93,8 +93,8 @@ module "prod-spoke-firewall" { } module "prod-spoke-cloudnat" { - for_each = toset(values(module.prod-spoke-vpc.subnet_regions)) source = "../../../modules/net-cloudnat" + for_each = toset(var.enable_cloud_nat ? values(module.prod-spoke-vpc.subnet_regions) : []) project_id = module.prod-spoke-project.project_id region = each.value name = "prod-nat-${local.region_shortnames[each.value]}" diff --git a/fast/stages/2-networking-d-separate-envs/variables.tf b/fast/stages/2-networking-d-separate-envs/variables.tf index f6dccda0..a105750a 100644 --- a/fast/stages/2-networking-d-separate-envs/variables.tf +++ b/fast/stages/2-networking-d-separate-envs/variables.tf @@ -80,6 +80,13 @@ variable "dns" { nullable = false } +variable "enable_cloud_nat" { + description = "Deploy Cloud NAT." + type = bool + default = false + nullable = false +} + variable "factories_config" { description = "Configuration for network resource factories." type = object({ diff --git a/fast/stages/2-networking-e-nva-bgp/README.md b/fast/stages/2-networking-e-nva-bgp/README.md index 4b684e20..7e56b3b4 100644 --- a/fast/stages/2-networking-e-nva-bgp/README.md +++ b/fast/stages/2-networking-e-nva-bgp/README.md @@ -102,7 +102,7 @@ Following the majority of real-life deployments, **we assume appliances to be st By default, the design assumes that: - on-premise networks (and related resources) are considered trusted. As such, the VPNs connecting with on-premises are terminated in GCP, in the trusted VPC -- the public Internet is considered untrusted. As such [Cloud NAT](https://cloud.google.com/nat/docs/overview) has been deployed in the untrusted landing VPC only. Also, the default route is set to carry traffic from the trusted VPCs, through the NVAs, to the untrusted VPC. +- the public Internet is considered untrusted. As such [Cloud NAT](https://cloud.google.com/nat/docs/overview) is deployed in the untrusted landing VPC only. Also, the default route is set to carry traffic from the trusted VPCs, through the NVAs, to the untrusted VPC. - cross-spoke (environment) traffic and traffic from any untrusted network to any trusted network (and vice versa) pass through the NVAs. - any traffic from a trusted network to an untrusted network (e.g. Internet) is natted by the NVAs. Users can configure further exclusions. @@ -190,7 +190,7 @@ The Cloud Routers (connected to the VPN gateways in the trusted VPC) are configu ### Internet egress -In this setup, Internet egress is realized through [Cloud NAT](https://cloud.google.com/nat/docs/overview), deployed in the untrusted landing VPC. This allows instances in all other VPCs to reach the Internet, passing through the NVAs (being the public Internet considered untrusted). +In this setup, Internet egress is realized through [Cloud NAT](https://cloud.google.com/nat/docs/overview), deployed in the untrusted landing VPC. This allows instances in all other VPCs to reach the Internet, passing through the NVAs (being the public Internet considered untrusted). Cloud NAT is disabled by default; enable it by setting the `enable_cloud_nat` variable Several other scenarios are possible, with various degrees of complexity: @@ -484,24 +484,25 @@ DNS configurations are centralised in the `dns-*.tf` files. Spokes delegate DNS |---|---|:---:|:---:|:---:|:---:| | [automation](variables.tf#L42) | Automation resources created by the bootstrap stage. | object({…}) | ✓ | | 0-bootstrap | | [billing_account](variables.tf#L50) | Billing account id. If billing account is not part of the same org set `is_org_level` to false. | object({…}) | ✓ | | 0-bootstrap | -| [folder_ids](variables.tf#L103) | Folders to be used for the networking resources in folders/nnnnnnnnnnn format. If null, folder will be created. | object({…}) | ✓ | | 1-resman | -| [organization](variables.tf#L157) | Organization details. | object({…}) | ✓ | | 0-bootstrap | -| [prefix](variables.tf#L173) | Prefix used for resources that need unique names. Use 9 characters or less. | string | ✓ | | 0-bootstrap | +| [folder_ids](variables.tf#L110) | Folders to be used for the networking resources in folders/nnnnnnnnnnn format. If null, folder will be created. | object({…}) | ✓ | | 1-resman | +| [organization](variables.tf#L164) | Organization details. | object({…}) | ✓ | | 0-bootstrap | +| [prefix](variables.tf#L180) | Prefix used for resources that need unique names. Use 9 characters or less. | string | ✓ | | 0-bootstrap | | [alert_config](variables.tf#L17) | Configuration for monitoring alerts. | object({…}) | | {…} | | | [custom_roles](variables.tf#L63) | Custom roles defined at the org level, in key => id format. | object({…}) | | null | 0-bootstrap | | [dns](variables.tf#L72) | DNS configuration. | object({…}) | | {} | | -| [factories_config](variables.tf#L82) | Configuration for network resource factories. | object({…}) | | {…} | | -| [gcp_ranges](variables.tf#L113) | GCP address ranges in name => range format. | map(string) | | {…} | | -| [groups](variables.tf#L128) | Group names or emails to grant organization-level permissions. If just the name is provided, the default organization domain is assumed. | object({…}) | | {} | 0-bootstrap | -| [ncc_asn](variables.tf#L138) | The NCC Cloud Routers ASN configuration. | map(number) | | {…} | | -| [onprem_cidr](variables.tf#L149) | Onprem addresses in name => range format. | map(string) | | {…} | | -| [outputs_location](variables.tf#L167) | Path where providers and tfvars files for the following stages are written. Leave empty to disable. | string | | null | | -| [psa_ranges](variables.tf#L184) | IP ranges used for Private Service Access (e.g. CloudSQL). Ranges is in name => range format. | object({…}) | | null | | -| [regions](variables.tf#L203) | Region definitions. | object({…}) | | {…} | | -| [service_accounts](variables.tf#L215) | Automation service accounts in name => email format. | object({…}) | | null | 1-resman | -| [vpn_onprem_primary_config](variables.tf#L229) | VPN gateway configuration for onprem interconnection in the primary region. | object({…}) | | null | | -| [vpn_onprem_secondary_config](variables.tf#L272) | VPN gateway configuration for onprem interconnection in the secondary region. | object({…}) | | null | | -| [zones](variables.tf#L315) | Zones in which NVAs are deployed. | list(string) | | ["b", "c"] | | +| [enable_cloud_nat](variables.tf#L82) | Deploy Cloud NAT. | bool | | false | | +| [factories_config](variables.tf#L89) | Configuration for network resource factories. | object({…}) | | {…} | | +| [gcp_ranges](variables.tf#L120) | GCP address ranges in name => range format. | map(string) | | {…} | | +| [groups](variables.tf#L135) | Group names or emails to grant organization-level permissions. If just the name is provided, the default organization domain is assumed. | object({…}) | | {} | 0-bootstrap | +| [ncc_asn](variables.tf#L145) | The NCC Cloud Routers ASN configuration. | map(number) | | {…} | | +| [onprem_cidr](variables.tf#L156) | Onprem addresses in name => range format. | map(string) | | {…} | | +| [outputs_location](variables.tf#L174) | Path where providers and tfvars files for the following stages are written. Leave empty to disable. | string | | null | | +| [psa_ranges](variables.tf#L191) | IP ranges used for Private Service Access (e.g. CloudSQL). Ranges is in name => range format. | object({…}) | | null | | +| [regions](variables.tf#L210) | Region definitions. | object({…}) | | {…} | | +| [service_accounts](variables.tf#L222) | Automation service accounts in name => email format. | object({…}) | | null | 1-resman | +| [vpn_onprem_primary_config](variables.tf#L236) | VPN gateway configuration for onprem interconnection in the primary region. | object({…}) | | null | | +| [vpn_onprem_secondary_config](variables.tf#L279) | VPN gateway configuration for onprem interconnection in the secondary region. | object({…}) | | null | | +| [zones](variables.tf#L322) | Zones in which NVAs are deployed. | list(string) | | ["b", "c"] | | ## Outputs diff --git a/fast/stages/2-networking-e-nva-bgp/net-landing.tf b/fast/stages/2-networking-e-nva-bgp/net-landing.tf index 07331717..4362a10c 100644 --- a/fast/stages/2-networking-e-nva-bgp/net-landing.tf +++ b/fast/stages/2-networking-e-nva-bgp/net-landing.tf @@ -1,5 +1,5 @@ /** - * Copyright 2023 Google LLC + * Copyright 2024 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -82,6 +82,7 @@ moved { module "landing-nat-primary" { source = "../../../modules/net-cloudnat" + count = var.enable_cloud_nat ? 1 : 0 project_id = module.landing-project.project_id region = var.regions.primary name = local.region_shortnames[var.regions.primary] @@ -97,6 +98,7 @@ moved { module "landing-nat-secondary" { source = "../../../modules/net-cloudnat" + count = var.enable_cloud_nat ? 1 : 0 project_id = module.landing-project.project_id region = var.regions.secondary name = local.region_shortnames[var.regions.secondary] diff --git a/fast/stages/2-networking-e-nva-bgp/variables.tf b/fast/stages/2-networking-e-nva-bgp/variables.tf index fd2c055e..3a47e095 100644 --- a/fast/stages/2-networking-e-nva-bgp/variables.tf +++ b/fast/stages/2-networking-e-nva-bgp/variables.tf @@ -79,6 +79,13 @@ variable "dns" { nullable = false } +variable "enable_cloud_nat" { + description = "Deploy Cloud NAT." + type = bool + default = false + nullable = false +} + variable "factories_config" { description = "Configuration for network resource factories." type = object({ diff --git a/tests/fast/stages/s2_networking_a_peering/common.tfvars b/tests/fast/stages/s2_networking_a_peering/common.tfvars index b46a10ab..8add6316 100644 --- a/tests/fast/stages/s2_networking_a_peering/common.tfvars +++ b/tests/fast/stages/s2_networking_a_peering/common.tfvars @@ -11,6 +11,7 @@ dns = { resolvers = ["10.10.10.10"] enable_logging = true } +enable_cloud_nat = true folder_ids = { networking = null networking-dev = null diff --git a/tests/fast/stages/s2_networking_b_vpn/common.tfvars b/tests/fast/stages/s2_networking_b_vpn/common.tfvars index 1aa1f51f..a285f822 100644 --- a/tests/fast/stages/s2_networking_b_vpn/common.tfvars +++ b/tests/fast/stages/s2_networking_b_vpn/common.tfvars @@ -11,6 +11,7 @@ dns = { resolvers = ["10.10.10.10"] enable_logging = true } +enable_cloud_nat = true folder_ids = { networking = null networking-dev = null diff --git a/tests/fast/stages/s2_networking_c_nva/common.tfvars b/tests/fast/stages/s2_networking_c_nva/common.tfvars index 8660ee8f..0a60b65d 100644 --- a/tests/fast/stages/s2_networking_c_nva/common.tfvars +++ b/tests/fast/stages/s2_networking_c_nva/common.tfvars @@ -11,6 +11,7 @@ dns = { resolvers = ["10.10.10.10"] enable_logging = true } +enable_cloud_nat = true folder_ids = { networking = null networking-dev = null diff --git a/tests/fast/stages/s2_networking_d_separate_envs/common.tfvars b/tests/fast/stages/s2_networking_d_separate_envs/common.tfvars index b7d966a2..3900d54d 100644 --- a/tests/fast/stages/s2_networking_d_separate_envs/common.tfvars +++ b/tests/fast/stages/s2_networking_d_separate_envs/common.tfvars @@ -12,6 +12,7 @@ dns = { prod_resolvers = ["10.20.10.10"] enable_logging = true } +enable_cloud_nat = true folder_ids = { networking = null networking-dev = null diff --git a/tests/fast/stages/s2_networking_e_nva_bgp/common.tfvars b/tests/fast/stages/s2_networking_e_nva_bgp/common.tfvars index 8660ee8f..0a60b65d 100644 --- a/tests/fast/stages/s2_networking_e_nva_bgp/common.tfvars +++ b/tests/fast/stages/s2_networking_e_nva_bgp/common.tfvars @@ -11,6 +11,7 @@ dns = { resolvers = ["10.10.10.10"] enable_logging = true } +enable_cloud_nat = true folder_ids = { networking = null networking-dev = null