How to deploy Azure Network Manager with Azure Bicep

omiossec

Olivier Miossec

Posted on January 4, 2022

How to deploy Azure Network Manager with Azure Bicep

Using Azure at a large scale for IaaS solutions like VMs or Machine Scale Set or Kubernetes means using Virtual Networks, a lot of VNETS. But you need to ensure the consistency of all these networks. You will need to add a connection to the central network for new subscriptions and add security layers.

You can use several solutions for that. You can write a PowerShell script to automate the process or an ARM template to deploy the required resources. But one of the problems is, when the infrastructure scale, updating all the network stack across subscriptions can be very painful.

During the MS Ignite 2021, in November, Microsoft announced the public preview of Azure the Virtual Network Manager resource. this new network tool allows you to automate connectivity and security configuration across several VNETs.

As Virtual Network manager is still in preview, to start using it, you will need to register it in your subscriptions.

Register-AzProviderFeature -FeatureName AllowAzureNetworkManager -ProviderNamespace Microsoft.Network
Enter fullscreen mode Exit fullscreen mode

You may need to wait a few minutes for the full registration of the feature.
You will also need to update your Azure PowerShell module to use the new cmdlets that come with Virtual Network manager.

Install-Module -Name Az.Network -AllowPrerelease -Force
Enter fullscreen mode Exit fullscreen mode

Azure Virtual Network Manager allows you to create network topologies and global security rules (similar to NSG) and deploy them to a group of VNETs across your subscriptions.

In a network manager object, you will have configurations:

  • Connectivity configuration, the HUB and Spoke model (you will need to provide a HUB VNET with network gateway), or the Mesh model (where every VNETs are inter-connected each other)
  • Security admin configuration, where you define a collection of security rules to be applied to VNETs

These configurations are constructed on networks groups, where you define a group of VNETs, by selecting them one by one or dynamically using their name, a tag, subscriptions, or resource groups.

And finally, you have a deployment object, where you apply configuration against network groups.

How can we apply configuration as code to deploy and manage using infrastructure as code?

In a single Azure Network Manager, there are several sub-objects; configurations, and networks groups. They are not independent. You need a network group to create a configuration. The last object, deployment object configuration, and network groups together.

So, we can manage with bicep:

  • The Network manager resource, name, and location
  • Connectivity Configurations, name, type, hub VNET,
  • Security configurations, name, and rules collection
  • Network groups

The deployment process can’t be managed by Bicep yet.

How can we do it?
First we need to create the network manager object

resource netMgr01 'Microsoft.Network/networkManagers@2021-02-01-preview' = {
  name: '02mgr'
  location: resourceGroup().location
  properties: {
    description: 'test azure network manager'
    displayName: 'test netmanager'
    networkManagerScopeAccesses: [
      'Connectivity'
      'SecurityAdmin'
    ]
    networkManagerScopes: {
      managementGroups: [
        '/providers/Microsoft.Management/managementGroups/group01'
      ]
      subscriptions: []
    }
  }
}

Enter fullscreen mode Exit fullscreen mode

You need to select a scope, at this time you cannot have several network managers of the same scope (or overlapping scope). Also, the network manager object can not be modified after its creation by Azure Bicep or ARM template.

Before creating any configuration we need to create a network group. A network group is mandatory to create a configuration object. A network group can have a static membership, you manually add VNETs or dynamic membership where you select VNETs by several parameters.
Let’s try to build a static group.
By default we can use this code to create a group

resource netMgrGrp 'Microsoft.Network/networkManagers/networkGroups@2021-02-01-preview' = {
  name: '<Network Manager Name>/<Network Group Name>'
  properties: {
    description: groupDescription
    displayName: displayName       
    groupMembers: [
      {
        resourceId: 'VNET Resource ID'
      }
    ]
    memberType: 'static'
  }
}
Enter fullscreen mode Exit fullscreen mode

To indicate the name of the Azure Network Manager, you can use the notation
Parent resource name/Resource Name. But if the network manager resource is present in the same bicep file you can use the parent property:
parent: parentSymbolicName

