Azure IPAM

How to manage IP address allocation for enterprise-scale landing zones

An Azure landing zone is a subscription for running applications and services in the cloud within a secure, well-governed environment that meets the standards defined in Microsoft’s Cloud Adoption Framework (CAF).  The CAF describes enterprise-scale landing zones that potentially comprise many Azure subscriptions, each providing a secure boundary for running distinct workloads. 

At enterprise scale, provisioning new landing zone subscriptions rapidly is critical and automating the process supports that aim.  Landing zones often include an Azure virtual network (VNet) to support running of the virtual machines that host the application/service being implemented. 

The IP address space assigned to each VNet must not overlap with other peered VNets or external networks connected through Azure gateway services e.g. on-premises datacentres.  This is easily manageable for very small networks but can be problematic when introducing new Azure VNets to a large network. 

An IP Address Management (IPAM) solution is required to track the allocation of IP address spaces as new VNets are created.  This can be a manual operation e.g. spreadsheets or there are third-party products available for purchase.

There is a solution freely available however at

AIPAS stores available IP address ranges in an Azure Storage table.  An Azure function provides REST API commands for adding address ranges to the table and for claiming an address range for use with a new VNet.

AIPAS allows the process of deploying new subscriptions to be more automated.  For example, a PowerShell script can be written to claim a free IP address range from AIPAS and create a new VNet with that range.  The script itself can be part of an Azure DevOps pipeline or GitHub Actions workflow.

A snippet of a DevOps pipeline is shown below which ultimately uses a Bicep template to define the VNet but could easily be a Terraform or ARM template or a Powershell/CLI command.

$uri = '[function app key]'
$body = @{
  'InputObject' = @{
    'ResourceGroup' = $rgName
    'VirtualNetworkName' = $vnetName
} | ConvertTo-Json
$params = @{
      'Uri'         = $uri
      'Method'      = 'POST'
      'ContentType' = 'application/json'
      'Body'        = $Body
$Result = Invoke-RestMethod @params
$networkAddress = $Result.NetworkAddress

Write-Host "Creating VNet $vnetName in resource group $rgName with network address $networkAddress"
New-AzDeployment -Name $cgZoneId$regionName -Location $regionName -TemplateFile ./main.bicep `
      -cgZoneId $cgZoneId `
      -regionName $regionName `
      -addressRange $networkAddress
Else {
    Write-Host "VNet $vnetName already exists in subscription $subName"

About the author