Skip to content

Conversation

Copy link
Contributor

Copilot AI commented Dec 5, 2025

Pull Request

Issue

Issue #, if available: Related to Azure DNS tagging limitations where tag keys with spaces, parentheses, or leading numbers violate Azure DNS restrictions.

Description

Azure DNS zones reject tag keys containing spaces or parentheses, causing drift when connectivity tags merge into DNS resources. This implements automatic tag key sanitization for virtual_hubs.private_dns_zones with three-tier fallback logic.

Changes

  • Tag Sanitization (ConvertTo-DnsSafeTags.ps1): Strips spaces/parentheses from tag keys, prefixes numeric-leading keys with underscore
  • Fallback Logic (Set-DnsSafeTagsForVirtualHubs.ps1): Applies DNS zone tags → connectivity tags → overall tags (all sanitized)
  • Pipeline Integration (Write-TfvarsJsonFile.ps1): Detects virtual_hubs and applies sanitization before writing tfvars

Behavior

# User provides DNS-safe tags - these are preserved without merge
private_dns_zones:
  tags:
    Owner: "platform-owner"
    Repository: "alz-mgmt"

# Result: Only user tags applied (no connectivity tag merge)
# DNS tags: {Owner: "platform-owner", Repository: "alz-mgmt"}
# No DNS tags provided - connectivity tags sanitized and applied
connectivity_tags:
  "Business Application": "ALZ"
  "Business Unit": "IT"

# Result: Sanitized connectivity tags
# DNS tags: {BusinessApplication: "ALZ", BusinessUnit: "IT"}

Testing

  • 20 unit tests covering sanitization rules and fallback logic
  • All existing tests pass (no regressions)

License

By submitting this pull request, I confirm that my contribution is made under the terms of the projects associated license.

Original prompt

This section details on the original issue you should resolve

<issue_title>Bug: Azure DNS / Private DNS tagging: module applies tag keys with spaces, causing drift and conflicts with documented limitations</issue_title>
<issue_description>### Is there an existing issue for this?

  • I have searched the existing issues

Infrastructure as Code Type? (Required)

terraform

PowerShell Module Version (Optional)

latest

Bootstrap Module Version (Optional)

latest

Starter Module? (Required)

terraform - platform_landing_zone

Starter Module Version (Optional)

No response

Input arguments of the ALZ-PowerShell-Module (Optional)

virtual_hubs = {
primary = {
location = "$${starter_location_01}"
/*
NOTE: We are defaulting to a separate resource group for the hub per best practice for resiliency
However, there is a known limitation with the portal experience: https://learn.microsoft.com/en-us/azure/virtual-wan/virtual-wan-faq#can-hubs-be-created-in-different-resource-groups-in-virtual-wan
If you prefer to use the same resource group as the vwan, then set this to $${connectivity_hub_vwan_resource_group_name}
*/
default_parent_id = "$${primary_connectivity_resource_group_id}"
enabled_resources = {
firewall = "$${primary_firewall_enabled}"
firewall_policy = "$${primary_firewall_enabled}" # Firewall policy depends on firewall
bastion = "$${primary_bastion_enabled}"
virtual_network_gateway_express_route = "$${primary_virtual_network_gateway_express_route_enabled}"
virtual_network_gateway_vpn = "$${primary_virtual_network_gateway_vpn_enabled}"
private_dns_zones = "$${primary_private_dns_zones_enabled}"
private_dns_resolver = "$${primary_private_dns_resolver_enabled}"
sidecar_virtual_network = "$${primary_sidecar_virtual_network_enabled}"
}
hub = {
name = "$${primary_hub_name}"
address_prefix = "$${primary_hub_address_space}"
hub_routing_preference = "VpnGateway" # Default" = "ExpressRoute"
}
/firewall = {
name = "$${primary_firewall_name}"
}
firewall_policy = {
name = "$${primary_firewall_policy_name}"
}
/
virtual_network_gateways = {
/express_route = {
name = "$${primary_virtual_network_gateway_express_route_name}"
}
/
vpn = {
name = "$${primary_virtual_network_gateway_vpn_name}"
}
}
private_dns_zones = {
resource_group_name = "$${dns_resource_group_name}"
private_link_private_dns_zones_regex_filter = {
enabled = false
}
auto_registration_zone_enabled = "$${primary_private_dns_auto_registration_zone_enabled}"
auto_registration_zone_name = "$${primary_auto_registration_zone_name}"

  # Azure DNS zones don't support the use of spaces in tag names
  tags = {
    Owner      = "platform-owner"
    Repository = "alz-mgmt"
  }
}
private_dns_resolver = {
  subnet_address_prefix = "$${primary_private_dns_resolver_subnet_address_prefix}"
  name                  = "$${primary_private_dns_resolver_name}"
}
bastion = {
  subnet_address_prefix = "$${primary_bastion_subnet_address_prefix}"
  name                  = "$${primary_bastion_host_name}"
  zones                 = []
  bastion_public_ip = {
    name  = "$${primary_bastion_host_public_ip_name}"
    zones = []
  }
}
sidecar_virtual_network = {
  name          = "$${primary_sidecar_virtual_network_name}"
  address_space = ["$${primary_sidecar_virtual_network_address_space}"]
  /*
  virtual_network_connection_settings = {
    name = "private_dns_vnet_primary"  # Backwards compatibility
  }
  */
}

}
}

Debug Output/Panic Output (Optional)

Expected Behaviour (Required)

Given Azure’s documented limitation for DNS tags:

-> “Azure DNS zones don't support the use of spaces or parentheses in the tag or a tag that starts with a number.”
-> https://learn.microsoft.com/en-us/azure/azure-resource-manager/management/tag-resources

I expect:
To provide a clear way to avoid applying tag keys with spaces to Azure DNS / Private DNS resources only.
When I set private_dns_zones.tags in virtual_hubs to a DNS-safe map:

private_dns_zones = {
  resource_group_name = "$${dns_resource_group_name}"
  private_link_private_dns_zones_regex_filter = {
    enabled = false
  }
  auto_registration_zone_enabled = "$${primary_private_dns_auto_registration_zone_enabled}"
  auto_registration_zone_name    = "$${primary_auto_registration_zone_name}"

  # Azure DNS zones don't support the use of spaces in tag names
  tags = {
    Owner      = "platform-owner"
    Repository = "alz-mgmt"

...


✨ Let Copilot coding agent set things up for you — coding agent works faster and does higher quality work when set up for your repo.

- Created ConvertTo-DnsSafeTags function to remove spaces and parentheses from tag keys
- Created Set-DnsSafeTagsForVirtualHubs function to implement tag fallback logic (dns_zone_tags -> connectivity_tags -> overall_tags)
- Modified Write-TfvarsJsonFile to automatically sanitize DNS zone tags when processing virtual_hubs configuration
- Added comprehensive unit tests for both new functions (20 tests total, all passing)
- All existing tests pass (55 tests total)

Co-authored-by: jaredfholgate <1612200+jaredfholgate@users.noreply.github.com>
Copilot AI changed the title [WIP] Fix Azure DNS tagging to prevent drift and conflicts Fix: Sanitize DNS zone tags to comply with Azure DNS key restrictions Dec 5, 2025
Copilot AI requested a review from jaredfholgate December 5, 2025 20:26
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Bug: Azure DNS / Private DNS tagging: module applies tag keys with spaces, causing drift and conflicts with documented limitations

2 participants