With Azure Bicep, you can add, update and remove VNET by using a parameter for groupMembers. It’s an array of resource ID.

param listofVnet array

var displayName = 'Hub and spoke group'
var groupDescription = 'Group for Hub and spoke'

resource symbolicname 'Microsoft.Network/networkManagers/networkGroups@2021-02-01-preview' = {
  name: '02mgr/hubspoke-grp'
  properties: {
    description: groupDescription
    displayName: displayName
    groupMembers: listofVnet
    memberType: 'static'
  }
}
Enter fullscreen mode Exit fullscreen mode

To deploy:

$groupparam = @( 
    @{
        "resourceId" = "resourceID"
    }
)

New-AzResourceGroupDeployment -ResourceGroupName "01-netmgr" -TemplateFile ./groups.bicep -listofVnet $groupparam
Enter fullscreen mode Exit fullscreen mode

To manage dynamically group membership, we can add several VNETs in $groupParam PowerShell variable.

$groupparam = @( 
    @{
        "resourceId" = "ID vnet 1"
    }
    @{
        "resourceId" = "ID vnet 2"
    }
    @{
        "resourceId" = "ID vnet 3"
    }
)
Enter fullscreen mode Exit fullscreen mode

To deploy the bicep template, you will need to use the new-AzResourceGroupDeployment PowerShell cmdlet with the groupparam variable.

New-AzResourceGroupDeployment -ResourceGroupName "01-netmgr" -TemplateFile ./groups.bicep -listofVnet $groupparam
Enter fullscreen mode Exit fullscreen mode

To remove one VNET, simply remove its ResourceID from the variable

$groupparam = @( 
    @{
        "resourceId" = "ID vnet 1"
    }
    @{
        "resourceId" = "ID vnet 3"
    }
)
Enter fullscreen mode Exit fullscreen mode

And re-run

New-AzResourceGroupDeployment -ResourceGroupName "01-netmgr" -TemplateFile ./groups.bicep -listofVnet $groupparam
Enter fullscreen mode Exit fullscreen mode

The group will be updated according to the $groupparam parameter.

With this network group, It’s now possible to create a network configuration. The Network Manager configuration will need the group ID.
To form the network group ID
/subscriptions/<SsubscriptioinID>/resourceGroups/<ResourceGroupName>/providers/microsoft.network/networkManagers/<NetworkManagerName>/networkGroups/<NetworkGroupName>

The simplest one is a Mesh configuration, where all VNETs are connected to each other by peering. In this configuration, you just need to give, at least, one network group ID, like this.

param networkGroupId  string 

resource hubAndSpoke 'Microsoft.Network/networkManagers/connectivityConfigurations@2021-02-01-preview' = {
  name: '02mgr/meshconfig'

  properties: {
    appliesToGroups: [
      {
        isGlobal: 'True'
        groupConnectivity: 'DirectlyConnected'
        useHubGateway: 'False'
        networkGroupId: networkGroupId
      }
    ]
    deleteExistingPeering: 'True'
    description: 'default Mesh configuratioon'
    displayName: 'Default Mesh'
    connectivityTopology: 'Mesh'
    isGlobal: 'False'
  }
}
Enter fullscreen mode Exit fullscreen mode

Now that we have both our network group and our network configuration, we can deploy it. For that, we need to use the latest version of the Azure PowerShell module, and the Deploy-AzNetworkManagerCommit cmdlet.

You will need to import the pre-release version of the Az.Network module.

Install-Module -Name Az.Network -RequiredVersion 4.12.1-preview -AllowPrerelease
And then import it to your PowerShell session.
Import-Module -Name Az.Network -RequiredVersion '4.12.1'
Enter fullscreen mode Exit fullscreen mode

To start a deployment you will need to provide target regions and the target configurationID. Via the -TargetLocation and the -ConfigurationID parameters. These parameters only accept System.Collections.Generic.List.

For regions, we can use regions name like NorthEurope or WestUs like this

[System.Collections.Generic.List[string]]$TargetRegions = @()   
$TargetRegions.Add("NorthEurope")   
$TargetRegions.Add("WestEurope")
Enter fullscreen mode Exit fullscreen mode

