AzVnetTools.psm1
#AzVnetTools.psm1 <# .SYNOPSIS Increments an IP address by a specified amount. .DESCRIPTION This function takes an IP address as a string and increments it by the specified amount. If no increment is specified, it defaults to 1. .PARAMETER IPAddress The IP address to increment. .PARAMETER IncrementBy The number to increment the IP address by. Defaults to 1. .EXAMPLE Increment-IPAddress -IPAddress "192.168.0.1" -IncrementBy 5 Returns: 192.168.0.6 .NOTES This function wraps around to 0.0.0.0 if the increment goes beyond 255.255.255.255. #> function Get-IncrementedIPAddress { param ( [Parameter(Mandatory = $true)] [string]$IPAddress, [Parameter(Mandatory = $false)] [int]$IncrementBy = 1 ) try { # Convert the IP address string to an IPAddress object $ip = [System.Net.IPAddress]::Parse($IPAddress) # Convert the IP address to a 32-bit unsigned integer $arrAddress = $ip.GetAddressBytes() [array]::Reverse($arrAddress) $ipInt = [System.BitConverter]::ToUInt32($arrAddress, 0) # Increment the integer $ipInt += $IncrementBy # Convert back to an IP address and reverse array $newIP = [System.Net.IPAddress]::new($ipInt) $arrAddress = $newIP.GetAddressBytes() [array]::Reverse($arrAddress) $newIP = [System.Net.IPAddress]::new($arrAddress) return $newIP.ToString() } catch { Write-Error "Failed to increment IP address: $_" return $null } } function Get-FlippedAddressBits { [CmdletBinding()] param ( [Parameter(Mandatory=$true)] $IPAddress ) try { # Convert the IP address string to an IPAddress object $ip = [System.Net.IPAddress]::Parse($IPAddress) # Convert the IP address to a 32-bit unsigned integer $arrAddress = $ip.GetAddressBytes() $ipInt = [System.BitConverter]::ToUInt32($arrAddress, 0) return $ipInt } catch { Write-Error "Failed to increment IP address: $_" return $null } } <# .SYNOPSIS Finds the next available subnet in an Azure Virtual Network. .DESCRIPTION This function searches for the next available subnet within a specified Azure Virtual Network that doesn't overlap with existing subnets. .PARAMETER ResourceGroupName The name of the resource group containing the Virtual Network. .PARAMETER VNetName The name of the Virtual Network. .PARAMETER NewSubnetMask The subnet mask for the new subnet (in CIDR notation, e.g., 24 for a /24 subnet). .EXAMPLE Get-AzNextAvailableSubnet -ResourceGroupName "MyRG" -VNetName "MyVNet" -NewSubnetMask 24 Returns: "10.0.1.0/24" (if this is the next available /24 subnet) .NOTES Requires the Az PowerShell module to be installed and connected to an Azure account. #> function Get-AzNextAvailableSubnet { param ( [Parameter(Mandatory=$true)] [string]$ResourceGroupName, [Parameter(Mandatory=$true)] [string]$VNetName, [Parameter(Mandatory=$true)] [int]$NewSubnetMask ) # Get the VNet $vnet = Get-AzVirtualNetwork -ResourceGroupName $ResourceGroupName -Name $VNetName if (-not $vnet) { Write-Error "VNet not found" return $null } # Get existing subnets $existingSubnets = $vnet.Subnets.AddressPrefix # Get the VNet address space $vnetAddressSpace = $vnet.AddressSpace.AddressPrefixes[0] $vnetNetwork = [System.Net.IPAddress]::Parse(($vnetAddressSpace -split "/")[0]) $vnetMask = [System.Convert]::ToInt32(($vnetAddressSpace -split "/")[1]) # Calculate the number of IP addresses in the new subnet $newSubnetSize = [Math]::Pow(2, (32 - $NewSubnetMask)) # Start from the beginning of the VNet range $currentIP = $vnetNetwork.IPAddressToString $maxAddress = Get-IncrementedIPAddress -IPAddress $vnetNetwork.IPAddressToString -IncrementBy ([Math]::Pow(2, (32 - $vnetMask))) $maxBit = [System.Net.IPAddress]::Parse($maxAddress).Address $maxBit = Get-FlippedAddressBits -IPAddress $maxBit while ((Get-FlippedAddressBits -IPAddress ([System.Net.IPAddress]::Parse($currentIP).Address)) -lt $maxBit) { $candidateCIDR = "$currentIP/$NewSubnetMask" # Check if this range overlaps with existing subnets $overlap = $false foreach ($subnet in $existingSubnets) { if (Test-SubnetOverlap -Subnet1 $candidateCIDR -Subnet2 $subnet) { $overlap = $true break } } if (-not $overlap) { return $candidateCIDR } # Move to the next potential subnet $currentIP = Get-IncrementedIPAddress -IPAddress $currentIP -IncrementBy $newSubnetSize } return } <# .SYNOPSIS Tests if two subnets overlap. .DESCRIPTION This function checks if two given subnets (in CIDR notation) overlap with each other. .PARAMETER Subnet1 The first subnet in CIDR notation (e.g., "192.168.1.0/24"). .PARAMETER Subnet2 The second subnet in CIDR notation (e.g., "192.168.2.0/24"). .EXAMPLE Test-SubnetOverlap -Subnet1 "192.168.1.0/24" -Subnet2 "192.168.1.128/25" Returns: $true (because these subnets overlap) .NOTES This function does not validate the correctness of the CIDR notation. #> function Test-SubnetOverlap { param ( [string]$Subnet1, [string]$Subnet2 ) $network1 = [System.Net.IPAddress]::Parse(($Subnet1 -split "/")[0]) $mask1 = [System.Convert]::ToInt32(($Subnet1 -split "/")[1]) $net1start = Get-FlippedAddressBits -IPAddress $network1.Address $net1end = $net1start + ([Math]::Pow(2, (32 - $mask1))) - 1 $network2 = [System.Net.IPAddress]::Parse(($Subnet2 -split "/")[0]) $mask2 = [System.Convert]::ToInt32(($Subnet2 -split "/")[1]) $net2start = Get-FlippedAddressBits -IPAddress $network2.Address $net2end = $net2start + ([Math]::Pow(2, (32 - $mask2))) -1 return (($net1start -le $net2end) -and ($net1end -ge $net2start)) } # Export the public functions Export-ModuleMember -Function Get-IncrementedIPAddress, Get-AzNextAvailableSubnet, Test-SubnetOverlap |