From 4ce694af0c15903072ef7fe68c77cec0b708b972 Mon Sep 17 00:00:00 2001 From: Ludo Date: Tue, 7 Feb 2023 00:40:21 +0100 Subject: [PATCH 01/16] configurable regions --- fast/stages/2-networking-a-peering/README.md | 18 ++++---- fast/stages/2-networking-a-peering/landing.tf | 13 ++++-- fast/stages/2-networking-a-peering/main.tf | 19 +++++--- fast/stages/2-networking-a-peering/outputs.tf | 4 +- .../2-networking-a-peering/spoke-dev.tf | 17 +++++++- .../2-networking-a-peering/spoke-prod.tf | 17 +++++++- .../2-networking-a-peering/variables.tf | 43 +++++++++++-------- .../2-networking-a-peering/vpn-onprem.tf | 21 +++++---- 8 files changed, 102 insertions(+), 50 deletions(-) diff --git a/fast/stages/2-networking-a-peering/README.md b/fast/stages/2-networking-a-peering/README.md index a29f6c7752..3eb0c1612d 100644 --- a/fast/stages/2-networking-a-peering/README.md +++ b/fast/stages/2-networking-a-peering/README.md @@ -298,20 +298,20 @@ DNS configurations are centralised in the `dns-*.tf` files. Spokes delegate DNS | [automation](variables.tf#L17) | Automation resources created by the bootstrap stage. | object({…}) | ✓ | | 0-bootstrap | | [billing_account](variables.tf#L25) | Billing account id. If billing account is not part of the same org set `is_org_level` to false. | object({…}) | ✓ | | 0-bootstrap | | [folder_ids](variables.tf#L78) | Folders to be used for the networking resources in folders/nnnnnnnnnnn format. If null, folder will be created. | object({…}) | ✓ | | 1-resman | -| [organization](variables.tf#L106) | Organization details. | object({…}) | ✓ | | 0-bootstrap | -| [prefix](variables.tf#L122) | Prefix used for resources that need unique names. Use 9 characters or less. | string | ✓ | | 0-bootstrap | +| [organization](variables.tf#L112) | Organization details. | object({…}) | ✓ | | 0-bootstrap | +| [prefix](variables.tf#L128) | Prefix used for resources that need unique names. Use 9 characters or less. | string | ✓ | | 0-bootstrap | | [custom_adv](variables.tf#L38) | Custom advertisement definitions in name => range format. | map(string) | | {…} | | | [custom_roles](variables.tf#L55) | Custom roles defined at the org level, in key => id format. | object({…}) | | null | 0-bootstrap | | [data_dir](variables.tf#L64) | Relative path for the folder storing configuration data for network resources. | string | | "data" | | | [dns](variables.tf#L70) | Onprem DNS resolvers. | map(list(string)) | | {…} | | -| [l7ilb_subnets](variables.tf#L88) | Subnets used for L7 ILBs. | map(list(object({…}))) | | {…} | | -| [outputs_location](variables.tf#L116) | Path where providers and tfvars files for the following stages are written. Leave empty to disable. | string | | null | | +| [l7ilb_subnets](variables.tf#L88) | Subnets used for L7 ILBs. | object({…}) | | {…} | | +| [outputs_location](variables.tf#L122) | Path where providers and tfvars files for the following stages are written. Leave empty to disable. | string | | null | | | [peering_configs](variables-peerings.tf#L19) | Peering configurations. | map(object({…})) | | {…} | | -| [psa_ranges](variables.tf#L133) | IP ranges used for Private Service Access (e.g. CloudSQL). | object({…}) | | null | | -| [region_trigram](variables.tf#L170) | Short names for GCP regions. | map(string) | | {…} | | -| [router_onprem_configs](variables.tf#L179) | Configurations for routers used for onprem connectivity. | map(object({…})) | | {…} | | -| [service_accounts](variables.tf#L197) | Automation service accounts in name => email format. | object({…}) | | null | 1-resman | -| [vpn_onprem_configs](variables.tf#L211) | VPN gateway configuration for onprem interconnection. | map(object({…})) | | {…} | | +| [psa_ranges](variables.tf#L139) | IP ranges used for Private Service Access (e.g. CloudSQL). | object({…}) | | null | | +| [regions](variables.tf#L176) | Region definitions. | object({…}) | | {…} | | +| [router_onprem_configs](variables.tf#L188) | Configurations for routers used for onprem connectivity. | map(object({…})) | | {…} | | +| [service_accounts](variables.tf#L206) | Automation service accounts in name => email format. | object({…}) | | null | 1-resman | +| [vpn_onprem_configs](variables.tf#L220) | VPN gateway configuration for onprem interconnection. | map(object({…})) | | {…} | | ## Outputs diff --git a/fast/stages/2-networking-a-peering/landing.tf b/fast/stages/2-networking-a-peering/landing.tf index 83a0d509af..2e84733ad5 100644 --- a/fast/stages/2-networking-a-peering/landing.tf +++ b/fast/stages/2-networking-a-peering/landing.tf @@ -79,13 +79,18 @@ module "landing-firewall" { } } -module "landing-nat-ew1" { +moved { + from = module.landing-nat-ew1 + to = module.landing-nat-primary +} + +module "landing-nat-primary" { source = "../../../modules/net-cloudnat" project_id = module.landing-project.project_id - region = "europe-west1" - name = "ew1" + region = var.regions.primary + name = local.region_shortnames[var.regions.primary] router_create = true - router_name = "prod-nat-ew1" + router_name = "prod-nat-${local.region_shortnames[var.regions.primary]}" router_network = module.landing-vpc.name router_asn = 4200001024 } diff --git a/fast/stages/2-networking-a-peering/main.tf b/fast/stages/2-networking-a-peering/main.tf index f68d39eb85..bb8d5e8c7d 100644 --- a/fast/stages/2-networking-a-peering/main.tf +++ b/fast/stages/2-networking-a-peering/main.tf @@ -17,13 +17,20 @@ # tfdoc:file:description Networking folder and hierarchical policy. locals { + _region_tokens = { for v in local._regions : v => split("-", v) } + _regions = distinct(concat( + [var.regions.primary, var.regions.secondary], + values(module.dev-spoke-vpc.subnet_regions), + values(module.landing-vpc.subnet_regions), + values(module.prod-spoke-vpc.subnet_regions), + )) custom_roles = coalesce(var.custom_roles, {}) - l7ilb_subnets = { - for env, v in var.l7ilb_subnets : env => [ - for s in v : merge(s, { - active = true - name = "${env}-l7ilb-${s.region}" - })] + region_shortnames = { + for k, v in local._region_tokens : k => join("", [ + substr(v.0, 0, 1), + substr(v.1, 0, 1), + substr(strrev(v.1), 0, 1), + ]) } stage3_sas_delegated_grants = [ "roles/composer.sharedVpcAgent", diff --git a/fast/stages/2-networking-a-peering/outputs.tf b/fast/stages/2-networking-a-peering/outputs.tf index 0e101f4123..628c706b38 100644 --- a/fast/stages/2-networking-a-peering/outputs.tf +++ b/fast/stages/2-networking-a-peering/outputs.tf @@ -89,8 +89,8 @@ output "tfvars" { output "vpn_gateway_endpoints" { description = "External IP Addresses for the GCP VPN gateways." value = local.enable_onprem_vpn == false ? null : { - onprem-ew1 = { - for v in module.landing-to-onprem-ew1-vpn[0].gateway.vpn_interfaces : + onprem-primary = { + for v in module.landing-to-onprem-primary-vpn[0].gateway.vpn_interfaces : v.id => v.ip_address } } diff --git a/fast/stages/2-networking-a-peering/spoke-dev.tf b/fast/stages/2-networking-a-peering/spoke-dev.tf index e67cfb70db..966d709cb7 100644 --- a/fast/stages/2-networking-a-peering/spoke-dev.tf +++ b/fast/stages/2-networking-a-peering/spoke-dev.tf @@ -16,6 +16,19 @@ # tfdoc:file:description Dev spoke VPC and related resources. +locals { + _l7ilb_subnets_dev = [ + for v in var.l7ilb_subnets.dev : merge(v, { + active = true + region = lookup(var.regions, v.region, v.region) + })] + l7ilb_subnets_dev = [ + for v in local._l7ilb_subnets_dev : merge(v, { + name = "dev-l7ilb-${local.region_shortnames[v.region]}" + }) + ] +} + module "dev-spoke-project" { source = "../../../modules/project" billing_account = var.billing_account.id @@ -50,7 +63,7 @@ module "dev-spoke-vpc" { mtu = 1500 data_folder = "${var.data_dir}/subnets/dev" psa_config = try(var.psa_ranges.dev, null) - subnets_proxy_only = local.l7ilb_subnets.dev + subnets_proxy_only = local.l7ilb_subnets_dev # set explicit routes for googleapis in case the default route is deleted routes = { private-googleapis = { @@ -84,7 +97,7 @@ module "dev-spoke-cloudnat" { source = "../../../modules/net-cloudnat" project_id = module.dev-spoke-project.project_id region = each.value - name = "dev-nat-${var.region_trigram[each.value]}" + name = "dev-nat-${local.region_shortnames[each.value]}" router_create = true router_network = module.dev-spoke-vpc.name router_asn = 4200001024 diff --git a/fast/stages/2-networking-a-peering/spoke-prod.tf b/fast/stages/2-networking-a-peering/spoke-prod.tf index cf49152fa1..7ce7dff4d3 100644 --- a/fast/stages/2-networking-a-peering/spoke-prod.tf +++ b/fast/stages/2-networking-a-peering/spoke-prod.tf @@ -16,6 +16,19 @@ # tfdoc:file:description Production spoke VPC and related resources. +locals { + _l7ilb_subnets_prod = [ + for v in var.l7ilb_subnets.prod : merge(v, { + active = true + region = lookup(var.regions, v.region, v.region) + })] + l7ilb_subnets_prod = [ + for v in local._l7ilb_subnets_prod : merge(v, { + name = "prod-l7ilb-${local.region_shortnames[v.region]}" + }) + ] +} + module "prod-spoke-project" { source = "../../../modules/project" billing_account = var.billing_account.id @@ -50,7 +63,7 @@ module "prod-spoke-vpc" { mtu = 1500 data_folder = "${var.data_dir}/subnets/prod" psa_config = try(var.psa_ranges.prod, null) - subnets_proxy_only = local.l7ilb_subnets.prod + subnets_proxy_only = local.l7ilb_subnets_prod # set explicit routes for googleapis in case the default route is deleted routes = { private-googleapis = { @@ -84,7 +97,7 @@ module "prod-spoke-cloudnat" { source = "../../../modules/net-cloudnat" project_id = module.prod-spoke-project.project_id region = each.value - name = "prod-nat-${var.region_trigram[each.value]}" + name = "prod-nat-${local.region_shortnames[each.value]}" router_create = true router_network = module.prod-spoke-vpc.name router_asn = 4200001024 diff --git a/fast/stages/2-networking-a-peering/variables.tf b/fast/stages/2-networking-a-peering/variables.tf index fb2fd8745b..ff85422b4d 100644 --- a/fast/stages/2-networking-a-peering/variables.tf +++ b/fast/stages/2-networking-a-peering/variables.tf @@ -87,18 +87,24 @@ variable "folder_ids" { variable "l7ilb_subnets" { description = "Subnets used for L7 ILBs." - type = map(list(object({ - ip_cidr_range = string - region = string - }))) + type = object({ + dev = optional(list(object({ + ip_cidr_range = string + region = string + })), []) + prod = optional(list(object({ + ip_cidr_range = string + region = string + })), []) + }) default = { - prod = [ - { ip_cidr_range = "10.128.92.0/24", region = "europe-west1" }, - { ip_cidr_range = "10.128.93.0/24", region = "europe-west4" } - ] dev = [ - { ip_cidr_range = "10.128.60.0/24", region = "europe-west1" }, - { ip_cidr_range = "10.128.61.0/24", region = "europe-west4" } + { ip_cidr_range = "10.128.60.0/24", region = "primary" }, + { ip_cidr_range = "10.128.61.0/24", region = "secondary" } + ] + prod = [ + { ip_cidr_range = "10.128.92.0/24", region = "primary" }, + { ip_cidr_range = "10.128.93.0/24", region = "secondary" } ] } } @@ -167,12 +173,15 @@ variable "psa_ranges" { # } } -variable "region_trigram" { - description = "Short names for GCP regions." - type = map(string) +variable "regions" { + description = "Region definitions." + type = object({ + primary = string + secondary = string + }) default = { - europe-west1 = "ew1" - europe-west3 = "ew3" + primary = "europe-west1" + secondary = "europe-west4" } } @@ -186,7 +195,7 @@ variable "router_onprem_configs" { asn = number })) default = { - landing-ew1 = { + landing-primary = { asn = "65533" adv = null # adv = { default = false, custom = [] } @@ -228,7 +237,7 @@ variable "vpn_onprem_configs" { })) })) default = { - landing-ew1 = { + landing-primary = { adv = { default = false custom = [ diff --git a/fast/stages/2-networking-a-peering/vpn-onprem.tf b/fast/stages/2-networking-a-peering/vpn-onprem.tf index 5237a05acb..a04a009765 100644 --- a/fast/stages/2-networking-a-peering/vpn-onprem.tf +++ b/fast/stages/2-networking-a-peering/vpn-onprem.tf @@ -32,28 +32,33 @@ locals { } } -module "landing-to-onprem-ew1-vpn" { +moved { + from = module.landing-to-onprem-ew1-vpn + to = module.landing-to-onprem-primary-vpn +} + +module "landing-to-onprem-primary-vpn" { count = local.enable_onprem_vpn ? 1 : 0 source = "../../../modules/net-vpn-ha" project_id = module.landing-project.project_id network = module.landing-vpc.self_link - region = "europe-west1" - name = "vpn-to-onprem-ew1" + region = var.regions.primary + name = "vpn-to-onprem-${local.region_shortnames[var.regions.primary]}" router_config = { - name = "landing-onprem-vpn-ew1" - asn = var.router_onprem_configs.landing-ew1.asn + name = "landing-onprem-vpn-${local.region_shortnames[var.regions.primary]}" + asn = var.router_onprem_configs.landing-primary.asn } peer_gateway = { - external = var.vpn_onprem_configs.landing-ew1.peer_external_gateway + external = var.vpn_onprem_configs.landing-primary.peer_external_gateway } tunnels = { - for t in var.vpn_onprem_configs.landing-ew1.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-ew1 + 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 From 61e0a346d0abcd4c12233e95428563c2eebb3fac Mon Sep 17 00:00:00 2001 From: Ludo Date: Tue, 7 Feb 2023 18:03:36 +0100 Subject: [PATCH 02/16] vpn, tests --- fast/stages/2-networking-a-peering/main.tf | 11 +--- fast/stages/2-networking-a-peering/regions.tf | 42 ++++++++++++++ fast/stages/2-networking-b-vpn/README.md | 27 ++++----- fast/stages/2-networking-b-vpn/landing.tf | 13 +++-- fast/stages/2-networking-b-vpn/main.tf | 14 ++--- fast/stages/2-networking-b-vpn/outputs.tf | 4 +- fast/stages/2-networking-b-vpn/regions.tf | 42 ++++++++++++++ fast/stages/2-networking-b-vpn/spoke-dev.tf | 17 +++++- fast/stages/2-networking-b-vpn/spoke-prod.tf | 17 +++++- .../2-networking-b-vpn/variables-vpn.tf | 22 ++++---- fast/stages/2-networking-b-vpn/variables.tf | 43 ++++++++------ fast/stages/2-networking-b-vpn/vpn-onprem.tf | 21 ++++--- .../2-networking-b-vpn/vpn-spoke-dev.tf | 56 +++++++++++-------- ...-prod-ew1.tf => vpn-spoke-prod-primary.tf} | 54 ++++++++++-------- ...rod-ew4.tf => vpn-spoke-prod-secondary.tf} | 54 ++++++++++-------- .../s2_networking_a_peering/common.tfvars | 5 -- 16 files changed, 295 insertions(+), 147 deletions(-) create mode 100644 fast/stages/2-networking-a-peering/regions.tf create mode 100644 fast/stages/2-networking-b-vpn/regions.tf rename fast/stages/2-networking-b-vpn/{vpn-spoke-prod-ew1.tf => vpn-spoke-prod-primary.tf} (58%) rename fast/stages/2-networking-b-vpn/{vpn-spoke-prod-ew4.tf => vpn-spoke-prod-secondary.tf} (57%) diff --git a/fast/stages/2-networking-a-peering/main.tf b/fast/stages/2-networking-a-peering/main.tf index bb8d5e8c7d..33370c8b32 100644 --- a/fast/stages/2-networking-a-peering/main.tf +++ b/fast/stages/2-networking-a-peering/main.tf @@ -17,21 +17,14 @@ # tfdoc:file:description Networking folder and hierarchical policy. locals { - _region_tokens = { for v in local._regions : v => split("-", v) } - _regions = distinct(concat( + # combine all regions from variables and subnets + regions = distinct(concat( [var.regions.primary, var.regions.secondary], values(module.dev-spoke-vpc.subnet_regions), values(module.landing-vpc.subnet_regions), values(module.prod-spoke-vpc.subnet_regions), )) custom_roles = coalesce(var.custom_roles, {}) - region_shortnames = { - for k, v in local._region_tokens : k => join("", [ - substr(v.0, 0, 1), - substr(v.1, 0, 1), - substr(strrev(v.1), 0, 1), - ]) - } stage3_sas_delegated_grants = [ "roles/composer.sharedVpcAgent", "roles/compute.networkUser", diff --git a/fast/stages/2-networking-a-peering/regions.tf b/fast/stages/2-networking-a-peering/regions.tf new file mode 100644 index 0000000000..53514afa9b --- /dev/null +++ b/fast/stages/2-networking-a-peering/regions.tf @@ -0,0 +1,42 @@ +/** + * 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. + */ + +# tfdoc:file:description Compute short names for regions. + +locals { + # only map when the first character would not work + _region_cardinal = { + southeast = "se" + } + # only map when the first character would not work + _region_geo = { + australia = "o" + } + # split in [geo, cardinal, number] tokens + _region_tokens = { + for v in local.regions : v => regexall("(?:[a-z]+)|(?:[0-9]+)", v) + } + region_shortnames = { + for k, v in local._region_tokens : k => join("", [ + # first token via geo alias map or first character + lookup(local._region_geo, v.0, substr(v.0, 0, 1)), + # first token via cardinal alias map or first character + lookup(local._region_cardinal, v.1, substr(v.1, 0, 1)), + # region number as is + v.2 + ]) + } +} diff --git a/fast/stages/2-networking-b-vpn/README.md b/fast/stages/2-networking-b-vpn/README.md index 8dbea716cc..8788c381b1 100644 --- a/fast/stages/2-networking-b-vpn/README.md +++ b/fast/stages/2-networking-b-vpn/README.md @@ -306,6 +306,7 @@ DNS configurations are centralised in the `dns-*.tf` files. Spokes delegate DNS | [main.tf](./main.tf) | Networking folder and hierarchical policy. | folder | | | [monitoring.tf](./monitoring.tf) | Network monitoring dashboards. | | google_monitoring_dashboard | | [outputs.tf](./outputs.tf) | Module outputs. | | google_storage_bucket_object · local_file | +| [regions.tf](./regions.tf) | Compute short names for regions. | | | | [spoke-dev.tf](./spoke-dev.tf) | Dev spoke VPC and related resources. | net-cloudnat · net-vpc · net-vpc-firewall · project | google_project_iam_binding | | [spoke-prod.tf](./spoke-prod.tf) | Production spoke VPC and related resources. | net-cloudnat · net-vpc · net-vpc-firewall · project | google_project_iam_binding | | [test-resources.tf](./test-resources.tf) | temporary instances for testing | compute-vm | | @@ -313,8 +314,8 @@ DNS configurations are centralised in the `dns-*.tf` files. Spokes delegate DNS | [variables.tf](./variables.tf) | Module variables. | | | | [vpn-onprem.tf](./vpn-onprem.tf) | VPN between landing and onprem. | net-vpn-ha | | | [vpn-spoke-dev.tf](./vpn-spoke-dev.tf) | VPN between landing and development spoke. | net-vpn-ha | | -| [vpn-spoke-prod-ew1.tf](./vpn-spoke-prod-ew1.tf) | VPN between landing and production spoke in ew1. | net-vpn-ha | | -| [vpn-spoke-prod-ew4.tf](./vpn-spoke-prod-ew4.tf) | VPN between landing and production spoke in ew4. | net-vpn-ha | | +| [vpn-spoke-prod-primary.tf](./vpn-spoke-prod-primary.tf) | VPN between landing and production spoke in ew1. | net-vpn-ha | | +| [vpn-spoke-prod-secondary.tf](./vpn-spoke-prod-secondary.tf) | VPN between landing and production spoke in ew4. | net-vpn-ha | | ## Variables @@ -323,21 +324,21 @@ DNS configurations are centralised in the `dns-*.tf` files. Spokes delegate DNS | [automation](variables.tf#L17) | Automation resources created by the bootstrap stage. | object({…}) | ✓ | | 0-bootstrap | | [billing_account](variables.tf#L25) | Billing account id. If billing account is not part of the same org set `is_org_level` to false. | object({…}) | ✓ | | 0-bootstrap | | [folder_ids](variables.tf#L78) | Folders to be used for the networking resources in folders/nnnnnnnnnnn format. If null, folder will be created. | object({…}) | ✓ | | 1-resman | -| [organization](variables.tf#L106) | Organization details. | object({…}) | ✓ | | 0-bootstrap | -| [prefix](variables.tf#L122) | Prefix used for resources that need unique names. Use 9 characters or less. | string | ✓ | | 0-bootstrap | +| [organization](variables.tf#L112) | Organization details. | object({…}) | ✓ | | 0-bootstrap | +| [prefix](variables.tf#L128) | Prefix used for resources that need unique names. Use 9 characters or less. | string | ✓ | | 0-bootstrap | | [custom_adv](variables.tf#L38) | Custom advertisement definitions in name => range format. | map(string) | | {…} | | | [custom_roles](variables.tf#L55) | Custom roles defined at the org level, in key => id format. | object({…}) | | null | 0-bootstrap | | [data_dir](variables.tf#L64) | Relative path for the folder storing configuration data for network resources. | string | | "data" | | | [dns](variables.tf#L70) | Onprem DNS resolvers. | map(list(string)) | | {…} | | -| [l7ilb_subnets](variables.tf#L88) | Subnets used for L7 ILBs. | map(list(object({…}))) | | {…} | | -| [outputs_location](variables.tf#L116) | Path where providers and tfvars files for the following stages are written. Leave empty to disable. | string | | null | | -| [psa_ranges](variables.tf#L133) | IP ranges used for Private Service Access (e.g. CloudSQL). | object({…}) | | null | | -| [region_trigram](variables.tf#L170) | Short names for GCP regions. | map(string) | | {…} | | -| [router_onprem_configs](variables.tf#L179) | Configurations for routers used for onprem connectivity. | map(object({…})) | | {…} | | -| [router_spoke_configs](variables-vpn.tf#L18) | Configurations for routers used for internal connectivity. | map(object({…})) | | {…} | | -| [service_accounts](variables.tf#L197) | Automation service accounts in name => email format. | object({…}) | | null | 1-resman | -| [vpn_onprem_configs](variables.tf#L211) | VPN gateway configuration for onprem interconnection. | map(object({…})) | | {…} | | -| [vpn_spoke_configs](variables-vpn.tf#L37) | VPN gateway configuration for spokes. | map(object({…})) | | {…} | | +| [l7ilb_subnets](variables.tf#L88) | Subnets used for L7 ILBs. | object({…}) | | {…} | | +| [outputs_location](variables.tf#L122) | Path where providers and tfvars files for the following stages are written. Leave empty to disable. | string | | null | | +| [psa_ranges](variables.tf#L139) | IP ranges used for Private Service Access (e.g. CloudSQL). | object({…}) | | null | | +| [regions](variables.tf#L176) | Region definitions. | object({…}) | | {…} | | +| [router_onprem_configs](variables.tf#L188) | Configurations for routers used for onprem connectivity. | map(object({…})) | | {…} | | +| [router_spoke_configs](variables-vpn.tf#L18) | Configurations for routers used for internal connectivity. | map(object({…})) | | {…} | | +| [service_accounts](variables.tf#L206) | Automation service accounts in name => email format. | object({…}) | | null | 1-resman | +| [vpn_onprem_configs](variables.tf#L220) | VPN gateway configuration for onprem interconnection. | map(object({…})) | | {…} | | +| [vpn_spoke_configs](variables-vpn.tf#L37) | VPN gateway configuration for spokes. | map(object({…})) | | {…} | | ## Outputs diff --git a/fast/stages/2-networking-b-vpn/landing.tf b/fast/stages/2-networking-b-vpn/landing.tf index 83a0d509af..2e84733ad5 100644 --- a/fast/stages/2-networking-b-vpn/landing.tf +++ b/fast/stages/2-networking-b-vpn/landing.tf @@ -79,13 +79,18 @@ module "landing-firewall" { } } -module "landing-nat-ew1" { +moved { + from = module.landing-nat-ew1 + to = module.landing-nat-primary +} + +module "landing-nat-primary" { source = "../../../modules/net-cloudnat" project_id = module.landing-project.project_id - region = "europe-west1" - name = "ew1" + region = var.regions.primary + name = local.region_shortnames[var.regions.primary] router_create = true - router_name = "prod-nat-ew1" + router_name = "prod-nat-${local.region_shortnames[var.regions.primary]}" router_network = module.landing-vpc.name router_asn = 4200001024 } diff --git a/fast/stages/2-networking-b-vpn/main.tf b/fast/stages/2-networking-b-vpn/main.tf index f68d39eb85..33370c8b32 100644 --- a/fast/stages/2-networking-b-vpn/main.tf +++ b/fast/stages/2-networking-b-vpn/main.tf @@ -17,14 +17,14 @@ # tfdoc:file:description Networking folder and hierarchical policy. locals { + # combine all regions from variables and subnets + regions = distinct(concat( + [var.regions.primary, var.regions.secondary], + values(module.dev-spoke-vpc.subnet_regions), + values(module.landing-vpc.subnet_regions), + values(module.prod-spoke-vpc.subnet_regions), + )) custom_roles = coalesce(var.custom_roles, {}) - l7ilb_subnets = { - for env, v in var.l7ilb_subnets : env => [ - for s in v : merge(s, { - active = true - name = "${env}-l7ilb-${s.region}" - })] - } stage3_sas_delegated_grants = [ "roles/composer.sharedVpcAgent", "roles/compute.networkUser", diff --git a/fast/stages/2-networking-b-vpn/outputs.tf b/fast/stages/2-networking-b-vpn/outputs.tf index 0e101f4123..628c706b38 100644 --- a/fast/stages/2-networking-b-vpn/outputs.tf +++ b/fast/stages/2-networking-b-vpn/outputs.tf @@ -89,8 +89,8 @@ output "tfvars" { output "vpn_gateway_endpoints" { description = "External IP Addresses for the GCP VPN gateways." value = local.enable_onprem_vpn == false ? null : { - onprem-ew1 = { - for v in module.landing-to-onprem-ew1-vpn[0].gateway.vpn_interfaces : + onprem-primary = { + for v in module.landing-to-onprem-primary-vpn[0].gateway.vpn_interfaces : v.id => v.ip_address } } diff --git a/fast/stages/2-networking-b-vpn/regions.tf b/fast/stages/2-networking-b-vpn/regions.tf new file mode 100644 index 0000000000..53514afa9b --- /dev/null +++ b/fast/stages/2-networking-b-vpn/regions.tf @@ -0,0 +1,42 @@ +/** + * 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. + */ + +# tfdoc:file:description Compute short names for regions. + +locals { + # only map when the first character would not work + _region_cardinal = { + southeast = "se" + } + # only map when the first character would not work + _region_geo = { + australia = "o" + } + # split in [geo, cardinal, number] tokens + _region_tokens = { + for v in local.regions : v => regexall("(?:[a-z]+)|(?:[0-9]+)", v) + } + region_shortnames = { + for k, v in local._region_tokens : k => join("", [ + # first token via geo alias map or first character + lookup(local._region_geo, v.0, substr(v.0, 0, 1)), + # first token via cardinal alias map or first character + lookup(local._region_cardinal, v.1, substr(v.1, 0, 1)), + # region number as is + v.2 + ]) + } +} diff --git a/fast/stages/2-networking-b-vpn/spoke-dev.tf b/fast/stages/2-networking-b-vpn/spoke-dev.tf index e67cfb70db..966d709cb7 100644 --- a/fast/stages/2-networking-b-vpn/spoke-dev.tf +++ b/fast/stages/2-networking-b-vpn/spoke-dev.tf @@ -16,6 +16,19 @@ # tfdoc:file:description Dev spoke VPC and related resources. +locals { + _l7ilb_subnets_dev = [ + for v in var.l7ilb_subnets.dev : merge(v, { + active = true + region = lookup(var.regions, v.region, v.region) + })] + l7ilb_subnets_dev = [ + for v in local._l7ilb_subnets_dev : merge(v, { + name = "dev-l7ilb-${local.region_shortnames[v.region]}" + }) + ] +} + module "dev-spoke-project" { source = "../../../modules/project" billing_account = var.billing_account.id @@ -50,7 +63,7 @@ module "dev-spoke-vpc" { mtu = 1500 data_folder = "${var.data_dir}/subnets/dev" psa_config = try(var.psa_ranges.dev, null) - subnets_proxy_only = local.l7ilb_subnets.dev + subnets_proxy_only = local.l7ilb_subnets_dev # set explicit routes for googleapis in case the default route is deleted routes = { private-googleapis = { @@ -84,7 +97,7 @@ module "dev-spoke-cloudnat" { source = "../../../modules/net-cloudnat" project_id = module.dev-spoke-project.project_id region = each.value - name = "dev-nat-${var.region_trigram[each.value]}" + name = "dev-nat-${local.region_shortnames[each.value]}" router_create = true router_network = module.dev-spoke-vpc.name router_asn = 4200001024 diff --git a/fast/stages/2-networking-b-vpn/spoke-prod.tf b/fast/stages/2-networking-b-vpn/spoke-prod.tf index cf49152fa1..7ce7dff4d3 100644 --- a/fast/stages/2-networking-b-vpn/spoke-prod.tf +++ b/fast/stages/2-networking-b-vpn/spoke-prod.tf @@ -16,6 +16,19 @@ # tfdoc:file:description Production spoke VPC and related resources. +locals { + _l7ilb_subnets_prod = [ + for v in var.l7ilb_subnets.prod : merge(v, { + active = true + region = lookup(var.regions, v.region, v.region) + })] + l7ilb_subnets_prod = [ + for v in local._l7ilb_subnets_prod : merge(v, { + name = "prod-l7ilb-${local.region_shortnames[v.region]}" + }) + ] +} + module "prod-spoke-project" { source = "../../../modules/project" billing_account = var.billing_account.id @@ -50,7 +63,7 @@ module "prod-spoke-vpc" { mtu = 1500 data_folder = "${var.data_dir}/subnets/prod" psa_config = try(var.psa_ranges.prod, null) - subnets_proxy_only = local.l7ilb_subnets.prod + subnets_proxy_only = local.l7ilb_subnets_prod # set explicit routes for googleapis in case the default route is deleted routes = { private-googleapis = { @@ -84,7 +97,7 @@ module "prod-spoke-cloudnat" { source = "../../../modules/net-cloudnat" project_id = module.prod-spoke-project.project_id region = each.value - name = "prod-nat-${var.region_trigram[each.value]}" + name = "prod-nat-${local.region_shortnames[each.value]}" router_create = true router_network = module.prod-spoke-vpc.name router_asn = 4200001024 diff --git a/fast/stages/2-networking-b-vpn/variables-vpn.tf b/fast/stages/2-networking-b-vpn/variables-vpn.tf index 3a6d756783..a6aab329aa 100644 --- a/fast/stages/2-networking-b-vpn/variables-vpn.tf +++ b/fast/stages/2-networking-b-vpn/variables-vpn.tf @@ -25,12 +25,12 @@ variable "router_spoke_configs" { asn = number })) default = { - landing-ew1 = { asn = "64512", adv = null } - landing-ew4 = { asn = "64512", adv = null } - spoke-dev-ew1 = { asn = "64513", adv = null } - spoke-dev-ew4 = { asn = "64513", adv = null } - spoke-prod-ew1 = { asn = "64514", adv = null } - spoke-prod-ew4 = { asn = "64514", adv = null } + landing-primary = { asn = "64512", adv = null } + landing-secondary = { asn = "64512", adv = null } + spoke-dev-primary = { asn = "64513", adv = null } + spoke-dev-secondary = { asn = "64513", adv = null } + spoke-prod-primary = { asn = "64514", adv = null } + spoke-prod-secondary = { asn = "64514", adv = null } } } @@ -41,23 +41,23 @@ variable "vpn_spoke_configs" { custom = list(string) })) default = { - landing-ew1 = { + landing-primary = { default = false custom = ["rfc_1918_10", "rfc_1918_172", "rfc_1918_192"] } - landing-ew4 = { + landing-secondary = { default = false custom = ["rfc_1918_10", "rfc_1918_172", "rfc_1918_192"] } - dev-ew1 = { + dev-primary = { default = false custom = ["gcp_dev"] } - prod-ew1 = { + prod-primary = { default = false custom = ["gcp_prod"] } - prod-ew4 = { + prod-secondary = { default = false custom = ["gcp_prod"] } diff --git a/fast/stages/2-networking-b-vpn/variables.tf b/fast/stages/2-networking-b-vpn/variables.tf index fb2fd8745b..ff85422b4d 100644 --- a/fast/stages/2-networking-b-vpn/variables.tf +++ b/fast/stages/2-networking-b-vpn/variables.tf @@ -87,18 +87,24 @@ variable "folder_ids" { variable "l7ilb_subnets" { description = "Subnets used for L7 ILBs." - type = map(list(object({ - ip_cidr_range = string - region = string - }))) + type = object({ + dev = optional(list(object({ + ip_cidr_range = string + region = string + })), []) + prod = optional(list(object({ + ip_cidr_range = string + region = string + })), []) + }) default = { - prod = [ - { ip_cidr_range = "10.128.92.0/24", region = "europe-west1" }, - { ip_cidr_range = "10.128.93.0/24", region = "europe-west4" } - ] dev = [ - { ip_cidr_range = "10.128.60.0/24", region = "europe-west1" }, - { ip_cidr_range = "10.128.61.0/24", region = "europe-west4" } + { ip_cidr_range = "10.128.60.0/24", region = "primary" }, + { ip_cidr_range = "10.128.61.0/24", region = "secondary" } + ] + prod = [ + { ip_cidr_range = "10.128.92.0/24", region = "primary" }, + { ip_cidr_range = "10.128.93.0/24", region = "secondary" } ] } } @@ -167,12 +173,15 @@ variable "psa_ranges" { # } } -variable "region_trigram" { - description = "Short names for GCP regions." - type = map(string) +variable "regions" { + description = "Region definitions." + type = object({ + primary = string + secondary = string + }) default = { - europe-west1 = "ew1" - europe-west3 = "ew3" + primary = "europe-west1" + secondary = "europe-west4" } } @@ -186,7 +195,7 @@ variable "router_onprem_configs" { asn = number })) default = { - landing-ew1 = { + landing-primary = { asn = "65533" adv = null # adv = { default = false, custom = [] } @@ -228,7 +237,7 @@ variable "vpn_onprem_configs" { })) })) default = { - landing-ew1 = { + landing-primary = { adv = { default = false custom = [ diff --git a/fast/stages/2-networking-b-vpn/vpn-onprem.tf b/fast/stages/2-networking-b-vpn/vpn-onprem.tf index 5237a05acb..a04a009765 100644 --- a/fast/stages/2-networking-b-vpn/vpn-onprem.tf +++ b/fast/stages/2-networking-b-vpn/vpn-onprem.tf @@ -32,28 +32,33 @@ locals { } } -module "landing-to-onprem-ew1-vpn" { +moved { + from = module.landing-to-onprem-ew1-vpn + to = module.landing-to-onprem-primary-vpn +} + +module "landing-to-onprem-primary-vpn" { count = local.enable_onprem_vpn ? 1 : 0 source = "../../../modules/net-vpn-ha" project_id = module.landing-project.project_id network = module.landing-vpc.self_link - region = "europe-west1" - name = "vpn-to-onprem-ew1" + region = var.regions.primary + name = "vpn-to-onprem-${local.region_shortnames[var.regions.primary]}" router_config = { - name = "landing-onprem-vpn-ew1" - asn = var.router_onprem_configs.landing-ew1.asn + name = "landing-onprem-vpn-${local.region_shortnames[var.regions.primary]}" + asn = var.router_onprem_configs.landing-primary.asn } peer_gateway = { - external = var.vpn_onprem_configs.landing-ew1.peer_external_gateway + external = var.vpn_onprem_configs.landing-primary.peer_external_gateway } tunnels = { - for t in var.vpn_onprem_configs.landing-ew1.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-ew1 + 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 diff --git a/fast/stages/2-networking-b-vpn/vpn-spoke-dev.tf b/fast/stages/2-networking-b-vpn/vpn-spoke-dev.tf index 317560af00..09cc31e03e 100644 --- a/fast/stages/2-networking-b-vpn/vpn-spoke-dev.tf +++ b/fast/stages/2-networking-b-vpn/vpn-spoke-dev.tf @@ -33,26 +33,31 @@ locals { # development spoke -module "landing-to-dev-ew1-vpn" { +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 = "europe-west1" - name = "vpn-to-dev-ew1" + 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-ew1" - asn = var.router_spoke_configs.landing-ew1.asn + name = "landing-vpn-${local.region_shortnames[var.regions.primary]}" + asn = var.router_spoke_configs.landing-primary.asn } - peer_gateway = { gcp = module.dev-to-landing-ew1-vpn.self_link } + peer_gateway = { 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-ew1.asn + asn = var.router_spoke_configs.spoke-dev-primary.asn } - bgp_peer_options = local.vpn_spoke_bgp_peer_options.landing-ew1 + bgp_peer_options = local.vpn_spoke_bgp_peer_options.landing-primary bgp_session_range = "${ cidrhost("169.254.0.0/27", 2) }/30" @@ -61,9 +66,9 @@ module "landing-to-dev-ew1-vpn" { 1 = { bgp_peer = { address = cidrhost("169.254.0.0/27", 5) - asn = var.router_spoke_configs.spoke-dev-ew1.asn + asn = var.router_spoke_configs.spoke-dev-primary.asn } - bgp_peer_options = local.vpn_spoke_bgp_peer_options.landing-ew1 + bgp_peer_options = local.vpn_spoke_bgp_peer_options.landing-primary bgp_session_range = "${ cidrhost("169.254.0.0/27", 6) }/30" @@ -71,44 +76,49 @@ module "landing-to-dev-ew1-vpn" { } } depends_on = [ - module.landing-to-prod-ew1-vpn.router + module.landing-to-prod-primary-vpn.router ] } -module "dev-to-landing-ew1-vpn" { +moved { + from = module.dev-to-landing-ew1-vpn + to = module.dev-to-landing-primary-vpn +} + +module "dev-to-landing-primary-vpn" { source = "../../../modules/net-vpn-ha" project_id = module.dev-spoke-project.project_id network = module.dev-spoke-vpc.self_link - region = "europe-west1" - name = "vpn-to-landing-ew1" + region = var.regions.primary + name = "vpn-to-landing-${local.region_shortnames[var.regions.primary]}" router_config = { - name = "dev-spoke-vpn-ew1" - asn = var.router_spoke_configs.spoke-dev-ew1.asn + name = "dev-spoke-vpn-${local.region_shortnames[var.regions.primary]}" + asn = var.router_spoke_configs.spoke-dev-primary.asn } - peer_gateway = { gcp = module.landing-to-dev-ew1-vpn.self_link } + peer_gateway = { gcp = module.landing-to-dev-primary-vpn.self_link } tunnels = { 0 = { bgp_peer = { address = cidrhost("169.254.0.0/27", 2) - asn = var.router_spoke_configs.landing-ew1.asn + asn = var.router_spoke_configs.landing-primary.asn } - bgp_peer_options = local.vpn_spoke_bgp_peer_options.dev-ew1 + bgp_peer_options = local.vpn_spoke_bgp_peer_options.dev-primary bgp_session_range = "${ cidrhost("169.254.0.0/27", 1) }/30" - shared_secret = module.landing-to-dev-ew1-vpn.random_secret + shared_secret = module.landing-to-dev-primary-vpn.random_secret vpn_gateway_interface = 0 } 1 = { bgp_peer = { address = cidrhost("169.254.0.0/27", 6) - asn = var.router_spoke_configs.landing-ew1.asn + asn = var.router_spoke_configs.landing-primary.asn } - bgp_peer_options = local.vpn_spoke_bgp_peer_options.dev-ew1 + bgp_peer_options = local.vpn_spoke_bgp_peer_options.dev-primary bgp_session_range = "${ cidrhost("169.254.0.0/27", 5) }/30" - shared_secret = module.landing-to-dev-ew1-vpn.random_secret + shared_secret = module.landing-to-dev-primary-vpn.random_secret vpn_gateway_interface = 1 } } diff --git a/fast/stages/2-networking-b-vpn/vpn-spoke-prod-ew1.tf b/fast/stages/2-networking-b-vpn/vpn-spoke-prod-primary.tf similarity index 58% rename from fast/stages/2-networking-b-vpn/vpn-spoke-prod-ew1.tf rename to fast/stages/2-networking-b-vpn/vpn-spoke-prod-primary.tf index a215ad4efb..071b1d0545 100644 --- a/fast/stages/2-networking-b-vpn/vpn-spoke-prod-ew1.tf +++ b/fast/stages/2-networking-b-vpn/vpn-spoke-prod-primary.tf @@ -18,24 +18,29 @@ # local.vpn_spoke_bgp_peer_options is defined in the dev VPN file -module "landing-to-prod-ew1-vpn" { +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 = "europe-west1" - name = "vpn-to-prod-ew1" + region = var.regions.primary + name = "vpn-to-prod-${local.region_shortnames[var.regions.primary]}" router_config = { - name = "landing-vpn-ew1" - asn = var.router_spoke_configs.landing-ew1.asn + name = "landing-vpn-${local.region_shortnames[var.regions.primary]}" + asn = var.router_spoke_configs.landing-primary.asn } - peer_gateway = { gcp = module.prod-to-landing-ew1-vpn.self_link } + peer_gateway = { 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-ew1.asn + asn = var.router_spoke_configs.spoke-prod-primary.asn } - bgp_peer_options = local.vpn_spoke_bgp_peer_options.landing-ew1 + bgp_peer_options = local.vpn_spoke_bgp_peer_options.landing-primary bgp_session_range = "${ cidrhost("169.254.0.64/27", 2) }/30" @@ -44,9 +49,9 @@ module "landing-to-prod-ew1-vpn" { 1 = { bgp_peer = { address = cidrhost("169.254.0.64/27", 5) - asn = var.router_spoke_configs.spoke-prod-ew1.asn + asn = var.router_spoke_configs.spoke-prod-primary.asn } - bgp_peer_options = local.vpn_spoke_bgp_peer_options.landing-ew1 + bgp_peer_options = local.vpn_spoke_bgp_peer_options.landing-primary bgp_session_range = "${ cidrhost("169.254.0.64/27", 6) }/30" @@ -55,40 +60,45 @@ module "landing-to-prod-ew1-vpn" { } } -module "prod-to-landing-ew1-vpn" { +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 = "europe-west1" - name = "vpn-to-landing-ew1" + region = var.regions.primary + name = "vpn-to-landing-${local.region_shortnames[var.regions.primary]}" router_config = { - name = "prod-spoke-vpn-ew1" - asn = var.router_spoke_configs.spoke-prod-ew1.asn + name = "prod-spoke-vpn-${local.region_shortnames[var.regions.primary]}" + asn = var.router_spoke_configs.spoke-prod-primary.asn } - peer_gateway = { gcp = module.landing-to-prod-ew1-vpn.self_link } + peer_gateway = { 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-ew1.asn + asn = var.router_spoke_configs.landing-primary.asn } - bgp_peer_options = local.vpn_spoke_bgp_peer_options.prod-ew1 + 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-ew1-vpn.random_secret + 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-ew1.asn + asn = var.router_spoke_configs.landing-primary.asn } - bgp_peer_options = local.vpn_spoke_bgp_peer_options.prod-ew1 + 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-ew1-vpn.random_secret + shared_secret = module.landing-to-prod-primary-vpn.random_secret vpn_gateway_interface = 1 } } diff --git a/fast/stages/2-networking-b-vpn/vpn-spoke-prod-ew4.tf b/fast/stages/2-networking-b-vpn/vpn-spoke-prod-secondary.tf similarity index 57% rename from fast/stages/2-networking-b-vpn/vpn-spoke-prod-ew4.tf rename to fast/stages/2-networking-b-vpn/vpn-spoke-prod-secondary.tf index 994fba0b1c..a7c0e0fe18 100644 --- a/fast/stages/2-networking-b-vpn/vpn-spoke-prod-ew4.tf +++ b/fast/stages/2-networking-b-vpn/vpn-spoke-prod-secondary.tf @@ -18,24 +18,29 @@ # local.vpn_spoke_bgp_peer_options is defined in the dev VPN file -module "landing-to-prod-ew4-vpn" { +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 = "europe-west4" - name = "vpn-to-prod-ew4" + region = var.regions.secondary + name = "vpn-to-prod-${local.region_shortnames[var.regions.secondary]}" router_config = { - name = "landing-vpn-ew4" - asn = var.router_spoke_configs.landing-ew4.asn + name = "landing-vpn-${local.region_shortnames[var.regions.secondary]}" + asn = var.router_spoke_configs.landing-secondary.asn } - peer_gateway = { gcp = module.prod-to-landing-ew4-vpn.self_link } + peer_gateway = { 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-ew4.asn + asn = var.router_spoke_configs.spoke-prod-secondary.asn } - bgp_peer_options = local.vpn_spoke_bgp_peer_options.landing-ew4 + bgp_peer_options = local.vpn_spoke_bgp_peer_options.landing-secondary bgp_session_range = "${ cidrhost("169.254.0.96/27", 2) }/30" @@ -44,9 +49,9 @@ module "landing-to-prod-ew4-vpn" { 1 = { bgp_peer = { address = cidrhost("169.254.0.96/27", 5) - asn = var.router_spoke_configs.spoke-prod-ew4.asn + asn = var.router_spoke_configs.spoke-prod-secondary.asn } - bgp_peer_options = local.vpn_spoke_bgp_peer_options.landing-ew4 + bgp_peer_options = local.vpn_spoke_bgp_peer_options.landing-secondary bgp_session_range = "${ cidrhost("169.254.0.96/27", 6) }/30" @@ -55,40 +60,45 @@ module "landing-to-prod-ew4-vpn" { } } -module "prod-to-landing-ew4-vpn" { +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 = "europe-west4" - name = "vpn-to-landing-ew4" + region = var.regions.secondary + name = "vpn-to-landing-${local.region_shortnames[var.regions.secondary]}" router_config = { - name = "prod-spoke-vpn-ew4" - asn = var.router_spoke_configs.spoke-prod-ew4.asn + name = "prod-spoke-vpn-${local.region_shortnames[var.regions.secondary]}" + asn = var.router_spoke_configs.spoke-prod-secondary.asn } - peer_gateway = { gcp = module.landing-to-prod-ew4-vpn.self_link } + peer_gateway = { 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-ew4.asn + asn = var.router_spoke_configs.landing-secondary.asn } - bgp_peer_options = local.vpn_spoke_bgp_peer_options.prod-ew4 + 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-ew4-vpn.random_secret + 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-ew4.asn + asn = var.router_spoke_configs.landing-secondary.asn } - bgp_peer_options = local.vpn_spoke_bgp_peer_options.prod-ew4 + 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-ew4-vpn.random_secret + shared_secret = module.landing-to-prod-secondary-vpn.random_secret vpn_gateway_interface = 1 } } diff --git a/tests/fast/stages/s2_networking_a_peering/common.tfvars b/tests/fast/stages/s2_networking_a_peering/common.tfvars index d3e0779fc3..6c2b0c0307 100644 --- a/tests/fast/stages/s2_networking_a_peering/common.tfvars +++ b/tests/fast/stages/s2_networking_a_peering/common.tfvars @@ -13,11 +13,6 @@ folder_ids = { networking-dev = null networking-prod = null } -region_trigram = { - europe-west1 = "ew1" - europe-west3 = "ew3" - europe-west8 = "ew8" -} service_accounts = { data-platform-dev = "string" data-platform-prod = "string" From dbb591b5386e1ef8d1fd23ed9cd9ef6822700f3f Mon Sep 17 00:00:00 2001 From: Ludo Date: Tue, 7 Feb 2023 18:05:19 +0100 Subject: [PATCH 03/16] tfdoc --- fast/stages/2-networking-a-peering/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/fast/stages/2-networking-a-peering/README.md b/fast/stages/2-networking-a-peering/README.md index 3eb0c1612d..588e0dc914 100644 --- a/fast/stages/2-networking-a-peering/README.md +++ b/fast/stages/2-networking-a-peering/README.md @@ -284,6 +284,7 @@ DNS configurations are centralised in the `dns-*.tf` files. Spokes delegate DNS | [monitoring.tf](./monitoring.tf) | Network monitoring dashboards. | | google_monitoring_dashboard | | [outputs.tf](./outputs.tf) | Module outputs. | | google_storage_bucket_object · local_file | | [peerings.tf](./peerings.tf) | None | net-vpc-peering | | +| [regions.tf](./regions.tf) | Compute short names for regions. | | | | [spoke-dev.tf](./spoke-dev.tf) | Dev spoke VPC and related resources. | net-cloudnat · net-vpc · net-vpc-firewall · project | google_project_iam_binding | | [spoke-prod.tf](./spoke-prod.tf) | Production spoke VPC and related resources. | net-cloudnat · net-vpc · net-vpc-firewall · project | google_project_iam_binding | | [test-resources.tf](./test-resources.tf) | temporary instances for testing | compute-vm | | From fc59a1ff7d6c74e686f0c70e7cb799d78715589d Mon Sep 17 00:00:00 2001 From: Ludo Date: Tue, 7 Feb 2023 20:44:50 +0100 Subject: [PATCH 04/16] separate envs --- fast/stages/2-networking-a-peering/main.tf | 2 +- fast/stages/2-networking-b-vpn/main.tf | 2 +- .../2-networking-d-separate-envs/README.md | 18 ++++---- .../2-networking-d-separate-envs/main.tf | 20 ++++++--- .../2-networking-d-separate-envs/outputs.tf | 8 ++-- .../2-networking-d-separate-envs/regions.tf | 42 +++++++++++++++++++ .../2-networking-d-separate-envs/spoke-dev.tf | 2 +- .../spoke-prod.tf | 2 +- .../2-networking-d-separate-envs/variables.tf | 20 ++++++--- .../vpn-onprem-dev.tf | 21 ++++++---- .../vpn-onprem-prod.tf | 21 ++++++---- 11 files changed, 114 insertions(+), 44 deletions(-) create mode 100644 fast/stages/2-networking-d-separate-envs/regions.tf diff --git a/fast/stages/2-networking-a-peering/main.tf b/fast/stages/2-networking-a-peering/main.tf index 33370c8b32..cfa41591e6 100644 --- a/fast/stages/2-networking-a-peering/main.tf +++ b/fast/stages/2-networking-a-peering/main.tf @@ -19,7 +19,7 @@ locals { # combine all regions from variables and subnets regions = distinct(concat( - [var.regions.primary, var.regions.secondary], + values(var.regions), values(module.dev-spoke-vpc.subnet_regions), values(module.landing-vpc.subnet_regions), values(module.prod-spoke-vpc.subnet_regions), diff --git a/fast/stages/2-networking-b-vpn/main.tf b/fast/stages/2-networking-b-vpn/main.tf index 33370c8b32..cfa41591e6 100644 --- a/fast/stages/2-networking-b-vpn/main.tf +++ b/fast/stages/2-networking-b-vpn/main.tf @@ -19,7 +19,7 @@ locals { # combine all regions from variables and subnets regions = distinct(concat( - [var.regions.primary, var.regions.secondary], + values(var.regions), values(module.dev-spoke-vpc.subnet_regions), values(module.landing-vpc.subnet_regions), values(module.prod-spoke-vpc.subnet_regions), diff --git a/fast/stages/2-networking-d-separate-envs/README.md b/fast/stages/2-networking-d-separate-envs/README.md index ad36ca3a1b..bd43a8d307 100644 --- a/fast/stages/2-networking-d-separate-envs/README.md +++ b/fast/stages/2-networking-d-separate-envs/README.md @@ -227,6 +227,7 @@ You're now ready to run `terraform init` and `apply`. | [main.tf](./main.tf) | Networking folder and hierarchical policy. | folder | | | [monitoring.tf](./monitoring.tf) | Network monitoring dashboards. | | google_monitoring_dashboard | | [outputs.tf](./outputs.tf) | Module outputs. | | google_storage_bucket_object · local_file | +| [regions.tf](./regions.tf) | Compute short names for regions. | | | | [spoke-dev.tf](./spoke-dev.tf) | Dev spoke VPC and related resources. | net-cloudnat · net-vpc · net-vpc-firewall · project | google_project_iam_binding | | [spoke-prod.tf](./spoke-prod.tf) | Production spoke VPC and related resources. | net-cloudnat · net-vpc · net-vpc-firewall · project | google_project_iam_binding | | [test-resources.tf](./test-resources.tf) | Temporary instances for testing | compute-vm | | @@ -241,18 +242,19 @@ You're now ready to run `terraform init` and `apply`. | [automation](variables.tf#L17) | Automation resources created by the bootstrap stage. | object({…}) | ✓ | | 0-bootstrap | | [billing_account](variables.tf#L25) | Billing account id. If billing account is not part of the same org set `is_org_level` to false. | object({…}) | ✓ | | 0-bootstrap | | [folder_ids](variables.tf#L78) | Folders to be used for the networking resources in folders/nnnnnnnnnnn format. If null, folder will be created. | object({…}) | ✓ | | 1-resman | -| [organization](variables.tf#L106) | Organization details. | object({…}) | ✓ | | 0-bootstrap | -| [prefix](variables.tf#L122) | Prefix used for resources that need unique names. Use 9 characters or less. | string | ✓ | | 0-bootstrap | +| [organization](variables.tf#L104) | Organization details. | object({…}) | ✓ | | 0-bootstrap | +| [prefix](variables.tf#L120) | Prefix used for resources that need unique names. Use 9 characters or less. | string | ✓ | | 0-bootstrap | | [custom_adv](variables.tf#L38) | Custom advertisement definitions in name => range format. | map(string) | | {…} | | | [custom_roles](variables.tf#L54) | Custom roles defined at the org level, in key => id format. | object({…}) | | null | 0-bootstrap | | [data_dir](variables.tf#L63) | Relative path for the folder storing configuration data for network resources. | string | | "data" | | | [dns](variables.tf#L69) | Onprem DNS resolvers. | map(list(string)) | | {…} | | -| [l7ilb_subnets](variables.tf#L88) | Subnets used for L7 ILBs. | map(list(object({…}))) | | {…} | | -| [outputs_location](variables.tf#L116) | Path where providers and tfvars files for the following stages are written. Leave empty to disable. | string | | null | | -| [psa_ranges](variables.tf#L133) | IP ranges used for Private Service Access (e.g. CloudSQL). | object({…}) | | null | | -| [router_onprem_configs](variables.tf#L170) | Configurations for routers used for onprem connectivity. | map(object({…})) | | {…} | | -| [service_accounts](variables.tf#L193) | Automation service accounts in name => email format. | object({…}) | | null | 1-resman | -| [vpn_onprem_configs](variables.tf#L205) | VPN gateway configuration for onprem interconnection. | map(object({…})) | | {…} | | +| [l7ilb_subnets](variables.tf#L88) | Subnets used for L7 ILBs. | map(list(object({…}))) | | {…} | | +| [outputs_location](variables.tf#L114) | Path where providers and tfvars files for the following stages are written. Leave empty to disable. | string | | null | | +| [psa_ranges](variables.tf#L131) | IP ranges used for Private Service Access (e.g. CloudSQL). | object({…}) | | null | | +| [regions](variables.tf#L168) | Region definitions. | object({…}) | | {…} | | +| [router_onprem_configs](variables.tf#L178) | Configurations for routers used for onprem connectivity. | map(object({…})) | | {…} | | +| [service_accounts](variables.tf#L201) | Automation service accounts in name => email format. | object({…}) | | null | 1-resman | +| [vpn_onprem_configs](variables.tf#L213) | VPN gateway configuration for onprem interconnection. | map(object({…})) | | {…} | | ## Outputs diff --git a/fast/stages/2-networking-d-separate-envs/main.tf b/fast/stages/2-networking-d-separate-envs/main.tf index 0b901e3307..cb7374be0b 100644 --- a/fast/stages/2-networking-d-separate-envs/main.tf +++ b/fast/stages/2-networking-d-separate-envs/main.tf @@ -18,17 +18,25 @@ locals { custom_roles = coalesce(var.custom_roles, {}) - l7ilb_subnets = { - for env, v in var.l7ilb_subnets : env => [ + _l7ilb_subnets = { + for k, v in var.l7ilb_subnets : k => [ for s in v : merge(s, { active = true - name = "${env}-l7ilb-${s.region}" + region = lookup(var.regions, s.region, s.region) })] } - region_trigram = { - europe-west1 = "ew1" - europe-west3 = "ew3" + l7ilb_subnets = { + for k, v in local._l7ilb_subnets : k => [ + for s in v : merge(s, { + name = "${k}-l7ilb-${local.region_shortnames[s.region]}" + })] } + # combine all regions from variables and subnets + regions = distinct(concat( + values(var.regions), + values(module.dev-spoke-vpc.subnet_regions), + values(module.prod-spoke-vpc.subnet_regions), + )) stage3_sas_delegated_grants = [ "roles/composer.sharedVpcAgent", "roles/compute.networkUser", diff --git a/fast/stages/2-networking-d-separate-envs/outputs.tf b/fast/stages/2-networking-d-separate-envs/outputs.tf index 97b0dc059e..59d70db6d2 100644 --- a/fast/stages/2-networking-d-separate-envs/outputs.tf +++ b/fast/stages/2-networking-d-separate-envs/outputs.tf @@ -90,12 +90,12 @@ output "tfvars" { output "vpn_gateway_endpoints" { description = "External IP Addresses for the GCP VPN gateways." value = local.enable_onprem_vpn == false ? null : { - dev-onprem-ew1 = { - for v in module.dev-to-onprem-ew1-vpn[0].gateway.vpn_interfaces : + dev-onprem-primary = { + for v in module.dev-to-onprem-primary-vpn[0].gateway.vpn_interfaces : v.id => v.ip_address } - prod-onprem-ew1 = { - for v in module.prod-to-onprem-ew1-vpn[0].gateway.vpn_interfaces : + prod-onprem-primary = { + for v in module.prod-to-onprem-primary-vpn[0].gateway.vpn_interfaces : v.id => v.ip_address } } diff --git a/fast/stages/2-networking-d-separate-envs/regions.tf b/fast/stages/2-networking-d-separate-envs/regions.tf new file mode 100644 index 0000000000..53514afa9b --- /dev/null +++ b/fast/stages/2-networking-d-separate-envs/regions.tf @@ -0,0 +1,42 @@ +/** + * 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. + */ + +# tfdoc:file:description Compute short names for regions. + +locals { + # only map when the first character would not work + _region_cardinal = { + southeast = "se" + } + # only map when the first character would not work + _region_geo = { + australia = "o" + } + # split in [geo, cardinal, number] tokens + _region_tokens = { + for v in local.regions : v => regexall("(?:[a-z]+)|(?:[0-9]+)", v) + } + region_shortnames = { + for k, v in local._region_tokens : k => join("", [ + # first token via geo alias map or first character + lookup(local._region_geo, v.0, substr(v.0, 0, 1)), + # first token via cardinal alias map or first character + lookup(local._region_cardinal, v.1, substr(v.1, 0, 1)), + # region number as is + v.2 + ]) + } +} diff --git a/fast/stages/2-networking-d-separate-envs/spoke-dev.tf b/fast/stages/2-networking-d-separate-envs/spoke-dev.tf index ca7d8d4686..e600531b88 100644 --- a/fast/stages/2-networking-d-separate-envs/spoke-dev.tf +++ b/fast/stages/2-networking-d-separate-envs/spoke-dev.tf @@ -83,7 +83,7 @@ module "dev-spoke-cloudnat" { source = "../../../modules/net-cloudnat" project_id = module.dev-spoke-project.project_id region = each.value - name = "dev-nat-${local.region_trigram[each.value]}" + name = "dev-nat-${local.region_shortnames[each.value]}" router_create = true router_network = module.dev-spoke-vpc.name router_asn = 4200001024 diff --git a/fast/stages/2-networking-d-separate-envs/spoke-prod.tf b/fast/stages/2-networking-d-separate-envs/spoke-prod.tf index eba530a6c4..2a4b054ed1 100644 --- a/fast/stages/2-networking-d-separate-envs/spoke-prod.tf +++ b/fast/stages/2-networking-d-separate-envs/spoke-prod.tf @@ -83,7 +83,7 @@ module "prod-spoke-cloudnat" { source = "../../../modules/net-cloudnat" project_id = module.prod-spoke-project.project_id region = each.value - name = "prod-nat-${local.region_trigram[each.value]}" + name = "prod-nat-${local.region_shortnames[each.value]}" router_create = true router_network = module.prod-spoke-vpc.name router_asn = 4200001024 diff --git a/fast/stages/2-networking-d-separate-envs/variables.tf b/fast/stages/2-networking-d-separate-envs/variables.tf index 61262a4215..9f82956614 100644 --- a/fast/stages/2-networking-d-separate-envs/variables.tf +++ b/fast/stages/2-networking-d-separate-envs/variables.tf @@ -94,11 +94,9 @@ variable "l7ilb_subnets" { default = { prod = [ { ip_cidr_range = "10.128.92.0/24", region = "europe-west1" }, - { ip_cidr_range = "10.128.93.0/24", region = "europe-west4" } ] dev = [ { ip_cidr_range = "10.128.60.0/24", region = "europe-west1" }, - { ip_cidr_range = "10.128.61.0/24", region = "europe-west4" } ] } } @@ -167,6 +165,16 @@ variable "psa_ranges" { # } } +variable "regions" { + description = "Region definitions." + type = object({ + primary = string + }) + default = { + primary = "europe-west1" + } +} + variable "router_onprem_configs" { description = "Configurations for routers used for onprem connectivity." type = map(object({ @@ -177,12 +185,12 @@ variable "router_onprem_configs" { asn = number })) default = { - prod-ew1 = { + prod-primary = { asn = "65533" adv = null # adv = { default = false, custom = [] } } - dev-ew1 = { + dev-primary = { asn = "65534" adv = null # adv = { default = false, custom = [] } @@ -222,7 +230,7 @@ variable "vpn_onprem_configs" { })) })) default = { - dev-ew1 = { + dev-primary = { adv = { default = false custom = [ @@ -251,7 +259,7 @@ variable "vpn_onprem_configs" { } ] } - prod-ew1 = { + prod-primary = { adv = { default = false custom = [ diff --git a/fast/stages/2-networking-d-separate-envs/vpn-onprem-dev.tf b/fast/stages/2-networking-d-separate-envs/vpn-onprem-dev.tf index 1b0ff11710..e95cd14f96 100644 --- a/fast/stages/2-networking-d-separate-envs/vpn-onprem-dev.tf +++ b/fast/stages/2-networking-d-separate-envs/vpn-onprem-dev.tf @@ -32,28 +32,33 @@ locals { } } -module "dev-to-onprem-ew1-vpn" { +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 = "europe-west1" - name = "vpn-to-onprem-ew1" + region = var.regions.primary + name = "vpn-to-onprem-${local.region_shortnames[var.regions.primary]}" router_config = { - name = "dev-onprem-vpn-ew1" - asn = var.router_onprem_configs.dev-ew1.asn + name = "dev-onprem-vpn-${local.region_shortnames[var.regions.primary]}" + asn = var.router_onprem_configs.dev-primary.asn } peer_gateway = { - external = var.vpn_onprem_configs.dev-ew1.peer_external_gateway + external = var.vpn_onprem_configs.dev-primary.peer_external_gateway } tunnels = { - for t in var.vpn_onprem_configs.dev-ew1.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-ew1 + 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 diff --git a/fast/stages/2-networking-d-separate-envs/vpn-onprem-prod.tf b/fast/stages/2-networking-d-separate-envs/vpn-onprem-prod.tf index d4b2af24e0..0793e2744d 100644 --- a/fast/stages/2-networking-d-separate-envs/vpn-onprem-prod.tf +++ b/fast/stages/2-networking-d-separate-envs/vpn-onprem-prod.tf @@ -16,28 +16,33 @@ # tfdoc:file:description VPN between prod and onprem. -module "prod-to-onprem-ew1-vpn" { +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 = "europe-west1" - name = "vpn-to-onprem-ew1" + region = var.regions.primary + name = "vpn-to-onprem-${local.region_shortnames[var.regions.primary]}" router_config = { - name = "prod-onprem-vpn-ew1" - asn = var.router_onprem_configs.prod-ew1.asn + name = "prod-onprem-vpn-${local.region_shortnames[var.regions.primary]}" + asn = var.router_onprem_configs.prod-primary.asn } peer_gateway = { - external = var.vpn_onprem_configs.prod-ew1.peer_external_gateway + external = var.vpn_onprem_configs.prod-primary.peer_external_gateway } tunnels = { - for t in var.vpn_onprem_configs.prod-ew1.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-ew1 + 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 From 78b4b0dc8ad03a2afa8c078e04990e026eb8e140 Mon Sep 17 00:00:00 2001 From: Ludo Date: Tue, 7 Feb 2023 23:35:21 +0100 Subject: [PATCH 05/16] nva --- fast/stages/2-networking-c-nva/README.md | 15 +-- fast/stages/2-networking-c-nva/landing.tf | 26 ++-- fast/stages/2-networking-c-nva/main.tf | 8 ++ fast/stages/2-networking-c-nva/nva.tf | 79 ++++++------ fast/stages/2-networking-c-nva/outputs.tf | 8 +- fast/stages/2-networking-c-nva/regions.tf | 42 +++++++ fast/stages/2-networking-c-nva/spoke-dev.tf | 39 ++++-- fast/stages/2-networking-c-nva/spoke-prod.tf | 39 ++++-- .../2-networking-c-nva/test-resources.tf | 112 +++++++++--------- fast/stages/2-networking-c-nva/variables.tf | 81 +++++-------- fast/stages/2-networking-c-nva/vpn-onprem.tf | 42 ++++--- 11 files changed, 292 insertions(+), 199 deletions(-) create mode 100644 fast/stages/2-networking-c-nva/regions.tf diff --git a/fast/stages/2-networking-c-nva/README.md b/fast/stages/2-networking-c-nva/README.md index 845f8a71b1..85117246df 100644 --- a/fast/stages/2-networking-c-nva/README.md +++ b/fast/stages/2-networking-c-nva/README.md @@ -358,6 +358,7 @@ DNS configurations are centralised in the `dns-*.tf` files. Spokes delegate DNS | [monitoring.tf](./monitoring.tf) | Network monitoring dashboards. | | google_monitoring_dashboard | | [nva.tf](./nva.tf) | None | compute-mig · compute-vm · simple-nva | | | [outputs.tf](./outputs.tf) | Module outputs. | | google_storage_bucket_object · local_file | +| [regions.tf](./regions.tf) | Compute short names for regions. | | | | [spoke-dev.tf](./spoke-dev.tf) | Dev spoke VPC and related resources. | net-vpc · net-vpc-firewall · net-vpc-peering · project | google_project_iam_binding | | [spoke-prod.tf](./spoke-prod.tf) | Production spoke VPC and related resources. | net-vpc · net-vpc-firewall · net-vpc-peering · project | google_project_iam_binding | | [test-resources.tf](./test-resources.tf) | temporary instances for testing | compute-vm | | @@ -373,18 +374,18 @@ DNS configurations are centralised in the `dns-*.tf` files. Spokes delegate DNS | [folder_ids](variables.tf#L83) | Folders to be used for the networking resources in folders/nnnnnnnnnnn format. If null, folder will be created. | object({…}) | ✓ | | 1-resman | | [organization](variables.tf#L119) | Organization details. | object({…}) | ✓ | | 0-bootstrap | | [prefix](variables.tf#L135) | Prefix used for resources that need unique names. Use 9 characters or less. | string | ✓ | | 0-bootstrap | -| [custom_adv](variables.tf#L38) | Custom advertisement definitions in name => range format. | map(string) | | {…} | | +| [custom_adv](variables.tf#L38) | Custom advertisement definitions in name => range format. | map(string) | | {…} | | | [custom_roles](variables.tf#L60) | Custom roles defined at the org level, in key => id format. | object({…}) | | null | 0-bootstrap | | [data_dir](variables.tf#L69) | Relative path for the folder storing configuration data for network resources. | string | | "data" | | | [dns](variables.tf#L75) | Onprem DNS resolvers. | map(list(string)) | | {…} | | -| [l7ilb_subnets](variables.tf#L93) | Subnets used for L7 ILBs. | map(list(object({…}))) | | {…} | | +| [l7ilb_subnets](variables.tf#L93) | Subnets used for L7 ILBs. | map(list(object({…}))) | | {…} | | | [onprem_cidr](variables.tf#L111) | Onprem addresses in name => range format. | map(string) | | {…} | | | [outputs_location](variables.tf#L129) | Path where providers and tfvars files for the following stages are written. Leave empty to disable. | string | | null | | -| [psa_ranges](variables.tf#L146) | IP ranges used for Private Service Access (e.g. CloudSQL). | object({…}) | | null | | -| [region_trigram](variables.tf#L187) | Short names for GCP regions. | map(string) | | {…} | | -| [router_configs](variables.tf#L196) | Configurations for CRs and onprem routers. | map(object({…})) | | {…} | | -| [service_accounts](variables.tf#L219) | Automation service accounts in name => email format. | object({…}) | | null | 1-resman | -| [vpn_onprem_configs](variables.tf#L233) | VPN gateway configuration for onprem interconnection. | map(object({…})) | | {…} | | +| [psa_ranges](variables.tf#L146) | IP ranges used for Private Service Access (e.g. CloudSQL). Ranges is in name => range format. | object({…}) | | null | | +| [regions](variables.tf#L167) | Region definitions. | object({…}) | | {…} | | +| [router_configs](variables.tf#L179) | Configurations for CRs and onprem routers. | map(object({…})) | | {…} | | +| [service_accounts](variables.tf#L202) | Automation service accounts in name => email format. | object({…}) | | null | 1-resman | +| [vpn_onprem_configs](variables.tf#L216) | VPN gateway configuration for onprem interconnection. | map(object({…})) | | {…} | | ## Outputs diff --git a/fast/stages/2-networking-c-nva/landing.tf b/fast/stages/2-networking-c-nva/landing.tf index 5a990030f0..e4a5ae5d17 100644 --- a/fast/stages/2-networking-c-nva/landing.tf +++ b/fast/stages/2-networking-c-nva/landing.tf @@ -71,24 +71,34 @@ module "landing-untrusted-firewall" { # NAT -module "landing-nat-ew1" { +moved { + from = module.landing-nat-ew1 + to = module.landing-nat-primary +} + +module "landing-nat-primary" { source = "../../../modules/net-cloudnat" project_id = module.landing-project.project_id - region = "europe-west1" - name = "ew1" + region = var.regions.primary + name = local.region_shortnames[var.regions.primary] router_create = true - router_name = "prod-nat-ew1" + router_name = "prod-nat-${local.region_shortnames[var.regions.primary]}" router_network = module.landing-untrusted-vpc.name router_asn = 4200001024 } -module "landing-nat-ew4" { +moved { + from = module.landing-nat-ew4 + to = module.landing-nat-secondary +} + +module "landing-nat-secondary" { source = "../../../modules/net-cloudnat" project_id = module.landing-project.project_id - region = "europe-west4" - name = "ew4" + region = var.regions.secondary + name = local.region_shortnames[var.regions.secondary] router_create = true - router_name = "prod-nat-ew4" + router_name = "prod-nat-${local.region_shortnames[var.regions.secondary]}" router_network = module.landing-untrusted-vpc.name router_asn = 4200001024 } diff --git a/fast/stages/2-networking-c-nva/main.tf b/fast/stages/2-networking-c-nva/main.tf index 4db5061ba0..97fb7daf16 100644 --- a/fast/stages/2-networking-c-nva/main.tf +++ b/fast/stages/2-networking-c-nva/main.tf @@ -24,6 +24,14 @@ locals { name = "${env}-l7ilb-${s.region}" })] } + # combine all regions from variables and subnets + regions = distinct(concat( + values(var.regions), + values(module.dev-spoke-vpc.subnet_regions), + values(module.landing-trusted-vpc.subnet_regions), + values(module.landing-untrusted-vpc.subnet_regions), + values(module.prod-spoke-vpc.subnet_regions), + )) service_accounts = { for k, v in coalesce(var.service_accounts, {}) : k => "serviceAccount:${v}" if v != null diff --git a/fast/stages/2-networking-c-nva/nva.tf b/fast/stages/2-networking-c-nva/nva.tf index f4f7b9e5ee..7ae9c30c88 100644 --- a/fast/stages/2-networking-c-nva/nva.tf +++ b/fast/stages/2-networking-c-nva/nva.tf @@ -21,29 +21,32 @@ locals { { name = "untrusted" routes = [ - var.custom_adv.gcp_landing_untrusted_ew1, - var.custom_adv.gcp_landing_untrusted_ew4, + var.custom_adv.gcp_landing_untrusted_primary, + var.custom_adv.gcp_landing_untrusted_secondary, ] }, { name = "trusted" routes = [ - var.custom_adv.gcp_dev_ew1, - var.custom_adv.gcp_dev_ew4, - var.custom_adv.gcp_landing_trusted_ew1, - var.custom_adv.gcp_landing_trusted_ew4, - var.custom_adv.gcp_prod_ew1, - var.custom_adv.gcp_prod_ew4, + var.custom_adv.gcp_dev_primary, + var.custom_adv.gcp_dev_secondary, + var.custom_adv.gcp_landing_trusted_primary, + var.custom_adv.gcp_landing_trusted_secondary, + var.custom_adv.gcp_prod_primary, + var.custom_adv.gcp_prod_secondary, ] }, ] nva_locality = { - europe-west1-b = { region = "europe-west1", trigram = "ew1", zone = "b" }, - europe-west1-c = { region = "europe-west1", trigram = "ew1", zone = "c" }, - europe-west4-b = { region = "europe-west4", trigram = "ew4", zone = "b" }, - europe-west4-c = { region = "europe-west4", trigram = "ew4", zone = "c" }, + for v in setproduct(keys(var.regions), local.nva_zones) : + join("-", v) => { + name = v.0 + region = var.regions[v.0] + shortname = local.region_shortnames[var.regions[v.0]] + zone = v.1 + } } - + nva_zones = ["b", "c"] } # NVA config @@ -57,7 +60,7 @@ module "nva-template" { for_each = local.nva_locality source = "../../../modules/compute-vm" project_id = module.landing-project.project_id - name = "nva-template-${each.value.trigram}-${each.value.zone}" + name = "nva-template-${each.key}" zone = "${each.value.region}-${each.value.zone}" instance_type = "e2-standard-2" tags = ["nva"] @@ -66,13 +69,13 @@ module "nva-template" { network_interfaces = [ { network = module.landing-untrusted-vpc.self_link - subnetwork = module.landing-untrusted-vpc.subnet_self_links["${each.value.region}/landing-untrusted-default-${each.value.trigram}"] + subnetwork = module.landing-untrusted-vpc.subnet_self_links["${each.value.region}/landing-untrusted-default-${each.value.shortname}"] nat = false addresses = null }, { network = module.landing-trusted-vpc.self_link - subnetwork = module.landing-trusted-vpc.subnet_self_links["${each.value.region}/landing-trusted-default-${each.value.trigram}"] + subnetwork = module.landing-trusted-vpc.subnet_self_links["${each.value.region}/landing-trusted-default-${each.value.shortname}"] nat = false addresses = null } @@ -98,7 +101,7 @@ module "nva-mig" { source = "../../../modules/compute-mig" project_id = module.landing-project.project_id location = each.value.region - name = "nva-cos-${each.value.trigram}-${each.value.zone}" + name = "nva-cos-${each.key}" instance_template = module.nva-template[each.key].template.self_link target_size = 1 auto_healing_policies = { @@ -113,21 +116,27 @@ module "nva-mig" { } module "ilb-nva-untrusted" { - for_each = { for l in local.nva_locality : l.region => l.trigram... } + for_each = { + for k, v in var.regions : k => { + region = v + shortname = local.region_shortnames[v] + subnet = "${v}/landing-untrusted-default-${local.region_shortnames[v]}" + } + } source = "../../../modules/net-ilb" project_id = module.landing-project.project_id - region = each.key - name = "nva-untrusted-${each.value.0}" + region = each.value.region + name = "nva-untrusted-${each.key}" service_label = var.prefix global_access = true vpc_config = { network = module.landing-untrusted-vpc.self_link - subnetwork = module.landing-untrusted-vpc.subnet_self_links["${each.key}/landing-untrusted-default-${each.value.0}"] + subnetwork = module.landing-untrusted-vpc.subnet_self_links[each.value.subnet] } backends = [ - for key, _ in local.nva_locality : { - group = module.nva-mig[key].group_manager.instance_group - } if local.nva_locality[key].region == each.key + for k, v in module.nva-mig : + { group = v.group_manager.instance_group } + if startswith(k, each.key) ] health_check_config = { enable_logging = true @@ -137,23 +146,28 @@ module "ilb-nva-untrusted" { } } - module "ilb-nva-trusted" { - for_each = { for l in local.nva_locality : l.region => l.trigram... } + for_each = { + for k, v in var.regions : k => { + region = v + shortname = local.region_shortnames[v] + subnet = "${v}/landing-trusted-default-${local.region_shortnames[v]}" + } + } source = "../../../modules/net-ilb" project_id = module.landing-project.project_id - region = each.key - name = "nva-trusted-${each.value.0}" + region = each.value.region + name = "nva-trusted-${each.key}" service_label = var.prefix global_access = true vpc_config = { network = module.landing-trusted-vpc.self_link - subnetwork = module.landing-trusted-vpc.subnet_self_links["${each.key}/landing-trusted-default-${each.value.0}"] + subnetwork = module.landing-trusted-vpc.subnet_self_links[each.value.subnet] } backends = [ - for key, _ in local.nva_locality : { - group = module.nva-mig[key].group_manager.instance_group - } if local.nva_locality[key].region == each.key + for k, v in module.nva-mig : + { group = v.group_manager.instance_group } + if startswith(k, each.key) ] health_check_config = { enable_logging = true @@ -162,4 +176,3 @@ module "ilb-nva-trusted" { } } } - diff --git a/fast/stages/2-networking-c-nva/outputs.tf b/fast/stages/2-networking-c-nva/outputs.tf index 97db168ee2..7462024273 100644 --- a/fast/stages/2-networking-c-nva/outputs.tf +++ b/fast/stages/2-networking-c-nva/outputs.tf @@ -79,12 +79,12 @@ output "tfvars" { output "vpn_gateway_endpoints" { description = "External IP Addresses for the GCP VPN gateways." value = local.enable_onprem_vpn == false ? null : { - onprem-ew1 = { - for v in module.landing-to-onprem-ew1-vpn[0].gateway.vpn_interfaces : + onprem-primary = { + for v in module.landing-to-onprem-primary-vpn[0].gateway.vpn_interfaces : v.id => v.ip_address } - onprem-ew4 = { - for v in module.landing-to-onprem-ew4-vpn[0].gateway.vpn_interfaces : + onprem-secondary = { + for v in module.landing-to-onprem-secondary-vpn[0].gateway.vpn_interfaces : v.id => v.ip_address } } diff --git a/fast/stages/2-networking-c-nva/regions.tf b/fast/stages/2-networking-c-nva/regions.tf new file mode 100644 index 0000000000..53514afa9b --- /dev/null +++ b/fast/stages/2-networking-c-nva/regions.tf @@ -0,0 +1,42 @@ +/** + * 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. + */ + +# tfdoc:file:description Compute short names for regions. + +locals { + # only map when the first character would not work + _region_cardinal = { + southeast = "se" + } + # only map when the first character would not work + _region_geo = { + australia = "o" + } + # split in [geo, cardinal, number] tokens + _region_tokens = { + for v in local.regions : v => regexall("(?:[a-z]+)|(?:[0-9]+)", v) + } + region_shortnames = { + for k, v in local._region_tokens : k => join("", [ + # first token via geo alias map or first character + lookup(local._region_geo, v.0, substr(v.0, 0, 1)), + # first token via cardinal alias map or first character + lookup(local._region_cardinal, v.1, substr(v.1, 0, 1)), + # region number as is + v.2 + ]) + } +} diff --git a/fast/stages/2-networking-c-nva/spoke-dev.tf b/fast/stages/2-networking-c-nva/spoke-dev.tf index fb88384c49..c375b009ba 100644 --- a/fast/stages/2-networking-c-nva/spoke-dev.tf +++ b/fast/stages/2-networking-c-nva/spoke-dev.tf @@ -16,6 +16,19 @@ # tfdoc:file:description Dev spoke VPC and related resources. +locals { + _l7ilb_subnets_dev = [ + for v in var.l7ilb_subnets.dev : merge(v, { + active = true + region = lookup(var.regions, v.region, v.region) + })] + l7ilb_subnets_dev = [ + for v in local._l7ilb_subnets_dev : merge(v, { + name = "dev-l7ilb-${local.region_shortnames[v.region]}" + }) + ] +} + module "dev-spoke-project" { source = "../../../modules/project" billing_account = var.billing_account.id @@ -50,7 +63,7 @@ module "dev-spoke-vpc" { data_folder = "${var.data_dir}/subnets/dev" delete_default_routes_on_create = true psa_config = try(var.psa_ranges.dev, null) - subnets_proxy_only = local.l7ilb_subnets.dev + subnets_proxy_only = local.l7ilb_subnets_dev # Set explicit routes for googleapis; send everything else to NVAs routes = { private-googleapis = { @@ -65,33 +78,33 @@ module "dev-spoke-vpc" { next_hop_type = "gateway" next_hop = "default-internet-gateway" } - nva-ew1-to-ew1 = { + nva-primary-to-primary = { dest_range = "0.0.0.0/0" priority = 1000 - tags = ["ew1"] + tags = ["primary"] next_hop_type = "ilb" - next_hop = module.ilb-nva-trusted["europe-west1"].forwarding_rule_address + next_hop = module.ilb-nva-trusted["primary"].forwarding_rule_address } - nva-ew4-to-ew4 = { + nva-secondary-to-secondary = { dest_range = "0.0.0.0/0" priority = 1000 - tags = ["ew4"] + tags = ["secondary"] next_hop_type = "ilb" - next_hop = module.ilb-nva-trusted["europe-west4"].forwarding_rule_address + next_hop = module.ilb-nva-trusted["secondary"].forwarding_rule_address } - nva-ew1-to-ew4 = { + nva-primary-to-secondary = { dest_range = "0.0.0.0/0" priority = 1001 - tags = ["ew1"] + tags = ["primary"] next_hop_type = "ilb" - next_hop = module.ilb-nva-trusted["europe-west4"].forwarding_rule_address + next_hop = module.ilb-nva-trusted["primary"].forwarding_rule_address } - nva-ew4-to-ew1 = { + nva-secondary-to-primary = { dest_range = "0.0.0.0/0" priority = 1001 - tags = ["ew4"] + tags = ["secondary"] next_hop_type = "ilb" - next_hop = module.ilb-nva-trusted["europe-west1"].forwarding_rule_address + next_hop = module.ilb-nva-trusted["secondary"].forwarding_rule_address } } } diff --git a/fast/stages/2-networking-c-nva/spoke-prod.tf b/fast/stages/2-networking-c-nva/spoke-prod.tf index 484550acac..d434c3817b 100644 --- a/fast/stages/2-networking-c-nva/spoke-prod.tf +++ b/fast/stages/2-networking-c-nva/spoke-prod.tf @@ -16,6 +16,19 @@ # tfdoc:file:description Production spoke VPC and related resources. +locals { + _l7ilb_subnets_prod = [ + for v in var.l7ilb_subnets.prod : merge(v, { + active = true + region = lookup(var.regions, v.region, v.region) + })] + l7ilb_subnets_prod = [ + for v in local._l7ilb_subnets_prod : merge(v, { + name = "prod-l7ilb-${local.region_shortnames[v.region]}" + }) + ] +} + module "prod-spoke-project" { source = "../../../modules/project" billing_account = var.billing_account.id @@ -50,7 +63,7 @@ module "prod-spoke-vpc" { data_folder = "${var.data_dir}/subnets/prod" delete_default_routes_on_create = true psa_config = try(var.psa_ranges.prod, null) - subnets_proxy_only = local.l7ilb_subnets.prod + subnets_proxy_only = local.l7ilb_subnets_prod # Set explicit routes for googleapis; send everything else to NVAs routes = { private-googleapis = { @@ -65,33 +78,33 @@ module "prod-spoke-vpc" { next_hop_type = "gateway" next_hop = "default-internet-gateway" } - nva-ew1-to-ew1 = { + nva-primary-to-primary = { dest_range = "0.0.0.0/0" priority = 1000 - tags = ["ew1"] + tags = ["primary"] next_hop_type = "ilb" - next_hop = module.ilb-nva-trusted["europe-west1"].forwarding_rule_address + next_hop = module.ilb-nva-trusted["primary"].forwarding_rule_address } - nva-ew4-to-ew4 = { + nva-secondary-to-secondary = { dest_range = "0.0.0.0/0" priority = 1000 - tags = ["ew4"] + tags = ["secondary"] next_hop_type = "ilb" - next_hop = module.ilb-nva-trusted["europe-west4"].forwarding_rule_address + next_hop = module.ilb-nva-trusted["secondary"].forwarding_rule_address } - nva-ew1-to-ew4 = { + nva-primary-to-secondary = { dest_range = "0.0.0.0/0" priority = 1001 - tags = ["ew1"] + tags = ["primary"] next_hop_type = "ilb" - next_hop = module.ilb-nva-trusted["europe-west4"].forwarding_rule_address + next_hop = module.ilb-nva-trusted["secondary"].forwarding_rule_address } - nva-ew4-to-ew1 = { + nva-secondary-to-primary = { dest_range = "0.0.0.0/0" priority = 1001 - tags = ["ew4"] + tags = ["secondary"] next_hop_type = "ilb" - next_hop = module.ilb-nva-trusted["europe-west1"].forwarding_rule_address + next_hop = module.ilb-nva-trusted["primary"].forwarding_rule_address } } } diff --git a/fast/stages/2-networking-c-nva/test-resources.tf b/fast/stages/2-networking-c-nva/test-resources.tf index d3b6109e3c..14676e8111 100644 --- a/fast/stages/2-networking-c-nva/test-resources.tf +++ b/fast/stages/2-networking-c-nva/test-resources.tf @@ -18,23 +18,23 @@ # # Untrusted (Landing) -# module "test-vm-landing-untrusted-ew1-0" { +# module "test-vm-landing-untrusted-primary-0" { # source = "../../../modules/compute-vm" # project_id = module.landing-project.project_id -# zone = "europe-west1-b" -# name = "test-vm-lnd-unt-ew1-0" +# zone = "${var.regions.primary}-b" +# name = "test-vm-lnd-unt-primary-0" # network_interfaces = [{ # network = module.landing-untrusted-vpc.self_link -# subnetwork = module.landing-untrusted-vpc.subnet_self_links["europe-west1/landing-untrusted-default-ew1"] +# subnetwork = module.landing-untrusted-vpc.subnet_self_links["${var.regions.primary}/landing-untrusted-default-${local.region_shortnames[var.regions.primary]}"] # }] -# tags = ["ew1", "ssh"] +# tags = ["primary", "ssh"] # service_account_create = true # boot_disk = { # image = "projects/debian-cloud/global/images/family/debian-10" # } # options = { -# spot = true -# termination_action = "STOP" +# spot = true +# termination_action = "STOP" # } # metadata = { # startup-script = < { bgp_peer = { address = cidrhost(t.session_range, 1) asn = t.peer_asn } - bgp_peer_options = local.bgp_peer_options_onprem.landing-trusted-ew1 + bgp_peer_options = 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 @@ -62,28 +67,33 @@ module "landing-to-onprem-ew1-vpn" { } } -module "landing-to-onprem-ew4-vpn" { +moved { + from = module.landing-to-onprem-ew4-vpn + to = module.landing-to-onprem-secondary-vpn +} + +module "landing-to-onprem-secondary-vpn" { count = local.enable_onprem_vpn ? 1 : 0 source = "../../../modules/net-vpn-ha" project_id = module.landing-project.project_id network = module.landing-trusted-vpc.self_link - region = "europe-west4" - name = "vpn-to-onprem-ew4" + region = var.regions.secondary + name = "vpn-to-onprem-${local.region_shortnames[var.regions.secondary]}" router_config = { - name = "landing-onprem-vpn-ew4" - asn = var.router_configs.landing-trusted-ew4.asn + name = "landing-onprem-vpn-${local.region_shortnames[var.regions.secondary]}" + asn = var.router_configs.landing-trusted-secondary.asn } peer_gateway = { - external = var.vpn_onprem_configs.landing-trusted-ew4.peer_external_gateway + external = var.vpn_onprem_configs.landing-trusted-secondary.peer_external_gateway } tunnels = { - for t in var.vpn_onprem_configs.landing-trusted-ew4.tunnels : + for t in var.vpn_onprem_configs.landing-trusted-secondary.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-trusted-ew4 + bgp_peer_options = 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 From a8499849d69684e33c03572dcf3850b0765040cb Mon Sep 17 00:00:00 2001 From: Ludo Date: Tue, 7 Feb 2023 23:39:39 +0100 Subject: [PATCH 06/16] test resources --- .../2-networking-a-peering/test-resources.tf | 24 +++++++++---------- .../2-networking-b-vpn/test-resources.tf | 24 +++++++++---------- .../test-resources.tf | 8 +++---- 3 files changed, 28 insertions(+), 28 deletions(-) diff --git a/fast/stages/2-networking-a-peering/test-resources.tf b/fast/stages/2-networking-a-peering/test-resources.tf index 204971fec8..67073845df 100644 --- a/fast/stages/2-networking-a-peering/test-resources.tf +++ b/fast/stages/2-networking-a-peering/test-resources.tf @@ -19,11 +19,11 @@ # module "test-vm-landing-0" { # source = "../../../modules/compute-vm" # project_id = module.landing-project.project_id -# zone = "europe-west1-b" +# zone = "${var.regions.primary}-b" # name = "test-vm-0" # network_interfaces = [{ # network = module.landing-vpc.self_link -# subnetwork = module.landing-vpc.subnet_self_links["europe-west1/landing-default-ew1"] +# subnetwork = module.landing-vpc.subnet_self_links["${var.regions.primary}/landing-default-${local.region_shortnames[var.regions.primary]}"] # }] # tags = ["ssh"] # service_account_create = true @@ -31,8 +31,8 @@ # image = "projects/debian-cloud/global/images/family/debian-10" # } # options = { -# spot = true -# termination_action = "STOP" +# spot = true +# termination_action = "STOP" # } # metadata = { # startup-script = < Date: Wed, 8 Feb 2023 09:11:05 +0100 Subject: [PATCH 07/16] add new custom role for tenant network service accounts --- fast/stages/0-bootstrap/README.md | 24 ++++++++++++------------ fast/stages/0-bootstrap/organization.tf | 4 ++++ fast/stages/0-bootstrap/variables.tf | 2 ++ 3 files changed, 18 insertions(+), 12 deletions(-) diff --git a/fast/stages/0-bootstrap/README.md b/fast/stages/0-bootstrap/README.md index 9e6512cf7f..2cab11510d 100644 --- a/fast/stages/0-bootstrap/README.md +++ b/fast/stages/0-bootstrap/README.md @@ -469,20 +469,20 @@ The remaining configuration is manual, as it regards the repositories themselves | name | description | type | required | default | producer | |---|---|:---:|:---:|:---:|:---:| | [billing_account](variables.tf#L17) | Billing account id. If billing account is not part of the same org set `is_org_level` to false. | object({…}) | ✓ | | | -| [organization](variables.tf#L194) | Organization details. | object({…}) | ✓ | | | -| [prefix](variables.tf#L209) | Prefix used for resources that need unique names. Use 9 characters or less. | string | ✓ | | | +| [organization](variables.tf#L196) | Organization details. | object({…}) | ✓ | | | +| [prefix](variables.tf#L211) | Prefix used for resources that need unique names. Use 9 characters or less. | string | ✓ | | | | [bootstrap_user](variables.tf#L29) | Email of the nominal user running this stage for the first time. | string | | null | | | [cicd_repositories](variables.tf#L35) | CI/CD repository configuration. Identity providers reference keys in the `federated_identity_providers` variable. Set to null to disable, or set individual repositories to null if not needed. | object({…}) | | null | | -| [custom_role_names](variables.tf#L81) | Names of custom roles defined at the org level. | object({…}) | | {…} | | -| [fast_features](variables.tf#L93) | Selective control for top-level FAST features. | object({…}) | | {} | | -| [federated_identity_providers](variables.tf#L106) | Workload Identity Federation pools. The `cicd_repositories` variable references keys here. | map(object({…})) | | {} | | -| [groups](variables.tf#L120) | Group names to grant organization-level permissions. | map(string) | | {…} | | -| [iam](variables.tf#L138) | Organization-level custom IAM settings in role => [principal] format. | map(list(string)) | | {} | | -| [iam_additive](variables.tf#L144) | Organization-level custom IAM settings in role => [principal] format for non-authoritative bindings. | map(list(string)) | | {} | | -| [locations](variables.tf#L150) | Optional locations for GCS, BigQuery, and logging buckets created here. | object({…}) | | {…} | | -| [log_sinks](variables.tf#L169) | Org-level log sinks, in name => {type, filter} format. | map(object({…})) | | {…} | | -| [outputs_location](variables.tf#L203) | Enable writing provider, tfvars and CI/CD workflow files to local filesystem. Leave null to disable. | string | | null | | -| [project_parent_ids](variables.tf#L219) | Optional parents for projects created here in folders/nnnnnnn format. Null values will use the organization as parent. | object({…}) | | {…} | | +| [custom_role_names](variables.tf#L81) | Names of custom roles defined at the org level. | object({…}) | | {…} | | +| [fast_features](variables.tf#L95) | Selective control for top-level FAST features. | object({…}) | | {} | | +| [federated_identity_providers](variables.tf#L108) | Workload Identity Federation pools. The `cicd_repositories` variable references keys here. | map(object({…})) | | {} | | +| [groups](variables.tf#L122) | Group names to grant organization-level permissions. | map(string) | | {…} | | +| [iam](variables.tf#L140) | Organization-level custom IAM settings in role => [principal] format. | map(list(string)) | | {} | | +| [iam_additive](variables.tf#L146) | Organization-level custom IAM settings in role => [principal] format for non-authoritative bindings. | map(list(string)) | | {} | | +| [locations](variables.tf#L152) | Optional locations for GCS, BigQuery, and logging buckets created here. | object({…}) | | {…} | | +| [log_sinks](variables.tf#L171) | Org-level log sinks, in name => {type, filter} format. | map(object({…})) | | {…} | | +| [outputs_location](variables.tf#L205) | Enable writing provider, tfvars and CI/CD workflow files to local filesystem. Leave null to disable. | string | | null | | +| [project_parent_ids](variables.tf#L221) | Optional parents for projects created here in folders/nnnnnnn format. Null values will use the organization as parent. | object({…}) | | {…} | | ## Outputs diff --git a/fast/stages/0-bootstrap/organization.tf b/fast/stages/0-bootstrap/organization.tf index 36b2ac344c..154b37fe59 100644 --- a/fast/stages/0-bootstrap/organization.tf +++ b/fast/stages/0-bootstrap/organization.tf @@ -186,6 +186,9 @@ module "organization" { "dns.networks.bindPrivateDNSZone", "resourcemanager.projects.get", ] + (var.custom_role_names.tenant_network_admin) = [ + "compute.globalOperations.get", + ] } logging_sinks = { for name, attrs in var.log_sinks : name => { @@ -217,6 +220,7 @@ resource "google_organization_iam_binding" "org_admin_delegated" { "roles/compute.xpnAdmin", "roles/orgpolicy.policyAdmin", "roles/resourcemanager.organizationViewer", + module.organization.custom_role_id[var.custom_role_names.tenant_network_admin] ], var.billing_account.is_org_level ? [ "roles/billing.admin", diff --git a/fast/stages/0-bootstrap/variables.tf b/fast/stages/0-bootstrap/variables.tf index c4b236695f..4ab90debac 100644 --- a/fast/stages/0-bootstrap/variables.tf +++ b/fast/stages/0-bootstrap/variables.tf @@ -83,10 +83,12 @@ variable "custom_role_names" { type = object({ organization_iam_admin = string service_project_network_admin = string + tenant_network_admin = string }) default = { organization_iam_admin = "organizationIamAdmin" service_project_network_admin = "serviceProjectNetworkAdmin" + tenant_network_admin = "tenantNetworkAdmin" } } From ff51cb3936b5cdb86b7e57fc8eb47bcada9ddb6b Mon Sep 17 00:00:00 2001 From: Ludo Date: Wed, 8 Feb 2023 09:11:38 +0100 Subject: [PATCH 08/16] allow setting firewall policy name in networking stages --- fast/stages/2-networking-a-peering/README.md | 24 ++++++++--------- fast/stages/2-networking-a-peering/landing.tf | 6 ++--- .../2-networking-a-peering/monitoring.tf | 2 +- .../2-networking-a-peering/spoke-dev.tf | 6 ++--- .../2-networking-a-peering/spoke-prod.tf | 6 ++--- .../2-networking-a-peering/variables.tf | 22 +++++++++++++--- fast/stages/2-networking-b-vpn/README.md | 24 ++++++++--------- fast/stages/2-networking-b-vpn/landing.tf | 6 ++--- fast/stages/2-networking-b-vpn/monitoring.tf | 2 +- fast/stages/2-networking-b-vpn/spoke-dev.tf | 6 ++--- fast/stages/2-networking-b-vpn/spoke-prod.tf | 6 ++--- fast/stages/2-networking-b-vpn/variables.tf | 22 +++++++++++++--- fast/stages/2-networking-c-nva/README.md | 26 +++++++++---------- fast/stages/2-networking-c-nva/landing.tf | 21 +++++++-------- fast/stages/2-networking-c-nva/main.tf | 8 +++--- fast/stages/2-networking-c-nva/monitoring.tf | 2 +- fast/stages/2-networking-c-nva/spoke-dev.tf | 6 ++--- fast/stages/2-networking-c-nva/spoke-prod.tf | 6 ++--- fast/stages/2-networking-c-nva/variables.tf | 22 +++++++++++++--- .../2-networking-d-separate-envs/README.md | 25 +++++++++--------- .../2-networking-d-separate-envs/main.tf | 8 +++--- .../monitoring.tf | 2 +- .../2-networking-d-separate-envs/spoke-dev.tf | 6 ++--- .../spoke-prod.tf | 6 ++--- .../2-networking-d-separate-envs/variables.tf | 22 +++++++++++++--- 25 files changed, 173 insertions(+), 119 deletions(-) diff --git a/fast/stages/2-networking-a-peering/README.md b/fast/stages/2-networking-a-peering/README.md index 588e0dc914..6e5435bea8 100644 --- a/fast/stages/2-networking-a-peering/README.md +++ b/fast/stages/2-networking-a-peering/README.md @@ -298,21 +298,21 @@ DNS configurations are centralised in the `dns-*.tf` files. Spokes delegate DNS |---|---|:---:|:---:|:---:|:---:| | [automation](variables.tf#L17) | Automation resources created by the bootstrap stage. | object({…}) | ✓ | | 0-bootstrap | | [billing_account](variables.tf#L25) | Billing account id. If billing account is not part of the same org set `is_org_level` to false. | object({…}) | ✓ | | 0-bootstrap | -| [folder_ids](variables.tf#L78) | Folders to be used for the networking resources in folders/nnnnnnnnnnn format. If null, folder will be created. | object({…}) | ✓ | | 1-resman | -| [organization](variables.tf#L112) | Organization details. | object({…}) | ✓ | | 0-bootstrap | -| [prefix](variables.tf#L128) | Prefix used for resources that need unique names. Use 9 characters or less. | string | ✓ | | 0-bootstrap | +| [folder_ids](variables.tf#L92) | Folders to be used for the networking resources in folders/nnnnnnnnnnn format. If null, folder will be created. | object({…}) | ✓ | | 1-resman | +| [organization](variables.tf#L126) | Organization details. | object({…}) | ✓ | | 0-bootstrap | +| [prefix](variables.tf#L142) | Prefix used for resources that need unique names. Use 9 characters or less. | string | ✓ | | 0-bootstrap | | [custom_adv](variables.tf#L38) | Custom advertisement definitions in name => range format. | map(string) | | {…} | | | [custom_roles](variables.tf#L55) | Custom roles defined at the org level, in key => id format. | object({…}) | | null | 0-bootstrap | -| [data_dir](variables.tf#L64) | Relative path for the folder storing configuration data for network resources. | string | | "data" | | -| [dns](variables.tf#L70) | Onprem DNS resolvers. | map(list(string)) | | {…} | | -| [l7ilb_subnets](variables.tf#L88) | Subnets used for L7 ILBs. | object({…}) | | {…} | | -| [outputs_location](variables.tf#L122) | Path where providers and tfvars files for the following stages are written. Leave empty to disable. | string | | null | | +| [dns](variables.tf#L84) | Onprem DNS resolvers. | map(list(string)) | | {…} | | +| [factories_config](variables.tf#L64) | Configuration for network resource factories. | object({…}) | | {…} | | +| [l7ilb_subnets](variables.tf#L102) | Subnets used for L7 ILBs. | object({…}) | | {…} | | +| [outputs_location](variables.tf#L136) | Path where providers and tfvars files for the following stages are written. Leave empty to disable. | string | | null | | | [peering_configs](variables-peerings.tf#L19) | Peering configurations. | map(object({…})) | | {…} | | -| [psa_ranges](variables.tf#L139) | IP ranges used for Private Service Access (e.g. CloudSQL). | object({…}) | | null | | -| [regions](variables.tf#L176) | Region definitions. | object({…}) | | {…} | | -| [router_onprem_configs](variables.tf#L188) | Configurations for routers used for onprem connectivity. | map(object({…})) | | {…} | | -| [service_accounts](variables.tf#L206) | Automation service accounts in name => email format. | object({…}) | | null | 1-resman | -| [vpn_onprem_configs](variables.tf#L220) | VPN gateway configuration for onprem interconnection. | map(object({…})) | | {…} | | +| [psa_ranges](variables.tf#L153) | IP ranges used for Private Service Access (e.g. CloudSQL). | object({…}) | | null | | +| [regions](variables.tf#L190) | Region definitions. | object({…}) | | {…} | | +| [router_onprem_configs](variables.tf#L202) | Configurations for routers used for onprem connectivity. | map(object({…})) | | {…} | | +| [service_accounts](variables.tf#L220) | Automation service accounts in name => email format. | object({…}) | | null | 1-resman | +| [vpn_onprem_configs](variables.tf#L234) | VPN gateway configuration for onprem interconnection. | map(object({…})) | | {…} | | ## Outputs diff --git a/fast/stages/2-networking-a-peering/landing.tf b/fast/stages/2-networking-a-peering/landing.tf index 2e84733ad5..37e3adfd44 100644 --- a/fast/stages/2-networking-a-peering/landing.tf +++ b/fast/stages/2-networking-a-peering/landing.tf @@ -63,7 +63,7 @@ module "landing-vpc" { next_hop = "default-internet-gateway" } } - data_folder = "${var.data_dir}/subnets/landing" + data_folder = "${var.factories_config.data_dir}/subnets/landing" } module "landing-firewall" { @@ -74,8 +74,8 @@ module "landing-firewall" { disabled = true } factories_config = { - cidr_tpl_file = "${var.data_dir}/cidrs.yaml" - rules_folder = "${var.data_dir}/firewall-rules/landing" + cidr_tpl_file = "${var.factories_config.data_dir}/cidrs.yaml" + rules_folder = "${var.factories_config.data_dir}/firewall-rules/landing" } } diff --git a/fast/stages/2-networking-a-peering/monitoring.tf b/fast/stages/2-networking-a-peering/monitoring.tf index 7b8b70c513..be3a47faac 100644 --- a/fast/stages/2-networking-a-peering/monitoring.tf +++ b/fast/stages/2-networking-a-peering/monitoring.tf @@ -17,7 +17,7 @@ # tfdoc:file:description Network monitoring dashboards. locals { - dashboard_path = "${var.data_dir}/dashboards" + dashboard_path = "${var.factories_config.data_dir}/dashboards" dashboard_files = fileset(local.dashboard_path, "*.json") dashboards = { for filename in local.dashboard_files : diff --git a/fast/stages/2-networking-a-peering/spoke-dev.tf b/fast/stages/2-networking-a-peering/spoke-dev.tf index 966d709cb7..ed7d13cb0b 100644 --- a/fast/stages/2-networking-a-peering/spoke-dev.tf +++ b/fast/stages/2-networking-a-peering/spoke-dev.tf @@ -61,7 +61,7 @@ module "dev-spoke-vpc" { project_id = module.dev-spoke-project.project_id name = "dev-spoke-0" mtu = 1500 - data_folder = "${var.data_dir}/subnets/dev" + data_folder = "${var.factories_config.data_dir}/subnets/dev" psa_config = try(var.psa_ranges.dev, null) subnets_proxy_only = local.l7ilb_subnets_dev # set explicit routes for googleapis in case the default route is deleted @@ -87,8 +87,8 @@ module "dev-spoke-firewall" { disabled = true } factories_config = { - cidr_tpl_file = "${var.data_dir}/cidrs.yaml" - rules_folder = "${var.data_dir}/firewall-rules/dev" + cidr_tpl_file = "${var.factories_config.data_dir}/cidrs.yaml" + rules_folder = "${var.factories_config.data_dir}/firewall-rules/dev" } } diff --git a/fast/stages/2-networking-a-peering/spoke-prod.tf b/fast/stages/2-networking-a-peering/spoke-prod.tf index 7ce7dff4d3..f584b32da8 100644 --- a/fast/stages/2-networking-a-peering/spoke-prod.tf +++ b/fast/stages/2-networking-a-peering/spoke-prod.tf @@ -61,7 +61,7 @@ module "prod-spoke-vpc" { project_id = module.prod-spoke-project.project_id name = "prod-spoke-0" mtu = 1500 - data_folder = "${var.data_dir}/subnets/prod" + data_folder = "${var.factories_config.data_dir}/subnets/prod" psa_config = try(var.psa_ranges.prod, null) subnets_proxy_only = local.l7ilb_subnets_prod # set explicit routes for googleapis in case the default route is deleted @@ -87,8 +87,8 @@ module "prod-spoke-firewall" { disabled = true } factories_config = { - cidr_tpl_file = "${var.data_dir}/cidrs.yaml" - rules_folder = "${var.data_dir}/firewall-rules/prod" + cidr_tpl_file = "${var.factories_config.data_dir}/cidrs.yaml" + rules_folder = "${var.factories_config.data_dir}/firewall-rules/prod" } } diff --git a/fast/stages/2-networking-a-peering/variables.tf b/fast/stages/2-networking-a-peering/variables.tf index ff85422b4d..6d30af9d7f 100644 --- a/fast/stages/2-networking-a-peering/variables.tf +++ b/fast/stages/2-networking-a-peering/variables.tf @@ -61,10 +61,24 @@ variable "custom_roles" { default = null } -variable "data_dir" { - description = "Relative path for the folder storing configuration data for network resources." - type = string - default = "data" +variable "factories_config" { + description = "Configuration for network resource factories." + type = object({ + data_dir = optional(string, "data") + firewall_policy_name = optional(string, "factory") + }) + default = { + data_dir = "data" + } + nullable = false + validation { + condition = var.factories_config.data_dir != null + error_message = "Data folder needs to be non-null." + } + validation { + condition = var.factories_config.firewall_policy_name != null + error_message = "Firewall policy name needs to be non-null." + } } variable "dns" { diff --git a/fast/stages/2-networking-b-vpn/README.md b/fast/stages/2-networking-b-vpn/README.md index 8788c381b1..dfb8ecbecd 100644 --- a/fast/stages/2-networking-b-vpn/README.md +++ b/fast/stages/2-networking-b-vpn/README.md @@ -323,21 +323,21 @@ DNS configurations are centralised in the `dns-*.tf` files. Spokes delegate DNS |---|---|:---:|:---:|:---:|:---:| | [automation](variables.tf#L17) | Automation resources created by the bootstrap stage. | object({…}) | ✓ | | 0-bootstrap | | [billing_account](variables.tf#L25) | Billing account id. If billing account is not part of the same org set `is_org_level` to false. | object({…}) | ✓ | | 0-bootstrap | -| [folder_ids](variables.tf#L78) | Folders to be used for the networking resources in folders/nnnnnnnnnnn format. If null, folder will be created. | object({…}) | ✓ | | 1-resman | -| [organization](variables.tf#L112) | Organization details. | object({…}) | ✓ | | 0-bootstrap | -| [prefix](variables.tf#L128) | Prefix used for resources that need unique names. Use 9 characters or less. | string | ✓ | | 0-bootstrap | +| [folder_ids](variables.tf#L92) | Folders to be used for the networking resources in folders/nnnnnnnnnnn format. If null, folder will be created. | object({…}) | ✓ | | 1-resman | +| [organization](variables.tf#L126) | Organization details. | object({…}) | ✓ | | 0-bootstrap | +| [prefix](variables.tf#L142) | Prefix used for resources that need unique names. Use 9 characters or less. | string | ✓ | | 0-bootstrap | | [custom_adv](variables.tf#L38) | Custom advertisement definitions in name => range format. | map(string) | | {…} | | | [custom_roles](variables.tf#L55) | Custom roles defined at the org level, in key => id format. | object({…}) | | null | 0-bootstrap | -| [data_dir](variables.tf#L64) | Relative path for the folder storing configuration data for network resources. | string | | "data" | | -| [dns](variables.tf#L70) | Onprem DNS resolvers. | map(list(string)) | | {…} | | -| [l7ilb_subnets](variables.tf#L88) | Subnets used for L7 ILBs. | object({…}) | | {…} | | -| [outputs_location](variables.tf#L122) | Path where providers and tfvars files for the following stages are written. Leave empty to disable. | string | | null | | -| [psa_ranges](variables.tf#L139) | IP ranges used for Private Service Access (e.g. CloudSQL). | object({…}) | | null | | -| [regions](variables.tf#L176) | Region definitions. | object({…}) | | {…} | | -| [router_onprem_configs](variables.tf#L188) | Configurations for routers used for onprem connectivity. | map(object({…})) | | {…} | | +| [dns](variables.tf#L84) | Onprem DNS resolvers. | map(list(string)) | | {…} | | +| [factories_config](variables.tf#L64) | Configuration for network resource factories. | object({…}) | | {…} | | +| [l7ilb_subnets](variables.tf#L102) | Subnets used for L7 ILBs. | object({…}) | | {…} | | +| [outputs_location](variables.tf#L136) | Path where providers and tfvars files for the following stages are written. Leave empty to disable. | string | | null | | +| [psa_ranges](variables.tf#L153) | IP ranges used for Private Service Access (e.g. CloudSQL). | object({…}) | | null | | +| [regions](variables.tf#L190) | Region definitions. | object({…}) | | {…} | | +| [router_onprem_configs](variables.tf#L202) | Configurations for routers used for onprem connectivity. | map(object({…})) | | {…} | | | [router_spoke_configs](variables-vpn.tf#L18) | Configurations for routers used for internal connectivity. | map(object({…})) | | {…} | | -| [service_accounts](variables.tf#L206) | Automation service accounts in name => email format. | object({…}) | | null | 1-resman | -| [vpn_onprem_configs](variables.tf#L220) | VPN gateway configuration for onprem interconnection. | map(object({…})) | | {…} | | +| [service_accounts](variables.tf#L220) | Automation service accounts in name => email format. | object({…}) | | null | 1-resman | +| [vpn_onprem_configs](variables.tf#L234) | VPN gateway configuration for onprem interconnection. | map(object({…})) | | {…} | | | [vpn_spoke_configs](variables-vpn.tf#L37) | VPN gateway configuration for spokes. | map(object({…})) | | {…} | | ## Outputs diff --git a/fast/stages/2-networking-b-vpn/landing.tf b/fast/stages/2-networking-b-vpn/landing.tf index 2e84733ad5..37e3adfd44 100644 --- a/fast/stages/2-networking-b-vpn/landing.tf +++ b/fast/stages/2-networking-b-vpn/landing.tf @@ -63,7 +63,7 @@ module "landing-vpc" { next_hop = "default-internet-gateway" } } - data_folder = "${var.data_dir}/subnets/landing" + data_folder = "${var.factories_config.data_dir}/subnets/landing" } module "landing-firewall" { @@ -74,8 +74,8 @@ module "landing-firewall" { disabled = true } factories_config = { - cidr_tpl_file = "${var.data_dir}/cidrs.yaml" - rules_folder = "${var.data_dir}/firewall-rules/landing" + cidr_tpl_file = "${var.factories_config.data_dir}/cidrs.yaml" + rules_folder = "${var.factories_config.data_dir}/firewall-rules/landing" } } diff --git a/fast/stages/2-networking-b-vpn/monitoring.tf b/fast/stages/2-networking-b-vpn/monitoring.tf index 7b8b70c513..be3a47faac 100644 --- a/fast/stages/2-networking-b-vpn/monitoring.tf +++ b/fast/stages/2-networking-b-vpn/monitoring.tf @@ -17,7 +17,7 @@ # tfdoc:file:description Network monitoring dashboards. locals { - dashboard_path = "${var.data_dir}/dashboards" + dashboard_path = "${var.factories_config.data_dir}/dashboards" dashboard_files = fileset(local.dashboard_path, "*.json") dashboards = { for filename in local.dashboard_files : diff --git a/fast/stages/2-networking-b-vpn/spoke-dev.tf b/fast/stages/2-networking-b-vpn/spoke-dev.tf index 966d709cb7..ed7d13cb0b 100644 --- a/fast/stages/2-networking-b-vpn/spoke-dev.tf +++ b/fast/stages/2-networking-b-vpn/spoke-dev.tf @@ -61,7 +61,7 @@ module "dev-spoke-vpc" { project_id = module.dev-spoke-project.project_id name = "dev-spoke-0" mtu = 1500 - data_folder = "${var.data_dir}/subnets/dev" + data_folder = "${var.factories_config.data_dir}/subnets/dev" psa_config = try(var.psa_ranges.dev, null) subnets_proxy_only = local.l7ilb_subnets_dev # set explicit routes for googleapis in case the default route is deleted @@ -87,8 +87,8 @@ module "dev-spoke-firewall" { disabled = true } factories_config = { - cidr_tpl_file = "${var.data_dir}/cidrs.yaml" - rules_folder = "${var.data_dir}/firewall-rules/dev" + cidr_tpl_file = "${var.factories_config.data_dir}/cidrs.yaml" + rules_folder = "${var.factories_config.data_dir}/firewall-rules/dev" } } diff --git a/fast/stages/2-networking-b-vpn/spoke-prod.tf b/fast/stages/2-networking-b-vpn/spoke-prod.tf index 7ce7dff4d3..f584b32da8 100644 --- a/fast/stages/2-networking-b-vpn/spoke-prod.tf +++ b/fast/stages/2-networking-b-vpn/spoke-prod.tf @@ -61,7 +61,7 @@ module "prod-spoke-vpc" { project_id = module.prod-spoke-project.project_id name = "prod-spoke-0" mtu = 1500 - data_folder = "${var.data_dir}/subnets/prod" + data_folder = "${var.factories_config.data_dir}/subnets/prod" psa_config = try(var.psa_ranges.prod, null) subnets_proxy_only = local.l7ilb_subnets_prod # set explicit routes for googleapis in case the default route is deleted @@ -87,8 +87,8 @@ module "prod-spoke-firewall" { disabled = true } factories_config = { - cidr_tpl_file = "${var.data_dir}/cidrs.yaml" - rules_folder = "${var.data_dir}/firewall-rules/prod" + cidr_tpl_file = "${var.factories_config.data_dir}/cidrs.yaml" + rules_folder = "${var.factories_config.data_dir}/firewall-rules/prod" } } diff --git a/fast/stages/2-networking-b-vpn/variables.tf b/fast/stages/2-networking-b-vpn/variables.tf index ff85422b4d..6d30af9d7f 100644 --- a/fast/stages/2-networking-b-vpn/variables.tf +++ b/fast/stages/2-networking-b-vpn/variables.tf @@ -61,10 +61,24 @@ variable "custom_roles" { default = null } -variable "data_dir" { - description = "Relative path for the folder storing configuration data for network resources." - type = string - default = "data" +variable "factories_config" { + description = "Configuration for network resource factories." + type = object({ + data_dir = optional(string, "data") + firewall_policy_name = optional(string, "factory") + }) + default = { + data_dir = "data" + } + nullable = false + validation { + condition = var.factories_config.data_dir != null + error_message = "Data folder needs to be non-null." + } + validation { + condition = var.factories_config.firewall_policy_name != null + error_message = "Firewall policy name needs to be non-null." + } } variable "dns" { diff --git a/fast/stages/2-networking-c-nva/README.md b/fast/stages/2-networking-c-nva/README.md index 85117246df..eebff0f1a8 100644 --- a/fast/stages/2-networking-c-nva/README.md +++ b/fast/stages/2-networking-c-nva/README.md @@ -371,21 +371,21 @@ DNS configurations are centralised in the `dns-*.tf` files. Spokes delegate DNS |---|---|:---:|:---:|:---:|:---:| | [automation](variables.tf#L17) | Automation resources created by the bootstrap stage. | object({…}) | ✓ | | 0-bootstrap | | [billing_account](variables.tf#L25) | Billing account id. If billing account is not part of the same org set `is_org_level` to false. | object({…}) | ✓ | | 0-bootstrap | -| [folder_ids](variables.tf#L83) | Folders to be used for the networking resources in folders/nnnnnnnnnnn format. If null, folder will be created. | object({…}) | ✓ | | 1-resman | -| [organization](variables.tf#L119) | Organization details. | object({…}) | ✓ | | 0-bootstrap | -| [prefix](variables.tf#L135) | Prefix used for resources that need unique names. Use 9 characters or less. | string | ✓ | | 0-bootstrap | +| [folder_ids](variables.tf#L97) | Folders to be used for the networking resources in folders/nnnnnnnnnnn format. If null, folder will be created. | object({…}) | ✓ | | 1-resman | +| [organization](variables.tf#L133) | Organization details. | object({…}) | ✓ | | 0-bootstrap | +| [prefix](variables.tf#L149) | Prefix used for resources that need unique names. Use 9 characters or less. | string | ✓ | | 0-bootstrap | | [custom_adv](variables.tf#L38) | Custom advertisement definitions in name => range format. | map(string) | | {…} | | | [custom_roles](variables.tf#L60) | Custom roles defined at the org level, in key => id format. | object({…}) | | null | 0-bootstrap | -| [data_dir](variables.tf#L69) | Relative path for the folder storing configuration data for network resources. | string | | "data" | | -| [dns](variables.tf#L75) | Onprem DNS resolvers. | map(list(string)) | | {…} | | -| [l7ilb_subnets](variables.tf#L93) | Subnets used for L7 ILBs. | map(list(object({…}))) | | {…} | | -| [onprem_cidr](variables.tf#L111) | Onprem addresses in name => range format. | map(string) | | {…} | | -| [outputs_location](variables.tf#L129) | Path where providers and tfvars files for the following stages are written. Leave empty to disable. | string | | null | | -| [psa_ranges](variables.tf#L146) | IP ranges used for Private Service Access (e.g. CloudSQL). Ranges is in name => range format. | object({…}) | | null | | -| [regions](variables.tf#L167) | Region definitions. | object({…}) | | {…} | | -| [router_configs](variables.tf#L179) | Configurations for CRs and onprem routers. | map(object({…})) | | {…} | | -| [service_accounts](variables.tf#L202) | Automation service accounts in name => email format. | object({…}) | | null | 1-resman | -| [vpn_onprem_configs](variables.tf#L216) | VPN gateway configuration for onprem interconnection. | map(object({…})) | | {…} | | +| [dns](variables.tf#L89) | Onprem DNS resolvers. | map(list(string)) | | {…} | | +| [factories_config](variables.tf#L69) | Configuration for network resource factories. | object({…}) | | {…} | | +| [l7ilb_subnets](variables.tf#L107) | Subnets used for L7 ILBs. | map(list(object({…}))) | | {…} | | +| [onprem_cidr](variables.tf#L125) | Onprem addresses in name => range format. | map(string) | | {…} | | +| [outputs_location](variables.tf#L143) | Path where providers and tfvars files for the following stages are written. Leave empty to disable. | string | | null | | +| [psa_ranges](variables.tf#L160) | IP ranges used for Private Service Access (e.g. CloudSQL). Ranges is in name => range format. | object({…}) | | null | | +| [regions](variables.tf#L181) | Region definitions. | object({…}) | | {…} | | +| [router_configs](variables.tf#L193) | Configurations for CRs and onprem routers. | map(object({…})) | | {…} | | +| [service_accounts](variables.tf#L216) | Automation service accounts in name => email format. | object({…}) | | null | 1-resman | +| [vpn_onprem_configs](variables.tf#L230) | VPN gateway configuration for onprem interconnection. | map(object({…})) | | {…} | | ## Outputs diff --git a/fast/stages/2-networking-c-nva/landing.tf b/fast/stages/2-networking-c-nva/landing.tf index e4a5ae5d17..e66b03db94 100644 --- a/fast/stages/2-networking-c-nva/landing.tf +++ b/fast/stages/2-networking-c-nva/landing.tf @@ -53,7 +53,7 @@ module "landing-untrusted-vpc" { inbound = false logging = false } - data_folder = "${var.data_dir}/subnets/landing-untrusted" + data_folder = "${var.factories_config.data_dir}/subnets/landing-untrusted" } module "landing-untrusted-firewall" { @@ -64,8 +64,8 @@ module "landing-untrusted-firewall" { disabled = true } factories_config = { - cidr_tpl_file = "${var.data_dir}/cidrs.yaml" - rules_folder = "${var.data_dir}/firewall-rules/landing-untrusted" + cidr_tpl_file = "${var.factories_config.data_dir}/cidrs.yaml" + rules_folder = "${var.factories_config.data_dir}/firewall-rules/landing-untrusted" } } @@ -111,7 +111,10 @@ module "landing-trusted-vpc" { name = "prod-trusted-landing-0" delete_default_routes_on_create = true mtu = 1500 - + data_folder = "${var.factories_config.data_dir}/subnets/landing-trusted" + dns_policy = { + inbound = true + } # Set explicit routes for googleapis in case the default route is deleted routes = { private-googleapis = { @@ -125,12 +128,6 @@ module "landing-trusted-vpc" { next_hop = "default-internet-gateway" } } - - dns_policy = { - inbound = true - } - - data_folder = "${var.data_dir}/subnets/landing-trusted" } module "landing-trusted-firewall" { @@ -141,7 +138,7 @@ module "landing-trusted-firewall" { disabled = true } factories_config = { - cidr_tpl_file = "${var.data_dir}/cidrs.yaml" - rules_folder = "${var.data_dir}/firewall-rules/landing-trusted" + cidr_tpl_file = "${var.factories_config.data_dir}/cidrs.yaml" + rules_folder = "${var.factories_config.data_dir}/firewall-rules/landing-trusted" } } diff --git a/fast/stages/2-networking-c-nva/main.tf b/fast/stages/2-networking-c-nva/main.tf index 97fb7daf16..e4066ba351 100644 --- a/fast/stages/2-networking-c-nva/main.tf +++ b/fast/stages/2-networking-c-nva/main.tf @@ -53,11 +53,11 @@ module "folder" { folder_create = var.folder_ids.networking == null id = var.folder_ids.networking firewall_policy_factory = { - cidr_file = "${var.data_dir}/cidrs.yaml" - policy_name = null - rules_file = "${var.data_dir}/hierarchical-policy-rules.yaml" + cidr_file = "${var.factories_config.data_dir}/cidrs.yaml" + policy_name = var.factories_config.firewall_policy_name + rules_file = "${var.factories_config.data_dir}/hierarchical-policy-rules.yaml" } firewall_policy_association = { - factory-policy = "factory" + factory-policy = var.factories_config.firewall_policy_name } } diff --git a/fast/stages/2-networking-c-nva/monitoring.tf b/fast/stages/2-networking-c-nva/monitoring.tf index 7b8b70c513..be3a47faac 100644 --- a/fast/stages/2-networking-c-nva/monitoring.tf +++ b/fast/stages/2-networking-c-nva/monitoring.tf @@ -17,7 +17,7 @@ # tfdoc:file:description Network monitoring dashboards. locals { - dashboard_path = "${var.data_dir}/dashboards" + dashboard_path = "${var.factories_config.data_dir}/dashboards" dashboard_files = fileset(local.dashboard_path, "*.json") dashboards = { for filename in local.dashboard_files : diff --git a/fast/stages/2-networking-c-nva/spoke-dev.tf b/fast/stages/2-networking-c-nva/spoke-dev.tf index c375b009ba..b229381314 100644 --- a/fast/stages/2-networking-c-nva/spoke-dev.tf +++ b/fast/stages/2-networking-c-nva/spoke-dev.tf @@ -60,7 +60,7 @@ module "dev-spoke-vpc" { project_id = module.dev-spoke-project.project_id name = "dev-spoke-0" mtu = 1500 - data_folder = "${var.data_dir}/subnets/dev" + data_folder = "${var.factories_config.data_dir}/subnets/dev" delete_default_routes_on_create = true psa_config = try(var.psa_ranges.dev, null) subnets_proxy_only = local.l7ilb_subnets_dev @@ -117,8 +117,8 @@ module "dev-spoke-firewall" { disabled = true } factories_config = { - cidr_tpl_file = "${var.data_dir}/cidrs.yaml" - rules_folder = "${var.data_dir}/firewall-rules/dev" + cidr_tpl_file = "${var.factories_config.data_dir}/cidrs.yaml" + rules_folder = "${var.factories_config.data_dir}/firewall-rules/dev" } } diff --git a/fast/stages/2-networking-c-nva/spoke-prod.tf b/fast/stages/2-networking-c-nva/spoke-prod.tf index d434c3817b..51ad297455 100644 --- a/fast/stages/2-networking-c-nva/spoke-prod.tf +++ b/fast/stages/2-networking-c-nva/spoke-prod.tf @@ -60,7 +60,7 @@ module "prod-spoke-vpc" { project_id = module.prod-spoke-project.project_id name = "prod-spoke-0" mtu = 1500 - data_folder = "${var.data_dir}/subnets/prod" + data_folder = "${var.factories_config.data_dir}/subnets/prod" delete_default_routes_on_create = true psa_config = try(var.psa_ranges.prod, null) subnets_proxy_only = local.l7ilb_subnets_prod @@ -117,8 +117,8 @@ module "prod-spoke-firewall" { disabled = true } factories_config = { - cidr_tpl_file = "${var.data_dir}/cidrs.yaml" - rules_folder = "${var.data_dir}/firewall-rules/prod" + cidr_tpl_file = "${var.factories_config.data_dir}/cidrs.yaml" + rules_folder = "${var.factories_config.data_dir}/firewall-rules/prod" } } diff --git a/fast/stages/2-networking-c-nva/variables.tf b/fast/stages/2-networking-c-nva/variables.tf index 7639bd7e35..76cb2cb6be 100644 --- a/fast/stages/2-networking-c-nva/variables.tf +++ b/fast/stages/2-networking-c-nva/variables.tf @@ -66,10 +66,24 @@ variable "custom_roles" { default = null } -variable "data_dir" { - description = "Relative path for the folder storing configuration data for network resources." - type = string - default = "data" +variable "factories_config" { + description = "Configuration for network resource factories." + type = object({ + data_dir = optional(string, "data") + firewall_policy_name = optional(string, "factory") + }) + default = { + data_dir = "data" + } + nullable = false + validation { + condition = var.factories_config.data_dir != null + error_message = "Data folder needs to be non-null." + } + validation { + condition = var.factories_config.firewall_policy_name != null + error_message = "Firewall policy name needs to be non-null." + } } variable "dns" { diff --git a/fast/stages/2-networking-d-separate-envs/README.md b/fast/stages/2-networking-d-separate-envs/README.md index bd43a8d307..27823f2b75 100644 --- a/fast/stages/2-networking-d-separate-envs/README.md +++ b/fast/stages/2-networking-d-separate-envs/README.md @@ -222,6 +222,7 @@ You're now ready to run `terraform init` and `apply`. | name | description | modules | resources | |---|---|---|---| +| [2-0-networking-providers.tf](./2-0-networking-providers.tf) | None | | | | [dns-dev.tf](./dns-dev.tf) | Development spoke DNS zones and peerings setup. | dns | | | [dns-prod.tf](./dns-prod.tf) | Production spoke DNS zones and peerings setup. | dns | | | [main.tf](./main.tf) | Networking folder and hierarchical policy. | folder | | @@ -241,20 +242,20 @@ You're now ready to run `terraform init` and `apply`. |---|---|:---:|:---:|:---:|:---:| | [automation](variables.tf#L17) | Automation resources created by the bootstrap stage. | object({…}) | ✓ | | 0-bootstrap | | [billing_account](variables.tf#L25) | Billing account id. If billing account is not part of the same org set `is_org_level` to false. | object({…}) | ✓ | | 0-bootstrap | -| [folder_ids](variables.tf#L78) | Folders to be used for the networking resources in folders/nnnnnnnnnnn format. If null, folder will be created. | object({…}) | ✓ | | 1-resman | -| [organization](variables.tf#L104) | Organization details. | object({…}) | ✓ | | 0-bootstrap | -| [prefix](variables.tf#L120) | Prefix used for resources that need unique names. Use 9 characters or less. | string | ✓ | | 0-bootstrap | +| [folder_ids](variables.tf#L92) | Folders to be used for the networking resources in folders/nnnnnnnnnnn format. If null, folder will be created. | object({…}) | ✓ | | 1-resman | +| [organization](variables.tf#L118) | Organization details. | object({…}) | ✓ | | 0-bootstrap | +| [prefix](variables.tf#L134) | Prefix used for resources that need unique names. Use 9 characters or less. | string | ✓ | | 0-bootstrap | | [custom_adv](variables.tf#L38) | Custom advertisement definitions in name => range format. | map(string) | | {…} | | | [custom_roles](variables.tf#L54) | Custom roles defined at the org level, in key => id format. | object({…}) | | null | 0-bootstrap | -| [data_dir](variables.tf#L63) | Relative path for the folder storing configuration data for network resources. | string | | "data" | | -| [dns](variables.tf#L69) | Onprem DNS resolvers. | map(list(string)) | | {…} | | -| [l7ilb_subnets](variables.tf#L88) | Subnets used for L7 ILBs. | map(list(object({…}))) | | {…} | | -| [outputs_location](variables.tf#L114) | Path where providers and tfvars files for the following stages are written. Leave empty to disable. | string | | null | | -| [psa_ranges](variables.tf#L131) | IP ranges used for Private Service Access (e.g. CloudSQL). | object({…}) | | null | | -| [regions](variables.tf#L168) | Region definitions. | object({…}) | | {…} | | -| [router_onprem_configs](variables.tf#L178) | Configurations for routers used for onprem connectivity. | map(object({…})) | | {…} | | -| [service_accounts](variables.tf#L201) | Automation service accounts in name => email format. | object({…}) | | null | 1-resman | -| [vpn_onprem_configs](variables.tf#L213) | VPN gateway configuration for onprem interconnection. | map(object({…})) | | {…} | | +| [dns](variables.tf#L83) | Onprem DNS resolvers. | map(list(string)) | | {…} | | +| [factories_config](variables.tf#L63) | Configuration for network resource factories. | object({…}) | | {…} | | +| [l7ilb_subnets](variables.tf#L102) | Subnets used for L7 ILBs. | map(list(object({…}))) | | {…} | | +| [outputs_location](variables.tf#L128) | Path where providers and tfvars files for the following stages are written. Leave empty to disable. | string | | null | | +| [psa_ranges](variables.tf#L145) | IP ranges used for Private Service Access (e.g. CloudSQL). | object({…}) | | null | | +| [regions](variables.tf#L182) | Region definitions. | object({…}) | | {…} | | +| [router_onprem_configs](variables.tf#L192) | Configurations for routers used for onprem connectivity. | map(object({…})) | | {…} | | +| [service_accounts](variables.tf#L215) | Automation service accounts in name => email format. | object({…}) | | null | 1-resman | +| [vpn_onprem_configs](variables.tf#L227) | VPN gateway configuration for onprem interconnection. | map(object({…})) | | {…} | | ## Outputs diff --git a/fast/stages/2-networking-d-separate-envs/main.tf b/fast/stages/2-networking-d-separate-envs/main.tf index cb7374be0b..dda1c252e5 100644 --- a/fast/stages/2-networking-d-separate-envs/main.tf +++ b/fast/stages/2-networking-d-separate-envs/main.tf @@ -55,12 +55,12 @@ module "folder" { folder_create = var.folder_ids.networking == null id = var.folder_ids.networking firewall_policy_factory = { - cidr_file = "${var.data_dir}/cidrs.yaml" - policy_name = null - rules_file = "${var.data_dir}/hierarchical-policy-rules.yaml" + cidr_file = "${var.factories_config.data_dir}/cidrs.yaml" + policy_name = var.factories_config.firewall_policy_name + rules_file = "${var.factories_config.data_dir}/hierarchical-policy-rules.yaml" } firewall_policy_association = { - factory-policy = "factory" + factory-policy = var.factories_config.firewall_policy_name } } diff --git a/fast/stages/2-networking-d-separate-envs/monitoring.tf b/fast/stages/2-networking-d-separate-envs/monitoring.tf index 463c6a083d..01ed0c4797 100644 --- a/fast/stages/2-networking-d-separate-envs/monitoring.tf +++ b/fast/stages/2-networking-d-separate-envs/monitoring.tf @@ -17,7 +17,7 @@ # tfdoc:file:description Network monitoring dashboards. locals { - dashboard_path = "${var.data_dir}/dashboards" + dashboard_path = "${var.factories_config.data_dir}/dashboards" dashboard_files = fileset(local.dashboard_path, "*.json") dashboards = { for filename in local.dashboard_files : diff --git a/fast/stages/2-networking-d-separate-envs/spoke-dev.tf b/fast/stages/2-networking-d-separate-envs/spoke-dev.tf index e600531b88..ecd0b07368 100644 --- a/fast/stages/2-networking-d-separate-envs/spoke-dev.tf +++ b/fast/stages/2-networking-d-separate-envs/spoke-dev.tf @@ -47,7 +47,7 @@ module "dev-spoke-vpc" { project_id = module.dev-spoke-project.project_id name = "dev-spoke-0" mtu = 1500 - data_folder = "${var.data_dir}/subnets/dev" + data_folder = "${var.factories_config.data_dir}/subnets/dev" psa_config = try(var.psa_ranges.dev, null) subnets_proxy_only = local.l7ilb_subnets.dev # set explicit routes for googleapis in case the default route is deleted @@ -73,8 +73,8 @@ module "dev-spoke-firewall" { disabled = true } factories_config = { - cidr_tpl_file = "${var.data_dir}/cidrs.yaml" - rules_folder = "${var.data_dir}/firewall-rules/dev" + cidr_tpl_file = "${var.factories_config.data_dir}/cidrs.yaml" + rules_folder = "${var.factories_config.data_dir}/firewall-rules/dev" } } diff --git a/fast/stages/2-networking-d-separate-envs/spoke-prod.tf b/fast/stages/2-networking-d-separate-envs/spoke-prod.tf index 2a4b054ed1..2e95a09e1b 100644 --- a/fast/stages/2-networking-d-separate-envs/spoke-prod.tf +++ b/fast/stages/2-networking-d-separate-envs/spoke-prod.tf @@ -47,7 +47,7 @@ module "prod-spoke-vpc" { project_id = module.prod-spoke-project.project_id name = "prod-spoke-0" mtu = 1500 - data_folder = "${var.data_dir}/subnets/prod" + data_folder = "${var.factories_config.data_dir}/subnets/prod" psa_config = try(var.psa_ranges.prod, null) subnets_proxy_only = local.l7ilb_subnets.prod # set explicit routes for googleapis in case the default route is deleted @@ -73,8 +73,8 @@ module "prod-spoke-firewall" { disabled = true } factories_config = { - cidr_tpl_file = "${var.data_dir}/cidrs.yaml" - rules_folder = "${var.data_dir}/firewall-rules/prod" + cidr_tpl_file = "${var.factories_config.data_dir}/cidrs.yaml" + rules_folder = "${var.factories_config.data_dir}/firewall-rules/prod" } } diff --git a/fast/stages/2-networking-d-separate-envs/variables.tf b/fast/stages/2-networking-d-separate-envs/variables.tf index 9f82956614..85ae3c9941 100644 --- a/fast/stages/2-networking-d-separate-envs/variables.tf +++ b/fast/stages/2-networking-d-separate-envs/variables.tf @@ -60,10 +60,24 @@ variable "custom_roles" { default = null } -variable "data_dir" { - description = "Relative path for the folder storing configuration data for network resources." - type = string - default = "data" +variable "factories_config" { + description = "Configuration for network resource factories." + type = object({ + data_dir = optional(string, "data") + firewall_policy_name = optional(string, "factory") + }) + default = { + data_dir = "data" + } + nullable = false + validation { + condition = var.factories_config.data_dir != null + error_message = "Data folder needs to be non-null." + } + validation { + condition = var.factories_config.firewall_policy_name != null + error_message = "Firewall policy name needs to be non-null." + } } variable "dns" { From 68854ca2860c7ee3895a79f185a6b951a42ac472 Mon Sep 17 00:00:00 2001 From: Ludo Date: Wed, 8 Feb 2023 09:11:56 +0100 Subject: [PATCH 09/16] fix stage links script --- fast/stage-links.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/fast/stage-links.sh b/fast/stage-links.sh index 0334ed2f2e..79d1973fa1 100755 --- a/fast/stage-links.sh +++ b/fast/stage-links.sh @@ -70,8 +70,8 @@ case $STAGE_NAME in exit 1 fi unset GLOBALS - PROVIDER="tenants/${TENANT}/providers/1-resman-tenant-providers.tf" - TFVARS="tenants/${TENANT}/tfvars/0-bootstrap-tenant.auto.tfvars.json" + PROVIDER="providers/1-resman-tenant-providers.tf" + TFVARS="tfvars/0-bootstrap-tenant.auto.tfvars.json" ;; "2-networking"*) PROVIDER="providers/2-networking-providers.tf" From 482968f456cb0fcbc6ae15f06486ca12dc3c25a8 Mon Sep 17 00:00:00 2001 From: Ludo Date: Wed, 8 Feb 2023 09:12:34 +0100 Subject: [PATCH 10/16] set custom role to tenant networking service account --- .../0-bootstrap-tenant/README.md | 34 +++++++++---------- .../0-bootstrap-tenant/automation-sas.tf | 8 +++++ .../0-bootstrap-tenant/outputs-gcs.tf | 6 ++-- .../0-bootstrap-tenant/variables.tf | 1 + 4 files changed, 29 insertions(+), 20 deletions(-) diff --git a/fast/stages-multitenant/0-bootstrap-tenant/README.md b/fast/stages-multitenant/0-bootstrap-tenant/README.md index c1fc9530fb..bbeaf9f69c 100644 --- a/fast/stages-multitenant/0-bootstrap-tenant/README.md +++ b/fast/stages-multitenant/0-bootstrap-tenant/README.md @@ -178,24 +178,24 @@ Once the configuration is done just go through the usual `init/apply` cycle. On |---|---|:---:|:---:|:---:|:---:| | [automation](variables.tf#L20) | Automation resources created by the organization-level bootstrap stage. | object({…}) | ✓ | | 0-bootstrap | | [billing_account](variables.tf#L38) | Billing account id. If billing account is not part of the same org set `is_org_level` to false. | object({…}) | ✓ | | 0-bootstrap | -| [organization](variables.tf#L193) | Organization details. | object({…}) | ✓ | | 0-bootstrap | -| [prefix](variables.tf#L209) | Prefix used for resources that need unique names. Use 9 characters or less. | string | ✓ | | 0-bootstrap | -| [tag_keys](variables.tf#L232) | Organization tag keys. | object({…}) | ✓ | | 1-resman | -| [tag_names](variables.tf#L243) | Customized names for resource management tags. | object({…}) | ✓ | | 1-resman | -| [tag_values](variables.tf#L254) | Organization resource management tag values. | map(string) | ✓ | | 1-resman | -| [tenant_config](variables.tf#L261) | Tenant configuration. Short name must be 4 characters or less. | object({…}) | ✓ | | | +| [organization](variables.tf#L194) | Organization details. | object({…}) | ✓ | | 0-bootstrap | +| [prefix](variables.tf#L210) | Prefix used for resources that need unique names. Use 9 characters or less. | string | ✓ | | 0-bootstrap | +| [tag_keys](variables.tf#L233) | Organization tag keys. | object({…}) | ✓ | | 1-resman | +| [tag_names](variables.tf#L244) | Customized names for resource management tags. | object({…}) | ✓ | | 1-resman | +| [tag_values](variables.tf#L255) | Organization resource management tag values. | map(string) | ✓ | | 1-resman | +| [tenant_config](variables.tf#L262) | Tenant configuration. Short name must be 4 characters or less. | object({…}) | ✓ | | | | [cicd_repositories](variables.tf#L51) | CI/CD repository configuration. Identity providers reference keys in the `federated_identity_providers` variable. Set to null to disable, or set individual repositories to null if not needed. | object({…}) | | null | | -| [custom_roles](variables.tf#L97) | Custom roles defined at the organization level, in key => id format. | object({…}) | | null | 0-bootstrap | -| [fast_features](variables.tf#L106) | Selective control for top-level FAST features. | object({…}) | | {} | 0-bootstrap | -| [federated_identity_providers](variables.tf#L120) | Workload Identity Federation pools. The `cicd_repositories` variable references keys here. | map(object({…})) | | {} | | -| [group_iam](variables.tf#L134) | Tenant-level custom group IAM settings in group => [roles] format. | map(list(string)) | | {} | | -| [iam](variables.tf#L140) | Tenant-level custom IAM settings in role => [principal] format. | map(list(string)) | | {} | | -| [iam_additive](variables.tf#L146) | Tenant-level custom IAM settings in role => [principal] format for non-authoritative bindings. | map(list(string)) | | {} | | -| [locations](variables.tf#L152) | Optional locations for GCS, BigQuery, and logging buckets created here. These are the defaults set at the organization level, and can be overridden via the tenant config variable. | object({…}) | | {…} | 0-bootstrap | -| [log_sinks](variables.tf#L172) | Tenant-level log sinks, in name => {type, filter} format. | map(object({…})) | | {…} | | -| [outputs_location](variables.tf#L203) | Enable writing provider, tfvars and CI/CD workflow files to local filesystem. Leave null to disable. | string | | null | | -| [project_parent_ids](variables.tf#L219) | Optional parents for projects created here in folders/nnnnnnn format. Null values will use the tenant folder as parent. | object({…}) | | {…} | | -| [test_principal](variables.tf#L301) | Used when testing to bypass the data source returning the current identity. | string | | null | | +| [custom_roles](variables.tf#L97) | Custom roles defined at the organization level, in key => id format. | object({…}) | | null | 0-bootstrap | +| [fast_features](variables.tf#L107) | Selective control for top-level FAST features. | object({…}) | | {} | 0-bootstrap | +| [federated_identity_providers](variables.tf#L121) | Workload Identity Federation pools. The `cicd_repositories` variable references keys here. | map(object({…})) | | {} | | +| [group_iam](variables.tf#L135) | Tenant-level custom group IAM settings in group => [roles] format. | map(list(string)) | | {} | | +| [iam](variables.tf#L141) | Tenant-level custom IAM settings in role => [principal] format. | map(list(string)) | | {} | | +| [iam_additive](variables.tf#L147) | Tenant-level custom IAM settings in role => [principal] format for non-authoritative bindings. | map(list(string)) | | {} | | +| [locations](variables.tf#L153) | Optional locations for GCS, BigQuery, and logging buckets created here. These are the defaults set at the organization level, and can be overridden via the tenant config variable. | object({…}) | | {…} | 0-bootstrap | +| [log_sinks](variables.tf#L173) | Tenant-level log sinks, in name => {type, filter} format. | map(object({…})) | | {…} | | +| [outputs_location](variables.tf#L204) | Enable writing provider, tfvars and CI/CD workflow files to local filesystem. Leave null to disable. | string | | null | | +| [project_parent_ids](variables.tf#L220) | Optional parents for projects created here in folders/nnnnnnn format. Null values will use the tenant folder as parent. | object({…}) | | {…} | | +| [test_principal](variables.tf#L302) | Used when testing to bypass the data source returning the current identity. | string | | null | | ## Outputs diff --git a/fast/stages-multitenant/0-bootstrap-tenant/automation-sas.tf b/fast/stages-multitenant/0-bootstrap-tenant/automation-sas.tf index c548f8d5fa..cae14093ea 100644 --- a/fast/stages-multitenant/0-bootstrap-tenant/automation-sas.tf +++ b/fast/stages-multitenant/0-bootstrap-tenant/automation-sas.tf @@ -125,3 +125,11 @@ resource "google_organization_iam_member" "org_policy_admin_stage2_3" { ]) } } + +# assign custom tenant network admin role to networking SA + +resource "google_organization_iam_member" "tenant_network_admin" { + org_id = var.organization.id + role = var.custom_roles.tenant_network_admin + member = module.automation-tf-resman-sa-stage2-3["networking"].iam_email +} diff --git a/fast/stages-multitenant/0-bootstrap-tenant/outputs-gcs.tf b/fast/stages-multitenant/0-bootstrap-tenant/outputs-gcs.tf index 7c0c7efc37..5196bad7de 100644 --- a/fast/stages-multitenant/0-bootstrap-tenant/outputs-gcs.tf +++ b/fast/stages-multitenant/0-bootstrap-tenant/outputs-gcs.tf @@ -19,13 +19,13 @@ resource "google_storage_bucket_object" "providers" { bucket = module.automation-tf-output-gcs.name # provider suffix allows excluding via .gitignore when linked from stages - name = "tenants/${var.tenant_config.short_name}/providers/1-resman-tenant-providers.tf" + name = "providers/1-resman-tenant-providers.tf" content = local.provider } resource "google_storage_bucket_object" "tfvars" { bucket = module.automation-tf-output-gcs.name - name = "tenants/${var.tenant_config.short_name}/tfvars/0-bootstrap-tenant.auto.tfvars.json" + name = "tfvars/0-bootstrap-tenant.auto.tfvars.json" content = jsonencode(local.tfvars) } @@ -36,6 +36,6 @@ resource "google_storage_bucket_object" "workflows" { ? var.automation.outputs_bucket : module.automation-tf-output-gcs.name ) - name = "tenants/${var.tenant_config.short_name}/workflows/${each.key}-${local.cicd_repositories[each.key].type}.yaml" + name = "workflows/${each.key}-${local.cicd_repositories[each.key].type}.yaml" content = each.value } diff --git a/fast/stages-multitenant/0-bootstrap-tenant/variables.tf b/fast/stages-multitenant/0-bootstrap-tenant/variables.tf index 1a0134b08e..d218986fd5 100644 --- a/fast/stages-multitenant/0-bootstrap-tenant/variables.tf +++ b/fast/stages-multitenant/0-bootstrap-tenant/variables.tf @@ -99,6 +99,7 @@ variable "custom_roles" { description = "Custom roles defined at the organization level, in key => id format." type = object({ service_project_network_admin = string + tenant_network_admin = string }) default = null } From 52d2673df1789fce88e9dc7385e3c836b14d34c0 Mon Sep 17 00:00:00 2001 From: Ludo Date: Wed, 8 Feb 2023 09:12:54 +0100 Subject: [PATCH 11/16] rename tenant stage 1 provider files --- .../1-resman-tenant/outputs.tf | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/fast/stages-multitenant/1-resman-tenant/outputs.tf b/fast/stages-multitenant/1-resman-tenant/outputs.tf index ad2d8dcfd3..592f995ea3 100644 --- a/fast/stages-multitenant/1-resman-tenant/outputs.tf +++ b/fast/stages-multitenant/1-resman-tenant/outputs.tf @@ -98,13 +98,13 @@ locals { ) providers = merge( { - "2-0-networking" = templatefile(local._tpl_providers, { + "2-networking" = templatefile(local._tpl_providers, { backend_extra = null bucket = module.branch-network-gcs.name name = "networking" sa = module.branch-network-sa.email }) - "2-0-security" = templatefile(local._tpl_providers, { + "2-security" = templatefile(local._tpl_providers, { backend_extra = null bucket = module.branch-security-gcs.name name = "security" @@ -112,13 +112,13 @@ locals { }) }, !var.fast_features.data_platform ? {} : { - "3-0-data-platform-dev" = templatefile(local._tpl_providers, { + "3-data-platform-dev" = templatefile(local._tpl_providers, { backend_extra = null bucket = module.branch-dp-dev-gcs.0.name name = "dp-dev" sa = module.branch-dp-dev-sa.0.email }) - "3-0-data-platform-prod" = templatefile(local._tpl_providers, { + "3-data-platform-prod" = templatefile(local._tpl_providers, { backend_extra = null bucket = module.branch-dp-prod-gcs.0.name name = "dp-prod" @@ -126,13 +126,13 @@ locals { }) }, !var.fast_features.gke ? {} : { - "3-0-gke-dev" = templatefile(local._tpl_providers, { + "3-gke-dev" = templatefile(local._tpl_providers, { backend_extra = null bucket = module.branch-gke-dev-gcs.0.name name = "gke-dev" sa = module.branch-gke-dev-sa.0.email }) - "3-0-gke-prod" = templatefile(local._tpl_providers, { + "3-gke-prod" = templatefile(local._tpl_providers, { backend_extra = null bucket = module.branch-gke-prod-gcs.0.name name = "gke-prod" @@ -140,13 +140,13 @@ locals { }) }, !var.fast_features.project_factory ? {} : { - "3-0-project-factory-dev" = templatefile(local._tpl_providers, { + "3-project-factory-dev" = templatefile(local._tpl_providers, { backend_extra = null bucket = module.branch-pf-dev-gcs.0.name name = "team-dev" sa = var.automation.service_accounts.pf-dev }) - "3-0-project-factory-prod" = templatefile(local._tpl_providers, { + "3-project-factory-prod" = templatefile(local._tpl_providers, { backend_extra = null bucket = module.branch-pf-prod-gcs.0.name name = "team-prod" @@ -154,7 +154,7 @@ locals { }) }, !var.fast_features.sandbox ? {} : { - "9-0-sandbox" = templatefile(local._tpl_providers, { + "9-sandbox" = templatefile(local._tpl_providers, { backend_extra = null bucket = module.branch-sandbox-gcs.0.name name = "sandbox" From e29c78eefb9c441071f241deee78e740cda0e19b Mon Sep 17 00:00:00 2001 From: Ludo Date: Wed, 8 Feb 2023 09:13:03 +0100 Subject: [PATCH 12/16] remove extra file --- fast/stages-multitenant/MULTITENANT-TODO.md | 8 -------- 1 file changed, 8 deletions(-) delete mode 100644 fast/stages-multitenant/MULTITENANT-TODO.md diff --git a/fast/stages-multitenant/MULTITENANT-TODO.md b/fast/stages-multitenant/MULTITENANT-TODO.md deleted file mode 100644 index a14d64ab5b..0000000000 --- a/fast/stages-multitenant/MULTITENANT-TODO.md +++ /dev/null @@ -1,8 +0,0 @@ -# Things to add before sending the PR - -- [x] multitenant resman stage -- [ ] identity providers for tenant bootstrap stages -- [ ] edit FAST top-level and stages READMEs for multitenant -- [ ] multitenant stages READMEs -- [ ] add test to ensure templates folder is the same in every stage -- [ ] add test to ensure identity providers code is the same in bootstrap and mt bootstrap From 5366a7995b8681f18eab324cd5fe0d1c3c267571 Mon Sep 17 00:00:00 2001 From: Ludo Date: Wed, 8 Feb 2023 09:21:42 +0100 Subject: [PATCH 13/16] fix peering and vpn --- fast/stages/2-networking-a-peering/main.tf | 6 +++--- fast/stages/2-networking-b-vpn/main.tf | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/fast/stages/2-networking-a-peering/main.tf b/fast/stages/2-networking-a-peering/main.tf index cfa41591e6..5888752d73 100644 --- a/fast/stages/2-networking-a-peering/main.tf +++ b/fast/stages/2-networking-a-peering/main.tf @@ -46,9 +46,9 @@ module "folder" { folder_create = var.folder_ids.networking == null id = var.folder_ids.networking firewall_policy_factory = { - cidr_file = "${var.data_dir}/cidrs.yaml" - policy_name = null - rules_file = "${var.data_dir}/hierarchical-policy-rules.yaml" + cidr_file = "${var.factories_config.data_dir}/cidrs.yaml" + policy_name = var.factories_config.firewall_policy_name + rules_file = "${var.factories_config.data_dir}/hierarchical-policy-rules.yaml" } firewall_policy_association = { factory-policy = "factory" diff --git a/fast/stages/2-networking-b-vpn/main.tf b/fast/stages/2-networking-b-vpn/main.tf index cfa41591e6..5888752d73 100644 --- a/fast/stages/2-networking-b-vpn/main.tf +++ b/fast/stages/2-networking-b-vpn/main.tf @@ -46,9 +46,9 @@ module "folder" { folder_create = var.folder_ids.networking == null id = var.folder_ids.networking firewall_policy_factory = { - cidr_file = "${var.data_dir}/cidrs.yaml" - policy_name = null - rules_file = "${var.data_dir}/hierarchical-policy-rules.yaml" + cidr_file = "${var.factories_config.data_dir}/cidrs.yaml" + policy_name = var.factories_config.firewall_policy_name + rules_file = "${var.factories_config.data_dir}/hierarchical-policy-rules.yaml" } firewall_policy_association = { factory-policy = "factory" From 132009da7837d52639b0c176240372673c688323 Mon Sep 17 00:00:00 2001 From: Ludo Date: Wed, 8 Feb 2023 09:23:32 +0100 Subject: [PATCH 14/16] tfdoc --- fast/stages/2-networking-d-separate-envs/README.md | 1 - 1 file changed, 1 deletion(-) diff --git a/fast/stages/2-networking-d-separate-envs/README.md b/fast/stages/2-networking-d-separate-envs/README.md index 27823f2b75..7284416b1c 100644 --- a/fast/stages/2-networking-d-separate-envs/README.md +++ b/fast/stages/2-networking-d-separate-envs/README.md @@ -222,7 +222,6 @@ You're now ready to run `terraform init` and `apply`. | name | description | modules | resources | |---|---|---|---| -| [2-0-networking-providers.tf](./2-0-networking-providers.tf) | None | | | | [dns-dev.tf](./dns-dev.tf) | Development spoke DNS zones and peerings setup. | dns | | | [dns-prod.tf](./dns-prod.tf) | Production spoke DNS zones and peerings setup. | dns | | | [main.tf](./main.tf) | Networking folder and hierarchical policy. | folder | | From 45a778feceb10959e2c50c9adad936bf52e4ff28 Mon Sep 17 00:00:00 2001 From: Ludo Date: Wed, 8 Feb 2023 09:26:54 +0100 Subject: [PATCH 15/16] fix variable order --- fast/stages/2-networking-a-peering/README.md | 4 ++-- .../stages/2-networking-a-peering/variables.tf | 16 ++++++++-------- fast/stages/2-networking-b-vpn/README.md | 4 ++-- fast/stages/2-networking-b-vpn/variables.tf | 16 ++++++++-------- fast/stages/2-networking-c-nva/README.md | 4 ++-- fast/stages/2-networking-c-nva/variables.tf | 16 ++++++++-------- .../2-networking-d-separate-envs/README.md | 4 ++-- .../2-networking-d-separate-envs/variables.tf | 18 +++++++++--------- 8 files changed, 41 insertions(+), 41 deletions(-) diff --git a/fast/stages/2-networking-a-peering/README.md b/fast/stages/2-networking-a-peering/README.md index 6e5435bea8..7966ce80bb 100644 --- a/fast/stages/2-networking-a-peering/README.md +++ b/fast/stages/2-networking-a-peering/README.md @@ -303,8 +303,8 @@ DNS configurations are centralised in the `dns-*.tf` files. Spokes delegate DNS | [prefix](variables.tf#L142) | Prefix used for resources that need unique names. Use 9 characters or less. | string | ✓ | | 0-bootstrap | | [custom_adv](variables.tf#L38) | Custom advertisement definitions in name => range format. | map(string) | | {…} | | | [custom_roles](variables.tf#L55) | Custom roles defined at the org level, in key => id format. | object({…}) | | null | 0-bootstrap | -| [dns](variables.tf#L84) | Onprem DNS resolvers. | map(list(string)) | | {…} | | -| [factories_config](variables.tf#L64) | Configuration for network resource factories. | object({…}) | | {…} | | +| [dns](variables.tf#L64) | Onprem DNS resolvers. | map(list(string)) | | {…} | | +| [factories_config](variables.tf#L72) | Configuration for network resource factories. | object({…}) | | {…} | | | [l7ilb_subnets](variables.tf#L102) | Subnets used for L7 ILBs. | object({…}) | | {…} | | | [outputs_location](variables.tf#L136) | Path where providers and tfvars files for the following stages are written. Leave empty to disable. | string | | null | | | [peering_configs](variables-peerings.tf#L19) | Peering configurations. | map(object({…})) | | {…} | | diff --git a/fast/stages/2-networking-a-peering/variables.tf b/fast/stages/2-networking-a-peering/variables.tf index 6d30af9d7f..f0443dc0b2 100644 --- a/fast/stages/2-networking-a-peering/variables.tf +++ b/fast/stages/2-networking-a-peering/variables.tf @@ -61,6 +61,14 @@ variable "custom_roles" { default = null } +variable "dns" { + description = "Onprem DNS resolvers." + type = map(list(string)) + default = { + onprem = ["10.0.200.3"] + } +} + variable "factories_config" { description = "Configuration for network resource factories." type = object({ @@ -81,14 +89,6 @@ variable "factories_config" { } } -variable "dns" { - description = "Onprem DNS resolvers." - type = map(list(string)) - default = { - onprem = ["10.0.200.3"] - } -} - variable "folder_ids" { # tfdoc:variable:source 1-resman description = "Folders to be used for the networking resources in folders/nnnnnnnnnnn format. If null, folder will be created." diff --git a/fast/stages/2-networking-b-vpn/README.md b/fast/stages/2-networking-b-vpn/README.md index dfb8ecbecd..2177f3113b 100644 --- a/fast/stages/2-networking-b-vpn/README.md +++ b/fast/stages/2-networking-b-vpn/README.md @@ -328,8 +328,8 @@ DNS configurations are centralised in the `dns-*.tf` files. Spokes delegate DNS | [prefix](variables.tf#L142) | Prefix used for resources that need unique names. Use 9 characters or less. | string | ✓ | | 0-bootstrap | | [custom_adv](variables.tf#L38) | Custom advertisement definitions in name => range format. | map(string) | | {…} | | | [custom_roles](variables.tf#L55) | Custom roles defined at the org level, in key => id format. | object({…}) | | null | 0-bootstrap | -| [dns](variables.tf#L84) | Onprem DNS resolvers. | map(list(string)) | | {…} | | -| [factories_config](variables.tf#L64) | Configuration for network resource factories. | object({…}) | | {…} | | +| [dns](variables.tf#L64) | Onprem DNS resolvers. | map(list(string)) | | {…} | | +| [factories_config](variables.tf#L72) | Configuration for network resource factories. | object({…}) | | {…} | | | [l7ilb_subnets](variables.tf#L102) | Subnets used for L7 ILBs. | object({…}) | | {…} | | | [outputs_location](variables.tf#L136) | Path where providers and tfvars files for the following stages are written. Leave empty to disable. | string | | null | | | [psa_ranges](variables.tf#L153) | IP ranges used for Private Service Access (e.g. CloudSQL). | object({…}) | | null | | diff --git a/fast/stages/2-networking-b-vpn/variables.tf b/fast/stages/2-networking-b-vpn/variables.tf index 6d30af9d7f..f0443dc0b2 100644 --- a/fast/stages/2-networking-b-vpn/variables.tf +++ b/fast/stages/2-networking-b-vpn/variables.tf @@ -61,6 +61,14 @@ variable "custom_roles" { default = null } +variable "dns" { + description = "Onprem DNS resolvers." + type = map(list(string)) + default = { + onprem = ["10.0.200.3"] + } +} + variable "factories_config" { description = "Configuration for network resource factories." type = object({ @@ -81,14 +89,6 @@ variable "factories_config" { } } -variable "dns" { - description = "Onprem DNS resolvers." - type = map(list(string)) - default = { - onprem = ["10.0.200.3"] - } -} - variable "folder_ids" { # tfdoc:variable:source 1-resman description = "Folders to be used for the networking resources in folders/nnnnnnnnnnn format. If null, folder will be created." diff --git a/fast/stages/2-networking-c-nva/README.md b/fast/stages/2-networking-c-nva/README.md index eebff0f1a8..425e1d195e 100644 --- a/fast/stages/2-networking-c-nva/README.md +++ b/fast/stages/2-networking-c-nva/README.md @@ -376,8 +376,8 @@ DNS configurations are centralised in the `dns-*.tf` files. Spokes delegate DNS | [prefix](variables.tf#L149) | Prefix used for resources that need unique names. Use 9 characters or less. | string | ✓ | | 0-bootstrap | | [custom_adv](variables.tf#L38) | Custom advertisement definitions in name => range format. | map(string) | | {…} | | | [custom_roles](variables.tf#L60) | Custom roles defined at the org level, in key => id format. | object({…}) | | null | 0-bootstrap | -| [dns](variables.tf#L89) | Onprem DNS resolvers. | map(list(string)) | | {…} | | -| [factories_config](variables.tf#L69) | Configuration for network resource factories. | object({…}) | | {…} | | +| [dns](variables.tf#L69) | Onprem DNS resolvers. | map(list(string)) | | {…} | | +| [factories_config](variables.tf#L77) | Configuration for network resource factories. | object({…}) | | {…} | | | [l7ilb_subnets](variables.tf#L107) | Subnets used for L7 ILBs. | map(list(object({…}))) | | {…} | | | [onprem_cidr](variables.tf#L125) | Onprem addresses in name => range format. | map(string) | | {…} | | | [outputs_location](variables.tf#L143) | Path where providers and tfvars files for the following stages are written. Leave empty to disable. | string | | null | | diff --git a/fast/stages/2-networking-c-nva/variables.tf b/fast/stages/2-networking-c-nva/variables.tf index 76cb2cb6be..5049300765 100644 --- a/fast/stages/2-networking-c-nva/variables.tf +++ b/fast/stages/2-networking-c-nva/variables.tf @@ -66,6 +66,14 @@ variable "custom_roles" { default = null } +variable "dns" { + description = "Onprem DNS resolvers." + type = map(list(string)) + default = { + onprem = ["10.0.200.3"] + } +} + variable "factories_config" { description = "Configuration for network resource factories." type = object({ @@ -86,14 +94,6 @@ variable "factories_config" { } } -variable "dns" { - description = "Onprem DNS resolvers." - type = map(list(string)) - default = { - onprem = ["10.0.200.3"] - } -} - variable "folder_ids" { # tfdoc:variable:source 1-resman description = "Folders to be used for the networking resources in folders/nnnnnnnnnnn format. If null, folder will be created." diff --git a/fast/stages/2-networking-d-separate-envs/README.md b/fast/stages/2-networking-d-separate-envs/README.md index 7284416b1c..a461dc97bf 100644 --- a/fast/stages/2-networking-d-separate-envs/README.md +++ b/fast/stages/2-networking-d-separate-envs/README.md @@ -246,8 +246,8 @@ You're now ready to run `terraform init` and `apply`. | [prefix](variables.tf#L134) | Prefix used for resources that need unique names. Use 9 characters or less. | string | ✓ | | 0-bootstrap | | [custom_adv](variables.tf#L38) | Custom advertisement definitions in name => range format. | map(string) | | {…} | | | [custom_roles](variables.tf#L54) | Custom roles defined at the org level, in key => id format. | object({…}) | | null | 0-bootstrap | -| [dns](variables.tf#L83) | Onprem DNS resolvers. | map(list(string)) | | {…} | | -| [factories_config](variables.tf#L63) | Configuration for network resource factories. | object({…}) | | {…} | | +| [dns](variables.tf#L63) | Onprem DNS resolvers. | map(list(string)) | | {…} | | +| [factories_config](variables.tf#L72) | Configuration for network resource factories. | object({…}) | | {…} | | | [l7ilb_subnets](variables.tf#L102) | Subnets used for L7 ILBs. | map(list(object({…}))) | | {…} | | | [outputs_location](variables.tf#L128) | Path where providers and tfvars files for the following stages are written. Leave empty to disable. | string | | null | | | [psa_ranges](variables.tf#L145) | IP ranges used for Private Service Access (e.g. CloudSQL). | object({…}) | | null | | diff --git a/fast/stages/2-networking-d-separate-envs/variables.tf b/fast/stages/2-networking-d-separate-envs/variables.tf index 85ae3c9941..03d5651396 100644 --- a/fast/stages/2-networking-d-separate-envs/variables.tf +++ b/fast/stages/2-networking-d-separate-envs/variables.tf @@ -60,6 +60,15 @@ variable "custom_roles" { default = null } +variable "dns" { + description = "Onprem DNS resolvers." + type = map(list(string)) + default = { + prod = ["10.0.1.1"] + dev = ["10.0.2.1"] + } +} + variable "factories_config" { description = "Configuration for network resource factories." type = object({ @@ -80,15 +89,6 @@ variable "factories_config" { } } -variable "dns" { - description = "Onprem DNS resolvers." - type = map(list(string)) - default = { - prod = ["10.0.1.1"] - dev = ["10.0.2.1"] - } -} - variable "folder_ids" { # tfdoc:variable:source 1-resman description = "Folders to be used for the networking resources in folders/nnnnnnnnnnn format. If null, folder will be created." From be12c5ca85f9d5f7ec3cb39d5adc364db15fbbf4 Mon Sep 17 00:00:00 2001 From: Ludo Date: Wed, 8 Feb 2023 09:45:43 +0100 Subject: [PATCH 16/16] tests --- tests/fast/stages/s0_bootstrap/simple.yaml | 3 ++- .../fast/stages_multitenant/s0_bootstrap_tenant/simple.tfvars | 1 + tests/fast/stages_multitenant/s0_bootstrap_tenant/simple.yaml | 4 ++-- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/tests/fast/stages/s0_bootstrap/simple.yaml b/tests/fast/stages/s0_bootstrap/simple.yaml index 4b65e836d5..63a64cb9e2 100644 --- a/tests/fast/stages/s0_bootstrap/simple.yaml +++ b/tests/fast/stages/s0_bootstrap/simple.yaml @@ -17,7 +17,7 @@ counts: google_bigquery_default_service_account: 3 google_logging_organization_sink: 2 google_organization_iam_binding: 19 - google_organization_iam_custom_role: 2 + google_organization_iam_custom_role: 3 google_organization_iam_member: 16 google_project: 3 google_project_iam_binding: 9 @@ -37,6 +37,7 @@ outputs: custom_roles: organization_iam_admin: organizations/123456789012/roles/organizationIamAdmin service_project_network_admin: organizations/123456789012/roles/serviceProjectNetworkAdmin + tenant_network_admin: organizations/123456789012/roles/tenantNetworkAdmin outputs_bucket: fast-prod-iac-core-outputs-0 project_ids: automation: fast-prod-iac-core-0 diff --git a/tests/fast/stages_multitenant/s0_bootstrap_tenant/simple.tfvars b/tests/fast/stages_multitenant/s0_bootstrap_tenant/simple.tfvars index f77e541152..52ca76a3db 100644 --- a/tests/fast/stages_multitenant/s0_bootstrap_tenant/simple.tfvars +++ b/tests/fast/stages_multitenant/s0_bootstrap_tenant/simple.tfvars @@ -11,6 +11,7 @@ billing_account = { custom_roles = { # organization_iam_admin = "organizations/123456789012/roles/organizationIamAdmin", service_project_network_admin = "organizations/123456789012/roles/xpnServiceAdmin" + tenant_network_admin = "organizations/123456789012/roles/TenantNetworkAdmin" } groups = { gcp-billing-admins = "gcp-billing-admins", diff --git a/tests/fast/stages_multitenant/s0_bootstrap_tenant/simple.yaml b/tests/fast/stages_multitenant/s0_bootstrap_tenant/simple.yaml index 7e132128c1..e5ccc4fd54 100644 --- a/tests/fast/stages_multitenant/s0_bootstrap_tenant/simple.yaml +++ b/tests/fast/stages_multitenant/s0_bootstrap_tenant/simple.yaml @@ -16,7 +16,7 @@ counts: google_bigquery_default_service_account: 2 google_folder: 2 google_folder_iam_binding: 5 - google_organization_iam_member: 38 + google_organization_iam_member: 39 google_project: 2 google_project_iam_binding: 8 google_project_service: 26 @@ -30,4 +30,4 @@ counts: google_tags_tag_binding: 1 google_tags_tag_value: 1 modules: 19 - resources: 128 + resources: 129