feat(2-networking): add NS And DS record dynamically from sub-zones records (#3818)
* feat(2-networking): add NS And DS record dynamically from sub-zones records * tfdoc * feat(test): 2-networking adding dns_delegations test with and without DSSEC --------- Co-authored-by: Ludovico Magnocavallo <ludomagno@google.com> Co-authored-by: Simone Ruffilli <sruffilli@google.com>
This commit is contained in:
@@ -12,6 +12,7 @@
|
||||
- [Networking projects](#networking-projects)
|
||||
- [VPCs](#vpcs)
|
||||
- [DNS](#dns)
|
||||
- [Delegated Public Zones](#delegated-public-zones)
|
||||
- [Firewall Policies](#firewall-policies)
|
||||
- [Cloud NAT and Routers](#cloud-nat-and-routers)
|
||||
- [VPC Connectivity](#vpc-connectivity)
|
||||
@@ -200,6 +201,68 @@ In the default dataset, DNS is centralized in the `net-core-0` (hub) project. It
|
||||
|
||||
The spoke VPCs have their own private zones for subdomains (e.g., `dev.test.`) and use the hub for all other DNS lookups.
|
||||
|
||||
#### Delegated Public Zones
|
||||
|
||||
The factory also supports delegating public zones, which is useful for scenarios where a parent public zone is managed in one project, and you want to delegate a subdomain to a different project.
|
||||
|
||||
To configure this, you first define the parent public zone. Then, for the delegated zone, you specify `delegation_config` pointing to the parent zone. This automatically creates the necessary `NS` (and `DS` records if you are using DNSSEC) records in the parent zone.
|
||||
|
||||
Here's an example of how to set this up:
|
||||
|
||||
```yaml
|
||||
# Parent public zone (e.g., in dns/zones/net-core-0/pub-gcp-example-com.yaml)
|
||||
#
|
||||
# yaml-language-server: $schema=../../../../../schemas/dns.schema.json
|
||||
|
||||
project_id: $project_ids:net-core-0
|
||||
domain: gcp.example.com.
|
||||
public:
|
||||
enable_logging: false
|
||||
dnssec_config:
|
||||
state: "on"
|
||||
non_existence: "nsec3"
|
||||
key_signing_key:
|
||||
algorithm: "ecdsap256sha256"
|
||||
key_length: 256
|
||||
zone_signing_key:
|
||||
algorithm: "ecdsap256sha256"
|
||||
key_length: 256
|
||||
recordsets:
|
||||
"A localhost":
|
||||
records: ["127.0.0.1"]
|
||||
delegations:
|
||||
- net-dev-0/pub-dev-gcp-example-com
|
||||
```
|
||||
|
||||
```yaml
|
||||
# Delegated child zone (e.g., in dns/zones/net-dev-0/pub-dev-gcp-example-com.yaml)
|
||||
#
|
||||
# yaml-language-server: $schema=../../../../../schemas/dns.schema.json
|
||||
|
||||
project_id: $project_ids:net-dev-0
|
||||
domain: dev.gcp.example.com.
|
||||
public:
|
||||
enable_logging: false
|
||||
dnssec_config:
|
||||
state: "on"
|
||||
non_existence: "nsec3"
|
||||
key_signing_key:
|
||||
algorithm: "ecdsap256sha256"
|
||||
key_length: 256
|
||||
zone_signing_key:
|
||||
algorithm: "ecdsap256sha256"
|
||||
key_length: 256
|
||||
recordsets:
|
||||
"A localhost":
|
||||
records: ["127.0.0.1"]
|
||||
|
||||
```
|
||||
|
||||
In this example:
|
||||
- A public zone for `gcp.example.com.` is created in the `net-core-0` project.
|
||||
- A separate public zone for `dev.gcp.example.com.` is created in the `net-dev-0` project.
|
||||
- The `delegation_config` in the parent zone tells the factory to find the child zone named `pub-dev-gcp-example-com` in the `net-dev-0` project and create the necessary `NS` and `DS` records to make the delegation effective.
|
||||
|
||||
### Firewall Policies
|
||||
|
||||
This stage supports both VPC-level firewall rules and hierarchical firewall policies.
|
||||
|
||||
@@ -75,6 +75,30 @@ locals {
|
||||
}
|
||||
)
|
||||
}
|
||||
# DNS delegations: auto-create NS and DS records in parent zones
|
||||
# from child zone outputs (name_servers, dns_keys).
|
||||
# Grouped by parent zone key so a single module call per parent
|
||||
# handles all its delegation recordsets.
|
||||
dns_delegation_recordsets = {
|
||||
for zone_key, zone_config in local.dns_zones :
|
||||
zone_key => merge(
|
||||
{
|
||||
for child_key in zone_config.delegations :
|
||||
"NS ${module.dns-zones[child_key].domain}" => {
|
||||
records = module.dns-zones[child_key].name_servers
|
||||
}
|
||||
},
|
||||
{
|
||||
for child_key in zone_config.delegations :
|
||||
"DS ${module.dns-zones[child_key].domain}" => {
|
||||
records = [module.dns-zones[child_key].dns_keys.key_signing_keys[0].ds_record]
|
||||
}
|
||||
if try(local.dns_zones[child_key].zone_config.public.dnssec_config.state, "off") == "on"
|
||||
}
|
||||
)
|
||||
if length(try(zone_config.delegations, [])) > 0
|
||||
}
|
||||
|
||||
# DNS response policies
|
||||
_dns_response_policies_files = try(
|
||||
fileset(local.paths.dns_response_policies, "**/*.yaml"), []
|
||||
@@ -115,6 +139,19 @@ module "dns-zones" {
|
||||
depends_on = [module.vpc-factory]
|
||||
}
|
||||
|
||||
module "dns-delegations" {
|
||||
source = "../../../modules/dns"
|
||||
for_each = local.dns_delegation_recordsets
|
||||
project_id = local.dns_zones[each.key].project_id
|
||||
name = replace(each.key, "/", "-")
|
||||
recordsets = each.value
|
||||
context = {
|
||||
project_ids = local.ctx_projects.project_ids
|
||||
networks = local.ctx_vpcs.self_links
|
||||
}
|
||||
depends_on = [module.dns-zones]
|
||||
}
|
||||
|
||||
module "dns-response-policies" {
|
||||
source = "../../../modules/dns-response-policy"
|
||||
for_each = local.dns_response_policies
|
||||
|
||||
@@ -38,6 +38,13 @@
|
||||
},
|
||||
"public": {
|
||||
"$ref": "#/$defs/public_zone"
|
||||
},
|
||||
"delegations": {
|
||||
"type": "array",
|
||||
"description": "List of child zone keys (e.g. 'net-dev-0/pvt-dev-zone') whose NS and DS records are auto-created in this parent zone.",
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
|
||||
@@ -16,6 +16,8 @@
|
||||
- **peering**: *reference([peering_zone](#refs-peering_zone))*
|
||||
- **forwarding**: *reference([forwarding_zone](#refs-forwarding_zone))*
|
||||
- **public**: *reference([public_zone](#refs-public_zone))*
|
||||
- **delegations**: *array*
|
||||
- items: *string*
|
||||
|
||||
## Definitions
|
||||
|
||||
|
||||
Reference in New Issue
Block a user