Simplify VPN implementation in FAST networking stages (#1228)

* peering stage

* fix link, toc

* vpn stage

* fix link

* nva stage

* fix examples and test

* separate envs stage

* tfdoc
This commit is contained in:
Ludovico Magnocavallo 2023-03-09 17:57:44 +01:00 committed by GitHub
parent 1b7864af2e
commit be06554bba
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
29 changed files with 1074 additions and 1169 deletions

View File

@ -40,6 +40,7 @@ The following diagram illustrates the high-level design, and should be used as a
- [Post-deployment activities](#post-deployment-activities) - [Post-deployment activities](#post-deployment-activities)
- [Customizations](#customizations) - [Customizations](#customizations)
- [Changing default regions](#changing-default-regions) - [Changing default regions](#changing-default-regions)
- [Configuring the VPN to on prem](#configuring-the-vpn-to-on-prem)
- [Adding an environment](#adding-an-environment) - [Adding an environment](#adding-an-environment)
## Design overview and choices ## Design overview and choices
@ -164,7 +165,7 @@ Subnets for [L7 ILBs](https://cloud.google.com/load-balancing/docs/l7-internal/p
### VPNs ### 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 ### 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 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 - 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 ### Adding an environment
To create a new environment (e.g. `staging`), a few changes are required. 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. | <code title="object&#40;&#123;&#10; outputs_bucket &#61; string&#10;&#125;&#41;">object&#40;&#123;&#8230;&#125;&#41;</code> | ✓ | | <code>0-bootstrap</code> | | [automation](variables.tf#L17) | Automation resources created by the bootstrap stage. | <code title="object&#40;&#123;&#10; outputs_bucket &#61; string&#10;&#125;&#41;">object&#40;&#123;&#8230;&#125;&#41;</code> | ✓ | | <code>0-bootstrap</code> |
| [billing_account](variables.tf#L25) | Billing account id. If billing account is not part of the same org set `is_org_level` to false. | <code title="object&#40;&#123;&#10; id &#61; string&#10; is_org_level &#61; optional&#40;bool, true&#41;&#10;&#125;&#41;">object&#40;&#123;&#8230;&#125;&#41;</code> | ✓ | | <code>0-bootstrap</code> | | [billing_account](variables.tf#L25) | Billing account id. If billing account is not part of the same org set `is_org_level` to false. | <code title="object&#40;&#123;&#10; id &#61; string&#10; is_org_level &#61; optional&#40;bool, true&#41;&#10;&#125;&#41;">object&#40;&#123;&#8230;&#125;&#41;</code> | ✓ | | <code>0-bootstrap</code> |
| [folder_ids](variables.tf#L92) | Folders to be used for the networking resources in folders/nnnnnnnnnnn format. If null, folder will be created. | <code title="object&#40;&#123;&#10; networking &#61; string&#10; networking-dev &#61; string&#10; networking-prod &#61; string&#10;&#125;&#41;">object&#40;&#123;&#8230;&#125;&#41;</code> | ✓ | | <code>1-resman</code> | | [folder_ids](variables.tf#L75) | Folders to be used for the networking resources in folders/nnnnnnnnnnn format. If null, folder will be created. | <code title="object&#40;&#123;&#10; networking &#61; string&#10; networking-dev &#61; string&#10; networking-prod &#61; string&#10;&#125;&#41;">object&#40;&#123;&#8230;&#125;&#41;</code> | ✓ | | <code>1-resman</code> |
| [organization](variables.tf#L102) | Organization details. | <code title="object&#40;&#123;&#10; domain &#61; string&#10; id &#61; number&#10; customer_id &#61; string&#10;&#125;&#41;">object&#40;&#123;&#8230;&#125;&#41;</code> | ✓ | | <code>0-bootstrap</code> | | [organization](variables.tf#L85) | Organization details. | <code title="object&#40;&#123;&#10; domain &#61; string&#10; id &#61; number&#10; customer_id &#61; string&#10;&#125;&#41;">object&#40;&#123;&#8230;&#125;&#41;</code> | ✓ | | <code>0-bootstrap</code> |
| [prefix](variables.tf#L118) | Prefix used for resources that need unique names. Use 9 characters or less. | <code>string</code> | ✓ | | <code>0-bootstrap</code> | | [prefix](variables.tf#L101) | Prefix used for resources that need unique names. Use 9 characters or less. | <code>string</code> | ✓ | | <code>0-bootstrap</code> |
| [custom_adv](variables.tf#L38) | Custom advertisement definitions in name => range format. | <code>map&#40;string&#41;</code> | | <code title="&#123;&#10; cloud_dns &#61; &#34;35.199.192.0&#47;19&#34;&#10; gcp_all &#61; &#34;10.128.0.0&#47;16&#34;&#10; gcp_dev &#61; &#34;10.128.32.0&#47;19&#34;&#10; gcp_landing &#61; &#34;10.128.0.0&#47;19&#34;&#10; gcp_prod &#61; &#34;10.128.64.0&#47;19&#34;&#10; googleapis_private &#61; &#34;199.36.153.8&#47;30&#34;&#10; googleapis_restricted &#61; &#34;199.36.153.4&#47;30&#34;&#10; rfc_1918_10 &#61; &#34;10.0.0.0&#47;8&#34;&#10; rfc_1918_172 &#61; &#34;172.16.0.0&#47;12&#34;&#10; rfc_1918_192 &#61; &#34;192.168.0.0&#47;16&#34;&#10;&#125;">&#123;&#8230;&#125;</code> | | | [custom_roles](variables.tf#L38) | Custom roles defined at the org level, in key => id format. | <code title="object&#40;&#123;&#10; service_project_network_admin &#61; string&#10;&#125;&#41;">object&#40;&#123;&#8230;&#125;&#41;</code> | | <code>null</code> | <code>0-bootstrap</code> |
| [custom_roles](variables.tf#L55) | Custom roles defined at the org level, in key => id format. | <code title="object&#40;&#123;&#10; service_project_network_admin &#61; string&#10;&#125;&#41;">object&#40;&#123;&#8230;&#125;&#41;</code> | | <code>null</code> | <code>0-bootstrap</code> | | [dns](variables.tf#L47) | Onprem DNS resolvers. | <code>map&#40;list&#40;string&#41;&#41;</code> | | <code title="&#123;&#10; onprem &#61; &#91;&#34;10.0.200.3&#34;&#93;&#10;&#125;">&#123;&#8230;&#125;</code> | |
| [dns](variables.tf#L64) | Onprem DNS resolvers. | <code>map&#40;list&#40;string&#41;&#41;</code> | | <code title="&#123;&#10; onprem &#61; &#91;&#34;10.0.200.3&#34;&#93;&#10;&#125;">&#123;&#8230;&#125;</code> | | | [factories_config](variables.tf#L55) | Configuration for network resource factories. | <code title="object&#40;&#123;&#10; data_dir &#61; optional&#40;string, &#34;data&#34;&#41;&#10; firewall_policy_name &#61; optional&#40;string, &#34;factory&#34;&#41;&#10;&#125;&#41;">object&#40;&#123;&#8230;&#125;&#41;</code> | | <code title="&#123;&#10; data_dir &#61; &#34;data&#34;&#10;&#125;">&#123;&#8230;&#125;</code> | |
| [factories_config](variables.tf#L72) | Configuration for network resource factories. | <code title="object&#40;&#123;&#10; data_dir &#61; optional&#40;string, &#34;data&#34;&#41;&#10; firewall_policy_name &#61; optional&#40;string, &#34;factory&#34;&#41;&#10;&#125;&#41;">object&#40;&#123;&#8230;&#125;&#41;</code> | | <code title="&#123;&#10; data_dir &#61; &#34;data&#34;&#10;&#125;">&#123;&#8230;&#125;</code> | | | [outputs_location](variables.tf#L95) | Path where providers and tfvars files for the following stages are written. Leave empty to disable. | <code>string</code> | | <code>null</code> | |
| [outputs_location](variables.tf#L112) | Path where providers and tfvars files for the following stages are written. Leave empty to disable. | <code>string</code> | | <code>null</code> | |
| [peering_configs](variables-peerings.tf#L19) | Peering configurations. | <code title="map&#40;object&#40;&#123;&#10; export_local_custom_routes &#61; bool&#10; export_peer_custom_routes &#61; bool&#10;&#125;&#41;&#41;">map&#40;object&#40;&#123;&#8230;&#125;&#41;&#41;</code> | | <code title="&#123;&#10; dev &#61; &#123;&#10; export_local_custom_routes &#61; true&#10; export_peer_custom_routes &#61; true&#10; &#125;&#10; prod &#61; &#123;&#10; export_local_custom_routes &#61; true&#10; export_peer_custom_routes &#61; true&#10; &#125;&#10;&#125;">&#123;&#8230;&#125;</code> | | | [peering_configs](variables-peerings.tf#L19) | Peering configurations. | <code title="map&#40;object&#40;&#123;&#10; export_local_custom_routes &#61; bool&#10; export_peer_custom_routes &#61; bool&#10;&#125;&#41;&#41;">map&#40;object&#40;&#123;&#8230;&#125;&#41;&#41;</code> | | <code title="&#123;&#10; dev &#61; &#123;&#10; export_local_custom_routes &#61; true&#10; export_peer_custom_routes &#61; true&#10; &#125;&#10; prod &#61; &#123;&#10; export_local_custom_routes &#61; true&#10; export_peer_custom_routes &#61; true&#10; &#125;&#10;&#125;">&#123;&#8230;&#125;</code> | |
| [psa_ranges](variables.tf#L129) | IP ranges used for Private Service Access (e.g. CloudSQL). | <code title="object&#40;&#123;&#10; dev &#61; object&#40;&#123;&#10; ranges &#61; map&#40;string&#41;&#10; routes &#61; object&#40;&#123;&#10; export &#61; bool&#10; import &#61; bool&#10; &#125;&#41;&#10; &#125;&#41;&#10; prod &#61; object&#40;&#123;&#10; ranges &#61; map&#40;string&#41;&#10; routes &#61; object&#40;&#123;&#10; export &#61; bool&#10; import &#61; bool&#10; &#125;&#41;&#10; &#125;&#41;&#10;&#125;&#41;">object&#40;&#123;&#8230;&#125;&#41;</code> | | <code>null</code> | | | [psa_ranges](variables.tf#L112) | IP ranges used for Private Service Access (CloudSQL, etc.). | <code title="object&#40;&#123;&#10; dev &#61; object&#40;&#123;&#10; ranges &#61; map&#40;string&#41;&#10; routes &#61; object&#40;&#123;&#10; export &#61; bool&#10; import &#61; bool&#10; &#125;&#41;&#10; &#125;&#41;&#10; prod &#61; object&#40;&#123;&#10; ranges &#61; map&#40;string&#41;&#10; routes &#61; object&#40;&#123;&#10; export &#61; bool&#10; import &#61; bool&#10; &#125;&#41;&#10; &#125;&#41;&#10;&#125;&#41;">object&#40;&#123;&#8230;&#125;&#41;</code> | | <code>null</code> | |
| [regions](variables.tf#L166) | Region definitions. | <code title="object&#40;&#123;&#10; primary &#61; string&#10; secondary &#61; string&#10;&#125;&#41;">object&#40;&#123;&#8230;&#125;&#41;</code> | | <code title="&#123;&#10; primary &#61; &#34;europe-west1&#34;&#10; secondary &#61; &#34;europe-west4&#34;&#10;&#125;">&#123;&#8230;&#125;</code> | | | [regions](variables.tf#L133) | Region definitions. | <code title="object&#40;&#123;&#10; primary &#61; string&#10; secondary &#61; string&#10;&#125;&#41;">object&#40;&#123;&#8230;&#125;&#41;</code> | | <code title="&#123;&#10; primary &#61; &#34;europe-west1&#34;&#10; secondary &#61; &#34;europe-west4&#34;&#10;&#125;">&#123;&#8230;&#125;</code> | |
| [router_onprem_configs](variables.tf#L178) | Configurations for routers used for onprem connectivity. | <code title="map&#40;object&#40;&#123;&#10; adv &#61; object&#40;&#123;&#10; custom &#61; list&#40;string&#41;&#10; default &#61; bool&#10; &#125;&#41;&#10; asn &#61; number&#10;&#125;&#41;&#41;">map&#40;object&#40;&#123;&#8230;&#125;&#41;&#41;</code> | | <code title="&#123;&#10; landing-primary &#61; &#123;&#10; asn &#61; &#34;65533&#34;&#10; adv &#61; null&#10; &#125;&#10;&#125;">&#123;&#8230;&#125;</code> | | | [service_accounts](variables.tf#L145) | Automation service accounts in name => email format. | <code title="object&#40;&#123;&#10; data-platform-dev &#61; string&#10; data-platform-prod &#61; string&#10; gke-dev &#61; string&#10; gke-prod &#61; string&#10; project-factory-dev &#61; string&#10; project-factory-prod &#61; string&#10;&#125;&#41;">object&#40;&#123;&#8230;&#125;&#41;</code> | | <code>null</code> | <code>1-resman</code> |
| [service_accounts](variables.tf#L196) | Automation service accounts in name => email format. | <code title="object&#40;&#123;&#10; data-platform-dev &#61; string&#10; data-platform-prod &#61; string&#10; gke-dev &#61; string&#10; gke-prod &#61; string&#10; project-factory-dev &#61; string&#10; project-factory-prod &#61; string&#10;&#125;&#41;">object&#40;&#123;&#8230;&#125;&#41;</code> | | <code>null</code> | <code>1-resman</code> | | [vpn_onprem_primary_config](variables.tf#L159) | VPN gateway configuration for onprem interconnection in the primary region. | <code title="object&#40;&#123;&#10; peer_external_gateways &#61; map&#40;object&#40;&#123;&#10; redundancy_type &#61; string&#10; interfaces &#61; list&#40;string&#41;&#10; &#125;&#41;&#41;&#10; router_config &#61; object&#40;&#123;&#10; create &#61; optional&#40;bool, true&#41;&#10; asn &#61; number&#10; name &#61; optional&#40;string&#41;&#10; keepalive &#61; optional&#40;number&#41;&#10; custom_advertise &#61; optional&#40;object&#40;&#123;&#10; all_subnets &#61; bool&#10; ip_ranges &#61; map&#40;string&#41;&#10; &#125;&#41;&#41;&#10; &#125;&#41;&#10; tunnels &#61; map&#40;object&#40;&#123;&#10; bgp_peer &#61; object&#40;&#123;&#10; address &#61; string&#10; asn &#61; number&#10; route_priority &#61; optional&#40;number, 1000&#41;&#10; custom_advertise &#61; optional&#40;object&#40;&#123;&#10; all_subnets &#61; bool&#10; all_vpc_subnets &#61; bool&#10; all_peer_vpc_subnets &#61; bool&#10; ip_ranges &#61; map&#40;string&#41;&#10; &#125;&#41;&#41;&#10; &#125;&#41;&#10; bgp_session_range &#61; string&#10; ike_version &#61; optional&#40;number, 2&#41;&#10; peer_external_gateway_interface &#61; optional&#40;number&#41;&#10; peer_gateway &#61; optional&#40;string, &#34;default&#34;&#41;&#10; router &#61; optional&#40;string&#41;&#10; shared_secret &#61; optional&#40;string&#41;&#10; vpn_gateway_interface &#61; number&#10; &#125;&#41;&#41;&#10;&#125;&#41;">object&#40;&#123;&#8230;&#125;&#41;</code> | | <code>null</code> | |
| [vpn_onprem_configs](variables.tf#L210) | VPN gateway configuration for onprem interconnection. | <code title="map&#40;object&#40;&#123;&#10; adv &#61; object&#40;&#123;&#10; default &#61; bool&#10; custom &#61; list&#40;string&#41;&#10; &#125;&#41;&#10; peer_external_gateway &#61; object&#40;&#123;&#10; redundancy_type &#61; string&#10; interfaces &#61; list&#40;string&#41;&#10; &#125;&#41;&#10; tunnels &#61; list&#40;object&#40;&#123;&#10; peer_asn &#61; number&#10; peer_external_gateway_interface &#61; number&#10; secret &#61; string&#10; session_range &#61; string&#10; vpn_gateway_interface &#61; number&#10; &#125;&#41;&#41;&#10;&#125;&#41;&#41;">map&#40;object&#40;&#123;&#8230;&#125;&#41;&#41;</code> | | <code title="&#123;&#10; landing-primary &#61; &#123;&#10; adv &#61; &#123;&#10; default &#61; false&#10; custom &#61; &#91;&#10; &#34;cloud_dns&#34;, &#34;googleapis_private&#34;, &#34;googleapis_restricted&#34;, &#34;gcp_all&#34;&#10; &#93;&#10; &#125;&#10; peer_external_gateway &#61; &#123;&#10; redundancy_type &#61; &#34;SINGLE_IP_INTERNALLY_REDUNDANT&#34;&#10; interfaces &#61; &#91;&#34;8.8.8.8&#34;&#93;&#10; &#125;&#10; tunnels &#61; &#91;&#10; &#123;&#10; peer_asn &#61; 65534&#10; peer_external_gateway_interface &#61; 0&#10; secret &#61; &#34;foobar&#34;&#10; session_range &#61; &#34;169.254.1.0&#47;30&#34;&#10; vpn_gateway_interface &#61; 0&#10; &#125;,&#10; &#123;&#10; peer_asn &#61; 65534&#10; peer_external_gateway_interface &#61; 0&#10; secret &#61; &#34;foobar&#34;&#10; session_range &#61; &#34;169.254.1.4&#47;30&#34;&#10; vpn_gateway_interface &#61; 1&#10; &#125;&#10; &#93;&#10; &#125;&#10;&#125;">&#123;&#8230;&#125;</code> | |
## Outputs ## Outputs

View File

@ -88,7 +88,7 @@ output "tfvars" {
output "vpn_gateway_endpoints" { output "vpn_gateway_endpoints" {
description = "External IP Addresses for the GCP VPN gateways." 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 = { onprem-primary = {
for v in module.landing-to-onprem-primary-vpn[0].gateway.vpn_interfaces : for v in module.landing-to-onprem-primary-vpn[0].gateway.vpn_interfaces :
v.id => v.ip_address v.id => v.ip_address

View File

@ -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" { variable "custom_roles" {
# tfdoc:variable:source 0-bootstrap # tfdoc:variable:source 0-bootstrap
description = "Custom roles defined at the org level, in key => id format." description = "Custom roles defined at the org level, in key => id format."
@ -127,7 +110,7 @@ variable "prefix" {
} }
variable "psa_ranges" { 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({ type = object({
dev = object({ dev = object({
ranges = map(string) ranges = map(string)
@ -145,22 +128,6 @@ variable "psa_ranges" {
}) })
}) })
default = null 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" { 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" { variable "service_accounts" {
# tfdoc:variable:source 1-resman # tfdoc:variable:source 1-resman
description = "Automation service accounts in name => email format." description = "Automation service accounts in name => email format."
@ -207,53 +156,45 @@ variable "service_accounts" {
default = null default = null
} }
variable "vpn_onprem_configs" { variable "vpn_onprem_primary_config" {
description = "VPN gateway configuration for onprem interconnection." description = "VPN gateway configuration for onprem interconnection in the primary region."
type = map(object({ type = object({
adv = object({ peer_external_gateways = map(object({
default = bool
custom = list(string)
})
peer_external_gateway = object({
redundancy_type = string redundancy_type = string
interfaces = list(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({ tunnels = map(object({
peer_asn = number bgp_peer = object({
peer_external_gateway_interface = number address = string
secret = string asn = number
session_range = string 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 vpn_gateway_interface = number
})) }))
})) })
default = { default = null
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
}
]
}
}
} }

View File

@ -17,54 +17,21 @@
# tfdoc:file:description VPN between landing and onprem. # tfdoc:file:description VPN between landing and onprem.
locals { locals {
enable_onprem_vpn = var.vpn_onprem_configs != null onprem_peer_gateways = try(
bgp_peer_options_onprem = local.enable_onprem_vpn == false ? null : { var.vpn_onprem_primary_config.peer_external_gateways, {}
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
} }
module "landing-to-onprem-primary-vpn" { module "landing-to-onprem-primary-vpn" {
count = local.enable_onprem_vpn ? 1 : 0 count = var.vpn_onprem_primary_config == null ? 0 : 1
source = "../../../modules/net-vpn-ha" source = "../../../modules/net-vpn-ha"
project_id = module.landing-project.project_id project_id = module.landing-project.project_id
network = module.landing-vpc.self_link network = module.landing-vpc.self_link
region = var.regions.primary region = var.regions.primary
name = "vpn-to-onprem-${local.region_shortnames[var.regions.primary]}" name = "vpn-to-onprem-${local.region_shortnames[var.regions.primary]}"
router_config = { router_config = try(var.vpn_onprem_primary_config.router_config, {})
name = "landing-onprem-vpn-${local.region_shortnames[var.regions.primary]}"
asn = var.router_onprem_configs.landing-primary.asn
}
peer_gateways = { peer_gateways = {
default = { for k, v in local.onprem_peer_gateways : k => { external = v }
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
}
} }
tunnels = try(var.vpn_onprem_primary_config.tunnels, {})
} }

View File

@ -40,6 +40,7 @@ The following diagram illustrates the high-level design, and should be used as a
- [Post-deployment activities](#post-deployment-activities) - [Post-deployment activities](#post-deployment-activities)
- [Customizations](#customizations) - [Customizations](#customizations)
- [Changing default regions](#changing-default-regions) - [Changing default regions](#changing-default-regions)
- [Configuring the VPN to on prem](#configuring-the-vpn-to-on-prem)
- [Adding an environment](#adding-an-environment) - [Adding an environment](#adding-an-environment)
## Design overview and choices ## Design overview and choices
@ -172,7 +173,7 @@ Subnets for [L7 ILBs](https://cloud.google.com/load-balancing/docs/l7-internal/p
#### External #### 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 #### 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 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 - 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 ### Adding an environment
To create a new environment (e.g. `staging`), a few changes are required. 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 | <code>compute-vm</code> | | | [test-resources.tf](./test-resources.tf) | temporary instances for testing | <code>compute-vm</code> | |
| [variables-vpn.tf](./variables-vpn.tf) | None | | | | [variables-vpn.tf](./variables-vpn.tf) | None | | |
| [variables.tf](./variables.tf) | Module variables. | | | | [variables.tf](./variables.tf) | Module variables. | | |
| [vpn-landing.tf](./vpn-landing.tf) | None | <code>net-vpn-ha</code> | |
| [vpn-onprem.tf](./vpn-onprem.tf) | VPN between landing and onprem. | <code>net-vpn-ha</code> | | | [vpn-onprem.tf](./vpn-onprem.tf) | VPN between landing and onprem. | <code>net-vpn-ha</code> | |
| [vpn-spoke-dev.tf](./vpn-spoke-dev.tf) | VPN between landing and development spoke. | <code>net-vpn-ha</code> | | | [vpn-spoke-dev.tf](./vpn-spoke-dev.tf) | VPN between landing and development spoke. | <code>net-vpn-ha</code> | |
| [vpn-spoke-prod-primary.tf](./vpn-spoke-prod-primary.tf) | VPN between landing and production spoke in ew1. | <code>net-vpn-ha</code> | | | [vpn-spoke-prod.tf](./vpn-spoke-prod.tf) | VPN between landing and production spoke in ew1. | <code>net-vpn-ha</code> | |
| [vpn-spoke-prod-secondary.tf](./vpn-spoke-prod-secondary.tf) | VPN between landing and production spoke in ew4. | <code>net-vpn-ha</code> | |
## Variables ## 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. | <code title="object&#40;&#123;&#10; outputs_bucket &#61; string&#10;&#125;&#41;">object&#40;&#123;&#8230;&#125;&#41;</code> | ✓ | | <code>0-bootstrap</code> | | [automation](variables.tf#L17) | Automation resources created by the bootstrap stage. | <code title="object&#40;&#123;&#10; outputs_bucket &#61; string&#10;&#125;&#41;">object&#40;&#123;&#8230;&#125;&#41;</code> | ✓ | | <code>0-bootstrap</code> |
| [billing_account](variables.tf#L25) | Billing account id. If billing account is not part of the same org set `is_org_level` to false. | <code title="object&#40;&#123;&#10; id &#61; string&#10; is_org_level &#61; optional&#40;bool, true&#41;&#10;&#125;&#41;">object&#40;&#123;&#8230;&#125;&#41;</code> | ✓ | | <code>0-bootstrap</code> | | [billing_account](variables.tf#L25) | Billing account id. If billing account is not part of the same org set `is_org_level` to false. | <code title="object&#40;&#123;&#10; id &#61; string&#10; is_org_level &#61; optional&#40;bool, true&#41;&#10;&#125;&#41;">object&#40;&#123;&#8230;&#125;&#41;</code> | ✓ | | <code>0-bootstrap</code> |
| [folder_ids](variables.tf#L92) | Folders to be used for the networking resources in folders/nnnnnnnnnnn format. If null, folder will be created. | <code title="object&#40;&#123;&#10; networking &#61; string&#10; networking-dev &#61; string&#10; networking-prod &#61; string&#10;&#125;&#41;">object&#40;&#123;&#8230;&#125;&#41;</code> | ✓ | | <code>1-resman</code> | | [folder_ids](variables.tf#L75) | Folders to be used for the networking resources in folders/nnnnnnnnnnn format. If null, folder will be created. | <code title="object&#40;&#123;&#10; networking &#61; string&#10; networking-dev &#61; string&#10; networking-prod &#61; string&#10;&#125;&#41;">object&#40;&#123;&#8230;&#125;&#41;</code> | ✓ | | <code>1-resman</code> |
| [organization](variables.tf#L102) | Organization details. | <code title="object&#40;&#123;&#10; domain &#61; string&#10; id &#61; number&#10; customer_id &#61; string&#10;&#125;&#41;">object&#40;&#123;&#8230;&#125;&#41;</code> | ✓ | | <code>0-bootstrap</code> | | [organization](variables.tf#L85) | Organization details. | <code title="object&#40;&#123;&#10; domain &#61; string&#10; id &#61; number&#10; customer_id &#61; string&#10;&#125;&#41;">object&#40;&#123;&#8230;&#125;&#41;</code> | ✓ | | <code>0-bootstrap</code> |
| [prefix](variables.tf#L118) | Prefix used for resources that need unique names. Use 9 characters or less. | <code>string</code> | ✓ | | <code>0-bootstrap</code> | | [prefix](variables.tf#L101) | Prefix used for resources that need unique names. Use 9 characters or less. | <code>string</code> | ✓ | | <code>0-bootstrap</code> |
| [custom_adv](variables.tf#L38) | Custom advertisement definitions in name => range format. | <code>map&#40;string&#41;</code> | | <code title="&#123;&#10; cloud_dns &#61; &#34;35.199.192.0&#47;19&#34;&#10; gcp_all &#61; &#34;10.128.0.0&#47;16&#34;&#10; gcp_dev &#61; &#34;10.128.32.0&#47;19&#34;&#10; gcp_landing &#61; &#34;10.128.0.0&#47;19&#34;&#10; gcp_prod &#61; &#34;10.128.64.0&#47;19&#34;&#10; googleapis_private &#61; &#34;199.36.153.8&#47;30&#34;&#10; googleapis_restricted &#61; &#34;199.36.153.4&#47;30&#34;&#10; rfc_1918_10 &#61; &#34;10.0.0.0&#47;8&#34;&#10; rfc_1918_172 &#61; &#34;172.16.0.0&#47;12&#34;&#10; rfc_1918_192 &#61; &#34;192.168.0.0&#47;16&#34;&#10;&#125;">&#123;&#8230;&#125;</code> | | | [custom_roles](variables.tf#L38) | Custom roles defined at the org level, in key => id format. | <code title="object&#40;&#123;&#10; service_project_network_admin &#61; string&#10;&#125;&#41;">object&#40;&#123;&#8230;&#125;&#41;</code> | | <code>null</code> | <code>0-bootstrap</code> |
| [custom_roles](variables.tf#L55) | Custom roles defined at the org level, in key => id format. | <code title="object&#40;&#123;&#10; service_project_network_admin &#61; string&#10;&#125;&#41;">object&#40;&#123;&#8230;&#125;&#41;</code> | | <code>null</code> | <code>0-bootstrap</code> | | [dns](variables.tf#L47) | Onprem DNS resolvers. | <code>map&#40;list&#40;string&#41;&#41;</code> | | <code title="&#123;&#10; onprem &#61; &#91;&#34;10.0.200.3&#34;&#93;&#10;&#125;">&#123;&#8230;&#125;</code> | |
| [dns](variables.tf#L64) | Onprem DNS resolvers. | <code>map&#40;list&#40;string&#41;&#41;</code> | | <code title="&#123;&#10; onprem &#61; &#91;&#34;10.0.200.3&#34;&#93;&#10;&#125;">&#123;&#8230;&#125;</code> | | | [factories_config](variables.tf#L55) | Configuration for network resource factories. | <code title="object&#40;&#123;&#10; data_dir &#61; optional&#40;string, &#34;data&#34;&#41;&#10; firewall_policy_name &#61; optional&#40;string, &#34;factory&#34;&#41;&#10;&#125;&#41;">object&#40;&#123;&#8230;&#125;&#41;</code> | | <code title="&#123;&#10; data_dir &#61; &#34;data&#34;&#10;&#125;">&#123;&#8230;&#125;</code> | |
| [factories_config](variables.tf#L72) | Configuration for network resource factories. | <code title="object&#40;&#123;&#10; data_dir &#61; optional&#40;string, &#34;data&#34;&#41;&#10; firewall_policy_name &#61; optional&#40;string, &#34;factory&#34;&#41;&#10;&#125;&#41;">object&#40;&#123;&#8230;&#125;&#41;</code> | | <code title="&#123;&#10; data_dir &#61; &#34;data&#34;&#10;&#125;">&#123;&#8230;&#125;</code> | | | [outputs_location](variables.tf#L95) | Path where providers and tfvars files for the following stages are written. Leave empty to disable. | <code>string</code> | | <code>null</code> | |
| [outputs_location](variables.tf#L112) | Path where providers and tfvars files for the following stages are written. Leave empty to disable. | <code>string</code> | | <code>null</code> | | | [psa_ranges](variables.tf#L112) | IP ranges used for Private Service Access (CloudSQL, etc.). | <code title="object&#40;&#123;&#10; dev &#61; object&#40;&#123;&#10; ranges &#61; map&#40;string&#41;&#10; routes &#61; object&#40;&#123;&#10; export &#61; bool&#10; import &#61; bool&#10; &#125;&#41;&#10; &#125;&#41;&#10; prod &#61; object&#40;&#123;&#10; ranges &#61; map&#40;string&#41;&#10; routes &#61; object&#40;&#123;&#10; export &#61; bool&#10; import &#61; bool&#10; &#125;&#41;&#10; &#125;&#41;&#10;&#125;&#41;">object&#40;&#123;&#8230;&#125;&#41;</code> | | <code>null</code> | |
| [psa_ranges](variables.tf#L129) | IP ranges used for Private Service Access (e.g. CloudSQL). | <code title="object&#40;&#123;&#10; dev &#61; object&#40;&#123;&#10; ranges &#61; map&#40;string&#41;&#10; routes &#61; object&#40;&#123;&#10; export &#61; bool&#10; import &#61; bool&#10; &#125;&#41;&#10; &#125;&#41;&#10; prod &#61; object&#40;&#123;&#10; ranges &#61; map&#40;string&#41;&#10; routes &#61; object&#40;&#123;&#10; export &#61; bool&#10; import &#61; bool&#10; &#125;&#41;&#10; &#125;&#41;&#10;&#125;&#41;">object&#40;&#123;&#8230;&#125;&#41;</code> | | <code>null</code> | | | [regions](variables.tf#L133) | Region definitions. | <code title="object&#40;&#123;&#10; primary &#61; string&#10; secondary &#61; string&#10;&#125;&#41;">object&#40;&#123;&#8230;&#125;&#41;</code> | | <code title="&#123;&#10; primary &#61; &#34;europe-west1&#34;&#10; secondary &#61; &#34;europe-west4&#34;&#10;&#125;">&#123;&#8230;&#125;</code> | |
| [regions](variables.tf#L166) | Region definitions. | <code title="object&#40;&#123;&#10; primary &#61; string&#10; secondary &#61; string&#10;&#125;&#41;">object&#40;&#123;&#8230;&#125;&#41;</code> | | <code title="&#123;&#10; primary &#61; &#34;europe-west1&#34;&#10; secondary &#61; &#34;europe-west4&#34;&#10;&#125;">&#123;&#8230;&#125;</code> | | | [service_accounts](variables.tf#L145) | Automation service accounts in name => email format. | <code title="object&#40;&#123;&#10; data-platform-dev &#61; string&#10; data-platform-prod &#61; string&#10; gke-dev &#61; string&#10; gke-prod &#61; string&#10; project-factory-dev &#61; string&#10; project-factory-prod &#61; string&#10;&#125;&#41;">object&#40;&#123;&#8230;&#125;&#41;</code> | | <code>null</code> | <code>1-resman</code> |
| [router_onprem_configs](variables.tf#L178) | Configurations for routers used for onprem connectivity. | <code title="map&#40;object&#40;&#123;&#10; adv &#61; object&#40;&#123;&#10; custom &#61; list&#40;string&#41;&#10; default &#61; bool&#10; &#125;&#41;&#10; asn &#61; number&#10;&#125;&#41;&#41;">map&#40;object&#40;&#123;&#8230;&#125;&#41;&#41;</code> | | <code title="&#123;&#10; landing-primary &#61; &#123;&#10; asn &#61; &#34;65533&#34;&#10; adv &#61; null&#10; &#125;&#10;&#125;">&#123;&#8230;&#125;</code> | | | [vpn_configs](variables-vpn.tf#L17) | Hub to spokes VPN configurations. | <code title="object&#40;&#123;&#10; dev &#61; object&#40;&#123;&#10; asn &#61; number&#10; custom_advertise &#61; optional&#40;object&#40;&#123;&#10; all_subnets &#61; bool&#10; ip_ranges &#61; map&#40;string&#41;&#10; &#125;&#41;&#41;&#10; &#125;&#41;&#10; landing &#61; object&#40;&#123;&#10; asn &#61; number&#10; custom_advertise &#61; optional&#40;object&#40;&#123;&#10; all_subnets &#61; bool&#10; ip_ranges &#61; map&#40;string&#41;&#10; &#125;&#41;&#41;&#10; &#125;&#41;&#10; prod &#61; object&#40;&#123;&#10; asn &#61; number&#10; custom_advertise &#61; optional&#40;object&#40;&#123;&#10; all_subnets &#61; bool&#10; ip_ranges &#61; map&#40;string&#41;&#10; &#125;&#41;&#41;&#10; &#125;&#41;&#10;&#125;&#41;">object&#40;&#123;&#8230;&#125;&#41;</code> | | <code title="&#123;&#10; dev &#61; &#123;&#10; asn &#61; 65501&#10; &#125;&#10; landing &#61; &#123;&#10; asn &#61; 65500&#10; &#125;&#10; prod &#61; &#123;&#10; asn &#61; 65502&#10; &#125;&#10;&#125;">&#123;&#8230;&#125;</code> | |
| [router_spoke_configs](variables-vpn.tf#L18) | Configurations for routers used for internal connectivity. | <code title="map&#40;object&#40;&#123;&#10; adv &#61; object&#40;&#123;&#10; custom &#61; list&#40;string&#41;&#10; default &#61; bool&#10; &#125;&#41;&#10; asn &#61; number&#10;&#125;&#41;&#41;">map&#40;object&#40;&#123;&#8230;&#125;&#41;&#41;</code> | | <code title="&#123;&#10; landing-primary &#61; &#123; asn &#61; &#34;64512&#34;, adv &#61; null &#125;&#10; landing-secondary &#61; &#123; asn &#61; &#34;64512&#34;, adv &#61; null &#125;&#10; spoke-dev-primary &#61; &#123; asn &#61; &#34;64513&#34;, adv &#61; null &#125;&#10; spoke-dev-secondary &#61; &#123; asn &#61; &#34;64513&#34;, adv &#61; null &#125;&#10; spoke-prod-primary &#61; &#123; asn &#61; &#34;64514&#34;, adv &#61; null &#125;&#10; spoke-prod-secondary &#61; &#123; asn &#61; &#34;64514&#34;, adv &#61; null &#125;&#10;&#125;">&#123;&#8230;&#125;</code> | | | [vpn_onprem_primary_config](variables.tf#L159) | VPN gateway configuration for onprem interconnection in the primary region. | <code title="object&#40;&#123;&#10; peer_external_gateways &#61; map&#40;object&#40;&#123;&#10; redundancy_type &#61; string&#10; interfaces &#61; list&#40;string&#41;&#10; &#125;&#41;&#41;&#10; router_config &#61; object&#40;&#123;&#10; create &#61; optional&#40;bool, true&#41;&#10; asn &#61; number&#10; name &#61; optional&#40;string&#41;&#10; keepalive &#61; optional&#40;number&#41;&#10; custom_advertise &#61; optional&#40;object&#40;&#123;&#10; all_subnets &#61; bool&#10; ip_ranges &#61; map&#40;string&#41;&#10; &#125;&#41;&#41;&#10; &#125;&#41;&#10; tunnels &#61; map&#40;object&#40;&#123;&#10; bgp_peer &#61; object&#40;&#123;&#10; address &#61; string&#10; asn &#61; number&#10; route_priority &#61; optional&#40;number, 1000&#41;&#10; custom_advertise &#61; optional&#40;object&#40;&#123;&#10; all_subnets &#61; bool&#10; all_vpc_subnets &#61; bool&#10; all_peer_vpc_subnets &#61; bool&#10; ip_ranges &#61; map&#40;string&#41;&#10; &#125;&#41;&#41;&#10; &#125;&#41;&#10; bgp_session_range &#61; string&#10; ike_version &#61; optional&#40;number, 2&#41;&#10; peer_external_gateway_interface &#61; optional&#40;number&#41;&#10; peer_gateway &#61; optional&#40;string, &#34;default&#34;&#41;&#10; router &#61; optional&#40;string&#41;&#10; shared_secret &#61; optional&#40;string&#41;&#10; vpn_gateway_interface &#61; number&#10; &#125;&#41;&#41;&#10;&#125;&#41;">object&#40;&#123;&#8230;&#125;&#41;</code> | | <code>null</code> | |
| [service_accounts](variables.tf#L196) | Automation service accounts in name => email format. | <code title="object&#40;&#123;&#10; data-platform-dev &#61; string&#10; data-platform-prod &#61; string&#10; gke-dev &#61; string&#10; gke-prod &#61; string&#10; project-factory-dev &#61; string&#10; project-factory-prod &#61; string&#10;&#125;&#41;">object&#40;&#123;&#8230;&#125;&#41;</code> | | <code>null</code> | <code>1-resman</code> |
| [vpn_onprem_configs](variables.tf#L210) | VPN gateway configuration for onprem interconnection. | <code title="map&#40;object&#40;&#123;&#10; adv &#61; object&#40;&#123;&#10; default &#61; bool&#10; custom &#61; list&#40;string&#41;&#10; &#125;&#41;&#10; peer_external_gateway &#61; object&#40;&#123;&#10; redundancy_type &#61; string&#10; interfaces &#61; list&#40;string&#41;&#10; &#125;&#41;&#10; tunnels &#61; list&#40;object&#40;&#123;&#10; peer_asn &#61; number&#10; peer_external_gateway_interface &#61; number&#10; secret &#61; string&#10; session_range &#61; string&#10; vpn_gateway_interface &#61; number&#10; &#125;&#41;&#41;&#10;&#125;&#41;&#41;">map&#40;object&#40;&#123;&#8230;&#125;&#41;&#41;</code> | | <code title="&#123;&#10; landing-primary &#61; &#123;&#10; adv &#61; &#123;&#10; default &#61; false&#10; custom &#61; &#91;&#10; &#34;cloud_dns&#34;, &#34;googleapis_private&#34;, &#34;googleapis_restricted&#34;, &#34;gcp_all&#34;&#10; &#93;&#10; &#125;&#10; peer_external_gateway &#61; &#123;&#10; redundancy_type &#61; &#34;SINGLE_IP_INTERNALLY_REDUNDANT&#34;&#10; interfaces &#61; &#91;&#34;8.8.8.8&#34;&#93;&#10; &#125;&#10; tunnels &#61; &#91;&#10; &#123;&#10; peer_asn &#61; 65534&#10; peer_external_gateway_interface &#61; 0&#10; secret &#61; &#34;foobar&#34;&#10; session_range &#61; &#34;169.254.1.0&#47;30&#34;&#10; vpn_gateway_interface &#61; 0&#10; &#125;,&#10; &#123;&#10; peer_asn &#61; 65534&#10; peer_external_gateway_interface &#61; 0&#10; secret &#61; &#34;foobar&#34;&#10; session_range &#61; &#34;169.254.1.4&#47;30&#34;&#10; vpn_gateway_interface &#61; 1&#10; &#125;&#10; &#93;&#10; &#125;&#10;&#125;">&#123;&#8230;&#125;</code> | |
| [vpn_spoke_configs](variables-vpn.tf#L37) | VPN gateway configuration for spokes. | <code title="map&#40;object&#40;&#123;&#10; default &#61; bool&#10; custom &#61; list&#40;string&#41;&#10;&#125;&#41;&#41;">map&#40;object&#40;&#123;&#8230;&#125;&#41;&#41;</code> | | <code title="&#123;&#10; landing-primary &#61; &#123;&#10; default &#61; false&#10; custom &#61; &#91;&#34;rfc_1918_10&#34;, &#34;rfc_1918_172&#34;, &#34;rfc_1918_192&#34;&#93;&#10; &#125;&#10; landing-secondary &#61; &#123;&#10; default &#61; false&#10; custom &#61; &#91;&#34;rfc_1918_10&#34;, &#34;rfc_1918_172&#34;, &#34;rfc_1918_192&#34;&#93;&#10; &#125;&#10; dev-primary &#61; &#123;&#10; default &#61; false&#10; custom &#61; &#91;&#34;gcp_dev&#34;&#93;&#10; &#125;&#10; prod-primary &#61; &#123;&#10; default &#61; false&#10; custom &#61; &#91;&#34;gcp_prod&#34;&#93;&#10; &#125;&#10; prod-secondary &#61; &#123;&#10; default &#61; false&#10; custom &#61; &#91;&#34;gcp_prod&#34;&#93;&#10; &#125;&#10;&#125;">&#123;&#8230;&#125;</code> | |
## Outputs ## Outputs

View File

@ -88,7 +88,7 @@ output "tfvars" {
output "vpn_gateway_endpoints" { output "vpn_gateway_endpoints" {
description = "External IP Addresses for the GCP VPN gateways." 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 = { onprem-primary = {
for v in module.landing-to-onprem-primary-vpn[0].gateway.vpn_interfaces : for v in module.landing-to-onprem-primary-vpn[0].gateway.vpn_interfaces :
v.id => v.ip_address v.id => v.ip_address

View File

@ -14,52 +14,40 @@
* limitations under the License. * limitations under the License.
*/ */
variable "vpn_configs" {
variable "router_spoke_configs" { description = "Hub to spokes VPN configurations."
description = "Configurations for routers used for internal connectivity." type = object({
type = map(object({ dev = object({
adv = object({ asn = number
custom = list(string) custom_advertise = optional(object({
default = bool 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 = { default = {
landing-primary = { asn = "64512", adv = null } dev = {
landing-secondary = { asn = "64512", adv = null } asn = 65501
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"]
} }
landing-secondary = { landing = {
default = false asn = 65500
custom = ["rfc_1918_10", "rfc_1918_172", "rfc_1918_192"]
} }
dev-primary = { prod = {
default = false asn = 65502
custom = ["gcp_dev"]
}
prod-primary = {
default = false
custom = ["gcp_prod"]
}
prod-secondary = {
default = false
custom = ["gcp_prod"]
} }
} }
} }

View File

@ -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" { variable "custom_roles" {
# tfdoc:variable:source 0-bootstrap # tfdoc:variable:source 0-bootstrap
description = "Custom roles defined at the org level, in key => id format." description = "Custom roles defined at the org level, in key => id format."
@ -127,7 +110,7 @@ variable "prefix" {
} }
variable "psa_ranges" { 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({ type = object({
dev = object({ dev = object({
ranges = map(string) ranges = map(string)
@ -145,22 +128,6 @@ variable "psa_ranges" {
}) })
}) })
default = null 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" { 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" { variable "service_accounts" {
# tfdoc:variable:source 1-resman # tfdoc:variable:source 1-resman
description = "Automation service accounts in name => email format." description = "Automation service accounts in name => email format."
@ -207,53 +156,45 @@ variable "service_accounts" {
default = null default = null
} }
variable "vpn_onprem_configs" { variable "vpn_onprem_primary_config" {
description = "VPN gateway configuration for onprem interconnection." description = "VPN gateway configuration for onprem interconnection in the primary region."
type = map(object({ type = object({
adv = object({ peer_external_gateways = map(object({
default = bool
custom = list(string)
})
peer_external_gateway = object({
redundancy_type = string redundancy_type = string
interfaces = list(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({ tunnels = map(object({
peer_asn = number bgp_peer = object({
peer_external_gateway_interface = number address = string
secret = string asn = number
session_range = string 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 vpn_gateway_interface = number
})) }))
})) })
default = { default = null
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
}
]
}
}
} }

View File

@ -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
}
}
}

View File

@ -17,54 +17,21 @@
# tfdoc:file:description VPN between landing and onprem. # tfdoc:file:description VPN between landing and onprem.
locals { locals {
enable_onprem_vpn = var.vpn_onprem_configs != null onprem_peer_gateways = try(
bgp_peer_options_onprem = local.enable_onprem_vpn == false ? null : { var.vpn_onprem_primary_config.peer_external_gateways, {}
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
} }
module "landing-to-onprem-primary-vpn" { module "landing-to-onprem-primary-vpn" {
count = local.enable_onprem_vpn ? 1 : 0 count = var.vpn_onprem_primary_config == null ? 0 : 1
source = "../../../modules/net-vpn-ha" source = "../../../modules/net-vpn-ha"
project_id = module.landing-project.project_id project_id = module.landing-project.project_id
network = module.landing-vpc.self_link network = module.landing-vpc.self_link
region = var.regions.primary region = var.regions.primary
name = "vpn-to-onprem-${local.region_shortnames[var.regions.primary]}" name = "vpn-to-onprem-${local.region_shortnames[var.regions.primary]}"
router_config = { router_config = try(var.vpn_onprem_primary_config.router_config, {})
name = "landing-onprem-vpn-${local.region_shortnames[var.regions.primary]}"
asn = var.router_onprem_configs.landing-primary.asn
}
peer_gateways = { peer_gateways = {
default = { for k, v in local.onprem_peer_gateways : k => { external = v }
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
}
} }
tunnels = try(var.vpn_onprem_primary_config.tunnels, {})
} }

View File

@ -16,113 +16,34 @@
# tfdoc:file:description VPN between landing and development spoke. # 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" { module "dev-to-landing-primary-vpn" {
source = "../../../modules/net-vpn-ha" source = "../../../modules/net-vpn-ha"
project_id = module.dev-spoke-project.project_id project_id = module.dev-spoke-project.project_id
network = module.dev-spoke-vpc.self_link network = module.dev-spoke-vpc.self_link
region = var.regions.primary region = var.regions.primary
name = "vpn-to-landing-${local.region_shortnames[var.regions.primary]}" name = "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
}
peer_gateways = { 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 = { tunnels = {
0 = { 0 = {
bgp_peer = { bgp_peer = {
address = cidrhost("169.254.0.0/27", 2) address = cidrhost(local.bgp_session_ranges.dev-primary.0, 1)
asn = var.router_spoke_configs.landing-primary.asn asn = var.vpn_configs.landing.asn
} }
bgp_peer_options = local.vpn_spoke_bgp_peer_options.dev-primary bgp_session_range = "${cidrhost(local.bgp_session_ranges.dev-primary.0, 2)}/30"
bgp_session_range = "${
cidrhost("169.254.0.0/27", 1)
}/30"
shared_secret = module.landing-to-dev-primary-vpn.random_secret
vpn_gateway_interface = 0 vpn_gateway_interface = 0
} }
1 = { 1 = {
bgp_peer = { bgp_peer = {
address = cidrhost("169.254.0.0/27", 6) address = cidrhost(local.bgp_session_ranges.dev-primary.1, 1)
asn = var.router_spoke_configs.landing-primary.asn asn = var.vpn_configs.landing.asn
} }
bgp_peer_options = local.vpn_spoke_bgp_peer_options.dev-primary bgp_session_range = "${cidrhost(local.bgp_session_ranges.dev-primary.1, 2)}/30"
bgp_session_range = "${
cidrhost("169.254.0.0/27", 5)
}/30"
shared_secret = module.landing-to-dev-primary-vpn.random_secret
vpn_gateway_interface = 1 vpn_gateway_interface = 1
} }
} }

View File

@ -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
}
}
}

View File

@ -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
}
}
}

View File

@ -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
}
}
}

View File

@ -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) - [Post-deployment activities](#post-deployment-activities)
- [Customizations](#customizations) - [Customizations](#customizations)
- [Changing default regions](#changing-default-regions) - [Changing default regions](#changing-default-regions)
- [Configuring the VPNs to on prem](#configuring-the-vpns-to-on-prem)
- [Adding an environment](#adding-an-environment) - [Adding an environment](#adding-an-environment)
## Design overview and choices ## Design overview and choices
@ -235,7 +236,7 @@ Subnets for [L7 ILBs](https://cloud.google.com/load-balancing/docs/l7-internal/p
### VPNs ### 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 ### 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 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 - 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 ### Adding an environment
To create a new environment (e.g. `staging`), a few changes are required: 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". 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. 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`). 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`).
>`custom_adv` is a map that "resolves" CIDR names to the actual addresses, and will be used later to configure routing. >`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. 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. | <code title="object&#40;&#123;&#10; outputs_bucket &#61; string&#10;&#125;&#41;">object&#40;&#123;&#8230;&#125;&#41;</code> | ✓ | | <code>0-bootstrap</code> | | [automation](variables.tf#L17) | Automation resources created by the bootstrap stage. | <code title="object&#40;&#123;&#10; outputs_bucket &#61; string&#10;&#125;&#41;">object&#40;&#123;&#8230;&#125;&#41;</code> | ✓ | | <code>0-bootstrap</code> |
| [billing_account](variables.tf#L25) | Billing account id. If billing account is not part of the same org set `is_org_level` to false. | <code title="object&#40;&#123;&#10; id &#61; string&#10; is_org_level &#61; optional&#40;bool, true&#41;&#10;&#125;&#41;">object&#40;&#123;&#8230;&#125;&#41;</code> | ✓ | | <code>0-bootstrap</code> | | [billing_account](variables.tf#L25) | Billing account id. If billing account is not part of the same org set `is_org_level` to false. | <code title="object&#40;&#123;&#10; id &#61; string&#10; is_org_level &#61; optional&#40;bool, true&#41;&#10;&#125;&#41;">object&#40;&#123;&#8230;&#125;&#41;</code> | ✓ | | <code>0-bootstrap</code> |
| [folder_ids](variables.tf#L97) | Folders to be used for the networking resources in folders/nnnnnnnnnnn format. If null, folder will be created. | <code title="object&#40;&#123;&#10; networking &#61; string&#10; networking-dev &#61; string&#10; networking-prod &#61; string&#10;&#125;&#41;">object&#40;&#123;&#8230;&#125;&#41;</code> | ✓ | | <code>1-resman</code> | | [folder_ids](variables.tf#L75) | Folders to be used for the networking resources in folders/nnnnnnnnnnn format. If null, folder will be created. | <code title="object&#40;&#123;&#10; networking &#61; string&#10; networking-dev &#61; string&#10; networking-prod &#61; string&#10;&#125;&#41;">object&#40;&#123;&#8230;&#125;&#41;</code> | ✓ | | <code>1-resman</code> |
| [organization](variables.tf#L115) | Organization details. | <code title="object&#40;&#123;&#10; domain &#61; string&#10; id &#61; number&#10; customer_id &#61; string&#10;&#125;&#41;">object&#40;&#123;&#8230;&#125;&#41;</code> | ✓ | | <code>0-bootstrap</code> | | [organization](variables.tf#L108) | Organization details. | <code title="object&#40;&#123;&#10; domain &#61; string&#10; id &#61; number&#10; customer_id &#61; string&#10;&#125;&#41;">object&#40;&#123;&#8230;&#125;&#41;</code> | ✓ | | <code>0-bootstrap</code> |
| [prefix](variables.tf#L131) | Prefix used for resources that need unique names. Use 9 characters or less. | <code>string</code> | ✓ | | <code>0-bootstrap</code> | | [prefix](variables.tf#L124) | Prefix used for resources that need unique names. Use 9 characters or less. | <code>string</code> | ✓ | | <code>0-bootstrap</code> |
| [custom_adv](variables.tf#L38) | Custom advertisement definitions in name => range format. | <code>map&#40;string&#41;</code> | | <code title="&#123;&#10; cloud_dns &#61; &#34;35.199.192.0&#47;19&#34;&#10; gcp_all &#61; &#34;10.128.0.0&#47;16&#34;&#10; gcp_dev_primary &#61; &#34;10.128.128.0&#47;19&#34;&#10; gcp_dev_secondary &#61; &#34;10.128.160.0&#47;19&#34;&#10; gcp_landing_trusted_primary &#61; &#34;10.128.64.0&#47;19&#34;&#10; gcp_landing_trusted_secondary &#61; &#34;10.128.96.0&#47;19&#34;&#10; gcp_landing_untrusted_primary &#61; &#34;10.128.0.0&#47;19&#34;&#10; gcp_landing_untrusted_secondary &#61; &#34;10.128.32.0&#47;19&#34;&#10; gcp_prod_primary &#61; &#34;10.128.192.0&#47;19&#34;&#10; gcp_prod_secondary &#61; &#34;10.128.224.0&#47;19&#34;&#10; googleapis_private &#61; &#34;199.36.153.8&#47;30&#34;&#10; googleapis_restricted &#61; &#34;199.36.153.4&#47;30&#34;&#10; rfc_1918_10 &#61; &#34;10.0.0.0&#47;8&#34;&#10; rfc_1918_172 &#61; &#34;172.16.0.0&#47;12&#34;&#10; rfc_1918_192 &#61; &#34;192.168.0.0&#47;16&#34;&#10;&#125;">&#123;&#8230;&#125;</code> | | | [custom_roles](variables.tf#L38) | Custom roles defined at the org level, in key => id format. | <code title="object&#40;&#123;&#10; service_project_network_admin &#61; string&#10;&#125;&#41;">object&#40;&#123;&#8230;&#125;&#41;</code> | | <code>null</code> | <code>0-bootstrap</code> |
| [custom_roles](variables.tf#L60) | Custom roles defined at the org level, in key => id format. | <code title="object&#40;&#123;&#10; service_project_network_admin &#61; string&#10;&#125;&#41;">object&#40;&#123;&#8230;&#125;&#41;</code> | | <code>null</code> | <code>0-bootstrap</code> | | [dns](variables.tf#L47) | Onprem DNS resolvers. | <code>map&#40;list&#40;string&#41;&#41;</code> | | <code title="&#123;&#10; onprem &#61; &#91;&#34;10.0.200.3&#34;&#93;&#10;&#125;">&#123;&#8230;&#125;</code> | |
| [dns](variables.tf#L69) | Onprem DNS resolvers. | <code>map&#40;list&#40;string&#41;&#41;</code> | | <code title="&#123;&#10; onprem &#61; &#91;&#34;10.0.200.3&#34;&#93;&#10;&#125;">&#123;&#8230;&#125;</code> | | | [factories_config](variables.tf#L55) | Configuration for network resource factories. | <code title="object&#40;&#123;&#10; data_dir &#61; optional&#40;string, &#34;data&#34;&#41;&#10; firewall_policy_name &#61; optional&#40;string, &#34;factory&#34;&#41;&#10;&#125;&#41;">object&#40;&#123;&#8230;&#125;&#41;</code> | | <code title="&#123;&#10; data_dir &#61; &#34;data&#34;&#10;&#125;">&#123;&#8230;&#125;</code> | |
| [factories_config](variables.tf#L77) | Configuration for network resource factories. | <code title="object&#40;&#123;&#10; data_dir &#61; optional&#40;string, &#34;data&#34;&#41;&#10; firewall_policy_name &#61; optional&#40;string, &#34;factory&#34;&#41;&#10;&#125;&#41;">object&#40;&#123;&#8230;&#125;&#41;</code> | | <code title="&#123;&#10; data_dir &#61; &#34;data&#34;&#10;&#125;">&#123;&#8230;&#125;</code> | | | [gcp_ranges](variables.tf#L85) | GCP address ranges in name => range format. | <code>map&#40;string&#41;</code> | | <code title="&#123;&#10; gcp_dev_primary &#61; &#34;10.128.128.0&#47;19&#34;&#10; gcp_dev_secondary &#61; &#34;10.128.160.0&#47;19&#34;&#10; gcp_landing_trusted_primary &#61; &#34;10.128.64.0&#47;19&#34;&#10; gcp_landing_trusted_secondary &#61; &#34;10.128.96.0&#47;19&#34;&#10; gcp_landing_untrusted_primary &#61; &#34;10.128.0.0&#47;19&#34;&#10; gcp_landing_untrusted_secondary &#61; &#34;10.128.32.0&#47;19&#34;&#10; gcp_prod_primary &#61; &#34;10.128.192.0&#47;19&#34;&#10; gcp_prod_secondary &#61; &#34;10.128.224.0&#47;19&#34;&#10;&#125;">&#123;&#8230;&#125;</code> | |
| [onprem_cidr](variables.tf#L107) | Onprem addresses in name => range format. | <code>map&#40;string&#41;</code> | | <code title="&#123;&#10; main &#61; &#34;10.0.0.0&#47;24&#34;&#10;&#125;">&#123;&#8230;&#125;</code> | | | [onprem_cidr](variables.tf#L100) | Onprem addresses in name => range format. | <code>map&#40;string&#41;</code> | | <code title="&#123;&#10; main &#61; &#34;10.0.0.0&#47;24&#34;&#10;&#125;">&#123;&#8230;&#125;</code> | |
| [outputs_location](variables.tf#L125) | Path where providers and tfvars files for the following stages are written. Leave empty to disable. | <code>string</code> | | <code>null</code> | | | [outputs_location](variables.tf#L118) | Path where providers and tfvars files for the following stages are written. Leave empty to disable. | <code>string</code> | | <code>null</code> | |
| [psa_ranges](variables.tf#L142) | IP ranges used for Private Service Access (e.g. CloudSQL). Ranges is in name => range format. | <code title="object&#40;&#123;&#10; dev &#61; object&#40;&#123;&#10; ranges &#61; map&#40;string&#41;&#10; routes &#61; object&#40;&#123;&#10; export &#61; bool&#10; import &#61; bool&#10; &#125;&#41;&#10; &#125;&#41;&#10; prod &#61; object&#40;&#123;&#10; ranges &#61; map&#40;string&#41;&#10; routes &#61; object&#40;&#123;&#10; export &#61; bool&#10; import &#61; bool&#10; &#125;&#41;&#10; &#125;&#41;&#10;&#125;&#41;">object&#40;&#123;&#8230;&#125;&#41;</code> | | <code>null</code> | | | [psa_ranges](variables.tf#L135) | IP ranges used for Private Service Access (e.g. CloudSQL). Ranges is in name => range format. | <code title="object&#40;&#123;&#10; dev &#61; object&#40;&#123;&#10; ranges &#61; map&#40;string&#41;&#10; routes &#61; object&#40;&#123;&#10; export &#61; bool&#10; import &#61; bool&#10; &#125;&#41;&#10; &#125;&#41;&#10; prod &#61; object&#40;&#123;&#10; ranges &#61; map&#40;string&#41;&#10; routes &#61; object&#40;&#123;&#10; export &#61; bool&#10; import &#61; bool&#10; &#125;&#41;&#10; &#125;&#41;&#10;&#125;&#41;">object&#40;&#123;&#8230;&#125;&#41;</code> | | <code>null</code> | |
| [regions](variables.tf#L163) | Region definitions. | <code title="object&#40;&#123;&#10; primary &#61; string&#10; secondary &#61; string&#10;&#125;&#41;">object&#40;&#123;&#8230;&#125;&#41;</code> | | <code title="&#123;&#10; primary &#61; &#34;europe-west1&#34;&#10; secondary &#61; &#34;europe-west4&#34;&#10;&#125;">&#123;&#8230;&#125;</code> | | | [regions](variables.tf#L156) | Region definitions. | <code title="object&#40;&#123;&#10; primary &#61; string&#10; secondary &#61; string&#10;&#125;&#41;">object&#40;&#123;&#8230;&#125;&#41;</code> | | <code title="&#123;&#10; primary &#61; &#34;europe-west1&#34;&#10; secondary &#61; &#34;europe-west4&#34;&#10;&#125;">&#123;&#8230;&#125;</code> | |
| [router_configs](variables.tf#L175) | Configurations for CRs and onprem routers. | <code title="map&#40;object&#40;&#123;&#10; adv &#61; object&#40;&#123;&#10; custom &#61; list&#40;string&#41;&#10; default &#61; bool&#10; &#125;&#41;&#10; asn &#61; number&#10;&#125;&#41;&#41;">map&#40;object&#40;&#123;&#8230;&#125;&#41;&#41;</code> | | <code title="&#123;&#10; landing-trusted-primary &#61; &#123;&#10; asn &#61; &#34;64512&#34;&#10; adv &#61; null&#10; &#125;&#10; landing-trusted-secondary &#61; &#123;&#10; asn &#61; &#34;64512&#34;&#10; adv &#61; null&#10; &#125;&#10;&#125;">&#123;&#8230;&#125;</code> | | | [service_accounts](variables.tf#L168) | Automation service accounts in name => email format. | <code title="object&#40;&#123;&#10; data-platform-dev &#61; string&#10; data-platform-prod &#61; string&#10; gke-dev &#61; string&#10; gke-prod &#61; string&#10; project-factory-dev &#61; string&#10; project-factory-prod &#61; string&#10;&#125;&#41;">object&#40;&#123;&#8230;&#125;&#41;</code> | | <code>null</code> | <code>1-resman</code> |
| [service_accounts](variables.tf#L198) | Automation service accounts in name => email format. | <code title="object&#40;&#123;&#10; data-platform-dev &#61; string&#10; data-platform-prod &#61; string&#10; gke-dev &#61; string&#10; gke-prod &#61; string&#10; project-factory-dev &#61; string&#10; project-factory-prod &#61; string&#10;&#125;&#41;">object&#40;&#123;&#8230;&#125;&#41;</code> | | <code>null</code> | <code>1-resman</code> | | [vpn_onprem_primary_config](variables.tf#L182) | VPN gateway configuration for onprem interconnection in the primary region. | <code title="object&#40;&#123;&#10; peer_external_gateways &#61; map&#40;object&#40;&#123;&#10; redundancy_type &#61; string&#10; interfaces &#61; list&#40;string&#41;&#10; &#125;&#41;&#41;&#10; router_config &#61; object&#40;&#123;&#10; create &#61; optional&#40;bool, true&#41;&#10; asn &#61; number&#10; name &#61; optional&#40;string&#41;&#10; keepalive &#61; optional&#40;number&#41;&#10; custom_advertise &#61; optional&#40;object&#40;&#123;&#10; all_subnets &#61; bool&#10; ip_ranges &#61; map&#40;string&#41;&#10; &#125;&#41;&#41;&#10; &#125;&#41;&#10; tunnels &#61; map&#40;object&#40;&#123;&#10; bgp_peer &#61; object&#40;&#123;&#10; address &#61; string&#10; asn &#61; number&#10; route_priority &#61; optional&#40;number, 1000&#41;&#10; custom_advertise &#61; optional&#40;object&#40;&#123;&#10; all_subnets &#61; bool&#10; all_vpc_subnets &#61; bool&#10; all_peer_vpc_subnets &#61; bool&#10; ip_ranges &#61; map&#40;string&#41;&#10; &#125;&#41;&#41;&#10; &#125;&#41;&#10; bgp_session_range &#61; string&#10; ike_version &#61; optional&#40;number, 2&#41;&#10; peer_external_gateway_interface &#61; optional&#40;number&#41;&#10; peer_gateway &#61; optional&#40;string, &#34;default&#34;&#41;&#10; router &#61; optional&#40;string&#41;&#10; shared_secret &#61; optional&#40;string&#41;&#10; vpn_gateway_interface &#61; number&#10; &#125;&#41;&#41;&#10;&#125;&#41;">object&#40;&#123;&#8230;&#125;&#41;</code> | | <code>null</code> | |
| [vpn_onprem_configs](variables.tf#L212) | VPN gateway configuration for onprem interconnection. | <code title="map&#40;object&#40;&#123;&#10; adv &#61; object&#40;&#123;&#10; default &#61; bool&#10; custom &#61; list&#40;string&#41;&#10; &#125;&#41;&#10; peer_external_gateway &#61; object&#40;&#123;&#10; redundancy_type &#61; string&#10; interfaces &#61; list&#40;string&#41;&#10; &#125;&#41;&#10; tunnels &#61; list&#40;object&#40;&#123;&#10; peer_asn &#61; number&#10; peer_external_gateway_interface &#61; number&#10; secret &#61; string&#10; session_range &#61; string&#10; vpn_gateway_interface &#61; number&#10; &#125;&#41;&#41;&#10;&#125;&#41;&#41;">map&#40;object&#40;&#123;&#8230;&#125;&#41;&#41;</code> | | <code title="&#123;&#10; landing-trusted-primary &#61; &#123;&#10; adv &#61; &#123;&#10; default &#61; false&#10; custom &#61; &#91;&#10; &#34;cloud_dns&#34;, &#34;googleapis_private&#34;, &#34;googleapis_restricted&#34;, &#34;gcp_all&#34;&#10; &#93;&#10; &#125;&#10; peer_external_gateway &#61; &#123;&#10; redundancy_type &#61; &#34;SINGLE_IP_INTERNALLY_REDUNDANT&#34;&#10; interfaces &#61; &#91;&#34;8.8.8.8&#34;&#93;&#10; &#125;&#10; tunnels &#61; &#91;&#10; &#123;&#10; peer_asn &#61; 65534&#10; peer_external_gateway_interface &#61; 0&#10; secret &#61; &#34;foobar&#34;&#10; session_range &#61; &#34;169.254.1.0&#47;30&#34;&#10; vpn_gateway_interface &#61; 0&#10; &#125;,&#10; &#123;&#10; peer_asn &#61; 65534&#10; peer_external_gateway_interface &#61; 0&#10; secret &#61; &#34;foobar&#34;&#10; session_range &#61; &#34;169.254.1.4&#47;30&#34;&#10; vpn_gateway_interface &#61; 1&#10; &#125;&#10; &#93;&#10; &#125;&#10; landing-trusted-secondary &#61; &#123;&#10; adv &#61; &#123;&#10; default &#61; false&#10; custom &#61; &#91;&#10; &#34;cloud_dns&#34;, &#34;googleapis_private&#34;, &#34;googleapis_restricted&#34;, &#34;gcp_all&#34;&#10; &#93;&#10; &#125;&#10; peer_external_gateway &#61; &#123;&#10; redundancy_type &#61; &#34;SINGLE_IP_INTERNALLY_REDUNDANT&#34;&#10; interfaces &#61; &#91;&#34;8.8.8.8&#34;&#93;&#10; &#125;&#10; tunnels &#61; &#91;&#10; &#123;&#10; peer_asn &#61; 65534&#10; peer_external_gateway_interface &#61; 0&#10; secret &#61; &#34;foobar&#34;&#10; session_range &#61; &#34;169.254.1.0&#47;30&#34;&#10; vpn_gateway_interface &#61; 0&#10; &#125;,&#10; &#123;&#10; peer_asn &#61; 65534&#10; peer_external_gateway_interface &#61; 0&#10; secret &#61; &#34;foobar&#34;&#10; session_range &#61; &#34;169.254.1.4&#47;30&#34;&#10; vpn_gateway_interface &#61; 1&#10; &#125;&#10; &#93;&#10; &#125;&#10;&#125;">&#123;&#8230;&#125;</code> | | | [vpn_onprem_secondary_config](variables.tf#L225) | VPN gateway configuration for onprem interconnection in the secondary region. | <code title="object&#40;&#123;&#10; peer_external_gateways &#61; map&#40;object&#40;&#123;&#10; redundancy_type &#61; string&#10; interfaces &#61; list&#40;string&#41;&#10; &#125;&#41;&#41;&#10; router_config &#61; object&#40;&#123;&#10; create &#61; optional&#40;bool, true&#41;&#10; asn &#61; number&#10; name &#61; optional&#40;string&#41;&#10; keepalive &#61; optional&#40;number&#41;&#10; custom_advertise &#61; optional&#40;object&#40;&#123;&#10; all_subnets &#61; bool&#10; ip_ranges &#61; map&#40;string&#41;&#10; &#125;&#41;&#41;&#10; &#125;&#41;&#10; tunnels &#61; map&#40;object&#40;&#123;&#10; bgp_peer &#61; object&#40;&#123;&#10; address &#61; string&#10; asn &#61; number&#10; route_priority &#61; optional&#40;number, 1000&#41;&#10; custom_advertise &#61; optional&#40;object&#40;&#123;&#10; all_subnets &#61; bool&#10; all_vpc_subnets &#61; bool&#10; all_peer_vpc_subnets &#61; bool&#10; ip_ranges &#61; map&#40;string&#41;&#10; &#125;&#41;&#41;&#10; &#125;&#41;&#10; bgp_session_range &#61; string&#10; ike_version &#61; optional&#40;number, 2&#41;&#10; peer_external_gateway_interface &#61; optional&#40;number&#41;&#10; peer_gateway &#61; optional&#40;string, &#34;default&#34;&#41;&#10; router &#61; optional&#40;string&#41;&#10; shared_secret &#61; optional&#40;string&#41;&#10; vpn_gateway_interface &#61; number&#10; &#125;&#41;&#41;&#10;&#125;&#41;">object&#40;&#123;&#8230;&#125;&#41;</code> | | <code>null</code> | |
## Outputs ## Outputs

View File

@ -21,19 +21,19 @@ locals {
{ {
name = "untrusted" name = "untrusted"
routes = [ routes = [
var.custom_adv.gcp_landing_untrusted_primary, var.gcp_ranges.gcp_landing_untrusted_primary,
var.custom_adv.gcp_landing_untrusted_secondary, var.gcp_ranges.gcp_landing_untrusted_secondary,
] ]
}, },
{ {
name = "trusted" name = "trusted"
routes = [ routes = [
var.custom_adv.gcp_dev_primary, var.gcp_ranges.gcp_dev_primary,
var.custom_adv.gcp_dev_secondary, var.gcp_ranges.gcp_dev_secondary,
var.custom_adv.gcp_landing_trusted_primary, var.gcp_ranges.gcp_landing_trusted_primary,
var.custom_adv.gcp_landing_trusted_secondary, var.gcp_ranges.gcp_landing_trusted_secondary,
var.custom_adv.gcp_prod_primary, var.gcp_ranges.gcp_prod_primary,
var.custom_adv.gcp_prod_secondary, var.gcp_ranges.gcp_prod_secondary,
] ]
}, },
] ]

View File

@ -78,13 +78,13 @@ output "tfvars" {
output "vpn_gateway_endpoints" { output "vpn_gateway_endpoints" {
description = "External IP Addresses for the GCP VPN gateways." description = "External IP Addresses for the GCP VPN gateways."
value = local.enable_onprem_vpn == false ? null : { value = {
onprem-primary = { onprem-primary = var.vpn_onprem_primary_config == null ? {} : {
for v in module.landing-to-onprem-primary-vpn[0].gateway.vpn_interfaces : for v in module.landing-to-onprem-primary-vpn.0.gateway.vpn_interfaces :
v.id => v.ip_address v.id => v.ip_address
} }
onprem-secondary = { onprem-secondary = var.vpn_onprem_secondary_config == null ? {} : {
for v in module.landing-to-onprem-secondary-vpn[0].gateway.vpn_interfaces : for v in module.landing-to-onprem-secondary-vpn.0.gateway.vpn_interfaces :
v.id => v.ip_address v.id => v.ip_address
} }
} }

View File

@ -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" { variable "custom_roles" {
# tfdoc:variable:source 0-bootstrap # tfdoc:variable:source 0-bootstrap
description = "Custom roles defined at the org level, in key => id format." 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" { variable "onprem_cidr" {
description = "Onprem addresses in name => range format." description = "Onprem addresses in name => range format."
type = map(string) 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" { variable "service_accounts" {
# tfdoc:variable:source 1-resman # tfdoc:variable:source 1-resman
description = "Automation service accounts in name => email format." description = "Automation service accounts in name => email format."
@ -209,81 +179,88 @@ variable "service_accounts" {
default = null default = null
} }
variable "vpn_onprem_configs" { variable "vpn_onprem_primary_config" {
description = "VPN gateway configuration for onprem interconnection." description = "VPN gateway configuration for onprem interconnection in the primary region."
type = map(object({ type = object({
adv = object({ peer_external_gateways = map(object({
default = bool
custom = list(string)
})
peer_external_gateway = object({
redundancy_type = string redundancy_type = string
interfaces = list(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({ tunnels = map(object({
peer_asn = number bgp_peer = object({
peer_external_gateway_interface = number address = string
secret = string asn = number
session_range = string 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 vpn_gateway_interface = number
})) }))
})) })
default = { default = null
landing-trusted-primary = { }
adv = {
default = false variable "vpn_onprem_secondary_config" {
custom = [ description = "VPN gateway configuration for onprem interconnection in the secondary region."
"cloud_dns", "googleapis_private", "googleapis_restricted", "gcp_all" type = object({
] peer_external_gateways = map(object({
} redundancy_type = string
peer_external_gateway = { interfaces = list(string)
redundancy_type = "SINGLE_IP_INTERNALLY_REDUNDANT" }))
interfaces = ["8.8.8.8"] router_config = object({
} create = optional(bool, true)
tunnels = [ asn = number
{ name = optional(string)
peer_asn = 65534 keepalive = optional(number)
peer_external_gateway_interface = 0 custom_advertise = optional(object({
secret = "foobar" all_subnets = bool
session_range = "169.254.1.0/30" ip_ranges = map(string)
vpn_gateway_interface = 0 }))
}, })
{ tunnels = map(object({
peer_asn = 65534 bgp_peer = object({
peer_external_gateway_interface = 0 address = string
secret = "foobar" asn = number
session_range = "169.254.1.4/30" route_priority = optional(number, 1000)
vpn_gateway_interface = 1 custom_advertise = optional(object({
} all_subnets = bool
] all_vpc_subnets = bool
} all_peer_vpc_subnets = bool
landing-trusted-secondary = { ip_ranges = map(string)
adv = { }))
default = false })
custom = [ # each BGP session on the same Cloud Router must use a unique /30 CIDR
"cloud_dns", "googleapis_private", "googleapis_restricted", "gcp_all" # from the 169.254.0.0/16 block.
] bgp_session_range = string
} ike_version = optional(number, 2)
peer_external_gateway = { peer_external_gateway_interface = optional(number)
redundancy_type = "SINGLE_IP_INTERNALLY_REDUNDANT" peer_gateway = optional(string, "default")
interfaces = ["8.8.8.8"] router = optional(string)
} shared_secret = optional(string)
tunnels = [ vpn_gateway_interface = number
{ }))
peer_asn = 65534 })
peer_external_gateway_interface = 0 default = null
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
}
]
}
}
} }

View File

@ -17,92 +17,40 @@
# tfdoc:file:description VPN between landing and onprem. # tfdoc:file:description VPN between landing and onprem.
locals { locals {
enable_onprem_vpn = var.vpn_onprem_configs != null onprem_peer_gateways = {
bgp_peer_options_onprem = local.enable_onprem_vpn == false ? null : { primary = try(
for k, v in var.vpn_onprem_configs : var.vpn_onprem_primary_config.peer_external_gateways, {}
k => v.adv == null ? null : { )
custom_advertise = try(v.adv.default, false) ? null : { secondary = try(
all_subnets = false var.vpn_onprem_secondary_config.peer_external_gateways, {}
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
}
} }
} }
moved {
from = module.landing-to-onprem-ew1-vpn
to = module.landing-to-onprem-primary-vpn
}
module "landing-to-onprem-primary-vpn" { module "landing-to-onprem-primary-vpn" {
count = local.enable_onprem_vpn ? 1 : 0 count = var.vpn_onprem_primary_config == null ? 0 : 1
source = "../../../modules/net-vpn-ha" source = "../../../modules/net-vpn-ha"
project_id = module.landing-project.project_id project_id = module.landing-project.project_id
network = module.landing-trusted-vpc.self_link network = module.landing-trusted-vpc.self_link
region = var.regions.primary region = var.regions.primary
name = "vpn-to-onprem-${local.region_shortnames[var.regions.primary]}" name = "vpn-to-onprem-${local.region_shortnames[var.regions.primary]}"
router_config = { router_config = try(var.vpn_onprem_primary_config.router_config, {})
name = "landing-onprem-vpn-${local.region_shortnames[var.regions.primary]}"
asn = var.router_configs.landing-trusted-primary.asn
}
peer_gateways = { peer_gateways = {
default = { for k, v in local.onprem_peer_gateways.primary : k => { external = v }
external = var.vpn_onprem_configs.landing-trusted-primary.peer_external_gateway
}
} }
tunnels = { tunnels = try(var.vpn_onprem_primary_config.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
} }
module "landing-to-onprem-secondary-vpn" { module "landing-to-onprem-secondary-vpn" {
count = local.enable_onprem_vpn ? 1 : 0 count = var.vpn_onprem_secondary_config == null ? 0 : 1
source = "../../../modules/net-vpn-ha" source = "../../../modules/net-vpn-ha"
project_id = module.landing-project.project_id project_id = module.landing-project.project_id
network = module.landing-trusted-vpc.self_link network = module.landing-trusted-vpc.self_link
region = var.regions.secondary region = var.regions.secondary
name = "vpn-to-onprem-${local.region_shortnames[var.regions.secondary]}" name = "vpn-to-onprem-${local.region_shortnames[var.regions.secondary]}"
router_config = { router_config = try(var.vpn_onprem_secondary_config.router_config, {})
name = "landing-onprem-vpn-${local.region_shortnames[var.regions.secondary]}"
asn = var.router_configs.landing-trusted-secondary.asn
}
peer_gateways = { peer_gateways = {
default = { for k, v in local.onprem_peer_gateways.secondary : k => { external = v }
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
}
} }
tunnels = try(var.vpn_onprem_secondary_config.tunnels, {})
} }

View File

@ -37,6 +37,7 @@ The following diagram illustrates the high-level design, and should be used as a
- [Running the stage](#running-the-stage) - [Running the stage](#running-the-stage)
- [Post-deployment activities](#post-deployment-activities) - [Post-deployment activities](#post-deployment-activities)
- [Customizations](#customizations) - [Customizations](#customizations)
- [Configuring the VPNs to on prem](#configuring-the-vpns-to-on-prem)
- [Changing default regions](#changing-default-regions) - [Changing default regions](#changing-default-regions)
## Design overview and choices ## Design overview and choices
@ -129,7 +130,7 @@ Subnets for [L7 ILBs](https://cloud.google.com/load-balancing/docs/l7-internal/p
### VPNs ### 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 ### Routing and BGP
@ -257,6 +258,55 @@ Per variable `vpn_onprem_configs` such ranges are advertised to onprem - further
## Customizations ## 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 ### 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: 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. | <code>net-cloudnat</code> · <code>net-vpc</code> · <code>net-vpc-firewall</code> · <code>project</code> | <code>google_project_iam_binding</code> | | [spoke-prod.tf](./spoke-prod.tf) | Production spoke VPC and related resources. | <code>net-cloudnat</code> · <code>net-vpc</code> · <code>net-vpc-firewall</code> · <code>project</code> | <code>google_project_iam_binding</code> |
| [test-resources.tf](./test-resources.tf) | Temporary instances for testing | <code>compute-vm</code> | | | [test-resources.tf](./test-resources.tf) | Temporary instances for testing | <code>compute-vm</code> | |
| [variables.tf](./variables.tf) | Module variables. | | | | [variables.tf](./variables.tf) | Module variables. | | |
| [vpn-onprem-dev.tf](./vpn-onprem-dev.tf) | VPN between dev and onprem. | <code>net-vpn-ha</code> | | | [vpn-onprem.tf](./vpn-onprem.tf) | VPN between landing and onprem. | <code>net-vpn-ha</code> | |
| [vpn-onprem-prod.tf](./vpn-onprem-prod.tf) | VPN between prod and onprem. | <code>net-vpn-ha</code> | |
## Variables ## 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. | <code title="object&#40;&#123;&#10; outputs_bucket &#61; string&#10;&#125;&#41;">object&#40;&#123;&#8230;&#125;&#41;</code> | ✓ | | <code>0-bootstrap</code> | | [automation](variables.tf#L17) | Automation resources created by the bootstrap stage. | <code title="object&#40;&#123;&#10; outputs_bucket &#61; string&#10;&#125;&#41;">object&#40;&#123;&#8230;&#125;&#41;</code> | ✓ | | <code>0-bootstrap</code> |
| [billing_account](variables.tf#L25) | Billing account id. If billing account is not part of the same org set `is_org_level` to false. | <code title="object&#40;&#123;&#10; id &#61; string&#10; is_org_level &#61; optional&#40;bool, true&#41;&#10;&#125;&#41;">object&#40;&#123;&#8230;&#125;&#41;</code> | ✓ | | <code>0-bootstrap</code> | | [billing_account](variables.tf#L25) | Billing account id. If billing account is not part of the same org set `is_org_level` to false. | <code title="object&#40;&#123;&#10; id &#61; string&#10; is_org_level &#61; optional&#40;bool, true&#41;&#10;&#125;&#41;">object&#40;&#123;&#8230;&#125;&#41;</code> | ✓ | | <code>0-bootstrap</code> |
| [folder_ids](variables.tf#L92) | Folders to be used for the networking resources in folders/nnnnnnnnnnn format. If null, folder will be created. | <code title="object&#40;&#123;&#10; networking &#61; string&#10; networking-dev &#61; string&#10; networking-prod &#61; string&#10;&#125;&#41;">object&#40;&#123;&#8230;&#125;&#41;</code> | ✓ | | <code>1-resman</code> | | [folder_ids](variables.tf#L76) | Folders to be used for the networking resources in folders/nnnnnnnnnnn format. If null, folder will be created. | <code title="object&#40;&#123;&#10; networking &#61; string&#10; networking-dev &#61; string&#10; networking-prod &#61; string&#10;&#125;&#41;">object&#40;&#123;&#8230;&#125;&#41;</code> | ✓ | | <code>1-resman</code> |
| [organization](variables.tf#L102) | Organization details. | <code title="object&#40;&#123;&#10; domain &#61; string&#10; id &#61; number&#10; customer_id &#61; string&#10;&#125;&#41;">object&#40;&#123;&#8230;&#125;&#41;</code> | ✓ | | <code>0-bootstrap</code> | | [organization](variables.tf#L86) | Organization details. | <code title="object&#40;&#123;&#10; domain &#61; string&#10; id &#61; number&#10; customer_id &#61; string&#10;&#125;&#41;">object&#40;&#123;&#8230;&#125;&#41;</code> | ✓ | | <code>0-bootstrap</code> |
| [prefix](variables.tf#L118) | Prefix used for resources that need unique names. Use 9 characters or less. | <code>string</code> | ✓ | | <code>0-bootstrap</code> | | [prefix](variables.tf#L102) | Prefix used for resources that need unique names. Use 9 characters or less. | <code>string</code> | ✓ | | <code>0-bootstrap</code> |
| [custom_adv](variables.tf#L38) | Custom advertisement definitions in name => range format. | <code>map&#40;string&#41;</code> | | <code title="&#123;&#10; cloud_dns &#61; &#34;35.199.192.0&#47;19&#34;&#10; gcp_all &#61; &#34;10.128.0.0&#47;16&#34;&#10; gcp_dev &#61; &#34;10.128.32.0&#47;19&#34;&#10; gcp_prod &#61; &#34;10.128.64.0&#47;19&#34;&#10; googleapis_private &#61; &#34;199.36.153.8&#47;30&#34;&#10; googleapis_restricted &#61; &#34;199.36.153.4&#47;30&#34;&#10; rfc_1918_10 &#61; &#34;10.0.0.0&#47;8&#34;&#10; rfc_1918_172 &#61; &#34;172.16.0.0&#47;12&#34;&#10; rfc_1918_192 &#61; &#34;192.168.0.0&#47;16&#34;&#10;&#125;">&#123;&#8230;&#125;</code> | | | [custom_roles](variables.tf#L38) | Custom roles defined at the org level, in key => id format. | <code title="object&#40;&#123;&#10; service_project_network_admin &#61; string&#10;&#125;&#41;">object&#40;&#123;&#8230;&#125;&#41;</code> | | <code>null</code> | <code>0-bootstrap</code> |
| [custom_roles](variables.tf#L54) | Custom roles defined at the org level, in key => id format. | <code title="object&#40;&#123;&#10; service_project_network_admin &#61; string&#10;&#125;&#41;">object&#40;&#123;&#8230;&#125;&#41;</code> | | <code>null</code> | <code>0-bootstrap</code> | | [dns](variables.tf#L47) | Onprem DNS resolvers. | <code>map&#40;list&#40;string&#41;&#41;</code> | | <code title="&#123;&#10; prod &#61; &#91;&#34;10.0.1.1&#34;&#93;&#10; dev &#61; &#91;&#34;10.0.2.1&#34;&#93;&#10;&#125;">&#123;&#8230;&#125;</code> | |
| [dns](variables.tf#L63) | Onprem DNS resolvers. | <code>map&#40;list&#40;string&#41;&#41;</code> | | <code title="&#123;&#10; prod &#61; &#91;&#34;10.0.1.1&#34;&#93;&#10; dev &#61; &#91;&#34;10.0.2.1&#34;&#93;&#10;&#125;">&#123;&#8230;&#125;</code> | | | [factories_config](variables.tf#L56) | Configuration for network resource factories. | <code title="object&#40;&#123;&#10; data_dir &#61; optional&#40;string, &#34;data&#34;&#41;&#10; firewall_policy_name &#61; optional&#40;string, &#34;factory&#34;&#41;&#10;&#125;&#41;">object&#40;&#123;&#8230;&#125;&#41;</code> | | <code title="&#123;&#10; data_dir &#61; &#34;data&#34;&#10;&#125;">&#123;&#8230;&#125;</code> | |
| [factories_config](variables.tf#L72) | Configuration for network resource factories. | <code title="object&#40;&#123;&#10; data_dir &#61; optional&#40;string, &#34;data&#34;&#41;&#10; firewall_policy_name &#61; optional&#40;string, &#34;factory&#34;&#41;&#10;&#125;&#41;">object&#40;&#123;&#8230;&#125;&#41;</code> | | <code title="&#123;&#10; data_dir &#61; &#34;data&#34;&#10;&#125;">&#123;&#8230;&#125;</code> | | | [outputs_location](variables.tf#L96) | Path where providers and tfvars files for the following stages are written. Leave empty to disable. | <code>string</code> | | <code>null</code> | |
| [outputs_location](variables.tf#L112) | Path where providers and tfvars files for the following stages are written. Leave empty to disable. | <code>string</code> | | <code>null</code> | | | [psa_ranges](variables.tf#L113) | IP ranges used for Private Service Access (e.g. CloudSQL). | <code title="object&#40;&#123;&#10; dev &#61; object&#40;&#123;&#10; ranges &#61; map&#40;string&#41;&#10; routes &#61; object&#40;&#123;&#10; export &#61; bool&#10; import &#61; bool&#10; &#125;&#41;&#10; &#125;&#41;&#10; prod &#61; object&#40;&#123;&#10; ranges &#61; map&#40;string&#41;&#10; routes &#61; object&#40;&#123;&#10; export &#61; bool&#10; import &#61; bool&#10; &#125;&#41;&#10; &#125;&#41;&#10;&#125;&#41;">object&#40;&#123;&#8230;&#125;&#41;</code> | | <code>null</code> | |
| [psa_ranges](variables.tf#L129) | IP ranges used for Private Service Access (e.g. CloudSQL). | <code title="object&#40;&#123;&#10; dev &#61; object&#40;&#123;&#10; ranges &#61; map&#40;string&#41;&#10; routes &#61; object&#40;&#123;&#10; export &#61; bool&#10; import &#61; bool&#10; &#125;&#41;&#10; &#125;&#41;&#10; prod &#61; object&#40;&#123;&#10; ranges &#61; map&#40;string&#41;&#10; routes &#61; object&#40;&#123;&#10; export &#61; bool&#10; import &#61; bool&#10; &#125;&#41;&#10; &#125;&#41;&#10;&#125;&#41;">object&#40;&#123;&#8230;&#125;&#41;</code> | | <code>null</code> | | | [regions](variables.tf#L134) | Region definitions. | <code title="object&#40;&#123;&#10; primary &#61; string&#10;&#125;&#41;">object&#40;&#123;&#8230;&#125;&#41;</code> | | <code title="&#123;&#10; primary &#61; &#34;europe-west1&#34;&#10;&#125;">&#123;&#8230;&#125;</code> | |
| [regions](variables.tf#L166) | Region definitions. | <code title="object&#40;&#123;&#10; primary &#61; string&#10;&#125;&#41;">object&#40;&#123;&#8230;&#125;&#41;</code> | | <code title="&#123;&#10; primary &#61; &#34;europe-west1&#34;&#10;&#125;">&#123;&#8230;&#125;</code> | | | [service_accounts](variables.tf#L144) | Automation service accounts in name => email format. | <code title="object&#40;&#123;&#10; data-platform-dev &#61; string&#10; data-platform-prod &#61; string&#10; project-factory-dev &#61; string&#10; project-factory-prod &#61; string&#10;&#125;&#41;">object&#40;&#123;&#8230;&#125;&#41;</code> | | <code>null</code> | <code>1-resman</code> |
| [router_onprem_configs](variables.tf#L176) | Configurations for routers used for onprem connectivity. | <code title="map&#40;object&#40;&#123;&#10; adv &#61; object&#40;&#123;&#10; custom &#61; list&#40;string&#41;&#10; default &#61; bool&#10; &#125;&#41;&#10; asn &#61; number&#10;&#125;&#41;&#41;">map&#40;object&#40;&#123;&#8230;&#125;&#41;&#41;</code> | | <code title="&#123;&#10; prod-primary &#61; &#123;&#10; asn &#61; &#34;65533&#34;&#10; adv &#61; null&#10; &#125;&#10; dev-primary &#61; &#123;&#10; asn &#61; &#34;65534&#34;&#10; adv &#61; null&#10; &#125;&#10;&#125;">&#123;&#8230;&#125;</code> | | | [vpn_onprem_dev_primary_config](variables.tf#L156) | VPN gateway configuration for onprem interconnection from dev in the primary region. | <code title="object&#40;&#123;&#10; peer_external_gateways &#61; map&#40;object&#40;&#123;&#10; redundancy_type &#61; string&#10; interfaces &#61; list&#40;string&#41;&#10; &#125;&#41;&#41;&#10; router_config &#61; object&#40;&#123;&#10; create &#61; optional&#40;bool, true&#41;&#10; asn &#61; number&#10; name &#61; optional&#40;string&#41;&#10; keepalive &#61; optional&#40;number&#41;&#10; custom_advertise &#61; optional&#40;object&#40;&#123;&#10; all_subnets &#61; bool&#10; ip_ranges &#61; map&#40;string&#41;&#10; &#125;&#41;&#41;&#10; &#125;&#41;&#10; tunnels &#61; map&#40;object&#40;&#123;&#10; bgp_peer &#61; object&#40;&#123;&#10; address &#61; string&#10; asn &#61; number&#10; route_priority &#61; optional&#40;number, 1000&#41;&#10; custom_advertise &#61; optional&#40;object&#40;&#123;&#10; all_subnets &#61; bool&#10; all_vpc_subnets &#61; bool&#10; all_peer_vpc_subnets &#61; bool&#10; ip_ranges &#61; map&#40;string&#41;&#10; &#125;&#41;&#41;&#10; &#125;&#41;&#10; bgp_session_range &#61; string&#10; ike_version &#61; optional&#40;number, 2&#41;&#10; peer_external_gateway_interface &#61; optional&#40;number&#41;&#10; peer_gateway &#61; optional&#40;string, &#34;default&#34;&#41;&#10; router &#61; optional&#40;string&#41;&#10; shared_secret &#61; optional&#40;string&#41;&#10; vpn_gateway_interface &#61; number&#10; &#125;&#41;&#41;&#10;&#125;&#41;">object&#40;&#123;&#8230;&#125;&#41;</code> | | <code>null</code> | |
| [service_accounts](variables.tf#L199) | Automation service accounts in name => email format. | <code title="object&#40;&#123;&#10; data-platform-dev &#61; string&#10; data-platform-prod &#61; string&#10; project-factory-dev &#61; string&#10; project-factory-prod &#61; string&#10;&#125;&#41;">object&#40;&#123;&#8230;&#125;&#41;</code> | | <code>null</code> | <code>1-resman</code> | | [vpn_onprem_prod_primary_config](variables.tf#L199) | VPN gateway configuration for onprem interconnection from prod in the primary region. | <code title="object&#40;&#123;&#10; peer_external_gateways &#61; map&#40;object&#40;&#123;&#10; redundancy_type &#61; string&#10; interfaces &#61; list&#40;string&#41;&#10; &#125;&#41;&#41;&#10; router_config &#61; object&#40;&#123;&#10; create &#61; optional&#40;bool, true&#41;&#10; asn &#61; number&#10; name &#61; optional&#40;string&#41;&#10; keepalive &#61; optional&#40;number&#41;&#10; custom_advertise &#61; optional&#40;object&#40;&#123;&#10; all_subnets &#61; bool&#10; ip_ranges &#61; map&#40;string&#41;&#10; &#125;&#41;&#41;&#10; &#125;&#41;&#10; tunnels &#61; map&#40;object&#40;&#123;&#10; bgp_peer &#61; object&#40;&#123;&#10; address &#61; string&#10; asn &#61; number&#10; route_priority &#61; optional&#40;number, 1000&#41;&#10; custom_advertise &#61; optional&#40;object&#40;&#123;&#10; all_subnets &#61; bool&#10; all_vpc_subnets &#61; bool&#10; all_peer_vpc_subnets &#61; bool&#10; ip_ranges &#61; map&#40;string&#41;&#10; &#125;&#41;&#41;&#10; &#125;&#41;&#10; bgp_session_range &#61; string&#10; ike_version &#61; optional&#40;number, 2&#41;&#10; peer_external_gateway_interface &#61; optional&#40;number&#41;&#10; peer_gateway &#61; optional&#40;string, &#34;default&#34;&#41;&#10; router &#61; optional&#40;string&#41;&#10; shared_secret &#61; optional&#40;string&#41;&#10; vpn_gateway_interface &#61; number&#10; &#125;&#41;&#41;&#10;&#125;&#41;">object&#40;&#123;&#8230;&#125;&#41;</code> | | <code>null</code> | |
| [vpn_onprem_configs](variables.tf#L211) | VPN gateway configuration for onprem interconnection. | <code title="map&#40;object&#40;&#123;&#10; adv &#61; object&#40;&#123;&#10; default &#61; bool&#10; custom &#61; list&#40;string&#41;&#10; &#125;&#41;&#10; peer_external_gateway &#61; object&#40;&#123;&#10; redundancy_type &#61; string&#10; interfaces &#61; list&#40;string&#41;&#10; &#125;&#41;&#10; tunnels &#61; list&#40;object&#40;&#123;&#10; peer_asn &#61; number&#10; peer_external_gateway_interface &#61; number&#10; secret &#61; string&#10; session_range &#61; string&#10; vpn_gateway_interface &#61; number&#10; &#125;&#41;&#41;&#10;&#125;&#41;&#41;">map&#40;object&#40;&#123;&#8230;&#125;&#41;&#41;</code> | | <code title="&#123;&#10; dev-primary &#61; &#123;&#10; adv &#61; &#123;&#10; default &#61; false&#10; custom &#61; &#91;&#10; &#34;cloud_dns&#34;, &#34;googleapis_private&#34;, &#34;googleapis_restricted&#34;, &#34;gcp_dev&#34;&#10; &#93;&#10; &#125;&#10; peer_external_gateway &#61; &#123;&#10; redundancy_type &#61; &#34;SINGLE_IP_INTERNALLY_REDUNDANT&#34;&#10; interfaces &#61; &#91;&#34;8.8.8.8&#34;&#93;&#10;&#10;&#10; &#125;&#10; tunnels &#61; &#91;&#10; &#123;&#10; peer_asn &#61; 65544&#10; peer_external_gateway_interface &#61; 0&#10; secret &#61; &#34;foobar&#34;&#10; session_range &#61; &#34;169.254.1.0&#47;30&#34;&#10; vpn_gateway_interface &#61; 0&#10; &#125;,&#10; &#123;&#10; peer_asn &#61; 65544&#10; peer_external_gateway_interface &#61; 0&#10; secret &#61; &#34;foobar&#34;&#10; session_range &#61; &#34;169.254.1.4&#47;30&#34;&#10; vpn_gateway_interface &#61; 1&#10; &#125;&#10; &#93;&#10; &#125;&#10; prod-primary &#61; &#123;&#10; adv &#61; &#123;&#10; default &#61; false&#10; custom &#61; &#91;&#10; &#34;cloud_dns&#34;, &#34;googleapis_private&#34;, &#34;googleapis_restricted&#34;, &#34;gcp_prod&#34;&#10; &#93;&#10; &#125;&#10; peer_external_gateway &#61; &#123;&#10; redundancy_type &#61; &#34;SINGLE_IP_INTERNALLY_REDUNDANT&#34;&#10; interfaces &#61; &#91;&#34;8.8.8.8&#34;&#93;&#10; &#125;&#10; tunnels &#61; &#91;&#10; &#123;&#10; peer_asn &#61; 65543&#10; peer_external_gateway_interface &#61; 0&#10; secret &#61; &#34;foobar&#34;&#10; session_range &#61; &#34;169.254.1.0&#47;30&#34;&#10; vpn_gateway_interface &#61; 0&#10; &#125;,&#10; &#123;&#10; peer_asn &#61; 65543&#10; peer_external_gateway_interface &#61; 0&#10; secret &#61; &#34;foobar&#34;&#10; session_range &#61; &#34;169.254.1.4&#47;30&#34;&#10; vpn_gateway_interface &#61; 1&#10; &#125;&#10; &#93;&#10; &#125;&#10;&#125;">&#123;&#8230;&#125;</code> | |
## Outputs ## Outputs

View File

@ -89,13 +89,13 @@ output "tfvars" {
output "vpn_gateway_endpoints" { output "vpn_gateway_endpoints" {
description = "External IP Addresses for the GCP VPN gateways." description = "External IP Addresses for the GCP VPN gateways."
value = local.enable_onprem_vpn == false ? null : { value = {
dev-onprem-primary = { dev-primary = var.vpn_onprem_dev_primary_config == null ? {} : {
for v in module.dev-to-onprem-primary-vpn[0].gateway.vpn_interfaces : for v in module.landing-to-onprem-dev-primary-vpn.0.gateway.vpn_interfaces :
v.id => v.ip_address v.id => v.ip_address
} }
prod-onprem-primary = { prod-primary = var.vpn_onprem_prod_primary_config == null ? {} : {
for v in module.prod-to-onprem-primary-vpn[0].gateway.vpn_interfaces : for v in module.landing-to-onprem-prod-primary-vpn.0.gateway.vpn_interfaces :
v.id => v.ip_address v.id => v.ip_address
} }
} }

View File

@ -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" { variable "custom_roles" {
# tfdoc:variable:source 0-bootstrap # tfdoc:variable:source 0-bootstrap
description = "Custom roles defined at the org level, in key => id format." description = "Custom roles defined at the org level, in key => id format."
@ -145,22 +129,6 @@ variable "psa_ranges" {
}) })
}) })
default = null 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" { 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" { variable "service_accounts" {
# tfdoc:variable:source 1-resman # tfdoc:variable:source 1-resman
description = "Automation service accounts in name => email format." description = "Automation service accounts in name => email format."
@ -208,82 +153,88 @@ variable "service_accounts" {
default = null default = null
} }
variable "vpn_onprem_configs" { variable "vpn_onprem_dev_primary_config" {
description = "VPN gateway configuration for onprem interconnection." description = "VPN gateway configuration for onprem interconnection from dev in the primary region."
type = map(object({ type = object({
adv = object({ peer_external_gateways = map(object({
default = bool
custom = list(string)
})
peer_external_gateway = object({
redundancy_type = string redundancy_type = string
interfaces = list(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({ tunnels = map(object({
peer_asn = number bgp_peer = object({
peer_external_gateway_interface = number address = string
secret = string asn = number
session_range = string 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 vpn_gateway_interface = number
})) }))
})) })
default = { default = null
dev-primary = { }
adv = {
default = false variable "vpn_onprem_prod_primary_config" {
custom = [ description = "VPN gateway configuration for onprem interconnection from prod in the primary region."
"cloud_dns", "googleapis_private", "googleapis_restricted", "gcp_dev" type = object({
] peer_external_gateways = map(object({
} redundancy_type = string
peer_external_gateway = { interfaces = list(string)
redundancy_type = "SINGLE_IP_INTERNALLY_REDUNDANT" }))
interfaces = ["8.8.8.8"] router_config = object({
create = optional(bool, true)
} asn = number
tunnels = [ name = optional(string)
{ keepalive = optional(number)
peer_asn = 65544 custom_advertise = optional(object({
peer_external_gateway_interface = 0 all_subnets = bool
secret = "foobar" ip_ranges = map(string)
session_range = "169.254.1.0/30" }))
vpn_gateway_interface = 0 })
}, tunnels = map(object({
{ bgp_peer = object({
peer_asn = 65544 address = string
peer_external_gateway_interface = 0 asn = number
secret = "foobar" route_priority = optional(number, 1000)
session_range = "169.254.1.4/30" custom_advertise = optional(object({
vpn_gateway_interface = 1 all_subnets = bool
} all_vpc_subnets = bool
] all_peer_vpc_subnets = bool
} ip_ranges = map(string)
prod-primary = { }))
adv = { })
default = false # each BGP session on the same Cloud Router must use a unique /30 CIDR
custom = [ # from the 169.254.0.0/16 block.
"cloud_dns", "googleapis_private", "googleapis_restricted", "gcp_prod" bgp_session_range = string
] ike_version = optional(number, 2)
} peer_external_gateway_interface = optional(number)
peer_external_gateway = { peer_gateway = optional(string, "default")
redundancy_type = "SINGLE_IP_INTERNALLY_REDUNDANT" router = optional(string)
interfaces = ["8.8.8.8"] shared_secret = optional(string)
} vpn_gateway_interface = number
tunnels = [ }))
{ })
peer_asn = 65543 default = null
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
}
]
}
}
} }

View File

@ -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
}
}
}

View File

@ -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
}
}
}

View File

@ -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, {})
}

View File

@ -27,3 +27,38 @@ organization = {
customer_id = "C00000000" customer_id = "C00000000"
} }
prefix = "fast2" 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
}
}
}

View File

@ -13,11 +13,6 @@ folder_ids = {
networking-dev = null networking-dev = null
networking-prod = null networking-prod = null
} }
region_trigram = {
europe-west1 = "ew1"
europe-west3 = "ew3"
europe-west8 = "ew8"
}
service_accounts = { service_accounts = {
data-platform-dev = "string" data-platform-dev = "string"
data-platform-prod = "string" data-platform-prod = "string"

View File

@ -27,3 +27,81 @@ organization = {
customer_id = "C00000000" customer_id = "C00000000"
} }
prefix = "fast2" 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
}
}
}

View File

@ -25,3 +25,81 @@ organization = {
customer_id = "C00000000" customer_id = "C00000000"
} }
prefix = "fast2" 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
}
}
}