NSGs belong to application teams, and that is fine until you need a rule that no team may remove: "block inbound RDP from the internet everywhere" or "always allow the monitoring subnet". Azure Virtual Network Manager (AVNM) security admin rules sit above NSGs and are evaluated first.
How evaluation works
| Admin rule action | What happens |
|---|---|
| Always allow | Traffic is allowed and NSGs are not evaluated |
| Deny | Traffic is dropped; NSGs are not evaluated |
| Allow | Traffic continues to NSG evaluation, which can still deny it |
So: use Deny for things nobody may open, Always allow for platform traffic that must never be blocked, and Allow rarely (mostly to document intent).
Caution
An "Always allow" rule bypasses application NSGs. Keep it tightly scoped to known source ranges and ports, or you create a hole teams cannot see in their own NSG.
Build blocks
- Network manager with a scope (management groups or subscriptions) and the "Security Admin" feature.
- Network groups: static members or dynamic membership through Azure Policy (for example all VNets tagged
env=prod). - Security admin configuration with rule collections that target network groups.
- Deployment of the configuration to chosen regions. Nothing applies until you deploy.
az extension add --name virtual-network-manager
az network manager create -g rg-netmgr -n avnm-corp -l westeurope \
--scope-accesses SecurityAdmin \
--network-manager-scopes management-groups="/providers/Microsoft.Management/managementGroups/mg-corp"
az network manager group create -g rg-netmgr --network-manager-name avnm-corp -n ng-prod \
--description "All production VNets"
Dynamic membership is an Azure Policy definition with the Microsoft.Network.Data mode that targets the network group; create it from the portal the first time and export it as code.
A baseline rule set
az network manager security-admin-config create -g rg-netmgr --network-manager-name avnm-corp \
-n sac-baseline --description "Org baseline"
az network manager security-admin-config rule-collection create -g rg-netmgr \
--network-manager-name avnm-corp --configuration-name sac-baseline -n rc-internet \
--applies-to-groups network-group-id=$(az network manager group show -g rg-netmgr --network-manager-name avnm-corp -n ng-prod --query id -o tsv)
az network manager security-admin-config rule-collection rule create -g rg-netmgr \
--network-manager-name avnm-corp --configuration-name sac-baseline --rule-collection-name rc-internet \
-n deny-inbound-mgmt-internet --kind Custom --protocol Tcp --access Deny --priority 100 \
--direction Inbound --sources address-prefix-type=ServiceTag address-prefix=Internet \
--dest-port-ranges 22 3389 5985 5986
Other rules worth having in a baseline:
| Rule | Action | Why |
|---|---|---|
| Inbound 22/3389 from Internet | Deny | Use Bastion or JIT |
| Inbound SQL/SMB from Internet (1433, 445) | Deny | Common ransomware entry points |
| Monitoring / scanner subnet to all VMs on agent ports | Always allow | Scans and agents keep working even if a team over-tightens NSGs |
| Outbound to known-bad ranges | Deny | Organisation-wide block list |
Flag names on these CLI commands vary between extension versions; check --help and treat the commands above as a template.
Deploy in rings
az network manager post-commit -g rg-netmgr --network-manager-name avnm-corp \
--commit-type SecurityAdmin \
--configuration-ids $(az network manager security-admin-config show -g rg-netmgr --network-manager-name avnm-corp -n sac-baseline --query id -o tsv) \
--target-locations westeurope
- Deploy first to a network group with only test VNets.
- Check traffic with NSG / VNet flow logs and Traffic Analytics for drops you did not expect.
- Add a single non-critical production region, then the rest.
Each commit replaces what is deployed in those regions. Deploying an empty configuration list removes the rules, which is your rollback.
See what applies to a VM
The NIC's effective security rules include admin rules:
az network nic list-effective-nsg -g rg-app -n vm01-nic
az network manager list-effective-security-admin-rule -g rg-app --vnet-name vnet-app
Network Watcher IP flow verify and Connection troubleshoot also show the rule that allowed or denied a flow.
Troubleshooting
| Symptom | Cause | Fix |
|---|---|---|
| Rule has no effect | Configuration created but not committed to that region | post-commit to the region |
| VNet not in group | Dynamic policy not evaluated yet or tag missing | Check policy compliance; trigger a scan |
| Team's NSG allow is ignored | Admin Deny wins | Expected; request an exception through the platform team |
| Traffic allowed despite team NSG deny | Always allow admin rule | Narrow the always-allow source |
Prevent it next time
- Keep AVNM configurations in source control and deploy them through a pipeline with a test ring.
- Publish the admin rule list to application teams so "my NSG is ignored" tickets are rare.
- Review always-allow rules every quarter.