Example code and tests for creating conditional NSG rules using optional parameters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{ | |
"$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json", | |
"contentVersion": "0.0.0.1", | |
"parameters": { | |
"vnetName": { | |
"type": "string" | |
}, | |
"vnetAddressPrefix": { | |
"type": "string" | |
}, | |
"webServerSubnetName": { | |
"type": "string" | |
}, | |
"webServerSubnetAddressPrefix": { | |
"type": "string" | |
}, | |
"webServerNsgName": { | |
"type": "string" | |
}, | |
"testRunnerIpRange": { | |
"type": "string", | |
"defaultValue": "" | |
} | |
}, | |
"resources": [ | |
{ | |
"name": "[parameters('vnetName')]", | |
"type": "Microsoft.Network/virtualNetworks", | |
"apiVersion": "2019-11-01", | |
"location": "[resourceGroup().location]", | |
"dependsOn": [ | |
"[parameters('webServerNsgName')]" | |
], | |
"properties": { | |
"addressSpace": { | |
"addressPrefixes": [ | |
"[parameters('vnetAddressPrefix')]" | |
] | |
}, | |
"subnets": [ | |
{ | |
"name": "[parameters('webServerSubnetName')]", | |
"properties": { | |
"addressPrefix": "[parameters('webServerSubnetAddressPrefix')]", | |
"networkSecurityGroup": { | |
"id": "[resourceId('Microsoft.Network/networkSecurityGroups', parameters('webServerNsgName'))]" | |
} | |
} | |
} | |
] | |
} | |
}, | |
{ | |
"name": "[parameters('webServerNsgName')]", | |
"type": "Microsoft.Network/networkSecurityGroups", | |
"apiVersion": "2019-11-01", | |
"location": "[resourceGroup().location]", | |
"properties": { | |
"securityRules": [ | |
{ | |
"name": "DefaultDeny", | |
"properties": { | |
"description": "Denies all inbound traffic not matched by a previous rule", | |
"protocol": "*", | |
"sourcePortRange": "*", | |
"destinationPortRange": "*", | |
"sourceAddressPrefix": "*", | |
"destinationAddressPrefix": "*", | |
"access": "Deny", | |
"priority": 4096, | |
"direction": "Inbound" | |
} | |
} | |
] | |
} | |
}, | |
{ | |
"name": "[concat(parameters('webServerNsgName'),'/allow8081fromTestSubnet')]", | |
"type": "Microsoft.Network/networkSecurityGroups/securityRules", | |
"location": "[resourceGroup().location]", | |
"dependsOn": [ | |
"[parameters('webServerNsgName')]" | |
], | |
"condition": "[greater(length(parameters('testRunnerIpRange')),0)]", | |
"apiVersion": "2019-11-01", | |
"properties": { | |
"description": "nsgRuleDescription", | |
"protocol": "tcp", | |
"sourcePortRange": "*", | |
"destinationPortRange": "8081", | |
"sourceAddressPrefix": "[parameters('testRunnerIpRange')]", | |
"destinationAddressPrefix": "[parameters('webServerSubnetAddressPrefix')]", | |
"access": "Allow", | |
"priority": 100, | |
"direction": "Inbound" | |
} | |
} | |
] | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
@{ | |
resourceGroupNamePrefix = 'conditionalNsgRulesDemoRg-' | |
resourceGroupLocation = 'UKSouth' | |
vNetConfig = @{ | |
vNetName = 'conditionalNsgRulesDemovNet' | |
addressPrefix = '192.168.0.0/24' | |
} | |
webSubnetConfig = @{ | |
subnetName = 'webServerSubnet' | |
addressPrefix = '192.168.0.0/25' | |
} | |
testSubnetConfig = @{ | |
subnetName = 'testSubnet' | |
addressPrefix = '192.168.0.128/25' | |
} | |
nsgName = 'webServerNsg' | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
$scriptRoot = $PSScriptRoot | |
Describe "NSG Tests" { | |
BeforeAll { | |
$Config = Import-PowerShellDataFile -Path $scriptRoot/config.psd1 | |
$someRandomLetters = -join ((65..90) + (97..122) | Get-Random -Count 20 | % {[char]$_}) | |
# source: https://devblogs.microsoft.com/scripting/generate-random-letters-with-powershell/ | |
$resourceGroupName = $Config.resourceGroupNamePrefix + '-' + $someRandomLetters | |
New-AzResourceGroup -Name $resourceGroupName -Location $Config.resourceGroupLocation | |
New-AzVirtualNetwork -Name $Config.vNetConfig.vNetName -ResourceGroupName $resourceGroupName -Location $Config.resourceGroupLocation -AddressPrefix $Config.vNetConfig.addressPrefix | |
$defaultTemplateParams = @{ | |
vnetName = $Config.vNetConfig.vNetName | |
vnetAddressPrefix = $Config.vNetConfig.addressPrefix | |
webServerSubnetName = $Config.webSubnetConfig.subnetName | |
webServerSubnetAddressPrefix = $Config.webSubnetConfig.addressPrefix | |
webServerNsgName = $Config.nsgName | |
} | |
$defaultDeploymentParams = @{ | |
ResourceGroupName = $resourceGroupName | |
TemplateFile = "$scriptRoot/azuredeploy.json" | |
Force = $true | |
} | |
$baseCaseAssertions = { | |
$vNet = Get-AzVirtualNetwork -Name $Config.vNetConfig.vNetName -ResourceGroupName $resourceGroupName -ExpandResource 'Subnets/NetworkSecurityGroup' | |
$webServerSubnet = Get-AzVirtualNetworkSubnetConfig -Name $Config.webSubnetConfig.subnetName -VirtualNetwork $vNet | |
$nsg = $webServerSubnet.NetworkSecurityGroup | |
It "Creates a vnet Called $($Config.vNetConfig.vNetName)" { | |
$vNet | Should -Not -BeNullOrEmpty | |
} | |
It "Creates a subnet called $($Config.webSubnetConfig.subnetName)" { | |
$webServerSubnet | Should -Not -BeNullOrEmpty | |
} | |
It "Attaches an NSG called $($Config.nsgName) to the subnet $($Config.webSubnetConfig.subnetName)" { | |
$webServerSubnet.NetworkSecurityGroup.Id.split("/") | select -last 1| Should -Be $Config.nsgName | |
} | |
It "Creates a Default Deny rule with priority 4096" { | |
$nsg.SecurityRules | ?{ $_.Priority -eq 4096 -and $_.Access -eq 'Deny' -and | |
$_.Direction -eq 'Inbound' -and $_.Protocol -eq '*' -and | |
$_.SourceAddressPrefix -eq '*' -and $_.DestinationAddressPrefix -eq '*'} | | |
Should -Not -BeNullOrEmpty | |
} | |
} | |
} | |
Context "Create the NSG without passing a value to the testRunnerIpRange parameter" { | |
$TemplateParams = $defaultTemplateParams | |
$deploymentParams = $defaultDeploymentParams + @{TemplateParameterObject = $TemplateParams; Mode = 'Complete'} | |
New-AzResourceGroupDeployment @deploymentParams | |
$vNet = Get-AzVirtualNetwork -Name $Config.vNetConfig.vNetName -ResourceGroupName $resourceGroupName -ExpandResource 'Subnets/NetworkSecurityGroup' | |
$webServerSubnet = Get-AzVirtualNetworkSubnetConfig -Name $Config.webSubnetConfig.subnetName -VirtualNetwork $vNet | |
$nsg = $webServerSubnet.NetworkSecurityGroup | |
It "Doesn't create an ingress rule for the testRunnerIpRange" { | |
$nsg.SecurityRules | ?{ $_.Access -eq 'Allow' -and | |
$_.Direction -eq 'Inbound' -and | |
$_.SourceAddressPrefix -eq $Config.testSubnetConfig.addressPrefix} | | |
Should -BeNullOrEmpty | |
} | |
Invoke-Command -ScriptBlock $baseCaseAssertions | |
} | |
Context "Create the NSG passing $($Config.testSubnetConfig.addressPrefix) to the testRunnerIpRange parameter" { | |
$TemplateParams = $defaultTemplateParams + @{testRunnerIpRange = $Config.testSubnetConfig.addressPrefix } | |
$deploymentParams = $defaultDeploymentParams + @{TemplateParameterObject = $TemplateParams; Mode = 'Complete'} | |
New-AzResourceGroupDeployment @deploymentParams | |
$vNet = Get-AzVirtualNetwork -Name $Config.vNetConfig.vNetName -ResourceGroupName $resourceGroupName -ExpandResource 'Subnets/NetworkSecurityGroup' | |
$webServerSubnet = Get-AzVirtualNetworkSubnetConfig -Name $Config.webSubnetConfig.subnetName -VirtualNetwork $vNet | |
$nsg = $webServerSubnet.NetworkSecurityGroup | |
It "Creates an ingress rule for the $($Config.testSubnetConfig.addressPrefix) CIDR" { | |
$nsg.SecurityRules | ?{ $_.Access -eq 'Allow' -and | |
$_.Direction -eq 'Inbound' -and | |
$_.DestinationPortRange -eq "8081" -and | |
$_.SourceAddressPrefix -eq $Config.testSubnetConfig.addressPrefix} | | |
Should -Not -BeNullOrEmpty | |
} | |
Invoke-Command -ScriptBlock $baseCaseAssertions | |
} | |
Context "Create the nsg in complete mode with the testRunnerIpRange parameter set then redeploy in Incremental Mode with the testRunnerIPRange parameter removed" { | |
$TemplateParams = $defaultTemplateParams + @{testRunnerIpRange = $Config.testSubnetConfig.addressPrefix } | |
$deploymentParams = $defaultDeploymentParams + @{TemplateParameterObject = $TemplateParams; Mode = 'Complete'} | |
New-AzResourceGroupDeployment @deploymentParams | |
$vNet = Get-AzVirtualNetwork -Name $Config.vNetConfig.vNetName -ResourceGroupName $resourceGroupName -ExpandResource 'Subnets/NetworkSecurityGroup' | |
$webServerSubnet = Get-AzVirtualNetworkSubnetConfig -Name $Config.webSubnetConfig.subnetName -VirtualNetwork $vNet | |
$nsg = $webServerSubnet.NetworkSecurityGroup | |
It "Creates the nsg rule on the initial deployment" { | |
$nsg.SecurityRules | ?{ $_.Access -eq 'Allow' -and | |
$_.Direction -eq 'Inbound' -and | |
$_.DestinationPortRange -eq "8081" -and | |
$_.SourceAddressPrefix -eq $Config.testSubnetConfig.addressPrefix} | | |
Should -Not -BeNullOrEmpty | |
} | |
$TemplateParams = $defaultTemplateParams | |
$deploymentParams = $defaultDeploymentParams + @{TemplateParameterObject = $TemplateParams; Mode = 'Incremental'} | |
New-AzResourceGroupDeployment @deploymentParams | |
$vNet = Get-AzVirtualNetwork -Name $Config.vNetConfig.vNetName -ResourceGroupName $resourceGroupName -ExpandResource 'Subnets/NetworkSecurityGroup' | |
$webServerSubnet = Get-AzVirtualNetworkSubnetConfig -Name $Config.webSubnetConfig.subnetName -VirtualNetwork $vNet | |
$nsg = $webServerSubnet.NetworkSecurityGroup | |
It "Deletes the Security Rule on the subsequent incremental deployment" { | |
$nsg.SecurityRules | ?{ $_.Access -eq 'Allow' -and | |
$_.Direction -eq 'Inbound' -and | |
$_.DestinationPortRange -eq "8081" -and | |
$_.SourceAddressPrefix -eq $Config.testSubnetConfig.addressPrefix} | | |
Should -BeNullOrEmpty | |
} | |
Invoke-Command -ScriptBlock $baseCaseAssertions | |
} | |
Context "Create the nsg in complete mode with the testRunnerIpRange parameter set then redeploy in Complete Mode with the testRunnerIPRange parameter removed" { | |
$TemplateParams = $defaultTemplateParams + @{testRunnerIpRange = $Config.testSubnetConfig.addressPrefix } | |
$deploymentParams = $defaultDeploymentParams + @{TemplateParameterObject = $TemplateParams; Mode = 'Complete'} | |
New-AzResourceGroupDeployment @deploymentParams | |
$vNet = Get-AzVirtualNetwork -Name $Config.vNetConfig.vNetName -ResourceGroupName $resourceGroupName -ExpandResource 'Subnets/NetworkSecurityGroup' | |
$webServerSubnet = Get-AzVirtualNetworkSubnetConfig -Name $Config.webSubnetConfig.subnetName -VirtualNetwork $vNet | |
$nsg = $webServerSubnet.NetworkSecurityGroup | |
It "Creates the nsg rule on the initial deployment" { | |
$nsg.SecurityRules | ?{ $_.Access -eq 'Allow' -and | |
$_.Direction -eq 'Inbound' -and | |
$_.DestinationPortRange -eq "8081" -and | |
$_.SourceAddressPrefix -eq $Config.testSubnetConfig.addressPrefix} | | |
Should -Not -BeNullOrEmpty | |
} | |
$TemplateParams = $defaultTemplateParams | |
$deploymentParams = $defaultDeploymentParams + @{TemplateParameterObject = $TemplateParams; Mode = 'Complete'} | |
New-AzResourceGroupDeployment @deploymentParams | |
$vNet = Get-AzVirtualNetwork -Name $Config.vNetConfig.vNetName -ResourceGroupName $resourceGroupName -ExpandResource 'Subnets/NetworkSecurityGroup' | |
$webServerSubnet = Get-AzVirtualNetworkSubnetConfig -Name $Config.webSubnetConfig.subnetName -VirtualNetwork $vNet | |
$nsg = $webServerSubnet.NetworkSecurityGroup | |
It "Deletes the Security Rule on the subsequent Complete Deployment" { | |
$nsg.SecurityRules | ?{ $_.Access -eq 'Allow' -and | |
$_.Direction -eq 'Inbound' -and | |
$_.DestinationPortRange -eq "8081" -and | |
$_.SourceAddressPrefix -eq $Config.testSubnetConfig.addressPrefix} | | |
Should -BeNullOrEmpty | |
} | |
Invoke-Command -ScriptBlock $baseCaseAssertions | |
} | |
Context "Create the nsg in complete mode with the testRunnerIpRange parameter unset then redeploy in Incremental Mode with the testRunnerIPRange parameter added" { | |
$TemplateParams = $defaultTemplateParams | |
$deploymentParams = $defaultDeploymentParams + @{TemplateParameterObject = $TemplateParams; Mode = 'Complete'} | |
New-AzResourceGroupDeployment @deploymentParams | |
$vNet = Get-AzVirtualNetwork -Name $Config.vNetConfig.vNetName -ResourceGroupName $resourceGroupName -ExpandResource 'Subnets/NetworkSecurityGroup' | |
$webServerSubnet = Get-AzVirtualNetworkSubnetConfig -Name $Config.webSubnetConfig.subnetName -VirtualNetwork $vNet | |
$nsg = $webServerSubnet.NetworkSecurityGroup | |
It "Doesn't create the nsg rule on the initial deployment" { | |
$nsg.SecurityRules | ?{ $_.Access -eq 'Allow' -and | |
$_.Direction -eq 'Inbound' -and | |
$_.DestinationPortRange -eq "8081" -and | |
$_.SourceAddressPrefix -eq $Config.testSubnetConfig.addressPrefix} | | |
Should -BeNullOrEmpty | |
} | |
$TemplateParams = $defaultTemplateParams + @{testRunnerIpRange = $Config.testSubnetConfig.addressPrefix } | |
$deploymentParams = $defaultDeploymentParams + @{TemplateParameterObject = $TemplateParams; Mode = 'Incremental'} | |
New-AzResourceGroupDeployment @deploymentParams | |
$vNet = Get-AzVirtualNetwork -Name $Config.vNetConfig.vNetName -ResourceGroupName $resourceGroupName -ExpandResource 'Subnets/NetworkSecurityGroup' | |
$webServerSubnet = Get-AzVirtualNetworkSubnetConfig -Name $Config.webSubnetConfig.subnetName -VirtualNetwork $vNet | |
$nsg = $webServerSubnet.NetworkSecurityGroup | |
It "Creates the Security Rule on the subsequent incremental deployment" { | |
$nsg.SecurityRules | ?{ $_.Access -eq 'Allow' -and | |
$_.Direction -eq 'Inbound' -and | |
$_.DestinationPortRange -eq "8081" -and | |
$_.SourceAddressPrefix -eq $Config.testSubnetConfig.addressPrefix} | | |
Should -Not -BeNullOrEmpty | |
} | |
Invoke-Command -ScriptBlock $baseCaseAssertions | |
} | |
Context "Create the nsg in complete mode with the testRunnerIpRange parameter unset then redeploy in Complete Mode with the testRunnerIPRange parameter added" { | |
$TemplateParams = $defaultTemplateParams | |
$deploymentParams = $defaultDeploymentParams + @{TemplateParameterObject = $TemplateParams; Mode = 'Complete'} | |
New-AzResourceGroupDeployment @deploymentParams | |
$vNet = Get-AzVirtualNetwork -Name $Config.vNetConfig.vNetName -ResourceGroupName $resourceGroupName -ExpandResource 'Subnets/NetworkSecurityGroup' | |
$webServerSubnet = Get-AzVirtualNetworkSubnetConfig -Name $Config.webSubnetConfig.subnetName -VirtualNetwork $vNet | |
$nsg = $webServerSubnet.NetworkSecurityGroup | |
It "Doesn't create the nsg rule on the initial deployment" { | |
$nsg.SecurityRules | ?{ $_.Access -eq 'Allow' -and | |
$_.Direction -eq 'Inbound' -and | |
$_.DestinationPortRange -eq "8081" -and | |
$_.SourceAddressPrefix -eq $Config.testSubnetConfig.addressPrefix} | | |
Should -BeNullOrEmpty | |
} | |
$TemplateParams = $defaultTemplateParams + @{testRunnerIpRange = $Config.testSubnetConfig.addressPrefix } | |
$deploymentParams = $defaultDeploymentParams + @{TemplateParameterObject = $TemplateParams; Mode = 'Complete'} | |
New-AzResourceGroupDeployment @deploymentParams | |
$vNet = Get-AzVirtualNetwork -Name $Config.vNetConfig.vNetName -ResourceGroupName $resourceGroupName -ExpandResource 'Subnets/NetworkSecurityGroup' | |
$webServerSubnet = Get-AzVirtualNetworkSubnetConfig -Name $Config.webSubnetConfig.subnetName -VirtualNetwork $vNet | |
$nsg = $webServerSubnet.NetworkSecurityGroup | |
It "Creates the Security Rule on the subsequent Complete Deployment" { | |
$nsg.SecurityRules | ?{ $_.Access -eq 'Allow' -and | |
$_.Direction -eq 'Inbound' -and | |
$_.DestinationPortRange -eq "8081" -and | |
$_.SourceAddressPrefix -eq $Config.testSubnetConfig.addressPrefix} | | |
Should -Not -BeNullOrEmpty | |
} | |
Invoke-Command -ScriptBlock $baseCaseAssertions | |
} | |
AfterAll { | |
Remove-AzResourceGroup -Name $resourceGroupName -Verbose -Force | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment