diff --git a/fast/stages/2-networking-a-peering/README.md b/fast/stages/2-networking-a-peering/README.md index 293a768e..9db5062e 100644 --- a/fast/stages/2-networking-a-peering/README.md +++ b/fast/stages/2-networking-a-peering/README.md @@ -40,6 +40,7 @@ The following diagram illustrates the high-level design, and should be used as a - [Post-deployment activities](#post-deployment-activities) - [Customizations](#customizations) - [Changing default regions](#changing-default-regions) + - [Configuring the VPN to on prem](#configuring-the-vpn-to-on-prem) - [Adding an environment](#adding-an-environment) ## Design overview and choices @@ -164,7 +165,7 @@ Subnets for [L7 ILBs](https://cloud.google.com/load-balancing/docs/l7-internal/p ### VPNs -Connectivity to on-prem is implemented with HA VPN ([`net-vpn`](../../../modules/net-vpn-ha)) and defined in [`vpn-onprem.tf`](./vpn-onprem.tf). The file provisionally implements a single logical connection between onprem and landing at `europe-west1`, and the relevant parameters for its configuration are found in variable `vpn_onprem_configs`. +Connectivity to on-prem is implemented with HA VPN ([`net-vpn`](../../../modules/net-vpn-ha)) and defined in [`vpn-onprem.tf`](./vpn-onprem.tf). The file provisionally implements a single logical connection between onprem and landing at `europe-west1`, and the relevant parameters for its configuration are found in variable `vpn_onprem_primary_configs`. An example configuration is provided [below](#configuring-the-vpn-to-on-prem). ### Routing and BGP @@ -302,6 +303,55 @@ Regions are defined via the `regions` variable which sets up a mapping between t - change the values of the mappings in the `regions` variable to the regions you are going to use - change the regions in the factory subnet files in the `data` folder +### Configuring the VPN to on prem + +This stage includes basic support for an HA VPN connecting the landing zone in the primary region to on prem. Configuration is via the `vpn_onprem_primary_config` variable, that closely mirrors the variables defined in the [`net-vpn-ha`](../../../modules/net-vpn-ha/). + +Support for the onprem VPN is disabled by default so that no resources are created, this is an example of how to configure the variable to enable the VPN: + +```hcl +vpn_onprem_primary_config = { + peer_external_gateways = { + default = { + redundancy_type = "SINGLE_IP_INTERNALLY_REDUNDANT" + interfaces = ["8.8.8.8"] + } + } + router_config = { + asn = 65501 + custom_advertise = { + all_subnets = false + ip_ranges = { + "10.1.0.0/16" = "gcp" + "35.199.192.0/19" = "gcp-dns" + "199.36.153.4/30" = "gcp-restricted" + } + } + } + tunnels = { + "0" = { + bgp_peer = { + address = "169.254.1.1" + asn = 65500 + } + bgp_session_range = "169.254.1.2/30" + shared_secret = "foo" + vpn_gateway_interface = 0 + } + "1" = { + bgp_peer = { + address = "169.254.2.1" + asn = 64513 + } + bgp_session_range = "169.254.2.2/30" + shared_secret = "foo" + vpn_gateway_interface = 1 + } + } +} +# tftest skip +``` + ### Adding an environment To create a new environment (e.g. `staging`), a few changes are required. @@ -346,20 +396,18 @@ DNS configurations are centralised in the `dns-*.tf` files. Spokes delegate DNS |---|---|:---:|:---:|:---:|:---:| | [automation](variables.tf#L17) | Automation resources created by the bootstrap stage. | object({…}) | ✓ | | 0-bootstrap | | [billing_account](variables.tf#L25) | 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#L92) | Folders to be used for the networking resources in folders/nnnnnnnnnnn format. If null, folder will be created. | object({…}) | ✓ | | 1-resman | -| [organization](variables.tf#L102) | Organization details. | object({…}) | ✓ | | 0-bootstrap | -| [prefix](variables.tf#L118) | Prefix used for resources that need unique names. Use 9 characters or less. | string | ✓ | | 0-bootstrap | -| [custom_adv](variables.tf#L38) | Custom advertisement definitions in name => range format. | map(string) | | {…} | | -| [custom_roles](variables.tf#L55) | Custom roles defined at the org level, in key => id format. | object({…}) | | null | 0-bootstrap | -| [dns](variables.tf#L64) | Onprem DNS resolvers. | map(list(string)) | | {…} | | -| [factories_config](variables.tf#L72) | Configuration for network resource factories. | object({…}) | | {…} | | -| [outputs_location](variables.tf#L112) | Path where providers and tfvars files for the following stages are written. Leave empty to disable. | string | | null | | +| [folder_ids](variables.tf#L75) | Folders to be used for the networking resources in folders/nnnnnnnnnnn format. If null, folder will be created. | object({…}) | ✓ | | 1-resman | +| [organization](variables.tf#L85) | Organization details. | object({…}) | ✓ | | 0-bootstrap | +| [prefix](variables.tf#L101) | Prefix used for resources that need unique names. Use 9 characters or less. | string | ✓ | | 0-bootstrap | +| [custom_roles](variables.tf#L38) | Custom roles defined at the org level, in key => id format. | object({…}) | | null | 0-bootstrap | +| [dns](variables.tf#L47) | Onprem DNS resolvers. | map(list(string)) | | {…} | | +| [factories_config](variables.tf#L55) | Configuration for network resource factories. | object({…}) | | {…} | | +| [outputs_location](variables.tf#L95) | 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. | map(object({…})) | | {…} | | -| [psa_ranges](variables.tf#L129) | IP ranges used for Private Service Access (e.g. CloudSQL). | object({…}) | | null | | -| [regions](variables.tf#L166) | Region definitions. | object({…}) | | {…} | | -| [router_onprem_configs](variables.tf#L178) | Configurations for routers used for onprem connectivity. | map(object({…})) | | {…} | | -| [service_accounts](variables.tf#L196) | Automation service accounts in name => email format. | object({…}) | | null | 1-resman | -| [vpn_onprem_configs](variables.tf#L210) | VPN gateway configuration for onprem interconnection. | map(object({…})) | | {…} | | +| [psa_ranges](variables.tf#L112) | IP ranges used for Private Service Access (CloudSQL, etc.). | object({…}) | | null | | +| [regions](variables.tf#L133) | Region definitions. | object({…}) | | {…} | | +| [service_accounts](variables.tf#L145) | Automation service accounts in name => email format. | object({…}) | | null | 1-resman | +| [vpn_onprem_primary_config](variables.tf#L159) | VPN gateway configuration for onprem interconnection in the primary region. | object({…}) | | null | | ## Outputs diff --git a/fast/stages/2-networking-a-peering/outputs.tf b/fast/stages/2-networking-a-peering/outputs.tf index 628c706b..e3111e4b 100644 --- a/fast/stages/2-networking-a-peering/outputs.tf +++ b/fast/stages/2-networking-a-peering/outputs.tf @@ -88,7 +88,7 @@ output "tfvars" { output "vpn_gateway_endpoints" { description = "External IP Addresses for the GCP VPN gateways." - value = local.enable_onprem_vpn == false ? null : { + value = var.vpn_onprem_primary_config == null ? null : { onprem-primary = { for v in module.landing-to-onprem-primary-vpn[0].gateway.vpn_interfaces : v.id => v.ip_address diff --git a/fast/stages/2-networking-a-peering/variables.tf b/fast/stages/2-networking-a-peering/variables.tf index 93ba2bea..8c20b623 100644 --- a/fast/stages/2-networking-a-peering/variables.tf +++ b/fast/stages/2-networking-a-peering/variables.tf @@ -35,23 +35,6 @@ variable "billing_account" { } } -variable "custom_adv" { - description = "Custom advertisement definitions in name => range format." - type = map(string) - default = { - cloud_dns = "35.199.192.0/19" - gcp_all = "10.128.0.0/16" - gcp_dev = "10.128.32.0/19" - gcp_landing = "10.128.0.0/19" - gcp_prod = "10.128.64.0/19" - googleapis_private = "199.36.153.8/30" - googleapis_restricted = "199.36.153.4/30" - rfc_1918_10 = "10.0.0.0/8" - rfc_1918_172 = "172.16.0.0/12" - rfc_1918_192 = "192.168.0.0/16" - } -} - variable "custom_roles" { # tfdoc:variable:source 0-bootstrap description = "Custom roles defined at the org level, in key => id format." @@ -127,7 +110,7 @@ variable "prefix" { } variable "psa_ranges" { - description = "IP ranges used for Private Service Access (e.g. CloudSQL)." + description = "IP ranges used for Private Service Access (CloudSQL, etc.)." type = object({ dev = object({ ranges = map(string) @@ -145,22 +128,6 @@ variable "psa_ranges" { }) }) default = null - # default = { - # dev = { - # ranges = { - # cloudsql-mysql = "10.128.62.0/24" - # cloudsql-sqlserver = "10.128.63.0/24" - # } - # routes = null - # } - # prod = { - # ranges = { - # cloudsql-mysql = "10.128.94.0/24" - # cloudsql-sqlserver = "10.128.95.0/24" - # } - # routes = null - # } - # } } variable "regions" { @@ -175,24 +142,6 @@ variable "regions" { } } -variable "router_onprem_configs" { - description = "Configurations for routers used for onprem connectivity." - type = map(object({ - adv = object({ - custom = list(string) - default = bool - }) - asn = number - })) - default = { - landing-primary = { - asn = "65533" - adv = null - # adv = { default = false, custom = [] } - } - } -} - variable "service_accounts" { # tfdoc:variable:source 1-resman description = "Automation service accounts in name => email format." @@ -207,53 +156,45 @@ variable "service_accounts" { default = null } -variable "vpn_onprem_configs" { - description = "VPN gateway configuration for onprem interconnection." - type = map(object({ - adv = object({ - default = bool - custom = list(string) - }) - peer_external_gateway = object({ +variable "vpn_onprem_primary_config" { + description = "VPN gateway configuration for onprem interconnection in the primary region." + type = object({ + peer_external_gateways = map(object({ redundancy_type = string interfaces = list(string) + })) + router_config = object({ + create = optional(bool, true) + asn = number + name = optional(string) + keepalive = optional(number) + custom_advertise = optional(object({ + all_subnets = bool + ip_ranges = map(string) + })) }) - tunnels = list(object({ - peer_asn = number - peer_external_gateway_interface = number - secret = string - session_range = string + tunnels = map(object({ + bgp_peer = object({ + address = string + asn = number + route_priority = optional(number, 1000) + custom_advertise = optional(object({ + all_subnets = bool + all_vpc_subnets = bool + all_peer_vpc_subnets = bool + ip_ranges = map(string) + })) + }) + # each BGP session on the same Cloud Router must use a unique /30 CIDR + # from the 169.254.0.0/16 block. + bgp_session_range = string + ike_version = optional(number, 2) + peer_external_gateway_interface = optional(number) + peer_gateway = optional(string, "default") + router = optional(string) + shared_secret = optional(string) vpn_gateway_interface = number })) - })) - default = { - landing-primary = { - adv = { - default = false - custom = [ - "cloud_dns", "googleapis_private", "googleapis_restricted", "gcp_all" - ] - } - peer_external_gateway = { - redundancy_type = "SINGLE_IP_INTERNALLY_REDUNDANT" - interfaces = ["8.8.8.8"] - } - tunnels = [ - { - peer_asn = 65534 - peer_external_gateway_interface = 0 - secret = "foobar" - session_range = "169.254.1.0/30" - vpn_gateway_interface = 0 - }, - { - peer_asn = 65534 - peer_external_gateway_interface = 0 - secret = "foobar" - session_range = "169.254.1.4/30" - vpn_gateway_interface = 1 - } - ] - } - } + }) + default = null } diff --git a/fast/stages/2-networking-a-peering/vpn-onprem.tf b/fast/stages/2-networking-a-peering/vpn-onprem.tf index 2e9f3c24..2f38f1a5 100644 --- a/fast/stages/2-networking-a-peering/vpn-onprem.tf +++ b/fast/stages/2-networking-a-peering/vpn-onprem.tf @@ -17,54 +17,21 @@ # tfdoc:file:description VPN between landing and onprem. locals { - enable_onprem_vpn = var.vpn_onprem_configs != null - bgp_peer_options_onprem = local.enable_onprem_vpn == false ? null : { - for k, v in var.vpn_onprem_configs : - k => v.adv == null ? null : { - advertise_groups = [] - advertise_ip_ranges = { - for adv in(v.adv == null ? [] : v.adv.custom) : - var.custom_adv[adv] => adv - } - advertise_mode = try(v.adv.default, false) ? "DEFAULT" : "CUSTOM" - route_priority = null - } - } -} - -moved { - from = module.landing-to-onprem-ew1-vpn - to = module.landing-to-onprem-primary-vpn + onprem_peer_gateways = try( + var.vpn_onprem_primary_config.peer_external_gateways, {} + ) } module "landing-to-onprem-primary-vpn" { - count = local.enable_onprem_vpn ? 1 : 0 - source = "../../../modules/net-vpn-ha" - project_id = module.landing-project.project_id - network = module.landing-vpc.self_link - region = var.regions.primary - name = "vpn-to-onprem-${local.region_shortnames[var.regions.primary]}" - router_config = { - name = "landing-onprem-vpn-${local.region_shortnames[var.regions.primary]}" - asn = var.router_onprem_configs.landing-primary.asn - } + count = var.vpn_onprem_primary_config == null ? 0 : 1 + source = "../../../modules/net-vpn-ha" + project_id = module.landing-project.project_id + network = module.landing-vpc.self_link + region = var.regions.primary + name = "vpn-to-onprem-${local.region_shortnames[var.regions.primary]}" + router_config = try(var.vpn_onprem_primary_config.router_config, {}) peer_gateways = { - default = { - external = var.vpn_onprem_configs.landing-primary.peer_external_gateway - } - } - tunnels = { - for t in var.vpn_onprem_configs.landing-primary.tunnels : - "remote-${t.vpn_gateway_interface}-${t.peer_external_gateway_interface}" => { - bgp_peer = { - address = cidrhost(t.session_range, 1) - asn = t.peer_asn - } - bgp_peer_options = local.bgp_peer_options_onprem.landing-primary - bgp_session_range = "${cidrhost(t.session_range, 2)}/30" - peer_external_gateway_interface = t.peer_external_gateway_interface - shared_secret = t.secret - vpn_gateway_interface = t.vpn_gateway_interface - } + for k, v in local.onprem_peer_gateways : k => { external = v } } + tunnels = try(var.vpn_onprem_primary_config.tunnels, {}) } diff --git a/fast/stages/2-networking-b-vpn/README.md b/fast/stages/2-networking-b-vpn/README.md index b2f34567..2be76bd9 100644 --- a/fast/stages/2-networking-b-vpn/README.md +++ b/fast/stages/2-networking-b-vpn/README.md @@ -40,6 +40,7 @@ The following diagram illustrates the high-level design, and should be used as a - [Post-deployment activities](#post-deployment-activities) - [Customizations](#customizations) - [Changing default regions](#changing-default-regions) + - [Configuring the VPN to on prem](#configuring-the-vpn-to-on-prem) - [Adding an environment](#adding-an-environment) ## Design overview and choices @@ -172,7 +173,7 @@ Subnets for [L7 ILBs](https://cloud.google.com/load-balancing/docs/l7-internal/p #### External -Connectivity to on-prem is implemented with HA VPN ([`net-vpn`](../../../modules/net-vpn-ha)) and defined in [`vpn-onprem.tf`](./vpn-onprem.tf). The file provisionally implements a single logical connection between onprem and landing at `europe-west1`, and the relevant parameters for its configuration are found in variable `vpn_onprem_configs`. +Connectivity to on-prem is implemented with HA VPN ([`net-vpn`](../../../modules/net-vpn-ha)) and defined in [`vpn-onprem.tf`](./vpn-onprem.tf). The file provisionally implements a single logical connection between onprem and landing at `europe-west1`, and the relevant parameters for its configuration are found in variable `vpn_onprem_primary_configs`. An example configuration is provided [below](#configuring-the-vpn-to-on-prem). #### Internal @@ -316,6 +317,55 @@ Regions are defined via the `regions` variable which sets up a mapping between t - change the values of the mappings in the `regions` variable to the regions you are going to use - change the regions in the factory subnet files in the `data` folder +### Configuring the VPN to on prem + +This stage includes basic support for an HA VPN connecting the landing zone in the primary region to on prem. Configuration is via the `vpn_onprem_primary_config` variable, that closely mirrors the variables defined in the [`net-vpn-ha`](../../../modules/net-vpn-ha/). + +Support for the onprem VPN is disabled by default so that no resources are created, this is an example of how to configure the variable to enable the VPN: + +```hcl +vpn_onprem_primary_config = { + peer_external_gateways = { + default = { + redundancy_type = "SINGLE_IP_INTERNALLY_REDUNDANT" + interfaces = ["8.8.8.8"] + } + } + router_config = { + asn = 65501 + custom_advertise = { + all_subnets = false + ip_ranges = { + "10.1.0.0/16" = "gcp" + "35.199.192.0/19" = "gcp-dns" + "199.36.153.4/30" = "gcp-restricted" + } + } + } + tunnels = { + "0" = { + bgp_peer = { + address = "169.254.1.1" + asn = 65500 + } + bgp_session_range = "169.254.1.2/30" + shared_secret = "foo" + vpn_gateway_interface = 0 + } + "1" = { + bgp_peer = { + address = "169.254.2.1" + asn = 64513 + } + bgp_session_range = "169.254.2.2/30" + shared_secret = "foo" + vpn_gateway_interface = 1 + } + } +} +# tftest skip +``` + ### Adding an environment To create a new environment (e.g. `staging`), a few changes are required. @@ -360,10 +410,10 @@ DNS configurations are centralised in the `dns-*.tf` files. Spokes delegate DNS | [test-resources.tf](./test-resources.tf) | temporary instances for testing | compute-vm | | | [variables-vpn.tf](./variables-vpn.tf) | None | | | | [variables.tf](./variables.tf) | Module variables. | | | +| [vpn-landing.tf](./vpn-landing.tf) | None | net-vpn-ha | | | [vpn-onprem.tf](./vpn-onprem.tf) | VPN between landing and onprem. | net-vpn-ha | | | [vpn-spoke-dev.tf](./vpn-spoke-dev.tf) | VPN between landing and development spoke. | net-vpn-ha | | -| [vpn-spoke-prod-primary.tf](./vpn-spoke-prod-primary.tf) | VPN between landing and production spoke in ew1. | net-vpn-ha | | -| [vpn-spoke-prod-secondary.tf](./vpn-spoke-prod-secondary.tf) | VPN between landing and production spoke in ew4. | net-vpn-ha | | +| [vpn-spoke-prod.tf](./vpn-spoke-prod.tf) | VPN between landing and production spoke in ew1. | net-vpn-ha | | ## Variables @@ -371,21 +421,18 @@ DNS configurations are centralised in the `dns-*.tf` files. Spokes delegate DNS |---|---|:---:|:---:|:---:|:---:| | [automation](variables.tf#L17) | Automation resources created by the bootstrap stage. | object({…}) | ✓ | | 0-bootstrap | | [billing_account](variables.tf#L25) | 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#L92) | Folders to be used for the networking resources in folders/nnnnnnnnnnn format. If null, folder will be created. | object({…}) | ✓ | | 1-resman | -| [organization](variables.tf#L102) | Organization details. | object({…}) | ✓ | | 0-bootstrap | -| [prefix](variables.tf#L118) | Prefix used for resources that need unique names. Use 9 characters or less. | string | ✓ | | 0-bootstrap | -| [custom_adv](variables.tf#L38) | Custom advertisement definitions in name => range format. | map(string) | | {…} | | -| [custom_roles](variables.tf#L55) | Custom roles defined at the org level, in key => id format. | object({…}) | | null | 0-bootstrap | -| [dns](variables.tf#L64) | Onprem DNS resolvers. | map(list(string)) | | {…} | | -| [factories_config](variables.tf#L72) | Configuration for network resource factories. | object({…}) | | {…} | | -| [outputs_location](variables.tf#L112) | Path where providers and tfvars files for the following stages are written. Leave empty to disable. | string | | null | | -| [psa_ranges](variables.tf#L129) | IP ranges used for Private Service Access (e.g. CloudSQL). | object({…}) | | null | | -| [regions](variables.tf#L166) | Region definitions. | object({…}) | | {…} | | -| [router_onprem_configs](variables.tf#L178) | Configurations for routers used for onprem connectivity. | map(object({…})) | | {…} | | -| [router_spoke_configs](variables-vpn.tf#L18) | Configurations for routers used for internal connectivity. | map(object({…})) | | {…} | | -| [service_accounts](variables.tf#L196) | Automation service accounts in name => email format. | object({…}) | | null | 1-resman | -| [vpn_onprem_configs](variables.tf#L210) | VPN gateway configuration for onprem interconnection. | map(object({…})) | | {…} | | -| [vpn_spoke_configs](variables-vpn.tf#L37) | VPN gateway configuration for spokes. | map(object({…})) | | {…} | | +| [folder_ids](variables.tf#L75) | Folders to be used for the networking resources in folders/nnnnnnnnnnn format. If null, folder will be created. | object({…}) | ✓ | | 1-resman | +| [organization](variables.tf#L85) | Organization details. | object({…}) | ✓ | | 0-bootstrap | +| [prefix](variables.tf#L101) | Prefix used for resources that need unique names. Use 9 characters or less. | string | ✓ | | 0-bootstrap | +| [custom_roles](variables.tf#L38) | Custom roles defined at the org level, in key => id format. | object({…}) | | null | 0-bootstrap | +| [dns](variables.tf#L47) | Onprem DNS resolvers. | map(list(string)) | | {…} | | +| [factories_config](variables.tf#L55) | Configuration for network resource factories. | object({…}) | | {…} | | +| [outputs_location](variables.tf#L95) | Path where providers and tfvars files for the following stages are written. Leave empty to disable. | string | | null | | +| [psa_ranges](variables.tf#L112) | IP ranges used for Private Service Access (CloudSQL, etc.). | object({…}) | | null | | +| [regions](variables.tf#L133) | Region definitions. | object({…}) | | {…} | | +| [service_accounts](variables.tf#L145) | 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#L159) | VPN gateway configuration for onprem interconnection in the primary region. | object({…}) | | null | | ## Outputs diff --git a/fast/stages/2-networking-b-vpn/outputs.tf b/fast/stages/2-networking-b-vpn/outputs.tf index 628c706b..e3111e4b 100644 --- a/fast/stages/2-networking-b-vpn/outputs.tf +++ b/fast/stages/2-networking-b-vpn/outputs.tf @@ -88,7 +88,7 @@ output "tfvars" { output "vpn_gateway_endpoints" { description = "External IP Addresses for the GCP VPN gateways." - value = local.enable_onprem_vpn == false ? null : { + value = var.vpn_onprem_primary_config == null ? null : { onprem-primary = { for v in module.landing-to-onprem-primary-vpn[0].gateway.vpn_interfaces : v.id => v.ip_address diff --git a/fast/stages/2-networking-b-vpn/variables-vpn.tf b/fast/stages/2-networking-b-vpn/variables-vpn.tf index a6aab329..64edb611 100644 --- a/fast/stages/2-networking-b-vpn/variables-vpn.tf +++ b/fast/stages/2-networking-b-vpn/variables-vpn.tf @@ -14,52 +14,40 @@ * limitations under the License. */ - -variable "router_spoke_configs" { - description = "Configurations for routers used for internal connectivity." - type = map(object({ - adv = object({ - custom = list(string) - default = bool +variable "vpn_configs" { + description = "Hub to spokes VPN configurations." + type = object({ + dev = object({ + asn = number + custom_advertise = optional(object({ + all_subnets = bool + ip_ranges = map(string) + })) }) - asn = number - })) + landing = object({ + asn = number + custom_advertise = optional(object({ + all_subnets = bool + ip_ranges = map(string) + })) + }) + prod = object({ + asn = number + custom_advertise = optional(object({ + all_subnets = bool + ip_ranges = map(string) + })) + }) + }) default = { - landing-primary = { asn = "64512", adv = null } - landing-secondary = { asn = "64512", adv = null } - spoke-dev-primary = { asn = "64513", adv = null } - spoke-dev-secondary = { asn = "64513", adv = null } - spoke-prod-primary = { asn = "64514", adv = null } - spoke-prod-secondary = { asn = "64514", adv = null } - } -} - -variable "vpn_spoke_configs" { - description = "VPN gateway configuration for spokes." - type = map(object({ - default = bool - custom = list(string) - })) - default = { - landing-primary = { - default = false - custom = ["rfc_1918_10", "rfc_1918_172", "rfc_1918_192"] + dev = { + asn = 65501 } - landing-secondary = { - default = false - custom = ["rfc_1918_10", "rfc_1918_172", "rfc_1918_192"] + landing = { + asn = 65500 } - dev-primary = { - default = false - custom = ["gcp_dev"] - } - prod-primary = { - default = false - custom = ["gcp_prod"] - } - prod-secondary = { - default = false - custom = ["gcp_prod"] + prod = { + asn = 65502 } } } diff --git a/fast/stages/2-networking-b-vpn/variables.tf b/fast/stages/2-networking-b-vpn/variables.tf index 93ba2bea..8c20b623 100644 --- a/fast/stages/2-networking-b-vpn/variables.tf +++ b/fast/stages/2-networking-b-vpn/variables.tf @@ -35,23 +35,6 @@ variable "billing_account" { } } -variable "custom_adv" { - description = "Custom advertisement definitions in name => range format." - type = map(string) - default = { - cloud_dns = "35.199.192.0/19" - gcp_all = "10.128.0.0/16" - gcp_dev = "10.128.32.0/19" - gcp_landing = "10.128.0.0/19" - gcp_prod = "10.128.64.0/19" - googleapis_private = "199.36.153.8/30" - googleapis_restricted = "199.36.153.4/30" - rfc_1918_10 = "10.0.0.0/8" - rfc_1918_172 = "172.16.0.0/12" - rfc_1918_192 = "192.168.0.0/16" - } -} - variable "custom_roles" { # tfdoc:variable:source 0-bootstrap description = "Custom roles defined at the org level, in key => id format." @@ -127,7 +110,7 @@ variable "prefix" { } variable "psa_ranges" { - description = "IP ranges used for Private Service Access (e.g. CloudSQL)." + description = "IP ranges used for Private Service Access (CloudSQL, etc.)." type = object({ dev = object({ ranges = map(string) @@ -145,22 +128,6 @@ variable "psa_ranges" { }) }) default = null - # default = { - # dev = { - # ranges = { - # cloudsql-mysql = "10.128.62.0/24" - # cloudsql-sqlserver = "10.128.63.0/24" - # } - # routes = null - # } - # prod = { - # ranges = { - # cloudsql-mysql = "10.128.94.0/24" - # cloudsql-sqlserver = "10.128.95.0/24" - # } - # routes = null - # } - # } } variable "regions" { @@ -175,24 +142,6 @@ variable "regions" { } } -variable "router_onprem_configs" { - description = "Configurations for routers used for onprem connectivity." - type = map(object({ - adv = object({ - custom = list(string) - default = bool - }) - asn = number - })) - default = { - landing-primary = { - asn = "65533" - adv = null - # adv = { default = false, custom = [] } - } - } -} - variable "service_accounts" { # tfdoc:variable:source 1-resman description = "Automation service accounts in name => email format." @@ -207,53 +156,45 @@ variable "service_accounts" { default = null } -variable "vpn_onprem_configs" { - description = "VPN gateway configuration for onprem interconnection." - type = map(object({ - adv = object({ - default = bool - custom = list(string) - }) - peer_external_gateway = object({ +variable "vpn_onprem_primary_config" { + description = "VPN gateway configuration for onprem interconnection in the primary region." + type = object({ + peer_external_gateways = map(object({ redundancy_type = string interfaces = list(string) + })) + router_config = object({ + create = optional(bool, true) + asn = number + name = optional(string) + keepalive = optional(number) + custom_advertise = optional(object({ + all_subnets = bool + ip_ranges = map(string) + })) }) - tunnels = list(object({ - peer_asn = number - peer_external_gateway_interface = number - secret = string - session_range = string + tunnels = map(object({ + bgp_peer = object({ + address = string + asn = number + route_priority = optional(number, 1000) + custom_advertise = optional(object({ + all_subnets = bool + all_vpc_subnets = bool + all_peer_vpc_subnets = bool + ip_ranges = map(string) + })) + }) + # each BGP session on the same Cloud Router must use a unique /30 CIDR + # from the 169.254.0.0/16 block. + bgp_session_range = string + ike_version = optional(number, 2) + peer_external_gateway_interface = optional(number) + peer_gateway = optional(string, "default") + router = optional(string) + shared_secret = optional(string) vpn_gateway_interface = number })) - })) - default = { - landing-primary = { - adv = { - default = false - custom = [ - "cloud_dns", "googleapis_private", "googleapis_restricted", "gcp_all" - ] - } - peer_external_gateway = { - redundancy_type = "SINGLE_IP_INTERNALLY_REDUNDANT" - interfaces = ["8.8.8.8"] - } - tunnels = [ - { - peer_asn = 65534 - peer_external_gateway_interface = 0 - secret = "foobar" - session_range = "169.254.1.0/30" - vpn_gateway_interface = 0 - }, - { - peer_asn = 65534 - peer_external_gateway_interface = 0 - secret = "foobar" - session_range = "169.254.1.4/30" - vpn_gateway_interface = 1 - } - ] - } - } + }) + default = null } diff --git a/fast/stages/2-networking-b-vpn/vpn-landing.tf b/fast/stages/2-networking-b-vpn/vpn-landing.tf new file mode 100644 index 00000000..7d15930b --- /dev/null +++ b/fast/stages/2-networking-b-vpn/vpn-landing.tf @@ -0,0 +1,128 @@ +/** + * Copyright 2023 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +locals { + # persistent_counter.units.values[k] + bgp_sessions_range_0 = "169.254.250.0/25" + bgp_sessions_range_1 = "169.254.250.128/25" + bgp_session_ranges = { + prod-primary = { + 0 = cidrsubnet(local.bgp_sessions_range_0, 5, 0) + 1 = cidrsubnet(local.bgp_sessions_range_1, 5, 0) + } + prod-secondary = { + 0 = cidrsubnet(local.bgp_sessions_range_0, 5, 1) + 1 = cidrsubnet(local.bgp_sessions_range_1, 5, 1) + } + dev-primary = { + 0 = cidrsubnet(local.bgp_sessions_range_0, 5, 2) + 1 = cidrsubnet(local.bgp_sessions_range_1, 5, 2) + } + } +} + +output "foo" { + value = local.bgp_session_ranges +} + +module "landing-to-spokes-primary-vpn" { + source = "../../../modules/net-vpn-ha" + project_id = module.landing-project.project_id + network = module.landing-vpc.self_link + region = var.regions.primary + name = "to-spokes-${local.region_shortnames[var.regions.primary]}" + peer_gateways = { + dev = { gcp = module.dev-to-landing-primary-vpn.self_link } + prod = { gcp = module.prod-to-landing-primary-vpn.self_link } + } + router_config = { + asn = var.vpn_configs.landing.asn + custom_advertise = var.vpn_configs.landing.custom_advertise + } + tunnels = { + dev-0 = { + bgp_peer = { + address = cidrhost(local.bgp_session_ranges.dev-primary.0, 2) + asn = var.vpn_configs.dev.asn + } + bgp_session_range = "${cidrhost(local.bgp_session_ranges.dev-primary.0, 1)}/30" + peer_gateway = "dev" + vpn_gateway_interface = 0 + } + dev-1 = { + bgp_peer = { + address = cidrhost(local.bgp_session_ranges.dev-primary.1, 2) + asn = var.vpn_configs.dev.asn + } + bgp_session_range = "${cidrhost(local.bgp_session_ranges.dev-primary.1, 1)}/30" + peer_gateway = "dev" + vpn_gateway_interface = 1 + } + prod-0 = { + bgp_peer = { + address = cidrhost(local.bgp_session_ranges.prod-primary.0, 2) + asn = var.vpn_configs.prod.asn + } + bgp_session_range = "${cidrhost(local.bgp_session_ranges.prod-primary.0, 1)}/30" + peer_gateway = "prod" + vpn_gateway_interface = 0 + } + prod-1 = { + bgp_peer = { + address = cidrhost(local.bgp_session_ranges.prod-primary.1, 2) + asn = var.vpn_configs.prod.asn + } + bgp_session_range = "${cidrhost(local.bgp_session_ranges.prod-primary.1, 1)}/30" + peer_gateway = "prod" + vpn_gateway_interface = 1 + } + } +} + +module "landing-to-spokes-secondary-vpn" { + source = "../../../modules/net-vpn-ha" + project_id = module.landing-project.project_id + network = module.landing-vpc.self_link + region = var.regions.secondary + name = "to-spokes-${local.region_shortnames[var.regions.secondary]}" + peer_gateways = { + prod = { gcp = module.prod-to-landing-secondary-vpn.self_link } + } + router_config = { + asn = var.vpn_configs.landing.asn + custom_advertise = var.vpn_configs.landing.custom_advertise + } + tunnels = { + prod-0 = { + bgp_peer = { + address = cidrhost(local.bgp_session_ranges.prod-secondary.0, 2) + asn = var.vpn_configs.prod.asn + } + bgp_session_range = "${cidrhost(local.bgp_session_ranges.prod-secondary.0, 1)}/30" + peer_gateway = "prod" + vpn_gateway_interface = 0 + } + prod-1 = { + bgp_peer = { + address = cidrhost(local.bgp_session_ranges.prod-secondary.1, 2) + asn = var.vpn_configs.prod.asn + } + bgp_session_range = "${cidrhost(local.bgp_session_ranges.prod-secondary.1, 1)}/30" + peer_gateway = "prod" + vpn_gateway_interface = 1 + } + } +} diff --git a/fast/stages/2-networking-b-vpn/vpn-onprem.tf b/fast/stages/2-networking-b-vpn/vpn-onprem.tf index 2e9f3c24..2f38f1a5 100644 --- a/fast/stages/2-networking-b-vpn/vpn-onprem.tf +++ b/fast/stages/2-networking-b-vpn/vpn-onprem.tf @@ -17,54 +17,21 @@ # tfdoc:file:description VPN between landing and onprem. locals { - enable_onprem_vpn = var.vpn_onprem_configs != null - bgp_peer_options_onprem = local.enable_onprem_vpn == false ? null : { - for k, v in var.vpn_onprem_configs : - k => v.adv == null ? null : { - advertise_groups = [] - advertise_ip_ranges = { - for adv in(v.adv == null ? [] : v.adv.custom) : - var.custom_adv[adv] => adv - } - advertise_mode = try(v.adv.default, false) ? "DEFAULT" : "CUSTOM" - route_priority = null - } - } -} - -moved { - from = module.landing-to-onprem-ew1-vpn - to = module.landing-to-onprem-primary-vpn + onprem_peer_gateways = try( + var.vpn_onprem_primary_config.peer_external_gateways, {} + ) } module "landing-to-onprem-primary-vpn" { - count = local.enable_onprem_vpn ? 1 : 0 - source = "../../../modules/net-vpn-ha" - project_id = module.landing-project.project_id - network = module.landing-vpc.self_link - region = var.regions.primary - name = "vpn-to-onprem-${local.region_shortnames[var.regions.primary]}" - router_config = { - name = "landing-onprem-vpn-${local.region_shortnames[var.regions.primary]}" - asn = var.router_onprem_configs.landing-primary.asn - } + count = var.vpn_onprem_primary_config == null ? 0 : 1 + source = "../../../modules/net-vpn-ha" + project_id = module.landing-project.project_id + network = module.landing-vpc.self_link + region = var.regions.primary + name = "vpn-to-onprem-${local.region_shortnames[var.regions.primary]}" + router_config = try(var.vpn_onprem_primary_config.router_config, {}) peer_gateways = { - default = { - external = var.vpn_onprem_configs.landing-primary.peer_external_gateway - } - } - tunnels = { - for t in var.vpn_onprem_configs.landing-primary.tunnels : - "remote-${t.vpn_gateway_interface}-${t.peer_external_gateway_interface}" => { - bgp_peer = { - address = cidrhost(t.session_range, 1) - asn = t.peer_asn - } - bgp_peer_options = local.bgp_peer_options_onprem.landing-primary - bgp_session_range = "${cidrhost(t.session_range, 2)}/30" - peer_external_gateway_interface = t.peer_external_gateway_interface - shared_secret = t.secret - vpn_gateway_interface = t.vpn_gateway_interface - } + for k, v in local.onprem_peer_gateways : k => { external = v } } + tunnels = try(var.vpn_onprem_primary_config.tunnels, {}) } diff --git a/fast/stages/2-networking-b-vpn/vpn-spoke-dev.tf b/fast/stages/2-networking-b-vpn/vpn-spoke-dev.tf index 97adc642..a9280aed 100644 --- a/fast/stages/2-networking-b-vpn/vpn-spoke-dev.tf +++ b/fast/stages/2-networking-b-vpn/vpn-spoke-dev.tf @@ -16,113 +16,34 @@ # tfdoc:file:description VPN between landing and development spoke. -locals { - # define the structures used for BGP peers in the VPN resources - vpn_spoke_bgp_peer_options = { - for k, v in var.vpn_spoke_configs : k => v == null ? null : { - advertise_groups = [] - advertise_ip_ranges = { - for range in(v == null ? [] : v.custom) : - try(var.custom_adv[range], range) => range - } - advertise_mode = try(v.default, false) ? "DEFAULT" : "CUSTOM" - route_priority = null - } - } -} - -# development spoke - -moved { - from = module.landing-to-dev-ew1-vpn - to = module.landing-to-dev-primary-vpn -} - -module "landing-to-dev-primary-vpn" { - source = "../../../modules/net-vpn-ha" - project_id = module.landing-project.project_id - network = module.landing-vpc.self_link - region = var.regions.primary - name = "vpn-to-dev-${local.region_shortnames[var.regions.primary]}" - router_config = { - # The router used for this VPN is managed in vpn-prod.tf - create = false - name = "landing-vpn-${local.region_shortnames[var.regions.primary]}" - asn = var.router_spoke_configs.landing-primary.asn - } - peer_gateways = { - default = { gcp = module.dev-to-landing-primary-vpn.self_link } - } - tunnels = { - 0 = { - bgp_peer = { - address = cidrhost("169.254.0.0/27", 1) - asn = var.router_spoke_configs.spoke-dev-primary.asn - } - bgp_peer_options = local.vpn_spoke_bgp_peer_options.landing-primary - bgp_session_range = "${ - cidrhost("169.254.0.0/27", 2) - }/30" - vpn_gateway_interface = 0 - } - 1 = { - bgp_peer = { - address = cidrhost("169.254.0.0/27", 5) - asn = var.router_spoke_configs.spoke-dev-primary.asn - } - bgp_peer_options = local.vpn_spoke_bgp_peer_options.landing-primary - bgp_session_range = "${ - cidrhost("169.254.0.0/27", 6) - }/30" - vpn_gateway_interface = 1 - } - } - depends_on = [ - module.landing-to-prod-primary-vpn.router - ] -} - -moved { - from = module.dev-to-landing-ew1-vpn - to = module.dev-to-landing-primary-vpn -} - module "dev-to-landing-primary-vpn" { source = "../../../modules/net-vpn-ha" project_id = module.dev-spoke-project.project_id network = module.dev-spoke-vpc.self_link region = var.regions.primary - name = "vpn-to-landing-${local.region_shortnames[var.regions.primary]}" - router_config = { - name = "dev-spoke-vpn-${local.region_shortnames[var.regions.primary]}" - asn = var.router_spoke_configs.spoke-dev-primary.asn - } + name = "to-landing-${local.region_shortnames[var.regions.primary]}" peer_gateways = { - default = { gcp = module.landing-to-dev-primary-vpn.self_link } + default = { gcp = module.landing-to-spokes-primary-vpn.self_link } + } + router_config = { + asn = var.vpn_configs.dev.asn + custom_advertise = var.vpn_configs.dev.custom_advertise } tunnels = { 0 = { bgp_peer = { - address = cidrhost("169.254.0.0/27", 2) - asn = var.router_spoke_configs.landing-primary.asn + address = cidrhost(local.bgp_session_ranges.dev-primary.0, 1) + asn = var.vpn_configs.landing.asn } - bgp_peer_options = local.vpn_spoke_bgp_peer_options.dev-primary - bgp_session_range = "${ - cidrhost("169.254.0.0/27", 1) - }/30" - shared_secret = module.landing-to-dev-primary-vpn.random_secret + bgp_session_range = "${cidrhost(local.bgp_session_ranges.dev-primary.0, 2)}/30" vpn_gateway_interface = 0 } 1 = { bgp_peer = { - address = cidrhost("169.254.0.0/27", 6) - asn = var.router_spoke_configs.landing-primary.asn + address = cidrhost(local.bgp_session_ranges.dev-primary.1, 1) + asn = var.vpn_configs.landing.asn } - bgp_peer_options = local.vpn_spoke_bgp_peer_options.dev-primary - bgp_session_range = "${ - cidrhost("169.254.0.0/27", 5) - }/30" - shared_secret = module.landing-to-dev-primary-vpn.random_secret + bgp_session_range = "${cidrhost(local.bgp_session_ranges.dev-primary.1, 2)}/30" vpn_gateway_interface = 1 } } diff --git a/fast/stages/2-networking-b-vpn/vpn-spoke-prod-primary.tf b/fast/stages/2-networking-b-vpn/vpn-spoke-prod-primary.tf deleted file mode 100644 index 9d36c16e..00000000 --- a/fast/stages/2-networking-b-vpn/vpn-spoke-prod-primary.tf +++ /dev/null @@ -1,109 +0,0 @@ -/** - * Copyright 2022 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. - */ - -# tfdoc:file:description VPN between landing and production spoke in ew1. - -# local.vpn_spoke_bgp_peer_options is defined in the dev VPN file - -moved { - from = module.landing-to-prod-ew1-vpn - to = module.landing-to-prod-primary-vpn -} - -module "landing-to-prod-primary-vpn" { - source = "../../../modules/net-vpn-ha" - project_id = module.landing-project.project_id - network = module.landing-vpc.self_link - region = var.regions.primary - name = "vpn-to-prod-${local.region_shortnames[var.regions.primary]}" - router_config = { - name = "landing-vpn-${local.region_shortnames[var.regions.primary]}" - asn = var.router_spoke_configs.landing-primary.asn - } - peer_gateways = { - default = { gcp = module.prod-to-landing-primary-vpn.self_link } - } - tunnels = { - 0 = { - bgp_peer = { - address = cidrhost("169.254.0.64/27", 1) - asn = var.router_spoke_configs.spoke-prod-primary.asn - } - bgp_peer_options = local.vpn_spoke_bgp_peer_options.landing-primary - bgp_session_range = "${ - cidrhost("169.254.0.64/27", 2) - }/30" - vpn_gateway_interface = 0 - } - 1 = { - bgp_peer = { - address = cidrhost("169.254.0.64/27", 5) - asn = var.router_spoke_configs.spoke-prod-primary.asn - } - bgp_peer_options = local.vpn_spoke_bgp_peer_options.landing-primary - bgp_session_range = "${ - cidrhost("169.254.0.64/27", 6) - }/30" - vpn_gateway_interface = 1 - } - } -} - -moved { - from = module.prod-to-landing-ew1-vpn - to = module.prod-to-landing-primary-vpn -} - -module "prod-to-landing-primary-vpn" { - source = "../../../modules/net-vpn-ha" - project_id = module.prod-spoke-project.project_id - network = module.prod-spoke-vpc.self_link - region = var.regions.primary - name = "vpn-to-landing-${local.region_shortnames[var.regions.primary]}" - router_config = { - name = "prod-spoke-vpn-${local.region_shortnames[var.regions.primary]}" - asn = var.router_spoke_configs.spoke-prod-primary.asn - } - peer_gateways = { - default = { gcp = module.landing-to-prod-primary-vpn.self_link } - } - tunnels = { - 0 = { - bgp_peer = { - address = cidrhost("169.254.0.64/27", 2) - asn = var.router_spoke_configs.landing-primary.asn - } - bgp_peer_options = local.vpn_spoke_bgp_peer_options.prod-primary - bgp_session_range = "${ - cidrhost("169.254.0.64/27", 1) - }/30" - shared_secret = module.landing-to-prod-primary-vpn.random_secret - vpn_gateway_interface = 0 - } - 1 = { - bgp_peer = { - address = cidrhost("169.254.0.64/27", 6) - asn = var.router_spoke_configs.landing-primary.asn - } - bgp_peer_options = local.vpn_spoke_bgp_peer_options.prod-primary - bgp_session_range = "${ - cidrhost("169.254.0.64/27", 5) - }/30" - shared_secret = module.landing-to-prod-primary-vpn.random_secret - vpn_gateway_interface = 1 - } - } -} diff --git a/fast/stages/2-networking-b-vpn/vpn-spoke-prod-secondary.tf b/fast/stages/2-networking-b-vpn/vpn-spoke-prod-secondary.tf deleted file mode 100644 index a3ee9e9f..00000000 --- a/fast/stages/2-networking-b-vpn/vpn-spoke-prod-secondary.tf +++ /dev/null @@ -1,109 +0,0 @@ -/** - * Copyright 2022 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. - */ - -# tfdoc:file:description VPN between landing and production spoke in ew4. - -# local.vpn_spoke_bgp_peer_options is defined in the dev VPN file - -moved { - from = module.landing-to-prod-ew4-vpn - to = module.landing-to-prod-secondary-vpn -} - -module "landing-to-prod-secondary-vpn" { - source = "../../../modules/net-vpn-ha" - project_id = module.landing-project.project_id - network = module.landing-vpc.self_link - region = var.regions.secondary - name = "vpn-to-prod-${local.region_shortnames[var.regions.secondary]}" - router_config = { - name = "landing-vpn-${local.region_shortnames[var.regions.secondary]}" - asn = var.router_spoke_configs.landing-secondary.asn - } - peer_gateways = { - default = { gcp = module.prod-to-landing-secondary-vpn.self_link } - } - tunnels = { - 0 = { - bgp_peer = { - address = cidrhost("169.254.0.96/27", 1) - asn = var.router_spoke_configs.spoke-prod-secondary.asn - } - bgp_peer_options = local.vpn_spoke_bgp_peer_options.landing-secondary - bgp_session_range = "${ - cidrhost("169.254.0.96/27", 2) - }/30" - vpn_gateway_interface = 0 - } - 1 = { - bgp_peer = { - address = cidrhost("169.254.0.96/27", 5) - asn = var.router_spoke_configs.spoke-prod-secondary.asn - } - bgp_peer_options = local.vpn_spoke_bgp_peer_options.landing-secondary - bgp_session_range = "${ - cidrhost("169.254.0.96/27", 6) - }/30" - vpn_gateway_interface = 1 - } - } -} - -moved { - from = module.prod-to-landing-ew4-vpn - to = module.prod-to-landing-secondary-vpn -} - -module "prod-to-landing-secondary-vpn" { - source = "../../../modules/net-vpn-ha" - project_id = module.prod-spoke-project.project_id - network = module.prod-spoke-vpc.self_link - region = var.regions.secondary - name = "vpn-to-landing-${local.region_shortnames[var.regions.secondary]}" - router_config = { - name = "prod-spoke-vpn-${local.region_shortnames[var.regions.secondary]}" - asn = var.router_spoke_configs.spoke-prod-secondary.asn - } - peer_gateways = { - default = { gcp = module.landing-to-prod-secondary-vpn.self_link } - } - tunnels = { - 0 = { - bgp_peer = { - address = cidrhost("169.254.0.96/27", 2) - asn = var.router_spoke_configs.landing-secondary.asn - } - bgp_peer_options = local.vpn_spoke_bgp_peer_options.prod-secondary - bgp_session_range = "${ - cidrhost("169.254.0.96/27", 1) - }/30" - shared_secret = module.landing-to-prod-secondary-vpn.random_secret - vpn_gateway_interface = 0 - } - 1 = { - bgp_peer = { - address = cidrhost("169.254.0.96/27", 6) - asn = var.router_spoke_configs.landing-secondary.asn - } - bgp_peer_options = local.vpn_spoke_bgp_peer_options.prod-secondary - bgp_session_range = "${ - cidrhost("169.254.0.96/27", 5) - }/30" - shared_secret = module.landing-to-prod-secondary-vpn.random_secret - vpn_gateway_interface = 1 - } - } -} diff --git a/fast/stages/2-networking-b-vpn/vpn-spoke-prod.tf b/fast/stages/2-networking-b-vpn/vpn-spoke-prod.tf new file mode 100644 index 00000000..2d31bba5 --- /dev/null +++ b/fast/stages/2-networking-b-vpn/vpn-spoke-prod.tf @@ -0,0 +1,83 @@ +/** + * Copyright 2022 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. + */ + +# tfdoc:file:description VPN between landing and production spoke in ew1. + +module "prod-to-landing-primary-vpn" { + source = "../../../modules/net-vpn-ha" + project_id = module.prod-spoke-project.project_id + network = module.prod-spoke-vpc.self_link + region = var.regions.primary + name = "to-landing-${local.region_shortnames[var.regions.primary]}" + peer_gateways = { + default = { gcp = module.landing-to-spokes-primary-vpn.self_link } + } + router_config = { + asn = var.vpn_configs.prod.asn + custom_advertise = var.vpn_configs.prod.custom_advertise + } + tunnels = { + 0 = { + bgp_peer = { + address = cidrhost(local.bgp_session_ranges.prod-primary.0, 1) + asn = var.vpn_configs.landing.asn + } + bgp_session_range = "${cidrhost(local.bgp_session_ranges.prod-primary.0, 2)}/30" + vpn_gateway_interface = 0 + } + 1 = { + bgp_peer = { + address = cidrhost(local.bgp_session_ranges.prod-primary.1, 1) + asn = var.vpn_configs.landing.asn + } + bgp_session_range = "${cidrhost(local.bgp_session_ranges.prod-primary.1, 2)}/30" + vpn_gateway_interface = 1 + } + } +} + +module "prod-to-landing-secondary-vpn" { + source = "../../../modules/net-vpn-ha" + project_id = module.prod-spoke-project.project_id + network = module.prod-spoke-vpc.self_link + region = var.regions.secondary + name = "to-landing-${local.region_shortnames[var.regions.secondary]}" + peer_gateways = { + default = { gcp = module.landing-to-spokes-secondary-vpn.self_link } + } + router_config = { + asn = var.vpn_configs.prod.asn + custom_advertise = var.vpn_configs.prod.custom_advertise + } + tunnels = { + 0 = { + bgp_peer = { + address = cidrhost(local.bgp_session_ranges.prod-secondary.0, 1) + asn = var.vpn_configs.landing.asn + } + bgp_session_range = "${cidrhost(local.bgp_session_ranges.prod-secondary.0, 2)}/30" + vpn_gateway_interface = 0 + } + 1 = { + bgp_peer = { + address = cidrhost(local.bgp_session_ranges.prod-secondary.1, 1) + asn = var.vpn_configs.landing.asn + } + bgp_session_range = "${cidrhost(local.bgp_session_ranges.prod-secondary.1, 2)}/30" + vpn_gateway_interface = 1 + } + } +} diff --git a/fast/stages/2-networking-c-nva/README.md b/fast/stages/2-networking-c-nva/README.md index 02cee132..5fbb8c14 100644 --- a/fast/stages/2-networking-c-nva/README.md +++ b/fast/stages/2-networking-c-nva/README.md @@ -47,6 +47,7 @@ The final number of subnets, and their IP addressing will depend on the user-spe - [Post-deployment activities](#post-deployment-activities) - [Customizations](#customizations) - [Changing default regions](#changing-default-regions) + - [Configuring the VPNs to on prem](#configuring-the-vpns-to-on-prem) - [Adding an environment](#adding-an-environment) ## Design overview and choices @@ -235,7 +236,7 @@ Subnets for [L7 ILBs](https://cloud.google.com/load-balancing/docs/l7-internal/p ### VPNs -The connectivity between on-premises and GCP (the trusted landing VPC) is implemented with Cloud HA VPN ([`net-vpn`](../../../modules/net-vpn-ha)) and defined in [`vpn-onprem.tf`](./vpn-onprem.tf). The file implements a single logical connection between on-premises and the trusted landing VPC, both in `europe-west1` and `europe-west4`. The relevant parameters for its configuration are found in the variable `vpn_onprem_configs`. +The connectivity between on-premises and GCP (the trusted landing VPC) is implemented with Cloud HA VPN ([`net-vpn`](../../../modules/net-vpn-ha)) and defined in [`vpn-onprem.tf`](./vpn-onprem.tf). The file implements a single logical connection between on-premises and the trusted landing VPC, both in `europe-west1` and `europe-west4`. The relevant parameters for its configuration are found in the variables `vpn_onprem_primary_config` and `vpn_onprem_secondary_config`. ### Routing and BGP @@ -375,6 +376,55 @@ Regions are defined via the `regions` variable which sets up a mapping between t - change the values of the mappings in the `regions` variable to the regions you are going to use - change the regions in the factory subnet files in the `data` folder +### Configuring the VPNs to on prem + +This stage includes basic support for an HA VPN connecting the landing zone in the primary region to on prem. Configuration is via the `vpn_onprem_primary_config` and `vpn_onprem_secondary_config` variables, that closely mirrors the variables defined in the [`net-vpn-ha`](../../../modules/net-vpn-ha/). + +Support for the onprem VPNs is disabled by default so that no resources are created, this is an example of how to configure one variable to enable the VPN in the primary region: + +```hcl +vpn_onprem_primary_config = { + peer_external_gateways = { + default = { + redundancy_type = "SINGLE_IP_INTERNALLY_REDUNDANT" + interfaces = ["8.8.8.8"] + } + } + router_config = { + asn = 65501 + custom_advertise = { + all_subnets = false + ip_ranges = { + "10.1.0.0/16" = "gcp" + "35.199.192.0/19" = "gcp-dns" + "199.36.153.4/30" = "gcp-restricted" + } + } + } + tunnels = { + "0" = { + bgp_peer = { + address = "169.254.1.1" + asn = 65500 + } + bgp_session_range = "169.254.1.2/30" + shared_secret = "foo" + vpn_gateway_interface = 0 + } + "1" = { + bgp_peer = { + address = "169.254.2.1" + asn = 64513 + } + bgp_session_range = "169.254.2.2/30" + shared_secret = "foo" + vpn_gateway_interface = 1 + } + } +} +# tftest skip +``` + ### Adding an environment To create a new environment (e.g. `staging`), a few changes are required: @@ -383,8 +433,8 @@ Create a `spoke-staging.tf` file by copying `spoke-prod.tf` file. Adapt the new file by replacing the value "prod" with the value "staging". Running `diff spoke-dev.tf spoke-prod.tf` can help to see how environment files differ. -The new VPC requires a set of dedicated CIDRs, one per region, added to variable `custom_adv` (for example as `spoke_staging_ew1` and `spoke_staging_ew4`). ->`custom_adv` is a map that "resolves" CIDR names to the actual addresses, and will be used later to configure routing. +The new VPC requires a set of dedicated CIDRs, one per region, added to variable `gcp_ranges` (for example as `spoke_staging_ew1` and `spoke_staging_ew4`). +>`gcp_ranges` is a map that "resolves" CIDR names to the actual addresses, and will be used later to configure routing. > Variables managing L7 Internal Load Balancers (`l7ilb_subnets`) and Private Service Access (`psa_ranges`) should also be adapted, and subnets and firewall rules for the new spoke should be added, as described above. @@ -420,20 +470,20 @@ DNS configurations are centralised in the `dns-*.tf` files. Spokes delegate DNS |---|---|:---:|:---:|:---:|:---:| | [automation](variables.tf#L17) | Automation resources created by the bootstrap stage. | object({…}) | ✓ | | 0-bootstrap | | [billing_account](variables.tf#L25) | 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#L97) | Folders to be used for the networking resources in folders/nnnnnnnnnnn format. If null, folder will be created. | object({…}) | ✓ | | 1-resman | -| [organization](variables.tf#L115) | Organization details. | object({…}) | ✓ | | 0-bootstrap | -| [prefix](variables.tf#L131) | Prefix used for resources that need unique names. Use 9 characters or less. | string | ✓ | | 0-bootstrap | -| [custom_adv](variables.tf#L38) | Custom advertisement definitions in name => range format. | map(string) | | {…} | | -| [custom_roles](variables.tf#L60) | Custom roles defined at the org level, in key => id format. | object({…}) | | null | 0-bootstrap | -| [dns](variables.tf#L69) | Onprem DNS resolvers. | map(list(string)) | | {…} | | -| [factories_config](variables.tf#L77) | Configuration for network resource factories. | object({…}) | | {…} | | -| [onprem_cidr](variables.tf#L107) | Onprem addresses in name => range format. | map(string) | | {…} | | -| [outputs_location](variables.tf#L125) | Path where providers and tfvars files for the following stages are written. Leave empty to disable. | string | | null | | -| [psa_ranges](variables.tf#L142) | IP ranges used for Private Service Access (e.g. CloudSQL). Ranges is in name => range format. | object({…}) | | null | | -| [regions](variables.tf#L163) | Region definitions. | object({…}) | | {…} | | -| [router_configs](variables.tf#L175) | Configurations for CRs and onprem routers. | map(object({…})) | | {…} | | -| [service_accounts](variables.tf#L198) | Automation service accounts in name => email format. | object({…}) | | null | 1-resman | -| [vpn_onprem_configs](variables.tf#L212) | VPN gateway configuration for onprem interconnection. | map(object({…})) | | {…} | | +| [folder_ids](variables.tf#L75) | Folders to be used for the networking resources in folders/nnnnnnnnnnn format. If null, folder will be created. | object({…}) | ✓ | | 1-resman | +| [organization](variables.tf#L108) | Organization details. | object({…}) | ✓ | | 0-bootstrap | +| [prefix](variables.tf#L124) | Prefix used for resources that need unique names. Use 9 characters or less. | string | ✓ | | 0-bootstrap | +| [custom_roles](variables.tf#L38) | Custom roles defined at the org level, in key => id format. | object({…}) | | null | 0-bootstrap | +| [dns](variables.tf#L47) | Onprem DNS resolvers. | map(list(string)) | | {…} | | +| [factories_config](variables.tf#L55) | Configuration for network resource factories. | object({…}) | | {…} | | +| [gcp_ranges](variables.tf#L85) | GCP address ranges in name => range format. | map(string) | | {…} | | +| [onprem_cidr](variables.tf#L100) | Onprem addresses in name => range format. | map(string) | | {…} | | +| [outputs_location](variables.tf#L118) | Path where providers and tfvars files for the following stages are written. Leave empty to disable. | string | | null | | +| [psa_ranges](variables.tf#L135) | IP ranges used for Private Service Access (e.g. CloudSQL). Ranges is in name => range format. | object({…}) | | null | | +| [regions](variables.tf#L156) | Region definitions. | object({…}) | | {…} | | +| [service_accounts](variables.tf#L168) | Automation service accounts in name => email format. | object({…}) | | null | 1-resman | +| [vpn_onprem_primary_config](variables.tf#L182) | VPN gateway configuration for onprem interconnection in the primary region. | object({…}) | | null | | +| [vpn_onprem_secondary_config](variables.tf#L225) | VPN gateway configuration for onprem interconnection in the secondary region. | object({…}) | | null | | ## Outputs diff --git a/fast/stages/2-networking-c-nva/nva.tf b/fast/stages/2-networking-c-nva/nva.tf index 7ae9c30c..be1465c0 100644 --- a/fast/stages/2-networking-c-nva/nva.tf +++ b/fast/stages/2-networking-c-nva/nva.tf @@ -21,19 +21,19 @@ locals { { name = "untrusted" routes = [ - var.custom_adv.gcp_landing_untrusted_primary, - var.custom_adv.gcp_landing_untrusted_secondary, + var.gcp_ranges.gcp_landing_untrusted_primary, + var.gcp_ranges.gcp_landing_untrusted_secondary, ] }, { name = "trusted" routes = [ - var.custom_adv.gcp_dev_primary, - var.custom_adv.gcp_dev_secondary, - var.custom_adv.gcp_landing_trusted_primary, - var.custom_adv.gcp_landing_trusted_secondary, - var.custom_adv.gcp_prod_primary, - var.custom_adv.gcp_prod_secondary, + var.gcp_ranges.gcp_dev_primary, + var.gcp_ranges.gcp_dev_secondary, + var.gcp_ranges.gcp_landing_trusted_primary, + var.gcp_ranges.gcp_landing_trusted_secondary, + var.gcp_ranges.gcp_prod_primary, + var.gcp_ranges.gcp_prod_secondary, ] }, ] diff --git a/fast/stages/2-networking-c-nva/outputs.tf b/fast/stages/2-networking-c-nva/outputs.tf index 74620242..eb53a63f 100644 --- a/fast/stages/2-networking-c-nva/outputs.tf +++ b/fast/stages/2-networking-c-nva/outputs.tf @@ -78,13 +78,13 @@ output "tfvars" { output "vpn_gateway_endpoints" { description = "External IP Addresses for the GCP VPN gateways." - value = local.enable_onprem_vpn == false ? null : { - onprem-primary = { - for v in module.landing-to-onprem-primary-vpn[0].gateway.vpn_interfaces : + value = { + onprem-primary = var.vpn_onprem_primary_config == null ? {} : { + for v in module.landing-to-onprem-primary-vpn.0.gateway.vpn_interfaces : v.id => v.ip_address } - onprem-secondary = { - for v in module.landing-to-onprem-secondary-vpn[0].gateway.vpn_interfaces : + onprem-secondary = var.vpn_onprem_secondary_config == null ? {} : { + for v in module.landing-to-onprem-secondary-vpn.0.gateway.vpn_interfaces : v.id => v.ip_address } } diff --git a/fast/stages/2-networking-c-nva/variables.tf b/fast/stages/2-networking-c-nva/variables.tf index 5104afce..e4fe6896 100644 --- a/fast/stages/2-networking-c-nva/variables.tf +++ b/fast/stages/2-networking-c-nva/variables.tf @@ -35,28 +35,6 @@ variable "billing_account" { } } -variable "custom_adv" { - description = "Custom advertisement definitions in name => range format." - type = map(string) - default = { - cloud_dns = "35.199.192.0/19" - gcp_all = "10.128.0.0/16" - gcp_dev_primary = "10.128.128.0/19" - gcp_dev_secondary = "10.128.160.0/19" - gcp_landing_trusted_primary = "10.128.64.0/19" - gcp_landing_trusted_secondary = "10.128.96.0/19" - gcp_landing_untrusted_primary = "10.128.0.0/19" - gcp_landing_untrusted_secondary = "10.128.32.0/19" - gcp_prod_primary = "10.128.192.0/19" - gcp_prod_secondary = "10.128.224.0/19" - googleapis_private = "199.36.153.8/30" - googleapis_restricted = "199.36.153.4/30" - rfc_1918_10 = "10.0.0.0/8" - rfc_1918_172 = "172.16.0.0/12" - rfc_1918_192 = "192.168.0.0/16" - } -} - variable "custom_roles" { # tfdoc:variable:source 0-bootstrap description = "Custom roles defined at the org level, in key => id format." @@ -104,6 +82,21 @@ variable "folder_ids" { }) } +variable "gcp_ranges" { + description = "GCP address ranges in name => range format." + type = map(string) + default = { + gcp_dev_primary = "10.128.128.0/19" + gcp_dev_secondary = "10.128.160.0/19" + gcp_landing_trusted_primary = "10.128.64.0/19" + gcp_landing_trusted_secondary = "10.128.96.0/19" + gcp_landing_untrusted_primary = "10.128.0.0/19" + gcp_landing_untrusted_secondary = "10.128.32.0/19" + gcp_prod_primary = "10.128.192.0/19" + gcp_prod_secondary = "10.128.224.0/19" + } +} + variable "onprem_cidr" { description = "Onprem addresses in name => range format." type = map(string) @@ -172,29 +165,6 @@ variable "regions" { } } -variable "router_configs" { - description = "Configurations for CRs and onprem routers." - type = map(object({ - adv = object({ - custom = list(string) - default = bool - }) - asn = number - })) - default = { - landing-trusted-primary = { - asn = "64512" - adv = null - # adv = { default = false, custom = [] } - } - landing-trusted-secondary = { - asn = "64512" - adv = null - # adv = { default = false, custom = [] } - } - } -} - variable "service_accounts" { # tfdoc:variable:source 1-resman description = "Automation service accounts in name => email format." @@ -209,81 +179,88 @@ variable "service_accounts" { default = null } -variable "vpn_onprem_configs" { - description = "VPN gateway configuration for onprem interconnection." - type = map(object({ - adv = object({ - default = bool - custom = list(string) - }) - peer_external_gateway = object({ +variable "vpn_onprem_primary_config" { + description = "VPN gateway configuration for onprem interconnection in the primary region." + type = object({ + peer_external_gateways = map(object({ redundancy_type = string interfaces = list(string) + })) + router_config = object({ + create = optional(bool, true) + asn = number + name = optional(string) + keepalive = optional(number) + custom_advertise = optional(object({ + all_subnets = bool + ip_ranges = map(string) + })) }) - tunnels = list(object({ - peer_asn = number - peer_external_gateway_interface = number - secret = string - session_range = string + tunnels = map(object({ + bgp_peer = object({ + address = string + asn = number + route_priority = optional(number, 1000) + custom_advertise = optional(object({ + all_subnets = bool + all_vpc_subnets = bool + all_peer_vpc_subnets = bool + ip_ranges = map(string) + })) + }) + # each BGP session on the same Cloud Router must use a unique /30 CIDR + # from the 169.254.0.0/16 block. + bgp_session_range = string + ike_version = optional(number, 2) + peer_external_gateway_interface = optional(number) + peer_gateway = optional(string, "default") + router = optional(string) + shared_secret = optional(string) vpn_gateway_interface = number })) - })) - default = { - landing-trusted-primary = { - adv = { - default = false - custom = [ - "cloud_dns", "googleapis_private", "googleapis_restricted", "gcp_all" - ] - } - peer_external_gateway = { - redundancy_type = "SINGLE_IP_INTERNALLY_REDUNDANT" - interfaces = ["8.8.8.8"] - } - tunnels = [ - { - peer_asn = 65534 - peer_external_gateway_interface = 0 - secret = "foobar" - session_range = "169.254.1.0/30" - vpn_gateway_interface = 0 - }, - { - peer_asn = 65534 - peer_external_gateway_interface = 0 - secret = "foobar" - session_range = "169.254.1.4/30" - vpn_gateway_interface = 1 - } - ] - } - landing-trusted-secondary = { - adv = { - default = false - custom = [ - "cloud_dns", "googleapis_private", "googleapis_restricted", "gcp_all" - ] - } - peer_external_gateway = { - redundancy_type = "SINGLE_IP_INTERNALLY_REDUNDANT" - interfaces = ["8.8.8.8"] - } - tunnels = [ - { - peer_asn = 65534 - peer_external_gateway_interface = 0 - secret = "foobar" - session_range = "169.254.1.0/30" - vpn_gateway_interface = 0 - }, - { - peer_asn = 65534 - peer_external_gateway_interface = 0 - secret = "foobar" - session_range = "169.254.1.4/30" - vpn_gateway_interface = 1 - } - ] - } - } + }) + default = null +} + +variable "vpn_onprem_secondary_config" { + description = "VPN gateway configuration for onprem interconnection in the secondary region." + type = object({ + peer_external_gateways = map(object({ + redundancy_type = string + interfaces = list(string) + })) + router_config = object({ + create = optional(bool, true) + asn = number + name = optional(string) + keepalive = optional(number) + custom_advertise = optional(object({ + all_subnets = bool + ip_ranges = map(string) + })) + }) + tunnels = map(object({ + bgp_peer = object({ + address = string + asn = number + route_priority = optional(number, 1000) + custom_advertise = optional(object({ + all_subnets = bool + all_vpc_subnets = bool + all_peer_vpc_subnets = bool + ip_ranges = map(string) + })) + }) + # each BGP session on the same Cloud Router must use a unique /30 CIDR + # from the 169.254.0.0/16 block. + bgp_session_range = string + ike_version = optional(number, 2) + peer_external_gateway_interface = optional(number) + peer_gateway = optional(string, "default") + router = optional(string) + shared_secret = optional(string) + vpn_gateway_interface = number + })) + }) + default = null } diff --git a/fast/stages/2-networking-c-nva/vpn-onprem.tf b/fast/stages/2-networking-c-nva/vpn-onprem.tf index 31adbe71..55127ce4 100644 --- a/fast/stages/2-networking-c-nva/vpn-onprem.tf +++ b/fast/stages/2-networking-c-nva/vpn-onprem.tf @@ -17,92 +17,40 @@ # tfdoc:file:description VPN between landing and onprem. locals { - enable_onprem_vpn = var.vpn_onprem_configs != null - bgp_peer_options_onprem = local.enable_onprem_vpn == false ? null : { - for k, v in var.vpn_onprem_configs : - k => v.adv == null ? null : { - custom_advertise = try(v.adv.default, false) ? null : { - all_subnets = false - all_vpc_subnets = false - all_peer_vpc_subnets = false - ip_ranges = { - for adv in(v.adv == null ? [] : v.adv.custom) : - var.custom_adv[adv] => adv - } - } - route_priority = null - } + onprem_peer_gateways = { + primary = try( + var.vpn_onprem_primary_config.peer_external_gateways, {} + ) + secondary = try( + var.vpn_onprem_secondary_config.peer_external_gateways, {} + ) } } -moved { - from = module.landing-to-onprem-ew1-vpn - to = module.landing-to-onprem-primary-vpn -} - module "landing-to-onprem-primary-vpn" { - count = local.enable_onprem_vpn ? 1 : 0 - source = "../../../modules/net-vpn-ha" - project_id = module.landing-project.project_id - network = module.landing-trusted-vpc.self_link - region = var.regions.primary - name = "vpn-to-onprem-${local.region_shortnames[var.regions.primary]}" - router_config = { - name = "landing-onprem-vpn-${local.region_shortnames[var.regions.primary]}" - asn = var.router_configs.landing-trusted-primary.asn - } + count = var.vpn_onprem_primary_config == null ? 0 : 1 + source = "../../../modules/net-vpn-ha" + project_id = module.landing-project.project_id + network = module.landing-trusted-vpc.self_link + region = var.regions.primary + name = "vpn-to-onprem-${local.region_shortnames[var.regions.primary]}" + router_config = try(var.vpn_onprem_primary_config.router_config, {}) peer_gateways = { - default = { - external = var.vpn_onprem_configs.landing-trusted-primary.peer_external_gateway - } + for k, v in local.onprem_peer_gateways.primary : k => { external = v } } - tunnels = { - for t in var.vpn_onprem_configs.landing-trusted-primary.tunnels : - "remote-${t.vpn_gateway_interface}-${t.peer_external_gateway_interface}" => { - bgp_peer = merge( - { address = cidrhost(t.session_range, 1), asn = t.peer_asn }, - local.bgp_peer_options_onprem.landing-trusted-primary - ) - bgp_session_range = "${cidrhost(t.session_range, 2)}/30" - peer_external_gateway_interface = t.peer_external_gateway_interface - shared_secret = t.secret - vpn_gateway_interface = t.vpn_gateway_interface - } - } -} - -moved { - from = module.landing-to-onprem-ew4-vpn - to = module.landing-to-onprem-secondary-vpn + tunnels = try(var.vpn_onprem_primary_config.tunnels, {}) } module "landing-to-onprem-secondary-vpn" { - count = local.enable_onprem_vpn ? 1 : 0 - source = "../../../modules/net-vpn-ha" - project_id = module.landing-project.project_id - network = module.landing-trusted-vpc.self_link - region = var.regions.secondary - name = "vpn-to-onprem-${local.region_shortnames[var.regions.secondary]}" - router_config = { - name = "landing-onprem-vpn-${local.region_shortnames[var.regions.secondary]}" - asn = var.router_configs.landing-trusted-secondary.asn - } + count = var.vpn_onprem_secondary_config == null ? 0 : 1 + source = "../../../modules/net-vpn-ha" + project_id = module.landing-project.project_id + network = module.landing-trusted-vpc.self_link + region = var.regions.secondary + name = "vpn-to-onprem-${local.region_shortnames[var.regions.secondary]}" + router_config = try(var.vpn_onprem_secondary_config.router_config, {}) peer_gateways = { - default = { - external = var.vpn_onprem_configs.landing-trusted-secondary.peer_external_gateway - } - } - tunnels = { - for t in var.vpn_onprem_configs.landing-trusted-secondary.tunnels : - "remote-${t.vpn_gateway_interface}-${t.peer_external_gateway_interface}" => { - bgp_peer = merge( - { address = cidrhost(t.session_range, 1), asn = t.peer_asn }, - local.bgp_peer_options_onprem.landing-trusted-secondary - ) - bgp_session_range = "${cidrhost(t.session_range, 2)}/30" - peer_external_gateway_interface = t.peer_external_gateway_interface - shared_secret = t.secret - vpn_gateway_interface = t.vpn_gateway_interface - } + for k, v in local.onprem_peer_gateways.secondary : k => { external = v } } + tunnels = try(var.vpn_onprem_secondary_config.tunnels, {}) } diff --git a/fast/stages/2-networking-d-separate-envs/README.md b/fast/stages/2-networking-d-separate-envs/README.md index 4c0aa1e8..0a7a2aed 100644 --- a/fast/stages/2-networking-d-separate-envs/README.md +++ b/fast/stages/2-networking-d-separate-envs/README.md @@ -37,6 +37,7 @@ The following diagram illustrates the high-level design, and should be used as a - [Running the stage](#running-the-stage) - [Post-deployment activities](#post-deployment-activities) - [Customizations](#customizations) + - [Configuring the VPNs to on prem](#configuring-the-vpns-to-on-prem) - [Changing default regions](#changing-default-regions) ## Design overview and choices @@ -129,7 +130,7 @@ Subnets for [L7 ILBs](https://cloud.google.com/load-balancing/docs/l7-internal/p ### VPNs -Connectivity to on-prem is implemented with HA VPN ([`net-vpn`](../../../modules/net-vpn-ha)) and defined in `vpn-onprem-{dev,prod}.tf`. The files provisionally implement each a single logical connection between onprem and environment at `europe-west1`, and the relevant parameters for its configuration are found in variable `vpn_onprem_configs`. +Connectivity to on-prem is implemented with HA VPN ([`net-vpn`](../../../modules/net-vpn-ha)) and defined in `vpn-onprem.tf`. The file implements a single logical connection between each environment and onprem in the primary region, and the relevant parameters for its configuration are found in the `vpn_onprem_dev_primary_config` and `vpn_onprem_prod_primary_config` variables. ### Routing and BGP @@ -257,6 +258,55 @@ Per variable `vpn_onprem_configs` such ranges are advertised to onprem - further ## Customizations +### Configuring the VPNs to on prem + +This stage includes basic support for an HA VPN connecting each environment landing zone in the primary region to on prem. Configuration is via the `vpn_onprem_dev_primary_config` and `vpn_onprem_prod_primary_config` variables, that closely mirrors the variables defined in the [`net-vpn-ha`](../../../modules/net-vpn-ha/). + +Support for the onprem VPNs is disabled by default so that no resources are created, this is an example of how to configure one variable to enable the VPN for dev in the primary region: + +```hcl +vpn_onprem_dev_primary_config = { + peer_external_gateways = { + default = { + redundancy_type = "SINGLE_IP_INTERNALLY_REDUNDANT" + interfaces = ["8.8.8.8"] + } + } + router_config = { + asn = 65501 + custom_advertise = { + all_subnets = false + ip_ranges = { + "10.1.0.0/16" = "gcp" + "35.199.192.0/19" = "gcp-dns" + "199.36.153.4/30" = "gcp-restricted" + } + } + } + tunnels = { + "0" = { + bgp_peer = { + address = "169.254.1.1" + asn = 65500 + } + bgp_session_range = "169.254.1.2/30" + shared_secret = "foo" + vpn_gateway_interface = 0 + } + "1" = { + bgp_peer = { + address = "169.254.2.1" + asn = 64513 + } + bgp_session_range = "169.254.2.2/30" + shared_secret = "foo" + vpn_gateway_interface = 1 + } + } +} +# tftest skip +``` + ### Changing default regions Regions are defined via the `regions` variable which sets up a mapping between the `regions.primary` and `regions.secondary` logical names and actual GCP region names. If you need to change regions from the defaults: @@ -281,8 +331,7 @@ Regions are defined via the `regions` variable which sets up a mapping between t | [spoke-prod.tf](./spoke-prod.tf) | Production spoke VPC and related resources. | net-cloudnat · net-vpc · net-vpc-firewall · project | google_project_iam_binding | | [test-resources.tf](./test-resources.tf) | Temporary instances for testing | compute-vm | | | [variables.tf](./variables.tf) | Module variables. | | | -| [vpn-onprem-dev.tf](./vpn-onprem-dev.tf) | VPN between dev and onprem. | net-vpn-ha | | -| [vpn-onprem-prod.tf](./vpn-onprem-prod.tf) | VPN between prod and onprem. | net-vpn-ha | | +| [vpn-onprem.tf](./vpn-onprem.tf) | VPN between landing and onprem. | net-vpn-ha | | ## Variables @@ -290,19 +339,18 @@ Regions are defined via the `regions` variable which sets up a mapping between t |---|---|:---:|:---:|:---:|:---:| | [automation](variables.tf#L17) | Automation resources created by the bootstrap stage. | object({…}) | ✓ | | 0-bootstrap | | [billing_account](variables.tf#L25) | 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#L92) | Folders to be used for the networking resources in folders/nnnnnnnnnnn format. If null, folder will be created. | object({…}) | ✓ | | 1-resman | -| [organization](variables.tf#L102) | Organization details. | object({…}) | ✓ | | 0-bootstrap | -| [prefix](variables.tf#L118) | Prefix used for resources that need unique names. Use 9 characters or less. | string | ✓ | | 0-bootstrap | -| [custom_adv](variables.tf#L38) | Custom advertisement definitions in name => range format. | map(string) | | {…} | | -| [custom_roles](variables.tf#L54) | Custom roles defined at the org level, in key => id format. | object({…}) | | null | 0-bootstrap | -| [dns](variables.tf#L63) | Onprem DNS resolvers. | map(list(string)) | | {…} | | -| [factories_config](variables.tf#L72) | Configuration for network resource factories. | object({…}) | | {…} | | -| [outputs_location](variables.tf#L112) | Path where providers and tfvars files for the following stages are written. Leave empty to disable. | string | | null | | -| [psa_ranges](variables.tf#L129) | IP ranges used for Private Service Access (e.g. CloudSQL). | object({…}) | | null | | -| [regions](variables.tf#L166) | Region definitions. | object({…}) | | {…} | | -| [router_onprem_configs](variables.tf#L176) | Configurations for routers used for onprem connectivity. | map(object({…})) | | {…} | | -| [service_accounts](variables.tf#L199) | Automation service accounts in name => email format. | object({…}) | | null | 1-resman | -| [vpn_onprem_configs](variables.tf#L211) | VPN gateway configuration for onprem interconnection. | map(object({…})) | | {…} | | +| [folder_ids](variables.tf#L76) | Folders to be used for the networking resources in folders/nnnnnnnnnnn format. If null, folder will be created. | object({…}) | ✓ | | 1-resman | +| [organization](variables.tf#L86) | Organization details. | object({…}) | ✓ | | 0-bootstrap | +| [prefix](variables.tf#L102) | Prefix used for resources that need unique names. Use 9 characters or less. | string | ✓ | | 0-bootstrap | +| [custom_roles](variables.tf#L38) | Custom roles defined at the org level, in key => id format. | object({…}) | | null | 0-bootstrap | +| [dns](variables.tf#L47) | Onprem DNS resolvers. | map(list(string)) | | {…} | | +| [factories_config](variables.tf#L56) | Configuration for network resource factories. | object({…}) | | {…} | | +| [outputs_location](variables.tf#L96) | Path where providers and tfvars files for the following stages are written. Leave empty to disable. | string | | null | | +| [psa_ranges](variables.tf#L113) | IP ranges used for Private Service Access (e.g. CloudSQL). | object({…}) | | null | | +| [regions](variables.tf#L134) | Region definitions. | object({…}) | | {…} | | +| [service_accounts](variables.tf#L144) | Automation service accounts in name => email format. | object({…}) | | null | 1-resman | +| [vpn_onprem_dev_primary_config](variables.tf#L156) | VPN gateway configuration for onprem interconnection from dev in the primary region. | object({…}) | | null | | +| [vpn_onprem_prod_primary_config](variables.tf#L199) | 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/outputs.tf b/fast/stages/2-networking-d-separate-envs/outputs.tf index 59d70db6..5b5b0749 100644 --- a/fast/stages/2-networking-d-separate-envs/outputs.tf +++ b/fast/stages/2-networking-d-separate-envs/outputs.tf @@ -89,13 +89,13 @@ output "tfvars" { output "vpn_gateway_endpoints" { description = "External IP Addresses for the GCP VPN gateways." - value = local.enable_onprem_vpn == false ? null : { - dev-onprem-primary = { - for v in module.dev-to-onprem-primary-vpn[0].gateway.vpn_interfaces : + value = { + dev-primary = var.vpn_onprem_dev_primary_config == null ? {} : { + for v in module.landing-to-onprem-dev-primary-vpn.0.gateway.vpn_interfaces : v.id => v.ip_address } - prod-onprem-primary = { - for v in module.prod-to-onprem-primary-vpn[0].gateway.vpn_interfaces : + prod-primary = var.vpn_onprem_prod_primary_config == null ? {} : { + for v in module.landing-to-onprem-prod-primary-vpn.0.gateway.vpn_interfaces : v.id => v.ip_address } } diff --git a/fast/stages/2-networking-d-separate-envs/variables.tf b/fast/stages/2-networking-d-separate-envs/variables.tf index fde3691b..4a3e8364 100644 --- a/fast/stages/2-networking-d-separate-envs/variables.tf +++ b/fast/stages/2-networking-d-separate-envs/variables.tf @@ -35,22 +35,6 @@ variable "billing_account" { } } -variable "custom_adv" { - description = "Custom advertisement definitions in name => range format." - type = map(string) - default = { - cloud_dns = "35.199.192.0/19" - gcp_all = "10.128.0.0/16" - gcp_dev = "10.128.32.0/19" - gcp_prod = "10.128.64.0/19" - googleapis_private = "199.36.153.8/30" - googleapis_restricted = "199.36.153.4/30" - rfc_1918_10 = "10.0.0.0/8" - rfc_1918_172 = "172.16.0.0/12" - rfc_1918_192 = "192.168.0.0/16" - } -} - variable "custom_roles" { # tfdoc:variable:source 0-bootstrap description = "Custom roles defined at the org level, in key => id format." @@ -145,22 +129,6 @@ variable "psa_ranges" { }) }) default = null - # default = { - # dev = { - # ranges = { - # cloudsql-mysql = "10.128.62.0/24" - # cloudsql-sqlserver = "10.128.63.0/24" - # } - # routes = null - # } - # prod = { - # ranges = { - # cloudsql-mysql = "10.128.94.0/24" - # cloudsql-sqlserver = "10.128.95.0/24" - # } - # routes = null - # } - # } } variable "regions" { @@ -173,29 +141,6 @@ variable "regions" { } } -variable "router_onprem_configs" { - description = "Configurations for routers used for onprem connectivity." - type = map(object({ - adv = object({ - custom = list(string) - default = bool - }) - asn = number - })) - default = { - prod-primary = { - asn = "65533" - adv = null - # adv = { default = false, custom = [] } - } - dev-primary = { - asn = "65534" - adv = null - # adv = { default = false, custom = [] } - } - } -} - variable "service_accounts" { # tfdoc:variable:source 1-resman description = "Automation service accounts in name => email format." @@ -208,82 +153,88 @@ variable "service_accounts" { default = null } -variable "vpn_onprem_configs" { - description = "VPN gateway configuration for onprem interconnection." - type = map(object({ - adv = object({ - default = bool - custom = list(string) - }) - peer_external_gateway = object({ +variable "vpn_onprem_dev_primary_config" { + description = "VPN gateway configuration for onprem interconnection from dev in the primary region." + type = object({ + peer_external_gateways = map(object({ redundancy_type = string interfaces = list(string) + })) + router_config = object({ + create = optional(bool, true) + asn = number + name = optional(string) + keepalive = optional(number) + custom_advertise = optional(object({ + all_subnets = bool + ip_ranges = map(string) + })) }) - tunnels = list(object({ - peer_asn = number - peer_external_gateway_interface = number - secret = string - session_range = string + tunnels = map(object({ + bgp_peer = object({ + address = string + asn = number + route_priority = optional(number, 1000) + custom_advertise = optional(object({ + all_subnets = bool + all_vpc_subnets = bool + all_peer_vpc_subnets = bool + ip_ranges = map(string) + })) + }) + # each BGP session on the same Cloud Router must use a unique /30 CIDR + # from the 169.254.0.0/16 block. + bgp_session_range = string + ike_version = optional(number, 2) + peer_external_gateway_interface = optional(number) + peer_gateway = optional(string, "default") + router = optional(string) + shared_secret = optional(string) vpn_gateway_interface = number })) - })) - default = { - dev-primary = { - adv = { - default = false - custom = [ - "cloud_dns", "googleapis_private", "googleapis_restricted", "gcp_dev" - ] - } - peer_external_gateway = { - redundancy_type = "SINGLE_IP_INTERNALLY_REDUNDANT" - interfaces = ["8.8.8.8"] - - } - tunnels = [ - { - peer_asn = 65544 - peer_external_gateway_interface = 0 - secret = "foobar" - session_range = "169.254.1.0/30" - vpn_gateway_interface = 0 - }, - { - peer_asn = 65544 - peer_external_gateway_interface = 0 - secret = "foobar" - session_range = "169.254.1.4/30" - vpn_gateway_interface = 1 - } - ] - } - prod-primary = { - adv = { - default = false - custom = [ - "cloud_dns", "googleapis_private", "googleapis_restricted", "gcp_prod" - ] - } - peer_external_gateway = { - redundancy_type = "SINGLE_IP_INTERNALLY_REDUNDANT" - interfaces = ["8.8.8.8"] - } - tunnels = [ - { - peer_asn = 65543 - peer_external_gateway_interface = 0 - secret = "foobar" - session_range = "169.254.1.0/30" - vpn_gateway_interface = 0 - }, - { - peer_asn = 65543 - peer_external_gateway_interface = 0 - secret = "foobar" - session_range = "169.254.1.4/30" - vpn_gateway_interface = 1 - } - ] - } - } + }) + default = null +} + +variable "vpn_onprem_prod_primary_config" { + description = "VPN gateway configuration for onprem interconnection from prod in the primary region." + type = object({ + peer_external_gateways = map(object({ + redundancy_type = string + interfaces = list(string) + })) + router_config = object({ + create = optional(bool, true) + asn = number + name = optional(string) + keepalive = optional(number) + custom_advertise = optional(object({ + all_subnets = bool + ip_ranges = map(string) + })) + }) + tunnels = map(object({ + bgp_peer = object({ + address = string + asn = number + route_priority = optional(number, 1000) + custom_advertise = optional(object({ + all_subnets = bool + all_vpc_subnets = bool + all_peer_vpc_subnets = bool + ip_ranges = map(string) + })) + }) + # each BGP session on the same Cloud Router must use a unique /30 CIDR + # from the 169.254.0.0/16 block. + bgp_session_range = string + ike_version = optional(number, 2) + peer_external_gateway_interface = optional(number) + peer_gateway = optional(string, "default") + router = optional(string) + shared_secret = optional(string) + vpn_gateway_interface = number + })) + }) + default = null } diff --git a/fast/stages/2-networking-d-separate-envs/vpn-onprem-dev.tf b/fast/stages/2-networking-d-separate-envs/vpn-onprem-dev.tf deleted file mode 100644 index c5269c4d..00000000 --- a/fast/stages/2-networking-d-separate-envs/vpn-onprem-dev.tf +++ /dev/null @@ -1,70 +0,0 @@ -/** - * Copyright 2022 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. - */ - -# tfdoc:file:description VPN between dev and onprem. - -locals { - enable_onprem_vpn = var.vpn_onprem_configs != null - bgp_peer_options_onprem = local.enable_onprem_vpn == false ? null : { - for k, v in var.vpn_onprem_configs : - k => v.adv == null ? null : { - advertise_groups = [] - advertise_ip_ranges = { - for adv in(v.adv == null ? [] : v.adv.custom) : - var.custom_adv[adv] => adv - } - advertise_mode = try(v.adv.default, false) ? "DEFAULT" : "CUSTOM" - route_priority = null - } - } -} - -moved { - from = module.dev-to-onprem-ew1-vpn - to = module.dev-to-onprem-primary-vpn -} - -module "dev-to-onprem-primary-vpn" { - count = local.enable_onprem_vpn ? 1 : 0 - source = "../../../modules/net-vpn-ha" - project_id = module.dev-spoke-project.project_id - network = module.dev-spoke-vpc.self_link - region = var.regions.primary - name = "vpn-to-onprem-${local.region_shortnames[var.regions.primary]}" - router_config = { - name = "dev-onprem-vpn-${local.region_shortnames[var.regions.primary]}" - asn = var.router_onprem_configs.dev-primary.asn - } - peer_gateways = { - default = { - external = var.vpn_onprem_configs.dev-primary.peer_external_gateway - } - } - tunnels = { - for t in var.vpn_onprem_configs.dev-primary.tunnels : - "remote-${t.vpn_gateway_interface}-${t.peer_external_gateway_interface}" => { - bgp_peer = { - address = cidrhost(t.session_range, 1) - asn = t.peer_asn - } - bgp_peer_options = local.bgp_peer_options_onprem.dev-primary - bgp_session_range = "${cidrhost(t.session_range, 2)}/30" - peer_external_gateway_interface = t.peer_external_gateway_interface - shared_secret = t.secret - vpn_gateway_interface = t.vpn_gateway_interface - } - } -} diff --git a/fast/stages/2-networking-d-separate-envs/vpn-onprem-prod.tf b/fast/stages/2-networking-d-separate-envs/vpn-onprem-prod.tf deleted file mode 100644 index 760ba4e5..00000000 --- a/fast/stages/2-networking-d-separate-envs/vpn-onprem-prod.tf +++ /dev/null @@ -1,54 +0,0 @@ -/** - * Copyright 2022 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. - */ - -# tfdoc:file:description VPN between prod and onprem. - -moved { - from = module.prod-to-onprem-ew1-vpn - to = module.prod-to-onprem-primary-vpn -} - -module "prod-to-onprem-primary-vpn" { - count = local.enable_onprem_vpn ? 1 : 0 - source = "../../../modules/net-vpn-ha" - project_id = module.prod-spoke-project.project_id - network = module.prod-spoke-vpc.self_link - region = var.regions.primary - name = "vpn-to-onprem-${local.region_shortnames[var.regions.primary]}" - router_config = { - name = "prod-onprem-vpn-${local.region_shortnames[var.regions.primary]}" - asn = var.router_onprem_configs.prod-primary.asn - } - peer_gateways = { - default = { - external = var.vpn_onprem_configs.prod-primary.peer_external_gateway - } - } - tunnels = { - for t in var.vpn_onprem_configs.prod-primary.tunnels : - "remote-${t.vpn_gateway_interface}-${t.peer_external_gateway_interface}" => { - bgp_peer = { - address = cidrhost(t.session_range, 1) - asn = t.peer_asn - } - bgp_peer_options = local.bgp_peer_options_onprem.prod-primary - bgp_session_range = "${cidrhost(t.session_range, 2)}/30" - peer_external_gateway_interface = t.peer_external_gateway_interface - shared_secret = t.secret - vpn_gateway_interface = t.vpn_gateway_interface - } - } -} diff --git a/fast/stages/2-networking-d-separate-envs/vpn-onprem.tf b/fast/stages/2-networking-d-separate-envs/vpn-onprem.tf new file mode 100644 index 00000000..d5300282 --- /dev/null +++ b/fast/stages/2-networking-d-separate-envs/vpn-onprem.tf @@ -0,0 +1,56 @@ +/** + * Copyright 2022 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. + */ + +# tfdoc:file:description VPN between landing and onprem. + +locals { + onprem_peer_gateways = { + dev = try( + var.vpn_onprem_dev_primary_config.peer_external_gateways, {} + ) + prod = try( + var.vpn_onprem_prod_primary_config.peer_external_gateways, {} + ) + } +} + +module "landing-to-onprem-dev-primary-vpn" { + count = var.vpn_onprem_dev_primary_config == null ? 0 : 1 + source = "../../../modules/net-vpn-ha" + project_id = module.dev-spoke-project.project_id + network = module.dev-spoke-vpc.self_link + region = var.regions.primary + name = "vpn-to-onprem-${local.region_shortnames[var.regions.primary]}" + router_config = try(var.vpn_onprem_dev_primary_config.router_config, {}) + peer_gateways = { + for k, v in local.onprem_peer_gateways.dev : k => { external = v } + } + tunnels = try(var.vpn_onprem_dev_primary_config.tunnels, {}) +} + +module "landing-to-onprem-prod-primary-vpn" { + count = var.vpn_onprem_prod_primary_config == null ? 0 : 1 + source = "../../../modules/net-vpn-ha" + project_id = module.prod-spoke-project.project_id + network = module.prod-spoke-vpc.self_link + region = var.regions.primary + name = "vpn-to-onprem-${local.region_shortnames[var.regions.primary]}" + router_config = try(var.vpn_onprem_prod_primary_config.router_config, {}) + peer_gateways = { + for k, v in local.onprem_peer_gateways.prod : k => { external = v } + } + tunnels = try(var.vpn_onprem_prod_primary_config.tunnels, {}) +} diff --git a/tests/fast/stages/s2_networking_a_peering/common.tfvars b/tests/fast/stages/s2_networking_a_peering/common.tfvars index 6c2b0c03..e7187df0 100644 --- a/tests/fast/stages/s2_networking_a_peering/common.tfvars +++ b/tests/fast/stages/s2_networking_a_peering/common.tfvars @@ -27,3 +27,38 @@ organization = { customer_id = "C00000000" } prefix = "fast2" +vpn_onprem_primary_config = { + peer_external_gateways = { + default = { + redundancy_type = "SINGLE_IP_INTERNALLY_REDUNDANT" + interfaces = ["8.8.8.8"] + } + } + router_config = { + asn = 65501 + custom_advertise = { + all_subnets = false + ip_ranges = { "10.1.0.0/16" = "gcp" } + } + } + tunnels = { + "0" = { + bgp_peer = { + address = "169.254.1.1" + asn = 65500 + } + bgp_session_range = "169.254.1.2/30" + shared_secret = "foo" + vpn_gateway_interface = 0 + } + "1" = { + bgp_peer = { + address = "169.254.2.1" + asn = 64513 + } + bgp_session_range = "169.254.2.2/30" + shared_secret = "foo" + vpn_gateway_interface = 1 + } + } +} diff --git a/tests/fast/stages/s2_networking_b_vpn/common.tfvars b/tests/fast/stages/s2_networking_b_vpn/common.tfvars index 66a7a609..c7d02e6c 100644 --- a/tests/fast/stages/s2_networking_b_vpn/common.tfvars +++ b/tests/fast/stages/s2_networking_b_vpn/common.tfvars @@ -13,11 +13,6 @@ folder_ids = { networking-dev = null networking-prod = null } -region_trigram = { - europe-west1 = "ew1" - europe-west3 = "ew3" - europe-west8 = "ew8" -} service_accounts = { data-platform-dev = "string" data-platform-prod = "string" diff --git a/tests/fast/stages/s2_networking_c_nva/common.tfvars b/tests/fast/stages/s2_networking_c_nva/common.tfvars index ad12b8d3..9980e655 100644 --- a/tests/fast/stages/s2_networking_c_nva/common.tfvars +++ b/tests/fast/stages/s2_networking_c_nva/common.tfvars @@ -27,3 +27,81 @@ organization = { customer_id = "C00000000" } prefix = "fast2" +vpn_onprem_primary_config = { + peer_external_gateways = { + default = { + redundancy_type = "SINGLE_IP_INTERNALLY_REDUNDANT" + interfaces = ["8.8.8.8"] + } + } + router_config = { + asn = 65501 + custom_advertise = { + all_subnets = false + ip_ranges = { + "10.1.0.0/16" = "gcp" + "35.199.192.0/19" = "gcp-dns" + "199.36.153.4/30" = "gcp-restricted" + } + } + } + tunnels = { + "0" = { + bgp_peer = { + address = "169.254.1.1" + asn = 65500 + } + bgp_session_range = "169.254.1.2/30" + shared_secret = "foo" + vpn_gateway_interface = 0 + } + "1" = { + bgp_peer = { + address = "169.254.2.1" + asn = 64513 + } + bgp_session_range = "169.254.2.2/30" + shared_secret = "foo" + vpn_gateway_interface = 1 + } + } +} +vpn_onprem_secondary_config = { + peer_external_gateways = { + default = { + redundancy_type = "SINGLE_IP_INTERNALLY_REDUNDANT" + interfaces = ["8.8.4.4"] + } + } + router_config = { + asn = 65501 + custom_advertise = { + all_subnets = false + ip_ranges = { + "10.1.0.0/16" = "gcp" + "35.199.192.0/19" = "gcp-dns" + "199.36.153.4/30" = "gcp-restricted" + } + } + } + tunnels = { + "0" = { + bgp_peer = { + address = "169.254.1.1" + asn = 65500 + } + bgp_session_range = "169.254.3.2/30" + shared_secret = "foo" + vpn_gateway_interface = 0 + } + "1" = { + bgp_peer = { + address = "169.254.2.1" + asn = 64513 + } + bgp_session_range = "169.254.4.2/30" + shared_secret = "foo" + vpn_gateway_interface = 1 + } + } +} 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 3ff0020a..f6b6b7f8 100644 --- a/tests/fast/stages/s2_networking_d_separate_envs/common.tfvars +++ b/tests/fast/stages/s2_networking_d_separate_envs/common.tfvars @@ -25,3 +25,81 @@ organization = { customer_id = "C00000000" } prefix = "fast2" +vpn_onprem_dev_primary_config = { + peer_external_gateways = { + default = { + redundancy_type = "SINGLE_IP_INTERNALLY_REDUNDANT" + interfaces = ["8.8.8.8"] + } + } + router_config = { + asn = 65501 + custom_advertise = { + all_subnets = false + ip_ranges = { + "10.1.0.0/16" = "gcp" + "35.199.192.0/19" = "gcp-dns" + "199.36.153.4/30" = "gcp-restricted" + } + } + } + tunnels = { + "0" = { + bgp_peer = { + address = "169.254.1.1" + asn = 65500 + } + bgp_session_range = "169.254.1.2/30" + shared_secret = "foo" + vpn_gateway_interface = 0 + } + "1" = { + bgp_peer = { + address = "169.254.2.1" + asn = 64513 + } + bgp_session_range = "169.254.2.2/30" + shared_secret = "foo" + vpn_gateway_interface = 1 + } + } +} +vpn_onprem_prod_primary_config = { + peer_external_gateways = { + default = { + redundancy_type = "SINGLE_IP_INTERNALLY_REDUNDANT" + interfaces = ["8.8.4.4"] + } + } + router_config = { + asn = 65501 + custom_advertise = { + all_subnets = false + ip_ranges = { + "10.1.0.0/16" = "gcp" + "35.199.192.0/19" = "gcp-dns" + "199.36.153.4/30" = "gcp-restricted" + } + } + } + tunnels = { + "0" = { + bgp_peer = { + address = "169.254.1.1" + asn = 65500 + } + bgp_session_range = "169.254.3.2/30" + shared_secret = "foo" + vpn_gateway_interface = 0 + } + "1" = { + bgp_peer = { + address = "169.254.2.1" + asn = 64513 + } + bgp_session_range = "169.254.4.2/30" + shared_secret = "foo" + vpn_gateway_interface = 1 + } + } +}