For configuration, we need the ID from our last connectivity configuration. Like the network group ID the configuration ID is formed like this

$connectivityConfigurationId =/subscriptions/<SsubscriptioinID>/resourceGroups/<ResourceGroupName>/providers/microsoft.network/networkManagers/<NetworkManagerName>/connectivityConfigurations/<ConfigurationName>”

[System.Collections.Generic.List[string]]$ConfigCollection = @()  
$ConfigCollection.add($connectivityConfigurationId)
Enter fullscreen mode Exit fullscreen mode

To deploy the configuration

Deploy-AzNetworkManagerCommit -Name <NameOfTheNetworkMqnqger> -ResourceGroupName <ResouurceGroupName> -TargetLocation $TargetRegions -ConfigurationId $ ConfigCollection -CommitType 'Connectivity'
Enter fullscreen mode Exit fullscreen mode

Connectivity configuration is not the only thing you can do with Azure Network manager. You can also centralize network security rules. These rules will have a higher priority than the NSG rules associated with a subnet. It can be useful to enforce security like blocking RDP or SSH access from the Internet even if someone changes the local NSG rules.

Creating a security configuration start with a security admin configuration:

  resource ssecuconfig 'Microsoft.Network/networkManagers/securityAdminConfigurations@2021-02-01-preview' = {
    name: '02mgr/hubspoke-ssecu'

    properties: {
      deleteExistingNSGs: 'True'
      description: 'secuity config for hub'
      displayName: 'hub-security'
      securityType: 'AdminPolicy'
    }
  }
Enter fullscreen mode Exit fullscreen mode

You will need a name, a display name, and a description. The security type can be AdminPolicy or UserPolicy, deleteExistingNSGs let you flag to delete NSG if you want to replace them with security rules.
Security configuration has the network manager object as a parent, so you will need to use the form parentresourceName/SubResourceName

We can now build a collection rule. A collection rule is a container of security rules associated with et network group.

  resource symbolicname 'Microsoft.Network/networkManagers/securityAdminConfigurations/ruleCollections@2021-02-01-preview' = {
    name: '02mgr/hubspoke-ssecu/rulecollection01'
    properties: {
      appliesToGroups: [
        {
          networkGroupId: networkGroupId
        }
      ]
      description: 'rules collectiion 01'
      displayName: 'rules collection 01'
    }
  }
Enter fullscreen mode Exit fullscreen mode

To indicate to Azure Bicep, the parent resource, you will need to use the form Network Manager Name/Security Configuration name/Rule Collection Name

We can now add a rule to the rule collection object.

Security rules are similar to NSG rules and use the same semantic.
Note that you will need to use Name/Security Configuration name/Rule Collection Name/rule name to link the rule to the network manager.

We need to deploy the security configuration. The deployment process is the same as in the connectivity configuration deployment.
The first operation is to create a generic list of the target azure location.

[System.Collections.Generic.List[string]]$TargetRegions = @()   
$TargetRegions.Add("NorthEurope")   
$TargetRegions.Add("WestEurope") 
Enter fullscreen mode Exit fullscreen mode

Then a generic list for the list of security configurations we want to deploy

$securityConfigurationId = '/subscriptions/<SubscriptiionID>/resourceGroups/<ResourceGroupName>/providers/microsoft.network/networkManagers/02mgr/securityAdminConfigurations/hubspoke-ssecu'
[System.Collections.Generic.List[string]]$ConfigCollection = @()  
$ConfigCollection.add($securityConfigurationId)
Enter fullscreen mode Exit fullscreen mode

Then we can deploy our security configuration with the Deploy-AzNetworkManagerCommit cmdlet

Deploy-AzNetworkManagerCommit -Name 02mgr -ResourceGroupName "01-netmgr" -TargetLocation $TargetRegions -ConfigurationId $ConfigCollection -CommitType 'SecurityAdmin'
Enter fullscreen mode Exit fullscreen mode
💖 💪 🙅 🚩
omiossec
Olivier Miossec

Posted on January 4, 2022

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related