Network Security Groups (NSG) are pretty good. I don’t mind them that much as for what they are, they do a good job. Designing them can be a little tricky, having to know all the nuances of working with them.
When it comes to implementing them, changing them at scale… well that’s where things can be a little tiresome. Well, I looked at it that way until recently when I had to really think about a better way to provision, deprovision and manipulate NSGs at scale.
There’s certainly content on the line that outlines how to better implement NSGs leveraging PowerShell, which I did consult the oracle to work out part of the solution I share here. The road block’s I’ve run into mostly came about because I’ve stopped using the AzureRM PowerShell module(s) and moved to the Az module(s) in mid January.
The general availability of the Az module is less than 6 months old (December 2018), from the time of me writing this. That’s fairly new. So what better excuse, and the fact that I’ve temporarily parted ways with my old PowerShell script stash, to work on putting together a better means of NSG security rule management, more so because I need it urgently for some work at a customer.
Here’s a list of things I needed to do efficiently, reliably and at scale:
Here’s the output from those requirements, a series of PowerShell scripts that I thought would be good to share. Enjoy!
Example:
$nsgs = Get-AzNetworkSecurityGroup
$exportPath = '<C:\somewhere>'
Foreach ($nsg in $nsgs){
New-Item -ItemType file -Path "$exportPath\$($nsg.Name).csv" -Force
$nsgRules = $nsg.SecurityRules
foreach ($nsgRule in $nsgRules){
$nsgRule | Select-Object Name,Description,Priority,Protocol,Access,Direction,@{Name=’SourceAddressPrefix’;Expression={[string]::join(“,”, ($_.SourceAddressPrefix))}},@{Name=’SourcePortRange’;Expression={[string]::join(“,”, ($_.SourcePortRange))}},@{Name=’DestinationAddressPrefix’;Expression={[string]::join(“,”, ($_.DestinationAddressPrefix))}},@{Name=’DestinationPortRange’;Expression={[string]::join(“,”, ($_.DestinationPortRange))}} `
| Export-Csv "$exportPath\$($nsg.Name).csv" -NoTypeInformation -Encoding ASCII -Append}
}
Example:
$NSG = Get-AzNetworkSecurityGroup -Name <NetworkSecurityGroup> -ResourceGroupName <ResourceGroup>
foreach($rule in import-csv "<C:\CSVFILEHERE.csv>"){$NSG | Remove-AzNetworkSecurityRuleConfig -Name $rule.name}
$NSG | Set-AzNetworkSecurityGroup
Example error output:
Set-AzNetworkSecurityGroup : Security rule has invalid Port range. Value provided: 80 8080 8081 443 444. Value should be an integer OR integer range with '-' delimiter. Valid range 0-65535.
StatusCode: 400
ReasonPhrase: Bad Request
OperationID : 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx'
At line:14 char:8
+ $NSG | Set-AzNetworkSecurityGroup
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : CloseError: (:) [Set-AzNetworkSecurityGroup], NetworkCloudException
+ FullyQualifiedErrorId : Microsoft.Azure.Commands.Network.SetAzureNetworkSecurityGroupCommand
Example:
$NSG = Get-AzNetworkSecurityGroup -Name <NetworkSecurityGroup> -ResourceGroupName <ResourceGroup>
foreach($rule in import-csv "<C:\CSVFILEHERE.csv>"){
$NSG | Add-AzNetworkSecurityRuleConfig `
-Name $rule.name `
-Description $rule.Description `
-Priority $rule.Priority `
-Protocol $rule.Protocol `
-Access $rule.Access `
-Direction $rule.Direction `
-SourceAddressPrefix ($rule.SourceAddressPrefix -split ',') `
-SourcePortRange ($rule.SourcePortRange -split ',') `
-DestinationAddressPrefix ($rule.DestinationAddressPrefix -split ',') `
-DestinationPortRange ($rule.DestinationPortRange -split ',')
}
$NSG | Set-AzNetworkSecurityGroup
PowerShell. Much heart, such useful. Enjoy! #PromptPowerShell