Skip to main content

Working with Bicep CIDR Functions - Part 1

· 4 min read
Hasan Gural

Welcome to the start of our journey with Bicep CIDR functions! This series is something I've been excited to share, offering insights into subnetting and network configurations, especially within the realm of Infrastructure as Code (IaC).

In this part, we're going to cover the basics of Bicep CIDR functions, including how they can be used and in which scenarios they are most applicable. But before we dive into the details, let's begin with a brief introduction to Bicep CIDR functions.

⚡ What are Bicep CIDR Functions?

CIDR (Classless Inter-Domain Routing) functions help set up the range of IP addresses in a network. They're handy for creating subnets and organizing network settings, especially when you're dealing with resources and networks.

image

In the image above, we have a simple representation of what type of functions we can use in Bicep. Let's go through each of them and cover their use cases and examples.

🏷️ parseCidr Function

The parseCIDR function is used to parse a CIDR notation string into its component parts. The function will return an object with the following properties:

  • network (string): The network address.
  • netmask (string): The netmask.
  • broadcast (string): The broadcast address.
  • firstUsable (string): The first usable address in the network.
  • lastUsable (string): The last usable address in the network.
  • cidr (int): The CIDR prefix length.

Here's an example of how to use the parseCIDR function:


var adressSpace = '192.168.8.0/22'

output parseCIDR object = parseCidr(adressSpace)

When you run the above code, you will get the following output:

"outputs": {
"parseCidr": {
"type": "Object",
"value": {
"broadcast": "192.168.11.255",
"cidr": 22,
"firstUsable": "192.168.8.1",
"lastUsable": "192.168.11.254",
"netmask": "255.255.252.0",
"network": "192.168.8.0"
}
}
}

image

Alright, but what we can do with this information? Knowing the network and the broadcast address helps you understand the entire scope of your network.

Same function can be used to calculate IPv6 addresses as well.


var IPv6 = 'fdad:3236:5555::/48'

output parseIPv6 object = parseCidr(IPv6)

"parseIPv6": {
"type": "Object",
"value": {
"cidr": 48,
"firstUsable": "fdad:3236:5555::",
"lastUsable": "fdad:3236:5555:ffff:ffff:ffff:ffff:ffff",
"netmask": "ffff:ffff:ffff::",
"network": "fdad:3236:5555::"
}
}
info

It is a really huge milestone for Bicep to include IP address calculations. It has been a long time coming for Terraform to calculate IP addresses.

🏷️ cidrSubnet Function

In a nutshell, the cidrSubnet function is used to calculate the subnet address for a given network address and prefix length. The function will return a string representing the subnet address.

Function is reqiured to have three parameters:

  • network (string): String containing an IP address range to convert in CIDR notation.
  • newCIDR (int): An integer representing the CIDR to be used to subnet. This value should be equal or larger than the CIDR value in the network parameter.
  • subnetIndex (int): Index of the desired subnet IP address range to return.

Here's an example of how to use the cidrSubnet function:


var addressRange = '192.168.8.0/24'
var newRange = 26
var subnetIndex = 1

output subnetAddress string = cidrSubnet(addressRange, newRange, subnetIndex)

This time, when we run the above code, we will get output as string to represent the subnet address:


"subnetAddress": {
"type": "String",
"value": "192.168.8.64/26"
}

I want to extend the usage of the cidrSubnet function with a real-world example. Let's say we have a requirement to create 8 subnets from a given address range. We can use the cidrSubnet function to calculate the subnet addresses.

The requirements are as follows:

  • We have an address range in CIDR notation.
  • Create X number of subnets from this address range depending on the requirement.
  • Each subnet should have a prefix length defined by the user."


var vNetAddress = '192.168.8.0/24'
var vSubnetCount = 4
var vSubnetRange = 26

//
var subnetNamePrefix = 'subnet-'
var vNetSubnets = [ for i in range(0, vSubnetCount): cidrSubnet(vNetAddress, vSubnetRange, i) ]

resource virtualNetworks 'Microsoft.Network/virtualNetworks@2023-04-01' = {

name : 'myBicepVNet'
location : 'uksouth'
properties: {
addressSpace: {
addressPrefixes: [
vNetAddress
]
}
subnets: [

for (subnet, idx) in vNetSubnets: {
name : '${subnetNamePrefix}${idx}'
properties: {
addressPrefix: subnet
}
}

]
}
}

The above-stated code will create four subnets from the given address range, with each subnet having a prefix length of 26. Additionally, a virtual network named myBicepVNet will be created in the uksouth region of Azure, respecting the address space for the virtual network. Let's cover deployment of virtual network and further functions in the next part of this series