From efb0ebe689a1780fa6157265f3d4e63379245a2d Mon Sep 17 00:00:00 2001 From: Ludovico Magnocavallo Date: Thu, 4 May 2023 07:38:40 +0200 Subject: [PATCH] Switch FAST networking stages to network policies for Google domains (#1352) * peering stage implementation * vpn stage implementation * tfdoc * tests * add most supported google domains * align all net stages * add support for factory to DNS response policy module * use dns policy factory in network stages * boilerplate --- fast/stages/2-networking-a-peering/README.md | 28 ++--- .../data/dns-policy-rules.yaml | 110 ++++++++++++++++ fast/stages/2-networking-a-peering/dns-dev.tf | 21 +++- .../2-networking-a-peering/dns-landing.tf | 105 ++++------------ .../stages/2-networking-a-peering/dns-prod.tf | 21 +++- .../2-networking-a-peering/variables.tf | 5 +- fast/stages/2-networking-b-vpn/README.md | 28 ++--- .../data/dns-policy-rules.yaml | 110 ++++++++++++++++ fast/stages/2-networking-b-vpn/dns-dev.tf | 21 +++- fast/stages/2-networking-b-vpn/dns-landing.tf | 105 ++++------------ fast/stages/2-networking-b-vpn/dns-prod.tf | 21 +++- fast/stages/2-networking-b-vpn/variables.tf | 5 +- fast/stages/2-networking-c-nva/README.md | 34 +++-- .../data/dns-policy-rules.yaml | 110 ++++++++++++++++ fast/stages/2-networking-c-nva/dns-dev.tf | 14 ++- fast/stages/2-networking-c-nva/dns-landing.tf | 117 ++++-------------- fast/stages/2-networking-c-nva/dns-prod.tf | 14 ++- fast/stages/2-networking-c-nva/variables.tf | 5 +- .../2-networking-d-separate-envs/README.md | 32 ++--- .../data/dns-policy-rules.yaml | 110 ++++++++++++++++ .../2-networking-d-separate-envs/dns-dev.tf | 96 +++----------- .../2-networking-d-separate-envs/dns-prod.tf | 96 +++----------- .../2-networking-d-separate-envs/variables.tf | 5 +- fast/stages/2-networking-e-nva-bgp/README.md | 38 +++--- .../data/dns-policy-rules.yaml | 110 ++++++++++++++++ fast/stages/2-networking-e-nva-bgp/dns-dev.tf | 14 ++- .../2-networking-e-nva-bgp/dns-landing.tf | 117 ++++-------------- .../stages/2-networking-e-nva-bgp/dns-prod.tf | 14 ++- .../2-networking-e-nva-bgp/variables.tf | 5 +- modules/dns-response-policy/README.md | 63 +++++++++- modules/dns-response-policy/main.tf | 13 +- modules/dns-response-policy/variables.tf | 6 + .../stages/s2_networking_a_peering/stage.yaml | 4 +- .../stages/s2_networking_b_vpn/stage.yaml | 4 +- .../stages/s2_networking_c_nva/stage.yaml | 4 +- .../s2_networking_d_separate_envs/stage.yaml | 4 +- .../stages/s2_networking_e_nva_bgp/stage.yaml | 4 +- .../examples/{nocreate.yaml => complex.yaml} | 57 ++++++--- 38 files changed, 1018 insertions(+), 652 deletions(-) create mode 100644 fast/stages/2-networking-a-peering/data/dns-policy-rules.yaml create mode 100644 fast/stages/2-networking-b-vpn/data/dns-policy-rules.yaml create mode 100644 fast/stages/2-networking-c-nva/data/dns-policy-rules.yaml create mode 100644 fast/stages/2-networking-d-separate-envs/data/dns-policy-rules.yaml create mode 100644 fast/stages/2-networking-e-nva-bgp/data/dns-policy-rules.yaml rename tests/modules/dns_response_policy/examples/{nocreate.yaml => complex.yaml} (51%) diff --git a/fast/stages/2-networking-a-peering/README.md b/fast/stages/2-networking-a-peering/README.md index f3c7c951..2552691a 100644 --- a/fast/stages/2-networking-a-peering/README.md +++ b/fast/stages/2-networking-a-peering/README.md @@ -130,13 +130,7 @@ DNS configuration is further centralized by leveraging peering zones, so that - the hub/landing Cloud DNS hosts configurations for on-prem forwarding, Google API domains, and the top-level private zone/s (e.g. gcp.example.com) - the spokes Cloud DNS host configurations for the environment-specific domains (e.g. prod.gcp.example.com), which are bound to the hub/landing leveraging [cross-project binding](https://cloud.google.com/dns/docs/zones/zones-overview#cross-project_binding); a peering zone for the `.` (root) zone is then created on each spoke, delegating all DNS resolution to hub/landing. -- Private Google Access is enabled for a selection of the [supported domains](https://cloud.google.com/vpc/docs/configure-private-google-access#domain-options), namely - - `private.googleapis.com` - - `restricted.googleapis.com` - - `gcr.io` - - `packages.cloud.google.com` - - `pkg.dev` - - `pki.goog` +- Private Google Access is enabled via [DNS Response Policies](https://cloud.google.com/dns/docs/zones/manage-response-policies#create-response-policy-rule) for most of the [supported domains](https://cloud.google.com/vpc/docs/configure-private-google-access#domain-options) To complete the configuration, the 35.199.192.0/19 range should be routed on the VPN tunnels from on-prem, and the following names configured for DNS forwarding to cloud: @@ -382,7 +376,7 @@ DNS configurations are centralised in the `dns-*.tf` files. Spokes delegate DNS | name | description | modules | resources | |---|---|---|---| | [dns-dev.tf](./dns-dev.tf) | Development spoke DNS zones and peerings setup. | dns | | -| [dns-landing.tf](./dns-landing.tf) | Landing DNS zones and peerings setup. | dns | | +| [dns-landing.tf](./dns-landing.tf) | Landing DNS zones and peerings setup. | dns · dns-response-policy | | | [dns-prod.tf](./dns-prod.tf) | Production spoke DNS zones and peerings setup. | dns | | | [landing.tf](./landing.tf) | Landing VPC and related resources. | net-cloudnat · net-vpc · net-vpc-firewall · project | | | [main.tf](./main.tf) | Networking folder and hierarchical policy. | folder | | @@ -403,18 +397,18 @@ DNS configurations are centralised in the `dns-*.tf` files. Spokes delegate DNS |---|---|:---:|:---:|:---:|:---:| | [automation](variables.tf#L17) | Automation resources created by the bootstrap stage. | object({…}) | ✓ | | 0-bootstrap | | [billing_account](variables.tf#L25) | Billing account id. If billing account is not part of the same org set `is_org_level` to false. | object({…}) | ✓ | | 0-bootstrap | -| [folder_ids](variables.tf#L75) | Folders to be used for the networking resources in folders/nnnnnnnnnnn format. If null, folder will be created. | object({…}) | ✓ | | 1-resman | -| [organization](variables.tf#L85) | Organization details. | object({…}) | ✓ | | 0-bootstrap | -| [prefix](variables.tf#L101) | Prefix used for resources that need unique names. Use 9 characters or less. | string | ✓ | | 0-bootstrap | +| [folder_ids](variables.tf#L76) | Folders to be used for the networking resources in folders/nnnnnnnnnnn format. If null, folder will be created. | object({…}) | ✓ | | 1-resman | +| [organization](variables.tf#L86) | Organization details. | object({…}) | ✓ | | 0-bootstrap | +| [prefix](variables.tf#L102) | Prefix used for resources that need unique names. Use 9 characters or less. | string | ✓ | | 0-bootstrap | | [custom_roles](variables.tf#L38) | Custom roles defined at the org level, in key => id format. | object({…}) | | null | 0-bootstrap | | [dns](variables.tf#L47) | Onprem DNS resolvers. | map(list(string)) | | {…} | | -| [factories_config](variables.tf#L55) | Configuration for network resource factories. | object({…}) | | {…} | | -| [outputs_location](variables.tf#L95) | Path where providers and tfvars files for the following stages are written. Leave empty to disable. | string | | null | | +| [factories_config](variables.tf#L55) | Configuration for network resource factories. | object({…}) | | {…} | | +| [outputs_location](variables.tf#L96) | Path where providers and tfvars files for the following stages are written. Leave empty to disable. | string | | null | | | [peering_configs](variables-peerings.tf#L19) | Peering configurations. | map(object({…})) | | {…} | | -| [psa_ranges](variables.tf#L112) | IP ranges used for Private Service Access (CloudSQL, etc.). | object({…}) | | null | | -| [regions](variables.tf#L133) | Region definitions. | object({…}) | | {…} | | -| [service_accounts](variables.tf#L145) | Automation service accounts in name => email format. | object({…}) | | null | 1-resman | -| [vpn_onprem_primary_config](variables.tf#L159) | VPN gateway configuration for onprem interconnection in the primary region. | object({…}) | | null | | +| [psa_ranges](variables.tf#L113) | IP ranges used for Private Service Access (CloudSQL, etc.). | object({…}) | | null | | +| [regions](variables.tf#L134) | Region definitions. | object({…}) | | {…} | | +| [service_accounts](variables.tf#L146) | Automation service accounts in name => email format. | object({…}) | | null | 1-resman | +| [vpn_onprem_primary_config](variables.tf#L160) | VPN gateway configuration for onprem interconnection in the primary region. | object({…}) | | null | | ## Outputs diff --git a/fast/stages/2-networking-a-peering/data/dns-policy-rules.yaml b/fast/stages/2-networking-a-peering/data/dns-policy-rules.yaml new file mode 100644 index 00000000..d091e4f0 --- /dev/null +++ b/fast/stages/2-networking-a-peering/data/dns-policy-rules.yaml @@ -0,0 +1,110 @@ +# skip boilerplate check + +accounts: + dns_name: "accounts.google.com." + local_data: { CNAME: { rrdatas: ["private.googleapis.com."] } } +backupdr-cloud: + dns_name: "backupdr.cloud.google.com." + local_data: { CNAME: { rrdatas: ["private.googleapis.com."] } } +backupdr-cloud-all: + dns_name: "*.backupdr.cloud.google.com." + local_data: { CNAME: { rrdatas: ["private.googleapis.com."] } } +backupdr-gu: + dns_name: "backupdr.googleusercontent.google.com." + local_data: { CNAME: { rrdatas: ["private.googleapis.com."] } } +backupdr-gu-all: + dns_name: "*.backupdr.googleusercontent.google.com." + local_data: { CNAME: { rrdatas: ["private.googleapis.com."] } } +cloudfunctions: + dns_name: "*.cloudfunctions.net." + local_data: { CNAME: { rrdatas: ["private.googleapis.com."] } } +cloudproxy: + dns_name: "*.cloudproxy.app." + local_data: { CNAME: { rrdatas: ["private.googleapis.com."] } } +composer-cloud-all: + dns_name: "*.composer.cloud.google.com." + local_data: { CNAME: { rrdatas: ["private.googleapis.com."] } } +composer-gu-all: + dns_name: "*.composer.googleusercontent.com." + local_data: { CNAME: { rrdatas: ["private.googleapis.com."] } } +datafusion-all: + dns_name: "*.datafusion.cloud.google.com." + local_data: { CNAME: { rrdatas: ["private.googleapis.com."] } } +datafusion-gu-all: + dns_name: "*.datafusion.googleusercontent.com." + local_data: { CNAME: { rrdatas: ["private.googleapis.com."] } } +dataproc: + dns_name: "dataproc.cloud.google.com." + local_data: { CNAME: { rrdatas: ["private.googleapis.com."] } } +dataproc-all: + dns_name: "*.dataproc.cloud.google.com." + local_data: { CNAME: { rrdatas: ["private.googleapis.com."] } } +dataproc-gu: + dns_name: "dataproc.googleusercontent.com." + local_data: { CNAME: { rrdatas: ["private.googleapis.com."] } } +dataproc-gu-all: + dns_name: "*.dataproc.googleusercontent.com." + local_data: { CNAME: { rrdatas: ["private.googleapis.com."] } } +dl: + dns_name: "dl.google.com." + local_data: { CNAME: { rrdatas: ["private.googleapis.com."] } } +gcr: + dns_name: "gcr.io." + local_data: { CNAME: { rrdatas: ["private.googleapis.com."] } } +gcr-all: + dns_name: "*.gcr.io." + local_data: { CNAME: { rrdatas: ["private.googleapis.com."] } } +googleapis-all: + dns_name: "*.googleapis.com." + local_data: { CNAME: { rrdatas: ["private.googleapis.com."] } } +googleapis-private: + dns_name: "private.googleapis.com." + local_data: + A: + rrdatas: + - 199.36.153.8 + - 199.36.153.9 + - 199.36.153.10 + - 199.36.153.11 +googleapis-restricted: + dns_name: "restricted.googleapis.com." + local_data: + A: + rrdatas: + - 199.36.153.4 + - 199.36.153.5 + - 199.36.153.6 + - 199.36.153.7 +gstatic-all: + dns_name: "*.gstatic.com." + local_data: { CNAME: { rrdatas: ["private.googleapis.com."] } } +notebooks-all: + dns_name: "*.notebooks.cloud.google.com." + local_data: { CNAME: { rrdatas: ["private.googleapis.com."] } } +notebooks-gu-all: + dns_name: "*.notebooks.googleusercontent.com." + local_data: { CNAME: { rrdatas: ["private.googleapis.com."] } } +packages-cloud: + dns_name: "packages.cloud.google.com." + local_data: { CNAME: { rrdatas: ["private.googleapis.com."] } } +packages-cloud-all: + dns_name: "*.packages.cloud.google.com." + local_data: { CNAME: { rrdatas: ["private.googleapis.com."] } } +pkgdev: + dns_name: "pkg.dev." + local_data: { CNAME: { rrdatas: ["private.googleapis.com."] } } +pkgdev-all: + dns_name: "*.pkg.dev." + local_data: { CNAME: { rrdatas: ["private.googleapis.com."] } } +pkigoog: + dns_name: "pki.goog." + local_data: { CNAME: { rrdatas: ["private.googleapis.com."] } } +pkigoog-all: + dns_name: "*.pki.goog." + local_data: { CNAME: { rrdatas: ["private.googleapis.com."] } } +run-all: + dns_name: "*.run.app." + local_data: { CNAME: { rrdatas: ["private.googleapis.com."] } } +source: + dns_name: "source.developers.google.com." + local_data: { CNAME: { rrdatas: ["private.googleapis.com."] } } diff --git a/fast/stages/2-networking-a-peering/dns-dev.tf b/fast/stages/2-networking-a-peering/dns-dev.tf index 03ae0122..efeabeae 100644 --- a/fast/stages/2-networking-a-peering/dns-dev.tf +++ b/fast/stages/2-networking-a-peering/dns-dev.tf @@ -18,7 +18,12 @@ # GCP-specific environment zone -module "dev-dns-private-zone" { +moved { + from = module.dev-dns-private-zone + to = module.dev-dns-priv-example +} + +module "dev-dns-priv-example" { source = "../../../modules/dns" project_id = module.dev-spoke-project.project_id type = "private" @@ -32,7 +37,12 @@ module "dev-dns-private-zone" { # root zone peering to landing to centralize configuration; remove if unneeded -module "dev-landing-root-dns-peering" { +moved { + from = module.dev-landing-root-dns-peering + to = module.dev-dns-peer-landing-root +} + +module "dev-dns-peer-landing-root" { source = "../../../modules/dns" project_id = module.dev-spoke-project.project_id type = "peering" @@ -42,7 +52,12 @@ module "dev-landing-root-dns-peering" { peer_network = module.landing-vpc.self_link } -module "dev-reverse-10-dns-peering" { +moved { + from = module.dev-reverse-10-dns-peering + to = module.dev-dns-peer-landing-rev-10 +} + +module "dev-dns-peer-landing-rev-10" { source = "../../../modules/dns" project_id = module.dev-spoke-project.project_id type = "peering" diff --git a/fast/stages/2-networking-a-peering/dns-landing.tf b/fast/stages/2-networking-a-peering/dns-landing.tf index 7b97a8cf..e6a441a5 100644 --- a/fast/stages/2-networking-a-peering/dns-landing.tf +++ b/fast/stages/2-networking-a-peering/dns-landing.tf @@ -18,7 +18,12 @@ # forwarding to on-prem DNS resolvers -module "onprem-example-dns-forwarding" { +moved { + from = module.onprem-example-dns-forwarding + to = module.landing-dns-fwd-onprem-example +} + +module "landing-dns-fwd-onprem-example" { source = "../../../modules/dns" project_id = module.landing-project.project_id type = "forwarding" @@ -28,7 +33,12 @@ module "onprem-example-dns-forwarding" { forwarders = { for ip in var.dns.onprem : ip => null } } -module "reverse-10-dns-forwarding" { +moved { + from = module.reverse-10-dns-forwarding + to = module.landing-dns-fwd-onprem-rev-10 +} + +module "landing-dns-fwd-onprem-rev-10" { source = "../../../modules/dns" project_id = module.landing-project.project_id type = "forwarding" @@ -38,7 +48,12 @@ module "reverse-10-dns-forwarding" { forwarders = { for ip in var.dns.onprem : ip => null } } -module "gcp-example-dns-private-zone" { +moved { + from = module.gcp-example-dns-private-zone + to = module.landing-dns-priv-gcp +} + +module "landing-dns-priv-gcp" { source = "../../../modules/dns" project_id = module.landing-project.project_id type = "private" @@ -50,82 +65,14 @@ module "gcp-example-dns-private-zone" { } } -# Google APIs +# Google APIs via response policies -module "googleapis-private-zone" { - source = "../../../modules/dns" - project_id = module.landing-project.project_id - type = "private" - name = "googleapis-com" - domain = "googleapis.com." - client_networks = [module.landing-vpc.self_link] - recordsets = { - "A private" = { records = [ - "199.36.153.8", "199.36.153.9", "199.36.153.10", "199.36.153.11" - ] } - "A restricted" = { records = [ - "199.36.153.4", "199.36.153.5", "199.36.153.6", "199.36.153.7" - ] } - "CNAME *" = { records = ["private.googleapis.com."] } - } -} - -module "gcrio-private-zone" { - source = "../../../modules/dns" - project_id = module.landing-project.project_id - type = "private" - name = "gcr-io" - domain = "gcr.io." - client_networks = [module.landing-vpc.self_link] - recordsets = { - "A gcr.io." = { ttl = 300, records = [ - "199.36.153.8", "199.36.153.9", "199.36.153.10", "199.36.153.11" - ] } - "CNAME *" = { ttl = 300, records = ["private.googleapis.com."] } - } -} - -module "packages-private-zone" { - source = "../../../modules/dns" - project_id = module.landing-project.project_id - type = "private" - name = "packages-cloud" - domain = "packages.cloud.google.com." - client_networks = [module.landing-vpc.self_link] - recordsets = { - "A packages.cloud.google.com." = { ttl = 300, records = [ - "199.36.153.8", "199.36.153.9", "199.36.153.10", "199.36.153.11" - ] } - "CNAME *" = { ttl = 300, records = ["private.googleapis.com."] } - } -} - -module "pkgdev-private-zone" { - source = "../../../modules/dns" - project_id = module.landing-project.project_id - type = "private" - name = "pkg-dev" - domain = "pkg.dev." - client_networks = [module.landing-vpc.self_link] - recordsets = { - "A pkg.dev." = { ttl = 300, records = [ - "199.36.153.8", "199.36.153.9", "199.36.153.10", "199.36.153.11" - ] } - "CNAME *" = { ttl = 300, records = ["private.googleapis.com."] } - } -} - -module "pkigoog-private-zone" { - source = "../../../modules/dns" - project_id = module.landing-project.project_id - type = "private" - name = "pki-goog" - domain = "pki.goog." - client_networks = [module.landing-vpc.self_link] - recordsets = { - "A pki.goog." = { ttl = 300, records = [ - "199.36.153.8", "199.36.153.9", "199.36.153.10", "199.36.153.11" - ] } - "CNAME *" = { ttl = 300, records = ["private.googleapis.com."] } +module "landing-dns-policy-googleapis" { + source = "../../../modules/dns-response-policy" + project_id = module.landing-project.project_id + name = "googleapis" + networks = { + landing = module.landing-vpc.self_link } + rules_file = var.factories_config.dns_policy_rules_file } diff --git a/fast/stages/2-networking-a-peering/dns-prod.tf b/fast/stages/2-networking-a-peering/dns-prod.tf index 5bb695fd..02fa8c23 100644 --- a/fast/stages/2-networking-a-peering/dns-prod.tf +++ b/fast/stages/2-networking-a-peering/dns-prod.tf @@ -18,7 +18,12 @@ # GCP-specific environment zone -module "prod-dns-private-zone" { +moved { + from = module.prod-dns-private-zone + to = module.prod-dns-priv-example +} + +module "prod-dns-priv-example" { source = "../../../modules/dns" project_id = module.prod-spoke-project.project_id type = "private" @@ -32,7 +37,12 @@ module "prod-dns-private-zone" { # root zone peering to landing to centralize configuration; remove if unneeded -module "prod-landing-root-dns-peering" { +moved { + from = module.prod-landing-root-dns-peering + to = module.prod-dns-peer-landing-root +} + +module "prod-dns-peer-landing-root" { source = "../../../modules/dns" project_id = module.prod-spoke-project.project_id type = "peering" @@ -42,7 +52,12 @@ module "prod-landing-root-dns-peering" { peer_network = module.landing-vpc.self_link } -module "prod-reverse-10-dns-peering" { +moved { + from = module.prod-reverse-10-dns-peering + to = module.prod-dns-peer-landing-rev-10 +} + +module "prod-dns-peer-landing-rev-10" { source = "../../../modules/dns" project_id = module.prod-spoke-project.project_id type = "peering" diff --git a/fast/stages/2-networking-a-peering/variables.tf b/fast/stages/2-networking-a-peering/variables.tf index 8c20b623..c5f58cd4 100644 --- a/fast/stages/2-networking-a-peering/variables.tf +++ b/fast/stages/2-networking-a-peering/variables.tf @@ -55,8 +55,9 @@ variable "dns" { variable "factories_config" { description = "Configuration for network resource factories." type = object({ - data_dir = optional(string, "data") - firewall_policy_name = optional(string, "factory") + data_dir = optional(string, "data") + dns_policy_rules_file = optional(string, "data/dns-policy-rules.yaml") + firewall_policy_name = optional(string, "factory") }) default = { data_dir = "data" diff --git a/fast/stages/2-networking-b-vpn/README.md b/fast/stages/2-networking-b-vpn/README.md index ab1b9734..b5b87cef 100644 --- a/fast/stages/2-networking-b-vpn/README.md +++ b/fast/stages/2-networking-b-vpn/README.md @@ -136,13 +136,7 @@ DNS configuration is further centralized by leveraging peering zones, so that - the hub/landing Cloud DNS hosts configurations for on-prem forwarding, Google API domains, and the top-level private zone/s (e.g. gcp.example.com) - the spokes Cloud DNS host configurations for the environment-specific domains (e.g. prod.gcp.example.com), which are bound to the hub/landing leveraging [cross-project binding](https://cloud.google.com/dns/docs/zones/zones-overview#cross-project_binding); a peering zone for the `.` (root) zone is then created on each spoke, delegating all DNS resolution to hub/landing. -- Private Google Access is enabled for a selection of the [supported domains](https://cloud.google.com/vpc/docs/configure-private-google-access#domain-options), namely - - `private.googleapis.com` - - `restricted.googleapis.com` - - `gcr.io` - - `packages.cloud.google.com` - - `pkg.dev` - - `pki.goog` +- Private Google Access is enabled via [DNS Response Policies](https://cloud.google.com/dns/docs/zones/manage-response-policies#create-response-policy-rule) for most of the [supported domains](https://cloud.google.com/vpc/docs/configure-private-google-access#domain-options) To complete the configuration, the 35.199.192.0/19 range should be routed on the VPN tunnels from on-prem, and the following names configured for DNS forwarding to cloud: @@ -405,7 +399,7 @@ DNS configurations are centralised in the `dns-*.tf` files. Spokes delegate DNS | name | description | modules | resources | |---|---|---|---| | [dns-dev.tf](./dns-dev.tf) | Development spoke DNS zones and peerings setup. | dns | | -| [dns-landing.tf](./dns-landing.tf) | Landing DNS zones and peerings setup. | dns | | +| [dns-landing.tf](./dns-landing.tf) | Landing DNS zones and peerings setup. | dns · dns-response-policy | | | [dns-prod.tf](./dns-prod.tf) | Production spoke DNS zones and peerings setup. | dns | | | [landing.tf](./landing.tf) | Landing VPC and related resources. | net-cloudnat · net-vpc · net-vpc-firewall · project | | | [main.tf](./main.tf) | Networking folder and hierarchical policy. | folder | | @@ -428,18 +422,18 @@ DNS configurations are centralised in the `dns-*.tf` files. Spokes delegate DNS |---|---|:---:|:---:|:---:|:---:| | [automation](variables.tf#L17) | Automation resources created by the bootstrap stage. | object({…}) | ✓ | | 0-bootstrap | | [billing_account](variables.tf#L25) | Billing account id. If billing account is not part of the same org set `is_org_level` to false. | object({…}) | ✓ | | 0-bootstrap | -| [folder_ids](variables.tf#L75) | Folders to be used for the networking resources in folders/nnnnnnnnnnn format. If null, folder will be created. | object({…}) | ✓ | | 1-resman | -| [organization](variables.tf#L85) | Organization details. | object({…}) | ✓ | | 0-bootstrap | -| [prefix](variables.tf#L101) | Prefix used for resources that need unique names. Use 9 characters or less. | string | ✓ | | 0-bootstrap | +| [folder_ids](variables.tf#L76) | Folders to be used for the networking resources in folders/nnnnnnnnnnn format. If null, folder will be created. | object({…}) | ✓ | | 1-resman | +| [organization](variables.tf#L86) | Organization details. | object({…}) | ✓ | | 0-bootstrap | +| [prefix](variables.tf#L102) | Prefix used for resources that need unique names. Use 9 characters or less. | string | ✓ | | 0-bootstrap | | [custom_roles](variables.tf#L38) | Custom roles defined at the org level, in key => id format. | object({…}) | | null | 0-bootstrap | | [dns](variables.tf#L47) | Onprem DNS resolvers. | map(list(string)) | | {…} | | -| [factories_config](variables.tf#L55) | Configuration for network resource factories. | object({…}) | | {…} | | -| [outputs_location](variables.tf#L95) | Path where providers and tfvars files for the following stages are written. Leave empty to disable. | string | | null | | -| [psa_ranges](variables.tf#L112) | IP ranges used for Private Service Access (CloudSQL, etc.). | object({…}) | | null | | -| [regions](variables.tf#L133) | Region definitions. | object({…}) | | {…} | | -| [service_accounts](variables.tf#L145) | Automation service accounts in name => email format. | object({…}) | | null | 1-resman | +| [factories_config](variables.tf#L55) | Configuration for network resource factories. | object({…}) | | {…} | | +| [outputs_location](variables.tf#L96) | Path where providers and tfvars files for the following stages are written. Leave empty to disable. | string | | null | | +| [psa_ranges](variables.tf#L113) | IP ranges used for Private Service Access (CloudSQL, etc.). | object({…}) | | null | | +| [regions](variables.tf#L134) | Region definitions. | object({…}) | | {…} | | +| [service_accounts](variables.tf#L146) | Automation service accounts in name => email format. | object({…}) | | null | 1-resman | | [vpn_configs](variables-vpn.tf#L17) | Hub to spokes VPN configurations. | object({…}) | | {…} | | -| [vpn_onprem_primary_config](variables.tf#L159) | VPN gateway configuration for onprem interconnection in the primary region. | object({…}) | | null | | +| [vpn_onprem_primary_config](variables.tf#L160) | VPN gateway configuration for onprem interconnection in the primary region. | object({…}) | | null | | ## Outputs diff --git a/fast/stages/2-networking-b-vpn/data/dns-policy-rules.yaml b/fast/stages/2-networking-b-vpn/data/dns-policy-rules.yaml new file mode 100644 index 00000000..d091e4f0 --- /dev/null +++ b/fast/stages/2-networking-b-vpn/data/dns-policy-rules.yaml @@ -0,0 +1,110 @@ +# skip boilerplate check + +accounts: + dns_name: "accounts.google.com." + local_data: { CNAME: { rrdatas: ["private.googleapis.com."] } } +backupdr-cloud: + dns_name: "backupdr.cloud.google.com." + local_data: { CNAME: { rrdatas: ["private.googleapis.com."] } } +backupdr-cloud-all: + dns_name: "*.backupdr.cloud.google.com." + local_data: { CNAME: { rrdatas: ["private.googleapis.com."] } } +backupdr-gu: + dns_name: "backupdr.googleusercontent.google.com." + local_data: { CNAME: { rrdatas: ["private.googleapis.com."] } } +backupdr-gu-all: + dns_name: "*.backupdr.googleusercontent.google.com." + local_data: { CNAME: { rrdatas: ["private.googleapis.com."] } } +cloudfunctions: + dns_name: "*.cloudfunctions.net." + local_data: { CNAME: { rrdatas: ["private.googleapis.com."] } } +cloudproxy: + dns_name: "*.cloudproxy.app." + local_data: { CNAME: { rrdatas: ["private.googleapis.com."] } } +composer-cloud-all: + dns_name: "*.composer.cloud.google.com." + local_data: { CNAME: { rrdatas: ["private.googleapis.com."] } } +composer-gu-all: + dns_name: "*.composer.googleusercontent.com." + local_data: { CNAME: { rrdatas: ["private.googleapis.com."] } } +datafusion-all: + dns_name: "*.datafusion.cloud.google.com." + local_data: { CNAME: { rrdatas: ["private.googleapis.com."] } } +datafusion-gu-all: + dns_name: "*.datafusion.googleusercontent.com." + local_data: { CNAME: { rrdatas: ["private.googleapis.com."] } } +dataproc: + dns_name: "dataproc.cloud.google.com." + local_data: { CNAME: { rrdatas: ["private.googleapis.com."] } } +dataproc-all: + dns_name: "*.dataproc.cloud.google.com." + local_data: { CNAME: { rrdatas: ["private.googleapis.com."] } } +dataproc-gu: + dns_name: "dataproc.googleusercontent.com." + local_data: { CNAME: { rrdatas: ["private.googleapis.com."] } } +dataproc-gu-all: + dns_name: "*.dataproc.googleusercontent.com." + local_data: { CNAME: { rrdatas: ["private.googleapis.com."] } } +dl: + dns_name: "dl.google.com." + local_data: { CNAME: { rrdatas: ["private.googleapis.com."] } } +gcr: + dns_name: "gcr.io." + local_data: { CNAME: { rrdatas: ["private.googleapis.com."] } } +gcr-all: + dns_name: "*.gcr.io." + local_data: { CNAME: { rrdatas: ["private.googleapis.com."] } } +googleapis-all: + dns_name: "*.googleapis.com." + local_data: { CNAME: { rrdatas: ["private.googleapis.com."] } } +googleapis-private: + dns_name: "private.googleapis.com." + local_data: + A: + rrdatas: + - 199.36.153.8 + - 199.36.153.9 + - 199.36.153.10 + - 199.36.153.11 +googleapis-restricted: + dns_name: "restricted.googleapis.com." + local_data: + A: + rrdatas: + - 199.36.153.4 + - 199.36.153.5 + - 199.36.153.6 + - 199.36.153.7 +gstatic-all: + dns_name: "*.gstatic.com." + local_data: { CNAME: { rrdatas: ["private.googleapis.com."] } } +notebooks-all: + dns_name: "*.notebooks.cloud.google.com." + local_data: { CNAME: { rrdatas: ["private.googleapis.com."] } } +notebooks-gu-all: + dns_name: "*.notebooks.googleusercontent.com." + local_data: { CNAME: { rrdatas: ["private.googleapis.com."] } } +packages-cloud: + dns_name: "packages.cloud.google.com." + local_data: { CNAME: { rrdatas: ["private.googleapis.com."] } } +packages-cloud-all: + dns_name: "*.packages.cloud.google.com." + local_data: { CNAME: { rrdatas: ["private.googleapis.com."] } } +pkgdev: + dns_name: "pkg.dev." + local_data: { CNAME: { rrdatas: ["private.googleapis.com."] } } +pkgdev-all: + dns_name: "*.pkg.dev." + local_data: { CNAME: { rrdatas: ["private.googleapis.com."] } } +pkigoog: + dns_name: "pki.goog." + local_data: { CNAME: { rrdatas: ["private.googleapis.com."] } } +pkigoog-all: + dns_name: "*.pki.goog." + local_data: { CNAME: { rrdatas: ["private.googleapis.com."] } } +run-all: + dns_name: "*.run.app." + local_data: { CNAME: { rrdatas: ["private.googleapis.com."] } } +source: + dns_name: "source.developers.google.com." + local_data: { CNAME: { rrdatas: ["private.googleapis.com."] } } diff --git a/fast/stages/2-networking-b-vpn/dns-dev.tf b/fast/stages/2-networking-b-vpn/dns-dev.tf index 03ae0122..efeabeae 100644 --- a/fast/stages/2-networking-b-vpn/dns-dev.tf +++ b/fast/stages/2-networking-b-vpn/dns-dev.tf @@ -18,7 +18,12 @@ # GCP-specific environment zone -module "dev-dns-private-zone" { +moved { + from = module.dev-dns-private-zone + to = module.dev-dns-priv-example +} + +module "dev-dns-priv-example" { source = "../../../modules/dns" project_id = module.dev-spoke-project.project_id type = "private" @@ -32,7 +37,12 @@ module "dev-dns-private-zone" { # root zone peering to landing to centralize configuration; remove if unneeded -module "dev-landing-root-dns-peering" { +moved { + from = module.dev-landing-root-dns-peering + to = module.dev-dns-peer-landing-root +} + +module "dev-dns-peer-landing-root" { source = "../../../modules/dns" project_id = module.dev-spoke-project.project_id type = "peering" @@ -42,7 +52,12 @@ module "dev-landing-root-dns-peering" { peer_network = module.landing-vpc.self_link } -module "dev-reverse-10-dns-peering" { +moved { + from = module.dev-reverse-10-dns-peering + to = module.dev-dns-peer-landing-rev-10 +} + +module "dev-dns-peer-landing-rev-10" { source = "../../../modules/dns" project_id = module.dev-spoke-project.project_id type = "peering" diff --git a/fast/stages/2-networking-b-vpn/dns-landing.tf b/fast/stages/2-networking-b-vpn/dns-landing.tf index 7b97a8cf..e6a441a5 100644 --- a/fast/stages/2-networking-b-vpn/dns-landing.tf +++ b/fast/stages/2-networking-b-vpn/dns-landing.tf @@ -18,7 +18,12 @@ # forwarding to on-prem DNS resolvers -module "onprem-example-dns-forwarding" { +moved { + from = module.onprem-example-dns-forwarding + to = module.landing-dns-fwd-onprem-example +} + +module "landing-dns-fwd-onprem-example" { source = "../../../modules/dns" project_id = module.landing-project.project_id type = "forwarding" @@ -28,7 +33,12 @@ module "onprem-example-dns-forwarding" { forwarders = { for ip in var.dns.onprem : ip => null } } -module "reverse-10-dns-forwarding" { +moved { + from = module.reverse-10-dns-forwarding + to = module.landing-dns-fwd-onprem-rev-10 +} + +module "landing-dns-fwd-onprem-rev-10" { source = "../../../modules/dns" project_id = module.landing-project.project_id type = "forwarding" @@ -38,7 +48,12 @@ module "reverse-10-dns-forwarding" { forwarders = { for ip in var.dns.onprem : ip => null } } -module "gcp-example-dns-private-zone" { +moved { + from = module.gcp-example-dns-private-zone + to = module.landing-dns-priv-gcp +} + +module "landing-dns-priv-gcp" { source = "../../../modules/dns" project_id = module.landing-project.project_id type = "private" @@ -50,82 +65,14 @@ module "gcp-example-dns-private-zone" { } } -# Google APIs +# Google APIs via response policies -module "googleapis-private-zone" { - source = "../../../modules/dns" - project_id = module.landing-project.project_id - type = "private" - name = "googleapis-com" - domain = "googleapis.com." - client_networks = [module.landing-vpc.self_link] - recordsets = { - "A private" = { records = [ - "199.36.153.8", "199.36.153.9", "199.36.153.10", "199.36.153.11" - ] } - "A restricted" = { records = [ - "199.36.153.4", "199.36.153.5", "199.36.153.6", "199.36.153.7" - ] } - "CNAME *" = { records = ["private.googleapis.com."] } - } -} - -module "gcrio-private-zone" { - source = "../../../modules/dns" - project_id = module.landing-project.project_id - type = "private" - name = "gcr-io" - domain = "gcr.io." - client_networks = [module.landing-vpc.self_link] - recordsets = { - "A gcr.io." = { ttl = 300, records = [ - "199.36.153.8", "199.36.153.9", "199.36.153.10", "199.36.153.11" - ] } - "CNAME *" = { ttl = 300, records = ["private.googleapis.com."] } - } -} - -module "packages-private-zone" { - source = "../../../modules/dns" - project_id = module.landing-project.project_id - type = "private" - name = "packages-cloud" - domain = "packages.cloud.google.com." - client_networks = [module.landing-vpc.self_link] - recordsets = { - "A packages.cloud.google.com." = { ttl = 300, records = [ - "199.36.153.8", "199.36.153.9", "199.36.153.10", "199.36.153.11" - ] } - "CNAME *" = { ttl = 300, records = ["private.googleapis.com."] } - } -} - -module "pkgdev-private-zone" { - source = "../../../modules/dns" - project_id = module.landing-project.project_id - type = "private" - name = "pkg-dev" - domain = "pkg.dev." - client_networks = [module.landing-vpc.self_link] - recordsets = { - "A pkg.dev." = { ttl = 300, records = [ - "199.36.153.8", "199.36.153.9", "199.36.153.10", "199.36.153.11" - ] } - "CNAME *" = { ttl = 300, records = ["private.googleapis.com."] } - } -} - -module "pkigoog-private-zone" { - source = "../../../modules/dns" - project_id = module.landing-project.project_id - type = "private" - name = "pki-goog" - domain = "pki.goog." - client_networks = [module.landing-vpc.self_link] - recordsets = { - "A pki.goog." = { ttl = 300, records = [ - "199.36.153.8", "199.36.153.9", "199.36.153.10", "199.36.153.11" - ] } - "CNAME *" = { ttl = 300, records = ["private.googleapis.com."] } +module "landing-dns-policy-googleapis" { + source = "../../../modules/dns-response-policy" + project_id = module.landing-project.project_id + name = "googleapis" + networks = { + landing = module.landing-vpc.self_link } + rules_file = var.factories_config.dns_policy_rules_file } diff --git a/fast/stages/2-networking-b-vpn/dns-prod.tf b/fast/stages/2-networking-b-vpn/dns-prod.tf index 5bb695fd..02fa8c23 100644 --- a/fast/stages/2-networking-b-vpn/dns-prod.tf +++ b/fast/stages/2-networking-b-vpn/dns-prod.tf @@ -18,7 +18,12 @@ # GCP-specific environment zone -module "prod-dns-private-zone" { +moved { + from = module.prod-dns-private-zone + to = module.prod-dns-priv-example +} + +module "prod-dns-priv-example" { source = "../../../modules/dns" project_id = module.prod-spoke-project.project_id type = "private" @@ -32,7 +37,12 @@ module "prod-dns-private-zone" { # root zone peering to landing to centralize configuration; remove if unneeded -module "prod-landing-root-dns-peering" { +moved { + from = module.prod-landing-root-dns-peering + to = module.prod-dns-peer-landing-root +} + +module "prod-dns-peer-landing-root" { source = "../../../modules/dns" project_id = module.prod-spoke-project.project_id type = "peering" @@ -42,7 +52,12 @@ module "prod-landing-root-dns-peering" { peer_network = module.landing-vpc.self_link } -module "prod-reverse-10-dns-peering" { +moved { + from = module.prod-reverse-10-dns-peering + to = module.prod-dns-peer-landing-rev-10 +} + +module "prod-dns-peer-landing-rev-10" { source = "../../../modules/dns" project_id = module.prod-spoke-project.project_id type = "peering" diff --git a/fast/stages/2-networking-b-vpn/variables.tf b/fast/stages/2-networking-b-vpn/variables.tf index 8c20b623..c5f58cd4 100644 --- a/fast/stages/2-networking-b-vpn/variables.tf +++ b/fast/stages/2-networking-b-vpn/variables.tf @@ -55,8 +55,9 @@ variable "dns" { variable "factories_config" { description = "Configuration for network resource factories." type = object({ - data_dir = optional(string, "data") - firewall_policy_name = optional(string, "factory") + data_dir = optional(string, "data") + dns_policy_rules_file = optional(string, "data/dns-policy-rules.yaml") + firewall_policy_name = optional(string, "factory") }) default = { data_dir = "data" diff --git a/fast/stages/2-networking-c-nva/README.md b/fast/stages/2-networking-c-nva/README.md index 5aeefa29..7ab05f56 100644 --- a/fast/stages/2-networking-c-nva/README.md +++ b/fast/stages/2-networking-c-nva/README.md @@ -210,13 +210,7 @@ DNS configuration is further centralized by leveraging peering zones, so that - the hub/landing Cloud DNS hosts configurations for on-prem forwarding, Google API domains, and the top-level private zone/s (e.g. gcp.example.com) - the spokes Cloud DNS host configurations for the environment-specific domains (e.g. prod.gcp.example.com), which are bound to the hub/landing leveraging [cross-project binding](https://cloud.google.com/dns/docs/zones/zones-overview#cross-project_binding); a peering zone for the `.` (root) zone is then created on each spoke, delegating all DNS resolution to hub/landing. -- Private Google Access is enabled for a selection of the [supported domains](https://cloud.google.com/vpc/docs/configure-private-google-access#domain-options), namely - - `private.googleapis.com` - - `restricted.googleapis.com` - - `gcr.io` - - `packages.cloud.google.com` - - `pkg.dev` - - `pki.goog` +- Private Google Access is enabled via [DNS Response Policies](https://cloud.google.com/dns/docs/zones/manage-response-policies#create-response-policy-rule) for most of the [supported domains](https://cloud.google.com/vpc/docs/configure-private-google-access#domain-options) To complete the configuration, the 35.199.192.0/19 range should be routed to the VPN tunnels from on-premises, and the following names should be configured for DNS forwarding to cloud: @@ -464,7 +458,7 @@ DNS configurations are centralised in the `dns-*.tf` files. Spokes delegate DNS | name | description | modules | resources | |---|---|---|---| | [dns-dev.tf](./dns-dev.tf) | Development spoke DNS zones and peerings setup. | dns | | -| [dns-landing.tf](./dns-landing.tf) | Landing DNS zones and peerings setup. | dns | | +| [dns-landing.tf](./dns-landing.tf) | Landing DNS zones and peerings setup. | dns · dns-response-policy | | | [dns-prod.tf](./dns-prod.tf) | Production spoke DNS zones and peerings setup. | dns | | | [landing.tf](./landing.tf) | Landing VPC and related resources. | net-cloudnat · net-vpc · net-vpc-firewall · project | | | [main.tf](./main.tf) | Networking folder and hierarchical policy. | folder | | @@ -484,20 +478,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#L75) | Folders to be used for the networking resources in folders/nnnnnnnnnnn format. If null, folder will be created. | object({…}) | ✓ | | 1-resman | -| [organization](variables.tf#L108) | Organization details. | object({…}) | ✓ | | 0-bootstrap | -| [prefix](variables.tf#L124) | Prefix used for resources that need unique names. Use 9 characters or less. | string | ✓ | | 0-bootstrap | +| [folder_ids](variables.tf#L76) | Folders to be used for the networking resources in folders/nnnnnnnnnnn format. If null, folder will be created. | object({…}) | ✓ | | 1-resman | +| [organization](variables.tf#L109) | Organization details. | object({…}) | ✓ | | 0-bootstrap | +| [prefix](variables.tf#L125) | Prefix used for resources that need unique names. Use 9 characters or less. | string | ✓ | | 0-bootstrap | | [custom_roles](variables.tf#L38) | Custom roles defined at the org level, in key => id format. | object({…}) | | null | 0-bootstrap | | [dns](variables.tf#L47) | Onprem DNS resolvers. | map(list(string)) | | {…} | | -| [factories_config](variables.tf#L55) | Configuration for network resource factories. | object({…}) | | {…} | | -| [gcp_ranges](variables.tf#L85) | GCP address ranges in name => range format. | map(string) | | {…} | | -| [onprem_cidr](variables.tf#L100) | Onprem addresses in name => range format. | map(string) | | {…} | | -| [outputs_location](variables.tf#L118) | Path where providers and tfvars files for the following stages are written. Leave empty to disable. | string | | null | | -| [psa_ranges](variables.tf#L135) | IP ranges used for Private Service Access (e.g. CloudSQL). Ranges is in name => range format. | object({…}) | | null | | -| [regions](variables.tf#L156) | Region definitions. | object({…}) | | {…} | | -| [service_accounts](variables.tf#L168) | Automation service accounts in name => email format. | object({…}) | | null | 1-resman | -| [vpn_onprem_primary_config](variables.tf#L182) | VPN gateway configuration for onprem interconnection in the primary region. | object({…}) | | null | | -| [vpn_onprem_secondary_config](variables.tf#L225) | VPN gateway configuration for onprem interconnection in the secondary region. | object({…}) | | null | | +| [factories_config](variables.tf#L55) | Configuration for network resource factories. | object({…}) | | {…} | | +| [gcp_ranges](variables.tf#L86) | GCP address ranges in name => range format. | map(string) | | {…} | | +| [onprem_cidr](variables.tf#L101) | Onprem addresses in name => range format. | map(string) | | {…} | | +| [outputs_location](variables.tf#L119) | Path where providers and tfvars files for the following stages are written. Leave empty to disable. | string | | null | | +| [psa_ranges](variables.tf#L136) | IP ranges used for Private Service Access (e.g. CloudSQL). Ranges is in name => range format. | object({…}) | | null | | +| [regions](variables.tf#L157) | Region definitions. | object({…}) | | {…} | | +| [service_accounts](variables.tf#L169) | Automation service accounts in name => email format. | object({…}) | | null | 1-resman | +| [vpn_onprem_primary_config](variables.tf#L183) | VPN gateway configuration for onprem interconnection in the primary region. | object({…}) | | null | | +| [vpn_onprem_secondary_config](variables.tf#L226) | VPN gateway configuration for onprem interconnection in the secondary region. | object({…}) | | null | | ## Outputs diff --git a/fast/stages/2-networking-c-nva/data/dns-policy-rules.yaml b/fast/stages/2-networking-c-nva/data/dns-policy-rules.yaml new file mode 100644 index 00000000..d091e4f0 --- /dev/null +++ b/fast/stages/2-networking-c-nva/data/dns-policy-rules.yaml @@ -0,0 +1,110 @@ +# skip boilerplate check + +accounts: + dns_name: "accounts.google.com." + local_data: { CNAME: { rrdatas: ["private.googleapis.com."] } } +backupdr-cloud: + dns_name: "backupdr.cloud.google.com." + local_data: { CNAME: { rrdatas: ["private.googleapis.com."] } } +backupdr-cloud-all: + dns_name: "*.backupdr.cloud.google.com." + local_data: { CNAME: { rrdatas: ["private.googleapis.com."] } } +backupdr-gu: + dns_name: "backupdr.googleusercontent.google.com." + local_data: { CNAME: { rrdatas: ["private.googleapis.com."] } } +backupdr-gu-all: + dns_name: "*.backupdr.googleusercontent.google.com." + local_data: { CNAME: { rrdatas: ["private.googleapis.com."] } } +cloudfunctions: + dns_name: "*.cloudfunctions.net." + local_data: { CNAME: { rrdatas: ["private.googleapis.com."] } } +cloudproxy: + dns_name: "*.cloudproxy.app." + local_data: { CNAME: { rrdatas: ["private.googleapis.com."] } } +composer-cloud-all: + dns_name: "*.composer.cloud.google.com." + local_data: { CNAME: { rrdatas: ["private.googleapis.com."] } } +composer-gu-all: + dns_name: "*.composer.googleusercontent.com." + local_data: { CNAME: { rrdatas: ["private.googleapis.com."] } } +datafusion-all: + dns_name: "*.datafusion.cloud.google.com." + local_data: { CNAME: { rrdatas: ["private.googleapis.com."] } } +datafusion-gu-all: + dns_name: "*.datafusion.googleusercontent.com." + local_data: { CNAME: { rrdatas: ["private.googleapis.com."] } } +dataproc: + dns_name: "dataproc.cloud.google.com." + local_data: { CNAME: { rrdatas: ["private.googleapis.com."] } } +dataproc-all: + dns_name: "*.dataproc.cloud.google.com." + local_data: { CNAME: { rrdatas: ["private.googleapis.com."] } } +dataproc-gu: + dns_name: "dataproc.googleusercontent.com." + local_data: { CNAME: { rrdatas: ["private.googleapis.com."] } } +dataproc-gu-all: + dns_name: "*.dataproc.googleusercontent.com." + local_data: { CNAME: { rrdatas: ["private.googleapis.com."] } } +dl: + dns_name: "dl.google.com." + local_data: { CNAME: { rrdatas: ["private.googleapis.com."] } } +gcr: + dns_name: "gcr.io." + local_data: { CNAME: { rrdatas: ["private.googleapis.com."] } } +gcr-all: + dns_name: "*.gcr.io." + local_data: { CNAME: { rrdatas: ["private.googleapis.com."] } } +googleapis-all: + dns_name: "*.googleapis.com." + local_data: { CNAME: { rrdatas: ["private.googleapis.com."] } } +googleapis-private: + dns_name: "private.googleapis.com." + local_data: + A: + rrdatas: + - 199.36.153.8 + - 199.36.153.9 + - 199.36.153.10 + - 199.36.153.11 +googleapis-restricted: + dns_name: "restricted.googleapis.com." + local_data: + A: + rrdatas: + - 199.36.153.4 + - 199.36.153.5 + - 199.36.153.6 + - 199.36.153.7 +gstatic-all: + dns_name: "*.gstatic.com." + local_data: { CNAME: { rrdatas: ["private.googleapis.com."] } } +notebooks-all: + dns_name: "*.notebooks.cloud.google.com." + local_data: { CNAME: { rrdatas: ["private.googleapis.com."] } } +notebooks-gu-all: + dns_name: "*.notebooks.googleusercontent.com." + local_data: { CNAME: { rrdatas: ["private.googleapis.com."] } } +packages-cloud: + dns_name: "packages.cloud.google.com." + local_data: { CNAME: { rrdatas: ["private.googleapis.com."] } } +packages-cloud-all: + dns_name: "*.packages.cloud.google.com." + local_data: { CNAME: { rrdatas: ["private.googleapis.com."] } } +pkgdev: + dns_name: "pkg.dev." + local_data: { CNAME: { rrdatas: ["private.googleapis.com."] } } +pkgdev-all: + dns_name: "*.pkg.dev." + local_data: { CNAME: { rrdatas: ["private.googleapis.com."] } } +pkigoog: + dns_name: "pki.goog." + local_data: { CNAME: { rrdatas: ["private.googleapis.com."] } } +pkigoog-all: + dns_name: "*.pki.goog." + local_data: { CNAME: { rrdatas: ["private.googleapis.com."] } } +run-all: + dns_name: "*.run.app." + local_data: { CNAME: { rrdatas: ["private.googleapis.com."] } } +source: + dns_name: "source.developers.google.com." + local_data: { CNAME: { rrdatas: ["private.googleapis.com."] } } diff --git a/fast/stages/2-networking-c-nva/dns-dev.tf b/fast/stages/2-networking-c-nva/dns-dev.tf index 4eb472a1..98d56aa7 100644 --- a/fast/stages/2-networking-c-nva/dns-dev.tf +++ b/fast/stages/2-networking-c-nva/dns-dev.tf @@ -32,7 +32,12 @@ module "dev-dns-private-zone" { # root zone peering to landing to centralize configuration; remove if unneeded -module "dev-landing-root-dns-peering" { +moved { + from = module.dev-landing-root-dns-peering + to = module.dev-dns-peer-landing-root +} + +module "dev-dns-peer-landing-root" { source = "../../../modules/dns" project_id = module.dev-spoke-project.project_id type = "peering" @@ -42,7 +47,12 @@ module "dev-landing-root-dns-peering" { peer_network = module.landing-trusted-vpc.self_link } -module "dev-reverse-10-dns-peering" { +moved { + from = module.dev-reverse-10-dns-peering + to = module.dev-dns-peer-landing-rev-10 +} + +module "dev-dns-peer-landing-rev-10" { source = "../../../modules/dns" project_id = module.dev-spoke-project.project_id type = "peering" diff --git a/fast/stages/2-networking-c-nva/dns-landing.tf b/fast/stages/2-networking-c-nva/dns-landing.tf index 40090279..50b65890 100644 --- a/fast/stages/2-networking-c-nva/dns-landing.tf +++ b/fast/stages/2-networking-c-nva/dns-landing.tf @@ -18,7 +18,12 @@ # forwarding to on-prem DNS resolvers -module "onprem-example-dns-forwarding" { +moved { + from = module.onprem-example-dns-forwarding + to = module.landing-dns-fwd-onprem-example +} + +module "landing-dns-fwd-onprem-example" { source = "../../../modules/dns" project_id = module.landing-project.project_id type = "forwarding" @@ -31,7 +36,12 @@ module "onprem-example-dns-forwarding" { forwarders = { for ip in var.dns.onprem : ip => null } } -module "reverse-10-dns-forwarding" { +moved { + from = module.reverse-10-dns-forwarding + to = module.landing-dns-fwd-onprem-rev-10 +} + +module "landing-dns-fwd-onprem-rev-10" { source = "../../../modules/dns" project_id = module.landing-project.project_id type = "forwarding" @@ -44,7 +54,12 @@ module "reverse-10-dns-forwarding" { forwarders = { for ip in var.dns.onprem : ip => null } } -module "gcp-example-dns-private-zone" { +moved { + from = module.gcp-example-dns-private-zone + to = module.landing-dns-priv-gcp +} + +module "landing-dns-priv-gcp" { source = "../../../modules/dns" project_id = module.landing-project.project_id type = "private" @@ -61,95 +76,13 @@ module "gcp-example-dns-private-zone" { # Google APIs -module "googleapis-private-zone" { - source = "../../../modules/dns" +module "landing-dns-policy-googleapis" { + source = "../../../modules/dns-response-policy" project_id = module.landing-project.project_id - type = "private" - name = "googleapis-com" - domain = "googleapis.com." - client_networks = [ - module.landing-untrusted-vpc.self_link, - module.landing-trusted-vpc.self_link - ] - recordsets = { - "A private" = { records = [ - "199.36.153.8", "199.36.153.9", "199.36.153.10", "199.36.153.11" - ] } - "A restricted" = { records = [ - "199.36.153.4", "199.36.153.5", "199.36.153.6", "199.36.153.7" - ] } - "CNAME *" = { records = ["private.googleapis.com."] } - } -} - -module "gcrio-private-zone" { - source = "../../../modules/dns" - project_id = module.landing-project.project_id - type = "private" - name = "gcr-io" - domain = "gcr.io." - client_networks = [ - module.landing-untrusted-vpc.self_link, - module.landing-trusted-vpc.self_link - ] - recordsets = { - "A gcr.io." = { ttl = 300, records = [ - "199.36.153.8", "199.36.153.9", "199.36.153.10", "199.36.153.11" - ] } - "CNAME *" = { ttl = 300, records = ["private.googleapis.com."] } - } -} - -module "packages-private-zone" { - source = "../../../modules/dns" - project_id = module.landing-project.project_id - type = "private" - name = "packages-cloud" - domain = "packages.cloud.google.com." - client_networks = [ - module.landing-untrusted-vpc.self_link, - module.landing-trusted-vpc.self_link - ] - recordsets = { - "A packages.cloud.google.com." = { ttl = 300, records = [ - "199.36.153.8", "199.36.153.9", "199.36.153.10", "199.36.153.11" - ] } - "CNAME *" = { ttl = 300, records = ["private.googleapis.com."] } - } -} - -module "pkgdev-private-zone" { - source = "../../../modules/dns" - project_id = module.landing-project.project_id - type = "private" - name = "pkg-dev" - domain = "pkg.dev." - client_networks = [ - module.landing-untrusted-vpc.self_link, - module.landing-trusted-vpc.self_link - ] - recordsets = { - "A pkg.dev." = { ttl = 300, records = [ - "199.36.153.8", "199.36.153.9", "199.36.153.10", "199.36.153.11" - ] } - "CNAME *" = { ttl = 300, records = ["private.googleapis.com."] } - } -} - -module "pkigoog-private-zone" { - source = "../../../modules/dns" - project_id = module.landing-project.project_id - type = "private" - name = "pki-goog" - domain = "pki.goog." - client_networks = [ - module.landing-untrusted-vpc.self_link, - module.landing-trusted-vpc.self_link - ] - recordsets = { - "A pki.goog." = { ttl = 300, records = [ - "199.36.153.8", "199.36.153.9", "199.36.153.10", "199.36.153.11" - ] } - "CNAME *" = { ttl = 300, records = ["private.googleapis.com."] } + name = "googleapis" + networks = { + landing-trusted = module.landing-trusted-vpc.self_link + landing-untrusted = module.landing-untrusted-vpc.self_link } + rules_file = var.factories_config.dns_policy_rules_file } diff --git a/fast/stages/2-networking-c-nva/dns-prod.tf b/fast/stages/2-networking-c-nva/dns-prod.tf index b54609df..5627e438 100644 --- a/fast/stages/2-networking-c-nva/dns-prod.tf +++ b/fast/stages/2-networking-c-nva/dns-prod.tf @@ -32,7 +32,12 @@ module "prod-dns-private-zone" { # root zone peering to landing to centralize configuration; remove if unneeded -module "prod-landing-root-dns-peering" { +moved { + from = module.prod-landing-root-dns-peering + to = module.prod-dns-peer-landing-root +} + +module "prod-dns-peer-landing-root" { source = "../../../modules/dns" project_id = module.prod-spoke-project.project_id type = "peering" @@ -42,7 +47,12 @@ module "prod-landing-root-dns-peering" { peer_network = module.landing-trusted-vpc.self_link } -module "prod-reverse-10-dns-peering" { +moved { + from = module.prod-reverse-10-dns-peering + to = module.prod-dns-peer-landing-rev-10 +} + +module "prod-dns-peer-landing-rev-10" { source = "../../../modules/dns" project_id = module.prod-spoke-project.project_id type = "peering" diff --git a/fast/stages/2-networking-c-nva/variables.tf b/fast/stages/2-networking-c-nva/variables.tf index e4fe6896..b56c72d8 100644 --- a/fast/stages/2-networking-c-nva/variables.tf +++ b/fast/stages/2-networking-c-nva/variables.tf @@ -55,8 +55,9 @@ variable "dns" { variable "factories_config" { description = "Configuration for network resource factories." type = object({ - data_dir = optional(string, "data") - firewall_policy_name = optional(string, "factory") + data_dir = optional(string, "data") + dns_policy_rules_file = optional(string, "data/dns-policy-rules.yaml") + firewall_policy_name = optional(string, "factory") }) default = { data_dir = "data" diff --git a/fast/stages/2-networking-d-separate-envs/README.md b/fast/stages/2-networking-d-separate-envs/README.md index a718cda8..3929db7e 100644 --- a/fast/stages/2-networking-d-separate-envs/README.md +++ b/fast/stages/2-networking-d-separate-envs/README.md @@ -95,13 +95,7 @@ DNS often goes hand in hand with networking, especially on GCP where Cloud DNS z - on-prem to cloud via private zones for cloud-managed domains, and an [inbound policy](https://cloud.google.com/dns/docs/server-policies-overview#dns-server-policy-in) used as forwarding target or via delegation (requires some extra configuration) from on-prem DNS resolvers - cloud to on-prem via forwarding zones for the on-prem managed domains -- Private Google Access is enabled for a selection of the [supported domains](https://cloud.google.com/vpc/docs/configure-private-google-access#domain-options), namely - - `private.googleapis.com` - - `restricted.googleapis.com` - - `gcr.io` - - `packages.cloud.google.com` - - `pkg.dev` - - `pki.goog` +- Private Google Access is enabled via [DNS Response Policies](https://cloud.google.com/dns/docs/zones/manage-response-policies#create-response-policy-rule) for most of the [supported domains](https://cloud.google.com/vpc/docs/configure-private-google-access#domain-options) To complete the configuration, the 35.199.192.0/19 range should be routed on the VPN tunnels from on-prem, and the following names configured for DNS forwarding to cloud: @@ -328,8 +322,8 @@ Regions are defined via the `regions` variable which sets up a mapping between t | name | description | modules | resources | |---|---|---|---| -| [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 | | +| [dns-dev.tf](./dns-dev.tf) | Development spoke DNS zones and peerings setup. | dns · dns-response-policy | | +| [dns-prod.tf](./dns-prod.tf) | Production spoke DNS zones and peerings setup. | dns · dns-response-policy | | | [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 | @@ -346,18 +340,18 @@ Regions are defined via the `regions` variable which sets up a mapping between t |---|---|:---:|:---:|:---:|:---:| | [automation](variables.tf#L17) | Automation resources created by the bootstrap stage. | object({…}) | ✓ | | 0-bootstrap | | [billing_account](variables.tf#L25) | Billing account id. If billing account is not part of the same org set `is_org_level` to false. | object({…}) | ✓ | | 0-bootstrap | -| [folder_ids](variables.tf#L76) | Folders to be used for the networking resources in folders/nnnnnnnnnnn format. If null, folder will be created. | object({…}) | ✓ | | 1-resman | -| [organization](variables.tf#L86) | Organization details. | object({…}) | ✓ | | 0-bootstrap | -| [prefix](variables.tf#L102) | Prefix used for resources that need unique names. Use 9 characters or less. | string | ✓ | | 0-bootstrap | +| [folder_ids](variables.tf#L77) | Folders to be used for the networking resources in folders/nnnnnnnnnnn format. If null, folder will be created. | object({…}) | ✓ | | 1-resman | +| [organization](variables.tf#L87) | Organization details. | object({…}) | ✓ | | 0-bootstrap | +| [prefix](variables.tf#L103) | Prefix used for resources that need unique names. Use 9 characters or less. | string | ✓ | | 0-bootstrap | | [custom_roles](variables.tf#L38) | Custom roles defined at the org level, in key => id format. | object({…}) | | null | 0-bootstrap | | [dns](variables.tf#L47) | Onprem DNS resolvers. | map(list(string)) | | {…} | | -| [factories_config](variables.tf#L56) | Configuration for network resource factories. | object({…}) | | {…} | | -| [outputs_location](variables.tf#L96) | Path where providers and tfvars files for the following stages are written. Leave empty to disable. | string | | null | | -| [psa_ranges](variables.tf#L113) | IP ranges used for Private Service Access (e.g. CloudSQL). | object({…}) | | null | | -| [regions](variables.tf#L134) | Region definitions. | object({…}) | | {…} | | -| [service_accounts](variables.tf#L144) | Automation service accounts in name => email format. | object({…}) | | null | 1-resman | -| [vpn_onprem_dev_primary_config](variables.tf#L158) | VPN gateway configuration for onprem interconnection from dev in the primary region. | object({…}) | | null | | -| [vpn_onprem_prod_primary_config](variables.tf#L201) | VPN gateway configuration for onprem interconnection from prod in the primary region. | object({…}) | | null | | +| [factories_config](variables.tf#L56) | Configuration for network resource factories. | object({…}) | | {…} | | +| [outputs_location](variables.tf#L97) | Path where providers and tfvars files for the following stages are written. Leave empty to disable. | string | | null | | +| [psa_ranges](variables.tf#L114) | IP ranges used for Private Service Access (e.g. CloudSQL). | object({…}) | | null | | +| [regions](variables.tf#L135) | Region definitions. | object({…}) | | {…} | | +| [service_accounts](variables.tf#L145) | Automation service accounts in name => email format. | object({…}) | | null | 1-resman | +| [vpn_onprem_dev_primary_config](variables.tf#L159) | VPN gateway configuration for onprem interconnection from dev in the primary region. | object({…}) | | null | | +| [vpn_onprem_prod_primary_config](variables.tf#L202) | VPN gateway configuration for onprem interconnection from prod in the primary region. | object({…}) | | null | | ## Outputs diff --git a/fast/stages/2-networking-d-separate-envs/data/dns-policy-rules.yaml b/fast/stages/2-networking-d-separate-envs/data/dns-policy-rules.yaml new file mode 100644 index 00000000..d091e4f0 --- /dev/null +++ b/fast/stages/2-networking-d-separate-envs/data/dns-policy-rules.yaml @@ -0,0 +1,110 @@ +# skip boilerplate check + +accounts: + dns_name: "accounts.google.com." + local_data: { CNAME: { rrdatas: ["private.googleapis.com."] } } +backupdr-cloud: + dns_name: "backupdr.cloud.google.com." + local_data: { CNAME: { rrdatas: ["private.googleapis.com."] } } +backupdr-cloud-all: + dns_name: "*.backupdr.cloud.google.com." + local_data: { CNAME: { rrdatas: ["private.googleapis.com."] } } +backupdr-gu: + dns_name: "backupdr.googleusercontent.google.com." + local_data: { CNAME: { rrdatas: ["private.googleapis.com."] } } +backupdr-gu-all: + dns_name: "*.backupdr.googleusercontent.google.com." + local_data: { CNAME: { rrdatas: ["private.googleapis.com."] } } +cloudfunctions: + dns_name: "*.cloudfunctions.net." + local_data: { CNAME: { rrdatas: ["private.googleapis.com."] } } +cloudproxy: + dns_name: "*.cloudproxy.app." + local_data: { CNAME: { rrdatas: ["private.googleapis.com."] } } +composer-cloud-all: + dns_name: "*.composer.cloud.google.com." + local_data: { CNAME: { rrdatas: ["private.googleapis.com."] } } +composer-gu-all: + dns_name: "*.composer.googleusercontent.com." + local_data: { CNAME: { rrdatas: ["private.googleapis.com."] } } +datafusion-all: + dns_name: "*.datafusion.cloud.google.com." + local_data: { CNAME: { rrdatas: ["private.googleapis.com."] } } +datafusion-gu-all: + dns_name: "*.datafusion.googleusercontent.com." + local_data: { CNAME: { rrdatas: ["private.googleapis.com."] } } +dataproc: + dns_name: "dataproc.cloud.google.com." + local_data: { CNAME: { rrdatas: ["private.googleapis.com."] } } +dataproc-all: + dns_name: "*.dataproc.cloud.google.com." + local_data: { CNAME: { rrdatas: ["private.googleapis.com."] } } +dataproc-gu: + dns_name: "dataproc.googleusercontent.com." + local_data: { CNAME: { rrdatas: ["private.googleapis.com."] } } +dataproc-gu-all: + dns_name: "*.dataproc.googleusercontent.com." + local_data: { CNAME: { rrdatas: ["private.googleapis.com."] } } +dl: + dns_name: "dl.google.com." + local_data: { CNAME: { rrdatas: ["private.googleapis.com."] } } +gcr: + dns_name: "gcr.io." + local_data: { CNAME: { rrdatas: ["private.googleapis.com."] } } +gcr-all: + dns_name: "*.gcr.io." + local_data: { CNAME: { rrdatas: ["private.googleapis.com."] } } +googleapis-all: + dns_name: "*.googleapis.com." + local_data: { CNAME: { rrdatas: ["private.googleapis.com."] } } +googleapis-private: + dns_name: "private.googleapis.com." + local_data: + A: + rrdatas: + - 199.36.153.8 + - 199.36.153.9 + - 199.36.153.10 + - 199.36.153.11 +googleapis-restricted: + dns_name: "restricted.googleapis.com." + local_data: + A: + rrdatas: + - 199.36.153.4 + - 199.36.153.5 + - 199.36.153.6 + - 199.36.153.7 +gstatic-all: + dns_name: "*.gstatic.com." + local_data: { CNAME: { rrdatas: ["private.googleapis.com."] } } +notebooks-all: + dns_name: "*.notebooks.cloud.google.com." + local_data: { CNAME: { rrdatas: ["private.googleapis.com."] } } +notebooks-gu-all: + dns_name: "*.notebooks.googleusercontent.com." + local_data: { CNAME: { rrdatas: ["private.googleapis.com."] } } +packages-cloud: + dns_name: "packages.cloud.google.com." + local_data: { CNAME: { rrdatas: ["private.googleapis.com."] } } +packages-cloud-all: + dns_name: "*.packages.cloud.google.com." + local_data: { CNAME: { rrdatas: ["private.googleapis.com."] } } +pkgdev: + dns_name: "pkg.dev." + local_data: { CNAME: { rrdatas: ["private.googleapis.com."] } } +pkgdev-all: + dns_name: "*.pkg.dev." + local_data: { CNAME: { rrdatas: ["private.googleapis.com."] } } +pkigoog: + dns_name: "pki.goog." + local_data: { CNAME: { rrdatas: ["private.googleapis.com."] } } +pkigoog-all: + dns_name: "*.pki.goog." + local_data: { CNAME: { rrdatas: ["private.googleapis.com."] } } +run-all: + dns_name: "*.run.app." + local_data: { CNAME: { rrdatas: ["private.googleapis.com."] } } +source: + dns_name: "source.developers.google.com." + local_data: { CNAME: { rrdatas: ["private.googleapis.com."] } } diff --git a/fast/stages/2-networking-d-separate-envs/dns-dev.tf b/fast/stages/2-networking-d-separate-envs/dns-dev.tf index 25adab5e..134b69cf 100644 --- a/fast/stages/2-networking-d-separate-envs/dns-dev.tf +++ b/fast/stages/2-networking-d-separate-envs/dns-dev.tf @@ -30,7 +30,12 @@ module "dev-dns-private-zone" { } } -module "dev-onprem-example-dns-forwarding" { +moved { + from = module.dev-onprem-example-dns-forwarding + to = module.dev-dns-fwd-onprem-example +} + +module "dev-dns-fwd-onprem-example" { source = "../../../modules/dns" project_id = module.dev-spoke-project.project_id type = "forwarding" @@ -40,7 +45,12 @@ module "dev-onprem-example-dns-forwarding" { forwarders = { for ip in var.dns.dev : ip => null } } -module "dev-reverse-10-dns-forwarding" { +moved { + from = module.dev-reverse-10-dns-forwarding + to = module.dev-dns-fwd-onprem-rev-10 +} + +module "dev-dns-fwd-onprem-rev-10" { source = "../../../modules/dns" project_id = module.dev-spoke-project.project_id type = "forwarding" @@ -52,80 +62,12 @@ module "dev-reverse-10-dns-forwarding" { # Google APIs -module "dev-googleapis-private-zone" { - source = "../../../modules/dns" - project_id = module.dev-spoke-project.project_id - type = "private" - name = "googleapis-com" - domain = "googleapis.com." - client_networks = [module.dev-spoke-vpc.self_link] - recordsets = { - "A private" = { records = [ - "199.36.153.8", "199.36.153.9", "199.36.153.10", "199.36.153.11" - ] } - "A restricted" = { records = [ - "199.36.153.4", "199.36.153.5", "199.36.153.6", "199.36.153.7" - ] } - "CNAME *" = { records = ["private.googleapis.com."] } - } -} - -module "dev-gcrio-private-zone" { - source = "../../../modules/dns" - project_id = module.dev-spoke-project.project_id - type = "private" - name = "gcr-io" - domain = "gcr.io." - client_networks = [module.dev-spoke-vpc.self_link] - recordsets = { - "A gcr.io." = { ttl = 300, records = [ - "199.36.153.8", "199.36.153.9", "199.36.153.10", "199.36.153.11" - ] } - "CNAME *" = { ttl = 300, records = ["private.googleapis.com."] } - } -} - -module "dev-packages-private-zone" { - source = "../../../modules/dns" - project_id = module.dev-spoke-project.project_id - type = "private" - name = "packages-cloud" - domain = "packages.cloud.google.com." - client_networks = [module.dev-spoke-vpc.self_link] - recordsets = { - "A packages.cloud.google.com." = { ttl = 300, records = [ - "199.36.153.8", "199.36.153.9", "199.36.153.10", "199.36.153.11" - ] } - "CNAME *" = { ttl = 300, records = ["private.googleapis.com."] } - } -} - -module "dev-pkgdev-private-zone" { - source = "../../../modules/dns" - project_id = module.dev-spoke-project.project_id - type = "private" - name = "pkg-dev" - domain = "pkg.dev." - client_networks = [module.dev-spoke-vpc.self_link] - recordsets = { - "A pkg.dev." = { ttl = 300, records = [ - "199.36.153.8", "199.36.153.9", "199.36.153.10", "199.36.153.11" - ] } - "CNAME *" = { ttl = 300, records = ["private.googleapis.com."] } - } -} - -module "dev-pkigoog-private-zone" { - source = "../../../modules/dns" - project_id = module.dev-spoke-project.project_id - type = "private" - name = "pki-goog" - domain = "pki.goog." - client_networks = [module.dev-spoke-vpc.self_link] - recordsets = { - "A pki.goog." = { ttl = 300, records = [ - "199.36.153.8", "199.36.153.9", "199.36.153.10", "199.36.153.11" - ] } - "CNAME *" = { ttl = 300, records = ["private.googleapis.com."] } +module "dev-dns-policy-googleapis" { + source = "../../../modules/dns-response-policy" + project_id = module.dev-spoke-project.project_id + name = "googleapis" + networks = { + dev = module.dev-spoke-vpc.self_link } + rules_file = var.factories_config.dns_policy_rules_file } diff --git a/fast/stages/2-networking-d-separate-envs/dns-prod.tf b/fast/stages/2-networking-d-separate-envs/dns-prod.tf index 47c8cdca..351db57f 100644 --- a/fast/stages/2-networking-d-separate-envs/dns-prod.tf +++ b/fast/stages/2-networking-d-separate-envs/dns-prod.tf @@ -30,7 +30,12 @@ module "prod-dns-private-zone" { } } -module "prod-onprem-example-dns-forwarding" { +moved { + from = module.prod-onprem-example-dns-forwarding + to = module.prod-dns-fwd-onprem-example +} + +module "prod-dns-fwd-onprem-example" { source = "../../../modules/dns" project_id = module.prod-spoke-project.project_id type = "forwarding" @@ -40,7 +45,12 @@ module "prod-onprem-example-dns-forwarding" { forwarders = { for ip in var.dns.prod : ip => null } } -module "prod-reverse-10-dns-forwarding" { +moved { + from = module.prod-reverse-10-dns-forwarding + to = module.prod-dns-fwd-onprem-rev-10 +} + +module "prod-dns-fwd-onprem-rev-10" { source = "../../../modules/dns" project_id = module.prod-spoke-project.project_id type = "forwarding" @@ -52,80 +62,12 @@ module "prod-reverse-10-dns-forwarding" { # Google APIs -module "prod-googleapis-private-zone" { - source = "../../../modules/dns" - project_id = module.prod-spoke-project.project_id - type = "private" - name = "googleapis-com" - domain = "googleapis.com." - client_networks = [module.prod-spoke-vpc.self_link] - recordsets = { - "A private" = { records = [ - "199.36.153.8", "199.36.153.9", "199.36.153.10", "199.36.153.11" - ] } - "A restricted" = { records = [ - "199.36.153.4", "199.36.153.5", "199.36.153.6", "199.36.153.7" - ] } - "CNAME *" = { records = ["private.googleapis.com."] } - } -} - -module "prod-gcrio-private-zone" { - source = "../../../modules/dns" - project_id = module.prod-spoke-project.project_id - type = "private" - name = "gcr-io" - domain = "gcr.io." - client_networks = [module.prod-spoke-vpc.self_link] - recordsets = { - "A gcr.io." = { ttl = 300, records = [ - "199.36.153.8", "199.36.153.9", "199.36.153.10", "199.36.153.11" - ] } - "CNAME *" = { ttl = 300, records = ["private.googleapis.com."] } - } -} - -module "prod-packages-private-zone" { - source = "../../../modules/dns" - project_id = module.prod-spoke-project.project_id - type = "private" - name = "packages-cloud" - domain = "packages.cloud.google.com." - client_networks = [module.prod-spoke-vpc.self_link] - recordsets = { - "A packages.cloud.google.com." = { ttl = 300, records = [ - "199.36.153.8", "199.36.153.9", "199.36.153.10", "199.36.153.11" - ] } - "CNAME *" = { ttl = 300, records = ["private.googleapis.com."] } - } -} - -module "prod-pkgdev-private-zone" { - source = "../../../modules/dns" - project_id = module.prod-spoke-project.project_id - type = "private" - name = "pkg-dev" - domain = "pkg.dev." - client_networks = [module.prod-spoke-vpc.self_link] - recordsets = { - "A pkg.dev." = { ttl = 300, records = [ - "199.36.153.8", "199.36.153.9", "199.36.153.10", "199.36.153.11" - ] } - "CNAME *" = { ttl = 300, records = ["private.googleapis.com."] } - } -} - -module "prod-pkigoog-private-zone" { - source = "../../../modules/dns" - project_id = module.prod-spoke-project.project_id - type = "private" - name = "pki-goog" - domain = "pki.goog." - client_networks = [module.prod-spoke-vpc.self_link] - recordsets = { - "A pki.goog." = { ttl = 300, records = [ - "199.36.153.8", "199.36.153.9", "199.36.153.10", "199.36.153.11" - ] } - "CNAME *" = { ttl = 300, records = ["private.googleapis.com."] } +module "prod-dns-policy-googleapis" { + source = "../../../modules/dns-response-policy" + project_id = module.prod-spoke-project.project_id + name = "googleapis" + networks = { + prod = module.prod-spoke-vpc.self_link } + rules_file = var.factories_config.dns_policy_rules_file } diff --git a/fast/stages/2-networking-d-separate-envs/variables.tf b/fast/stages/2-networking-d-separate-envs/variables.tf index a8920c53..5ea75c52 100644 --- a/fast/stages/2-networking-d-separate-envs/variables.tf +++ b/fast/stages/2-networking-d-separate-envs/variables.tf @@ -56,8 +56,9 @@ variable "dns" { variable "factories_config" { description = "Configuration for network resource factories." type = object({ - data_dir = optional(string, "data") - firewall_policy_name = optional(string, "factory") + data_dir = optional(string, "data") + dns_policy_rules_file = optional(string, "data/dns-policy-rules.yaml") + firewall_policy_name = optional(string, "factory") }) default = { data_dir = "data" diff --git a/fast/stages/2-networking-e-nva-bgp/README.md b/fast/stages/2-networking-e-nva-bgp/README.md index ea1e2ec5..4fee9735 100644 --- a/fast/stages/2-networking-e-nva-bgp/README.md +++ b/fast/stages/2-networking-e-nva-bgp/README.md @@ -230,13 +230,7 @@ DNS configuration is further centralized by leveraging peering zones, so that - the hub/landing Cloud DNS hosts configurations for on-prem forwarding, Google API domains, and the top-level private zone/s (e.g. gcp.example.com) - the spokes Cloud DNS host configurations for the environment-specific domains (e.g. prod.gcp.example.com), which are bound to the hub/landing leveraging [cross-project binding](https://cloud.google.com/dns/docs/zones/zones-overview#cross-project_binding); a peering zone for the `.` (root) zone is then created on each spoke, delegating all DNS resolution to hub/landing. -- Private Google Access is enabled for a selection of the [supported domains](https://cloud.google.com/vpc/docs/configure-private-google-access#domain-options), namely - - `private.googleapis.com` - - `restricted.googleapis.com` - - `gcr.io` - - `packages.cloud.google.com` - - `pkg.dev` - - `pki.goog` +- Private Google Access is enabled via [DNS Response Policies](https://cloud.google.com/dns/docs/zones/manage-response-policies#create-response-policy-rule) for most of the [supported domains](https://cloud.google.com/vpc/docs/configure-private-google-access#domain-options) To complete the configuration, the 35.199.192.0/19 range should be routed to the VPN tunnels from on-premises, and the following names should be configured for DNS forwarding to cloud: @@ -488,7 +482,7 @@ DNS configurations are centralised in the `dns-*.tf` files. Spokes delegate DNS | name | description | modules | resources | |---|---|---|---| | [dns-dev.tf](./dns-dev.tf) | Development spoke DNS zones and peerings setup. | dns | | -| [dns-landing.tf](./dns-landing.tf) | Landing DNS zones and peerings setup. | dns | | +| [dns-landing.tf](./dns-landing.tf) | Landing DNS zones and peerings setup. | dns · dns-response-policy | | | [dns-prod.tf](./dns-prod.tf) | Production spoke DNS zones and peerings setup. | dns | | | [landing.tf](./landing.tf) | Landing VPC and related resources. | net-cloudnat · net-vpc · net-vpc-firewall · project | | | [main.tf](./main.tf) | Networking folder and hierarchical policy. | folder | | @@ -509,22 +503,22 @@ 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#L75) | Folders to be used for the networking resources in folders/nnnnnnnnnnn format. If null, folder will be created. | object({…}) | ✓ | | 1-resman | -| [organization](variables.tf#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#L76) | Folders to be used for the networking resources in folders/nnnnnnnnnnn format. If null, folder will be created. | object({…}) | ✓ | | 1-resman | +| [organization](variables.tf#L120) | Organization details. | object({…}) | ✓ | | 0-bootstrap | +| [prefix](variables.tf#L136) | Prefix used for resources that need unique names. Use 9 characters or less. | string | ✓ | | 0-bootstrap | | [custom_roles](variables.tf#L38) | Custom roles defined at the org level, in key => id format. | object({…}) | | null | 0-bootstrap | | [dns](variables.tf#L47) | Onprem DNS resolvers. | map(list(string)) | | {…} | | -| [factories_config](variables.tf#L55) | Configuration for network resource factories. | object({…}) | | {…} | | -| [gcp_ranges](variables.tf#L85) | GCP address ranges in name => range format. | map(string) | | {…} | | -| [ncc_asn](variables.tf#L100) | The NCC Cloud Routers ASN configuration. | map(number) | | {…} | | -| [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({…}) | | {…} | | -| [service_accounts](variables.tf#L179) | Automation service accounts in name => email format. | object({…}) | | null | 1-resman | -| [vpn_onprem_primary_config](variables.tf#L193) | VPN gateway configuration for onprem interconnection in the primary region. | object({…}) | | null | | -| [vpn_onprem_secondary_config](variables.tf#L236) | VPN gateway configuration for onprem interconnection in the secondary region. | object({…}) | | null | | -| [zones](variables.tf#L279) | Zones in which NVAs are deployed. | list(string) | | ["b", "c"] | | +| [factories_config](variables.tf#L55) | Configuration for network resource factories. | object({…}) | | {…} | | +| [gcp_ranges](variables.tf#L86) | GCP address ranges in name => range format. | map(string) | | {…} | | +| [ncc_asn](variables.tf#L101) | The NCC Cloud Routers ASN configuration. | map(number) | | {…} | | +| [onprem_cidr](variables.tf#L112) | Onprem addresses in name => range format. | map(string) | | {…} | | +| [outputs_location](variables.tf#L130) | Path where providers and tfvars files for the following stages are written. Leave empty to disable. | string | | null | | +| [psa_ranges](variables.tf#L147) | IP ranges used for Private Service Access (e.g. CloudSQL). Ranges is in name => range format. | object({…}) | | null | | +| [regions](variables.tf#L168) | Region definitions. | object({…}) | | {…} | | +| [service_accounts](variables.tf#L180) | Automation service accounts in name => email format. | object({…}) | | null | 1-resman | +| [vpn_onprem_primary_config](variables.tf#L194) | VPN gateway configuration for onprem interconnection in the primary region. | object({…}) | | null | | +| [vpn_onprem_secondary_config](variables.tf#L237) | VPN gateway configuration for onprem interconnection in the secondary region. | object({…}) | | null | | +| [zones](variables.tf#L280) | Zones in which NVAs are deployed. | list(string) | | ["b", "c"] | | ## Outputs diff --git a/fast/stages/2-networking-e-nva-bgp/data/dns-policy-rules.yaml b/fast/stages/2-networking-e-nva-bgp/data/dns-policy-rules.yaml new file mode 100644 index 00000000..d091e4f0 --- /dev/null +++ b/fast/stages/2-networking-e-nva-bgp/data/dns-policy-rules.yaml @@ -0,0 +1,110 @@ +# skip boilerplate check + +accounts: + dns_name: "accounts.google.com." + local_data: { CNAME: { rrdatas: ["private.googleapis.com."] } } +backupdr-cloud: + dns_name: "backupdr.cloud.google.com." + local_data: { CNAME: { rrdatas: ["private.googleapis.com."] } } +backupdr-cloud-all: + dns_name: "*.backupdr.cloud.google.com." + local_data: { CNAME: { rrdatas: ["private.googleapis.com."] } } +backupdr-gu: + dns_name: "backupdr.googleusercontent.google.com." + local_data: { CNAME: { rrdatas: ["private.googleapis.com."] } } +backupdr-gu-all: + dns_name: "*.backupdr.googleusercontent.google.com." + local_data: { CNAME: { rrdatas: ["private.googleapis.com."] } } +cloudfunctions: + dns_name: "*.cloudfunctions.net." + local_data: { CNAME: { rrdatas: ["private.googleapis.com."] } } +cloudproxy: + dns_name: "*.cloudproxy.app." + local_data: { CNAME: { rrdatas: ["private.googleapis.com."] } } +composer-cloud-all: + dns_name: "*.composer.cloud.google.com." + local_data: { CNAME: { rrdatas: ["private.googleapis.com."] } } +composer-gu-all: + dns_name: "*.composer.googleusercontent.com." + local_data: { CNAME: { rrdatas: ["private.googleapis.com."] } } +datafusion-all: + dns_name: "*.datafusion.cloud.google.com." + local_data: { CNAME: { rrdatas: ["private.googleapis.com."] } } +datafusion-gu-all: + dns_name: "*.datafusion.googleusercontent.com." + local_data: { CNAME: { rrdatas: ["private.googleapis.com."] } } +dataproc: + dns_name: "dataproc.cloud.google.com." + local_data: { CNAME: { rrdatas: ["private.googleapis.com."] } } +dataproc-all: + dns_name: "*.dataproc.cloud.google.com." + local_data: { CNAME: { rrdatas: ["private.googleapis.com."] } } +dataproc-gu: + dns_name: "dataproc.googleusercontent.com." + local_data: { CNAME: { rrdatas: ["private.googleapis.com."] } } +dataproc-gu-all: + dns_name: "*.dataproc.googleusercontent.com." + local_data: { CNAME: { rrdatas: ["private.googleapis.com."] } } +dl: + dns_name: "dl.google.com." + local_data: { CNAME: { rrdatas: ["private.googleapis.com."] } } +gcr: + dns_name: "gcr.io." + local_data: { CNAME: { rrdatas: ["private.googleapis.com."] } } +gcr-all: + dns_name: "*.gcr.io." + local_data: { CNAME: { rrdatas: ["private.googleapis.com."] } } +googleapis-all: + dns_name: "*.googleapis.com." + local_data: { CNAME: { rrdatas: ["private.googleapis.com."] } } +googleapis-private: + dns_name: "private.googleapis.com." + local_data: + A: + rrdatas: + - 199.36.153.8 + - 199.36.153.9 + - 199.36.153.10 + - 199.36.153.11 +googleapis-restricted: + dns_name: "restricted.googleapis.com." + local_data: + A: + rrdatas: + - 199.36.153.4 + - 199.36.153.5 + - 199.36.153.6 + - 199.36.153.7 +gstatic-all: + dns_name: "*.gstatic.com." + local_data: { CNAME: { rrdatas: ["private.googleapis.com."] } } +notebooks-all: + dns_name: "*.notebooks.cloud.google.com." + local_data: { CNAME: { rrdatas: ["private.googleapis.com."] } } +notebooks-gu-all: + dns_name: "*.notebooks.googleusercontent.com." + local_data: { CNAME: { rrdatas: ["private.googleapis.com."] } } +packages-cloud: + dns_name: "packages.cloud.google.com." + local_data: { CNAME: { rrdatas: ["private.googleapis.com."] } } +packages-cloud-all: + dns_name: "*.packages.cloud.google.com." + local_data: { CNAME: { rrdatas: ["private.googleapis.com."] } } +pkgdev: + dns_name: "pkg.dev." + local_data: { CNAME: { rrdatas: ["private.googleapis.com."] } } +pkgdev-all: + dns_name: "*.pkg.dev." + local_data: { CNAME: { rrdatas: ["private.googleapis.com."] } } +pkigoog: + dns_name: "pki.goog." + local_data: { CNAME: { rrdatas: ["private.googleapis.com."] } } +pkigoog-all: + dns_name: "*.pki.goog." + local_data: { CNAME: { rrdatas: ["private.googleapis.com."] } } +run-all: + dns_name: "*.run.app." + local_data: { CNAME: { rrdatas: ["private.googleapis.com."] } } +source: + dns_name: "source.developers.google.com." + local_data: { CNAME: { rrdatas: ["private.googleapis.com."] } } diff --git a/fast/stages/2-networking-e-nva-bgp/dns-dev.tf b/fast/stages/2-networking-e-nva-bgp/dns-dev.tf index 4eb472a1..98d56aa7 100644 --- a/fast/stages/2-networking-e-nva-bgp/dns-dev.tf +++ b/fast/stages/2-networking-e-nva-bgp/dns-dev.tf @@ -32,7 +32,12 @@ module "dev-dns-private-zone" { # root zone peering to landing to centralize configuration; remove if unneeded -module "dev-landing-root-dns-peering" { +moved { + from = module.dev-landing-root-dns-peering + to = module.dev-dns-peer-landing-root +} + +module "dev-dns-peer-landing-root" { source = "../../../modules/dns" project_id = module.dev-spoke-project.project_id type = "peering" @@ -42,7 +47,12 @@ module "dev-landing-root-dns-peering" { peer_network = module.landing-trusted-vpc.self_link } -module "dev-reverse-10-dns-peering" { +moved { + from = module.dev-reverse-10-dns-peering + to = module.dev-dns-peer-landing-rev-10 +} + +module "dev-dns-peer-landing-rev-10" { source = "../../../modules/dns" project_id = module.dev-spoke-project.project_id type = "peering" diff --git a/fast/stages/2-networking-e-nva-bgp/dns-landing.tf b/fast/stages/2-networking-e-nva-bgp/dns-landing.tf index 40090279..50b65890 100644 --- a/fast/stages/2-networking-e-nva-bgp/dns-landing.tf +++ b/fast/stages/2-networking-e-nva-bgp/dns-landing.tf @@ -18,7 +18,12 @@ # forwarding to on-prem DNS resolvers -module "onprem-example-dns-forwarding" { +moved { + from = module.onprem-example-dns-forwarding + to = module.landing-dns-fwd-onprem-example +} + +module "landing-dns-fwd-onprem-example" { source = "../../../modules/dns" project_id = module.landing-project.project_id type = "forwarding" @@ -31,7 +36,12 @@ module "onprem-example-dns-forwarding" { forwarders = { for ip in var.dns.onprem : ip => null } } -module "reverse-10-dns-forwarding" { +moved { + from = module.reverse-10-dns-forwarding + to = module.landing-dns-fwd-onprem-rev-10 +} + +module "landing-dns-fwd-onprem-rev-10" { source = "../../../modules/dns" project_id = module.landing-project.project_id type = "forwarding" @@ -44,7 +54,12 @@ module "reverse-10-dns-forwarding" { forwarders = { for ip in var.dns.onprem : ip => null } } -module "gcp-example-dns-private-zone" { +moved { + from = module.gcp-example-dns-private-zone + to = module.landing-dns-priv-gcp +} + +module "landing-dns-priv-gcp" { source = "../../../modules/dns" project_id = module.landing-project.project_id type = "private" @@ -61,95 +76,13 @@ module "gcp-example-dns-private-zone" { # Google APIs -module "googleapis-private-zone" { - source = "../../../modules/dns" +module "landing-dns-policy-googleapis" { + source = "../../../modules/dns-response-policy" project_id = module.landing-project.project_id - type = "private" - name = "googleapis-com" - domain = "googleapis.com." - client_networks = [ - module.landing-untrusted-vpc.self_link, - module.landing-trusted-vpc.self_link - ] - recordsets = { - "A private" = { records = [ - "199.36.153.8", "199.36.153.9", "199.36.153.10", "199.36.153.11" - ] } - "A restricted" = { records = [ - "199.36.153.4", "199.36.153.5", "199.36.153.6", "199.36.153.7" - ] } - "CNAME *" = { records = ["private.googleapis.com."] } - } -} - -module "gcrio-private-zone" { - source = "../../../modules/dns" - project_id = module.landing-project.project_id - type = "private" - name = "gcr-io" - domain = "gcr.io." - client_networks = [ - module.landing-untrusted-vpc.self_link, - module.landing-trusted-vpc.self_link - ] - recordsets = { - "A gcr.io." = { ttl = 300, records = [ - "199.36.153.8", "199.36.153.9", "199.36.153.10", "199.36.153.11" - ] } - "CNAME *" = { ttl = 300, records = ["private.googleapis.com."] } - } -} - -module "packages-private-zone" { - source = "../../../modules/dns" - project_id = module.landing-project.project_id - type = "private" - name = "packages-cloud" - domain = "packages.cloud.google.com." - client_networks = [ - module.landing-untrusted-vpc.self_link, - module.landing-trusted-vpc.self_link - ] - recordsets = { - "A packages.cloud.google.com." = { ttl = 300, records = [ - "199.36.153.8", "199.36.153.9", "199.36.153.10", "199.36.153.11" - ] } - "CNAME *" = { ttl = 300, records = ["private.googleapis.com."] } - } -} - -module "pkgdev-private-zone" { - source = "../../../modules/dns" - project_id = module.landing-project.project_id - type = "private" - name = "pkg-dev" - domain = "pkg.dev." - client_networks = [ - module.landing-untrusted-vpc.self_link, - module.landing-trusted-vpc.self_link - ] - recordsets = { - "A pkg.dev." = { ttl = 300, records = [ - "199.36.153.8", "199.36.153.9", "199.36.153.10", "199.36.153.11" - ] } - "CNAME *" = { ttl = 300, records = ["private.googleapis.com."] } - } -} - -module "pkigoog-private-zone" { - source = "../../../modules/dns" - project_id = module.landing-project.project_id - type = "private" - name = "pki-goog" - domain = "pki.goog." - client_networks = [ - module.landing-untrusted-vpc.self_link, - module.landing-trusted-vpc.self_link - ] - recordsets = { - "A pki.goog." = { ttl = 300, records = [ - "199.36.153.8", "199.36.153.9", "199.36.153.10", "199.36.153.11" - ] } - "CNAME *" = { ttl = 300, records = ["private.googleapis.com."] } + name = "googleapis" + networks = { + landing-trusted = module.landing-trusted-vpc.self_link + landing-untrusted = module.landing-untrusted-vpc.self_link } + rules_file = var.factories_config.dns_policy_rules_file } diff --git a/fast/stages/2-networking-e-nva-bgp/dns-prod.tf b/fast/stages/2-networking-e-nva-bgp/dns-prod.tf index b54609df..5627e438 100644 --- a/fast/stages/2-networking-e-nva-bgp/dns-prod.tf +++ b/fast/stages/2-networking-e-nva-bgp/dns-prod.tf @@ -32,7 +32,12 @@ module "prod-dns-private-zone" { # root zone peering to landing to centralize configuration; remove if unneeded -module "prod-landing-root-dns-peering" { +moved { + from = module.prod-landing-root-dns-peering + to = module.prod-dns-peer-landing-root +} + +module "prod-dns-peer-landing-root" { source = "../../../modules/dns" project_id = module.prod-spoke-project.project_id type = "peering" @@ -42,7 +47,12 @@ module "prod-landing-root-dns-peering" { peer_network = module.landing-trusted-vpc.self_link } -module "prod-reverse-10-dns-peering" { +moved { + from = module.prod-reverse-10-dns-peering + to = module.prod-dns-peer-landing-rev-10 +} + +module "prod-dns-peer-landing-rev-10" { source = "../../../modules/dns" project_id = module.prod-spoke-project.project_id type = "peering" diff --git a/fast/stages/2-networking-e-nva-bgp/variables.tf b/fast/stages/2-networking-e-nva-bgp/variables.tf index 85d3c7c0..155a715c 100644 --- a/fast/stages/2-networking-e-nva-bgp/variables.tf +++ b/fast/stages/2-networking-e-nva-bgp/variables.tf @@ -55,8 +55,9 @@ variable "dns" { variable "factories_config" { description = "Configuration for network resource factories." type = object({ - data_dir = optional(string, "data") - firewall_policy_name = optional(string, "factory") + data_dir = optional(string, "data") + dns_policy_rules_file = optional(string, "data/dns-policy-rules.yaml") + firewall_policy_name = optional(string, "factory") }) default = { data_dir = "data" diff --git a/modules/dns-response-policy/README.md b/modules/dns-response-policy/README.md index dddf4aba..e55cd3d3 100644 --- a/modules/dns-response-policy/README.md +++ b/modules/dns-response-policy/README.md @@ -2,6 +2,8 @@ This module allows management of a [Google Cloud DNS policy and its rules](https://cloud.google.com/dns/docs/zones/manage-response-policies). The policy can already exist and be referenced by name by setting the `policy_create` variable to `false`. +The module also allows setting rules via a factory. An example is given below. + ## Examples ### Manage policy and override resolution for specific names @@ -44,7 +46,15 @@ module "dns-policy" { landing = var.vpc.self_link } rules = { - default = { + gcr = { + dns_name = "gcr.io." + local_data = { + CNAME = { + rrdatas = ["restricted.googleapis.com."] + } + } + } + googleapis-all = { dns_name = "*.googleapis.com." local_data = { CNAME = { @@ -59,13 +69,59 @@ module "dns-policy" { dns_name = "restricted.googleapis.com." local_data = { A = { - rrdatas = ["199.36.153.4", "199.36.153.5"] + rrdatas = [ + "199.36.153.4", + "199.36.153.5", + "199.36.153.6", + "199.36.153.7" + ] } } } } } -# tftest modules=1 resources=3 inventory=nocreate.yaml +# tftest modules=1 resources=4 inventory=complex.yaml +``` + +### Define policy rules via a factory file + +This example shows how to define rules in a factory file, that mirrors the rules defined via variables in the previous example. Rules defined via the variable are merged with factory rules and take precedence over them when using the same rule names. The YAML syntax closely follows the `rules` variable type. + +```hcl +module "dns-policy" { + source = "./fabric/modules/dns-response-policy" + project_id = "myproject" + name = "googleapis" + policy_create = false + networks = { + landing = var.vpc.self_link + } + rules_file = "config/rules.yaml" +} +# tftest modules=1 resources=4 files=rules-file inventory=complex.yaml +``` + +```yaml +gcr: + dns_name: "gcr.io." + local_data: + CNAME: {rrdatas: ["restricted.googleapis.com."]} +googleapis-all: + dns_name: "*.googleapis.com." + local_data: + CNAME: {rrdatas: ["restricted.googleapis.com."]} +pubsub: + dns_name: "pubsub.googleapis.com." +restricted: + dns_name: "restricted.googleapis.com." + local_data: + A: + rrdatas: + - 199.36.153.4 + - 199.36.153.5 + - 199.36.153.6 + - 199.36.153.7 +# tftest-file id=rules-file path=config/rules.yaml ``` @@ -80,6 +136,7 @@ module "dns-policy" { | [networks](variables.tf#L35) | Map of VPC self links to which this policy is applied in name => self link format. | map(string) | | {} | | [policy_create](variables.tf#L42) | Set to false to use the existing policy matching name and only manage rules. | bool | | true | | [rules](variables.tf#L54) | Map of policy rules in name => rule format. Local data takes precedence over behavior and is in the form record type => attributes. | map(object({…})) | | {} | +| [rules_file](variables.tf#L68) | Optional data file in YAML format listing rules that will be combined with those passed in via the `rules` variable. | string | | null | ## Outputs diff --git a/modules/dns-response-policy/main.tf b/modules/dns-response-policy/main.tf index 26d0a26f..69b7ff4a 100644 --- a/modules/dns-response-policy/main.tf +++ b/modules/dns-response-policy/main.tf @@ -15,6 +15,17 @@ */ locals { + _factory_rules = try(yamldecode(file(var.rules_file)), {}) + factory_rules = { + for k, v in local._factory_rules : k => { + dns_name = v.dns_name + behavior = lookup(v, "behavior", "bypassResponsePolicy") + local_data = { + for kk, vv in lookup(v, "local_data", {}) : + kk => merge({ ttl = null, rrdatas = [] }, vv) + } + } + } policy_name = ( var.policy_create ? google_dns_response_policy.default.0.response_policy_name @@ -43,7 +54,7 @@ resource "google_dns_response_policy" "default" { resource "google_dns_response_policy_rule" "default" { provider = google-beta - for_each = var.rules + for_each = merge(local.factory_rules, var.rules) project = var.project_id response_policy = local.policy_name rule_name = each.key diff --git a/modules/dns-response-policy/variables.tf b/modules/dns-response-policy/variables.tf index 8f37ec2b..fa26c3bb 100644 --- a/modules/dns-response-policy/variables.tf +++ b/modules/dns-response-policy/variables.tf @@ -64,3 +64,9 @@ variable "rules" { default = {} nullable = false } + +variable "rules_file" { + description = "Optional data file in YAML format listing rules that will be combined with those passed in via the `rules` variable." + type = string + default = null +} diff --git a/tests/fast/stages/s2_networking_a_peering/stage.yaml b/tests/fast/stages/s2_networking_a_peering/stage.yaml index 556d8f14..e307c614 100644 --- a/tests/fast/stages/s2_networking_a_peering/stage.yaml +++ b/tests/fast/stages/s2_networking_a_peering/stage.yaml @@ -13,5 +13,5 @@ # limitations under the License. counts: - modules: 31 - resources: 122 \ No newline at end of file + modules: 27 + resources: 139 diff --git a/tests/fast/stages/s2_networking_b_vpn/stage.yaml b/tests/fast/stages/s2_networking_b_vpn/stage.yaml index d63a3e4f..ebe3fb48 100644 --- a/tests/fast/stages/s2_networking_b_vpn/stage.yaml +++ b/tests/fast/stages/s2_networking_b_vpn/stage.yaml @@ -13,5 +13,5 @@ # limitations under the License. counts: - modules: 33 - resources: 159 + modules: 29 + resources: 176 diff --git a/tests/fast/stages/s2_networking_c_nva/stage.yaml b/tests/fast/stages/s2_networking_c_nva/stage.yaml index f79d4015..bbd6d6ba 100644 --- a/tests/fast/stages/s2_networking_c_nva/stage.yaml +++ b/tests/fast/stages/s2_networking_c_nva/stage.yaml @@ -13,5 +13,5 @@ # limitations under the License. counts: - modules: 45 - resources: 168 + modules: 41 + resources: 185 diff --git a/tests/fast/stages/s2_networking_d_separate_envs/stage.yaml b/tests/fast/stages/s2_networking_d_separate_envs/stage.yaml index c6824980..0313e359 100644 --- a/tests/fast/stages/s2_networking_d_separate_envs/stage.yaml +++ b/tests/fast/stages/s2_networking_d_separate_envs/stage.yaml @@ -13,5 +13,5 @@ # limitations under the License. counts: - modules: 28 - resources: 122 + modules: 20 + resources: 156 diff --git a/tests/fast/stages/s2_networking_e_nva_bgp/stage.yaml b/tests/fast/stages/s2_networking_e_nva_bgp/stage.yaml index 660e718f..10abee57 100644 --- a/tests/fast/stages/s2_networking_e_nva_bgp/stage.yaml +++ b/tests/fast/stages/s2_networking_e_nva_bgp/stage.yaml @@ -13,5 +13,5 @@ # limitations under the License. counts: - modules: 39 - resources: 181 + modules: 35 + resources: 198 diff --git a/tests/modules/dns_response_policy/examples/nocreate.yaml b/tests/modules/dns_response_policy/examples/complex.yaml similarity index 51% rename from tests/modules/dns_response_policy/examples/nocreate.yaml rename to tests/modules/dns_response_policy/examples/complex.yaml index ccef34bc..1b22df2a 100644 --- a/tests/modules/dns_response_policy/examples/nocreate.yaml +++ b/tests/modules/dns_response_policy/examples/complex.yaml @@ -13,19 +13,34 @@ # limitations under the License. values: - module.dns-policy.google_dns_response_policy_rule.default["default"]: + module.dns-policy.google_dns_response_policy_rule.default["gcr"]: behavior: null - dns_name: '*.googleapis.com.' + dns_name: gcr.io. local_data: - - local_datas: - - name: '*.googleapis.com.' - rrdatas: - - restricted.googleapis.com. - ttl: null - type: CNAME + - local_datas: + - name: gcr.io. + rrdatas: + - restricted.googleapis.com. + ttl: null + type: CNAME project: myproject response_policy: googleapis - rule_name: default + rule_name: gcr + timeouts: null + module.dns-policy.google_dns_response_policy_rule.default["googleapis-all"]: + behavior: null + dns_name: "*.googleapis.com." + local_data: + - local_datas: + - name: "*.googleapis.com." + rrdatas: + - restricted.googleapis.com. + ttl: null + type: CNAME + project: myproject + response_policy: googleapis + rule_name: googleapis-all + timeouts: null module.dns-policy.google_dns_response_policy_rule.default["pubsub"]: behavior: bypassResponsePolicy dns_name: pubsub.googleapis.com. @@ -33,20 +48,28 @@ values: project: myproject response_policy: googleapis rule_name: pubsub + timeouts: null module.dns-policy.google_dns_response_policy_rule.default["restricted"]: behavior: null dns_name: restricted.googleapis.com. local_data: - - local_datas: - - name: restricted.googleapis.com. - rrdatas: - - 199.36.153.4 - - 199.36.153.5 - ttl: null - type: A + - local_datas: + - name: restricted.googleapis.com. + rrdatas: + - 199.36.153.4 + - 199.36.153.5 + - 199.36.153.6 + - 199.36.153.7 + ttl: null + type: A project: myproject response_policy: googleapis rule_name: restricted + timeouts: null counts: - google_dns_response_policy_rule: 3 + google_dns_response_policy_rule: 4 + modules: 1 + resources: 4 + +outputs: {}