When your estate has ten VNets, peering and NSGs are manageable by hand. At a hundred VNets across dozens of subscriptions, they are not: peerings drift, someone’s NSG allows what the security team explicitly banned, and onboarding a new spoke is a ticket driven ceremony. Azure Virtual Network Manager (AVNM) is the control plane that makes network topology and baseline security declarative across the whole tenant.
Network Groups: Membership as Policy
Everything in AVNM operates on network groups. Membership is either static (explicitly added VNets) or dynamic via Azure Policy conditions: every VNet with tag environment equals production, or every VNet under the corp management group, joins automatically. Dynamic membership is the scaling trick, because a new spoke created by your subscription vending pipeline lands in the right groups, and therefore inherits the right topology and security, with zero AVNM changes.
resource "azurerm_network_manager" "this" {
name = "avnm-contoso"
location = "westeurope"
resource_group_name = azurerm_resource_group.net.name
scope_accesses = ["Connectivity", "SecurityAdmin"]
scope {
management_group_ids = [azurerm_management_group.root.id]
}
}
resource "azurerm_network_manager_network_group" "prod_spokes" {
name = "ng-prod-spokes"
network_manager_id = azurerm_network_manager.this.id
}
resource "azurerm_policy_definition" "prod_spoke_membership" {
name = "avnm-prod-spokes"
policy_type = "Custom"
mode = "Microsoft.Network.Data"
display_name = "Prod spokes join AVNM group"
policy_rule = jsonencode({
if = {
allOf = [
{ field = "type", equals = "Microsoft.Network/virtualNetworks" },
{ field = "tags['environment']", equals = "production" }
]
}
then = {
effect = "addToNetworkGroup"
details = {
networkGroupId = azurerm_network_manager_network_group.prod_spokes.id
}
}
})
}
Connectivity Configurations
A connectivity configuration applied to a group builds topology automatically. Hub and spoke mode creates and maintains the peerings from every group member to your hub, including for VNets that join the group next month. Mesh mode connects members directly to each other, useful for a set of closely cooperating VNets where hairpinning through a hub adds nothing. The hub and spoke config can also enable direct connectivity between spokes within the group, giving you a hybrid: hub for shared services and inspection, direct spoke to spoke for the flows you deliberately exempt. If you run classic hub and spoke today, AVNM simply becomes the machine that maintains it; if you run Virtual WAN, AVNM’s connectivity side is redundant but its security side still applies.
Security Admin Rules: Above the NSG
This is the feature that changes governance. Security admin rules evaluate before NSGs, and an Always Allow or Deny outcome cannot be overridden by anything a workload team writes. The security organization finally gets a layer that is theirs: deny high risk management ports from the internet across every production VNet, always allow the monitoring and update infrastructure so a team cannot break their own patching with an overzealous NSG, and leave everything else to workload NSGs as before.
resource "azurerm_network_manager_security_admin_configuration" "baseline" {
name = "sac-baseline"
network_manager_id = azurerm_network_manager.this.id
}
resource "azurerm_network_manager_admin_rule_collection" "prod" {
name = "arc-prod"
security_admin_configuration_id = azurerm_network_manager_security_admin_configuration.baseline.id
network_group_ids = [azurerm_network_manager_network_group.prod_spokes.id]
}
resource "azurerm_network_manager_admin_rule" "deny_rdp_ssh" {
name = "deny-mgmt-from-internet"
admin_rule_collection_id = azurerm_network_manager_admin_rule_collection.prod.id
action = "Deny"
direction = "Inbound"
priority = 100
protocol = "Tcp"
source_port_ranges = ["0-65535"]
destination_port_ranges = ["22", "3389"]
source {
address_prefix_type = "ServiceTag"
address_prefix = "Internet"
}
destination {
address_prefix_type = "IPPrefix"
address_prefix = "*"
}
}
Nothing in AVNM takes effect until you deploy a configuration to regions, which is a deliberate commit step, keep it in your pipeline like everything else. Start with connectivity in a lab group, then security admin rules in audit adjacent mode (deploy to a test group first), and roll outward. The end state is the one this whole series aims at: a new subscription gets its network, its peering, and its security floor by existing, not by ticket.
Cheers
Osama
Leave a comment