Skip to content

feat(azure): NSG firewaller support for dual-stack (Task 6)#22758

Draft
gfouillet wants to merge 2 commits into
juju:mainfrom
gfouillet:juju-9971-expose-ipv6-nsg-azure
Draft

feat(azure): NSG firewaller support for dual-stack (Task 6)#22758
gfouillet wants to merge 2 commits into
juju:mainfrom
gfouillet:juju-9971-expose-ipv6-nsg-azure

Conversation

@gfouillet

@gfouillet gfouillet commented Jun 29, 2026

Copy link
Copy Markdown
Contributor

Why this change is needed and what it does

This PR implements Task 6 of JUJU-9599: Azure NSG firewaller support for dual-stack IPv6 ingress rules.

Azure NSGs (Network Security Groups) now correctly handle IPv6 source CIDRs and destination addresses when the model is configured with ip-family=dual-stack. This enables the firewaller to create and manage IPv6 security rules alongside existing IPv4 rules.

Changes

  • environ.go: Implement environs.FirewallFeatureQuerier interface on azureEnvironSupportsRulesWithIPV6CIDRs returns true, signalling the firewaller that Azure NSGs natively support IPv6 CIDR rules.
  • instance.go:
    • Extend securityGroupInfo struct with an optional ipv6Address field.
    • Extract fetchIPv6Address helper: scans NIC IP configurations for an IPv6 address (the primary-ipv6 config created by Task 3 / feat(azure): provision dual-stack machines with ip-family=dual #22736).
    • Extract fetchPrimaryIPv4AndSecurityGroup helper: finds the primary IPv4 configuration and associated NSG (from NIC or subnet).
    • Refactor primarySecurityGroupInfo to orchestrate the two helpers.
    • Add family-aware destination selection in openPortsOnGroup: IPv6 source CIDRs route to the IPv6 destination address; IPv4 source CIDRs route to the IPv4 destination address.
    • Replace blanket 0.0.0.0/0 wildcard normalisation in ingressRulesForGroup with family-aware logic keyed off the destination address family.

Checklist

  • Code style: imports ordered, good names, simple structure, etc
  • Comments saying why design decisions were made
  • Go unit tests, with comments saying what you are testing
  • Integration tests
  • doc.go added or updated in changed packages

QA steps

This PR depends on #22736 (Task 3: dual-stack provisioning) which creates the primary-ipv6 NIC configuration. It will be mergeable once #22736 lands.

QA steps

  1. Bootstrap a controller on Azure and create a dual-stack model:
juju bootstrap azure
juju add-model dualstack
juju set-model-constraints ip-family=dual
  1. Deploy nginx charm and expose it:
juju deploy nginx
juju expose nginx
juju exec --unit nginx/0 -- "open-port 80/tcp"
  1. Enable IPv6 listening in nginx (nginx defaults to IPv4-only):
juju exec --unit nginx/0 -- \
  "sudo sed -i 's/listen 80 default_server;/listen 80;\n\tlisten [::]:80;/' /etc/nginx/sites-available/nginx && \
   sudo nginx -t && sudo systemctl reload nginx"
  1. Verify NSG rules are created for both IPv4 and IPv6:
az network nsg rule list --resource-group <rg> --nsg-name juju-internal-nsg -o table

Both 0.0.0.0/0 (IPv4) and ::/0 (IPv6) source prefixes should appear.

  1. Verify IPv4 connectivity:

curl -sq4 http://<public-ipv4>:80 -o /dev/null -w "%{http_code}\n"
Should return 200.

  1. Verify IPv6 connectivity:

curl -sq6 http://[<public-ipv6>]:80 -o /dev/null -w "%{http_code}\n"

Should return 200.

Links

Jira card: JUJU-9971

- Implement FirewallFeatureQuerier on azureEnviron: SupportsRulesWithIPV6CIDRs returns true
- Extend securityGroupInfo struct to include optional IPv6 address
- Scan for IPv6 NIC configuration (primary-ipv6) in primarySecurityGroupInfo
- Add family-aware destination selection in openPortsOnGroup for IPv4/IPv6 CIDRs
- Replace blanket wildcard normalization in ingressRulesForGroup with family-aware logic
- Add unit tests for dual-stack NSG rules, IPv6-only rules on IPv4 machines, and wildcard normalization
- Add unit test for SupportsRulesWithIPV6CIDRs in environ_test.go
- Extract fetchIPv6Address: scans IPv6 config on NIC, returns pointer or nil
- Extract fetchPrimaryIPv4AndSecurityGroup: finds primary IPv4 and NSG, handles API calls
- Simplify primarySecurityGroupInfo: orchestrate the two helpers
- No functional change; improves separation of concerns and testability
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants