Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
127 changes: 127 additions & 0 deletions avnm/avnm.bicep
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
import {
// Base Landing Zone User Defined Types
tagsType
} from './configuration/shared/lz.type.bicep'

targetScope = 'resourceGroup'

metadata name = 'Azure Virtual Network Manager with IPAM'
metadata description = 'Azure Virtual Network Manager with IPAM Module.'
metadata version = '1.0.0'
metadata author = 'Insight APAC Platform Engineering'

@description('Optional. Location for the resources.')
param location string = resourceGroup().location

@description('Optional. Tags of the resource.')
param tags tagsType?

@description('Required. Configuration for the Azure Virtual Network Manager.')
param avnmConfiguration avnmType

@description('Required. List of regions for the Ipam Pool.')
param regions ipamRegionType

@description('Required. Set to true to deploy IPAM resources, false to only generate outputs.')
param deploy bool

@description('Resource. Azure Virtual Network Manager.')
module networkManagers 'br/public:avm/res/network/network-manager:0.5.3' = if (deploy) {
params: {
location: location
name: avnmConfiguration.name
networkManagerScopes: {
managementGroups: avnmConfiguration.?managementGroupScopes
subscriptions: avnmConfiguration.?subscriptionScopes
}
tags: tags
}
}

@description('Module: IPAM')
module ipam './ipam.bicep' = if (deploy) {
params: {
avnmConfiguration: avnmConfiguration
avnmName: networkManagers.?outputs.name ?? ''
deploy: deploy
location: location
regions: regions
tags: tags
}
}

// Outputs
@description('The resource ID of the network manager.')
output avnmNameResourceId string = networkManagers.?outputs.resourceId ?? ''

@description('The name of the network manager.')
output avnmName string = networkManagers.?outputs.name ?? ''

// User Defined Types
import { networkGroupType, securityAdminConfigurationType } from 'br/public:avm/res/network/network-manager:0.5.3'
type avnmType = {
@minLength(1)
@maxLength(64)
@description('Required. Name of the Network Manager.')
name: string

@description('Optional. Subscription scopes for the Network Manager.')
subscriptionScopes: string[]?

@description('Optional. Management group scopes for the Network Manager.')
managementGroupScopes: string[]?

@description('Optional. Security Admin Configurations requires enabling the "SecurityAdmin" feature on Network Manager. A security admin configuration contains a set of rule collections. Each rule collection contains one or more security admin rules. You then associate the rule collection with the network groups that you want to apply the security admin rules to.')
securityAdminConfigurations: securityAdminConfigurationType[]?

@description('Conditional. Network Groups and static members to create for the network manager. Required if using "connectivityConfigurations" or "securityAdminConfigurations" parameters. A network group is global container that includes a set of virtual network resources from any region. Then, configurations are applied to target the network group, which applies the configuration to all members of the group. The two types are group memberships are static and dynamic memberships. Static membership allows you to explicitly add virtual networks to a group by manually selecting individual virtual networks, and is available as a child module, while dynamic membership is defined through Azure policy. See [How Azure Policy works with Network Groups](https://learn.microsoft.com/en-us/azure/virtual-network-manager/concept-azure-policy-integration) for more details.')
networkGroups: networkGroupType[]?

@description('Required. IPAM Root Settings.')
ipamRootSettings: ipamRootType
}

type ipamRootType = {
@minLength(1)
@maxLength(64)
@description('Required. Name of the root IPAM pool.')
rootIpamPoolName: string

@minLength(9)
@maxLength(18)
@description('Required. CIDR block for the Azure Supernet.')
azureCidr: string

@maxValue(32)
@minValue(8)
@description('Required. CIDR size for the region IPAM pools.')
regionCidrSize: int

@maxValue(32)
@minValue(8)
@description('Required. CIDR split size for the region IPAM pools.')
regionLzCidrSize: int
}

@maxLength(16)
type ipamRegionType = {
@minLength(1)
@maxLength(64)
@description('Required. Name of the Azure region.')
name: string

@minLength(1)
@maxLength(256)
@description('Required. Display name of the Azureregion.')
displayName: string

@maxValue(100)
@minValue(0)
@description('Required. Factor to divide the Azureregion CIDR into platform and application landing zones, in percentage.')
Comment on lines +115 to +120

Copilot AI Jan 26, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is a space missing between "Azure" and "region" in the description. It should be "Azure region" instead of "Azureregion".

Suggested change
@description('Required. Display name of the Azureregion.')
displayName: string
@maxValue(100)
@minValue(0)
@description('Required. Factor to divide the Azureregion CIDR into platform and application landing zones, in percentage.')
@description('Required. Display name of the Azure region.')
displayName: string
@maxValue(100)
@minValue(0)
@description('Required. Factor to divide the Azure region CIDR into platform and application landing zones, in percentage.')

Copilot uses AI. Check for mistakes.
Comment on lines +115 to +120

Copilot AI Jan 26, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is a space missing between "Azure" and "region" in the description. It should be "Azure region" instead of "Azureregion".

Suggested change
@description('Required. Display name of the Azureregion.')
displayName: string
@maxValue(100)
@minValue(0)
@description('Required. Factor to divide the Azureregion CIDR into platform and application landing zones, in percentage.')
@description('Required. Display name of the Azure region.')
displayName: string
@maxValue(100)
@minValue(0)
@description('Required. Factor to divide the Azure region CIDR into platform and application landing zones, in percentage.')

Copilot uses AI. Check for mistakes.
platformAndApplicationSplitFactor: int

@minLength(9)
@maxLength(18)
@description('Required. CIDR block for the Azure region.')
cidr: string
}[]
Binary file added avnm/configuration/.DS_Store
Binary file not shown.
40 changes: 40 additions & 0 deletions avnm/configuration/platform/platformConnectivity-avnm.bicepparam
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
using '../../avnm.bicep'

param deploy = true // Set to false to skip deployment of AVNM resources and get a plan only.
param tags = {
environment: 'conn'
applicationName: 'Azure Virtual Network Manager'
owner: 'Platform Team'
criticality: 'Tier0'
costCenter: '1234'
contactEmail: 'test@outlook.com'
dataClassification: 'Internal'
iac: 'Bicep'
}
param avnmConfiguration = {
name: 'avnm-aue-plat-conn-01'
subscriptionScopes: []
managementGroupScopes: [
'/providers/Microsoft.Management/managementGroups/mg-alz'
]
ipamRootSettings: {
rootIpamPoolName: 'AU-RootPool'
azureCidr: '10.10.0.0/16'
regionCidrSize: 17 // This number needs to be smaller than or equal to the Azure CIDR size. Each region needs to fit within this CIDR.
regionLzCidrSize: 22
}
}
param regions = [
{
displayName: 'Australia East'
name: 'australiaeast'
cidr: cidrSubnet(avnmConfiguration.ipamRootSettings.azureCidr, avnmConfiguration.ipamRootSettings.regionCidrSize, 0)
platformAndApplicationSplitFactor: 5
}
{
displayName: 'Australia Southeast'
name: 'australiasoutheast'
cidr: cidrSubnet(avnmConfiguration.ipamRootSettings.azureCidr, avnmConfiguration.ipamRootSettings.regionCidrSize, 1)
platformAndApplicationSplitFactor: 5
}
]
Loading
Loading