Today I’m working on creating and updating Azure Network Security Group rules from the Az PowerShell module. However I hit a bit of a bump.
I’m trying to do something simple like add 1 rule to an existing NSG that has other rules:
# Find the security group where it matches a variable $nsgs = Get-AzNetworkSecurityGroup -ResourceGroupName $rgname | where-object { $_.Name -like "$nsgsuffix" } # For the selected security group, add a rule, and then apply it $nsgs | add-aznetworksecurityruleconfig -Access Allow -DestinationAddressPrefix $ips -DestinationPortRange 443 ` -Direction Outbound -name allowOut-To3rdParty_443 -Priority 400 ` -SourceAddressPrefix * -SourcePortRange * -Protocol * | Set-AzNetworkSecurityGroup |
This NSG and other rules were previously deployed through TerraForm, and I want to add an “out-of-band” rule that isn’t tracked in the Terraform state.
When I run these commands, I get this error:
Required security rule parameters are missing for security rule with Id: Security rule must specify either DestinationPortRange or DestinationPortRanges.
That’s super strange; when I look at that rule in the Portal, it has ports listed:
So I check my $nsgs variable that was previously populated, looking specifically for the SecurityRules property:
$nsgs.SecurityRules |
What I find is that for any rule that the portal displays having multiple ports, it lists them just fine (see Destination Port Range property below):
Name : test_test.test Id : /subscriptions/1/resourceGroups/rg/providers/Microsoft.Network /networkSecurityGroups/db-nsg/securityRules/test_test.test Etag : W/"3a98e199-3bf6-4308-806c-8d84bc03723e" ProvisioningState : Succeeded Description : Protocol : * SourcePortRange : {*} DestinationPortRange : {123, 456, 789} SourceAddressPrefix : {10.8.1.} DestinationAddressPrefix : {10.8.1.} SourceApplicationSecurityGroups : [] DestinationApplicationSecurityGroups : [] Access : Allow Priority : 109 Direction : Inbound |
But for any rule that only has a SINGLE port shown in the portal, it is blank for that property:
Name : web_.db Id : /subscriptions/1/resourceGroups/rg/providers/Microsoft.Network /networkSecurityGroups/db-nsg/securityRules/web_.db Etag : W/"3a98e199-3bf6-4308-806c-8d84bc03723e" ProvisioningState : Succeeded Description : Protocol : * SourcePortRange : {*} DestinationPortRange : {} SourceAddressPrefix : {10.0.0.1, 10.0.0.2} DestinationAddressPrefix : {10.1.1.100} SourceApplicationSecurityGroups : [] DestinationApplicationSecurityGroups : [] Access : Allow Priority : 107 Direction : Inbound |
My first thought was “how is this possible”?
I think this is because for these single port rules, we’re using the following Terraform syntax:
destination_port_ranges = ["${var.port-https}"] |
Terraform is expecting a list, but we’re only passing a single value. Terraform doesn’t consider this invalid, and it is applied to Azure successfully. However the flaw is revealed when trying to use the “Set-AzNetworkSecurityGroup” cmdlet because that attempts to re-validate ALL rules on the NSG, not just the one that I added or modified.
If I change that Terraform property to destination_port_range (note the singular) then everything appears to work properly when using Az PowerShell afterwards.