Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / DevOps / automation

Add Multiple Rules to NSG using PowerShell and CSV

3.00/5 (1 vote)
3 Jul 2019CPOL2 min read 15.4K  
Resolution of Security rule has invalid Port range issue

Introduction

Sometimes, while creating a VNET in Azure, we don't know the exact number of NSG rules to be set. If there is a need to add more NSG rules to a particular Network Security Group, instead of going to portal and adding the rules manually, we can use a simple .CSV file with the rules to apply and a PowerShell script.

*Issue - Security rule has invalid Port range

This sample addresses the Security rule has invalid Port range issue which occurs when we try to supply multiple ports in Source or Destination.

Background

Following are the prerequisites to complete this exercise:

  1. Basic understanding of PowerShell script
  2. An Azure subscription (you can play around with a free trial subscription here) and a Network Security Group (NSG) available under a resource group
  3. Please note, I've used the Azure PowerShell Az module in the article below, if you've not migrated to this version, you need to replace the commands with AzureRM keyword in place of Az in the code snippet below.

Using the Code

Create a .CSV file with all the rules defined in that, for testing, I've added just one record, you can add more row in your .CSV file as per your requirement.

Rules in CSV File

NSG Name NSG Rule Name

NSG
Rule Description

NSG Rule Access NSG Rule Protocol NSG Rule Direction NSG Rule Priority NSG Rule Source Address Prefix NSG Rule Source Port Range NSG Rule Desti-
nation Address Prefix
NSG Rule Destination
Port
Range
test-nsg-001 new-rdp-rule Allow RDP Allow tcp Inbound 1010 Internet * * 443;5300;1025-5000

Now, we need powershell script to attach these rules to the intended NSG.

Open a PowerShell ISE (as administrator) and add the following code to read the .CSV and push the changes to Azure.

PowerShell
param(
[Parameter(Mandatory=$True)]
[string]
$subscriptionId,
[Parameter(Mandatory=$True)]
[string]
$resourceGroupName,

[string]
$nsgName,

[string]
$nsgRuleName,
[string]
$nsgRuleDescription,
[string]
$nsgRuleAccess,
[string]
$nsgRuleProtocol,
[string]
$nsgRuleDirection,
[string]
$nsgRulePriority,
[string]
$nsgRuleSourceAddressPrefix,
[string]
$nsgRuleSourcePortRange,
[string]
$nsgRuleDestinationAddressPrefix,
[string]
$nsgRuleDestinationPortRange,
$csvFilePath = "C:\prakash\Add NSG Rules.csv"
)

# sign in
Write-Host "Logging in...";
Connect-AzAccount;

# select subscription
Write-Host "Selecting subscription '$subscriptionId'";
Select-AzSubscription -SubscriptionID $subscriptionId;

Import-Csv $csvFilePath |`
  ForEach-Object {
    $nsgName = $_."NSG Name"
    $nsgRuleName = $_."NSG Rule Name"
        $nsgRuleDescription = $_."NSG Rule Description"
    $nsgRuleAccess = $_."NSG Rule Access"
        $nsgRuleProtocol = $_."NSG Rule Protocol"
    $nsgRuleDirection = $_."NSG Rule Direction"
        $nsgRulePriority = $_."NSG Rule Priority"
    $nsgRuleSourceAddressPrefix = $_."NSG Rule Source Address Prefix"
        $nsgRuleSourcePortRange = $_."NSG Rule Source Port Range"
//    $nsgRuleDestinationAddressPrefix = $_."NSG Rule Destination Address Prefix"
        $nsgRuleDestinationPortRange = $_."NSG Rule Destination Port Range"

    #Getting the right NSG and setting new rule to it    
    $nsgRuleNameValue = Get-AzNetworkSecurityGroup 
       -Name $nsgName -ResourceGroupName $resourceGroupName | 
       Get-AzNetworkSecurityRuleConfig -Name $nsgRuleName -ErrorAction SilentlyContinue
    if($nsgRuleNameValue.Name -match $nsgRuleName){
       Write-Host "A rule with this name (" $nsgRuleNameValue.Name ") already exists"
       }
    else{
         Get-AzNetworkSecurityGroup -Name  $nsgName -ResourceGroupName $resourceGroupName | 
        Add-AzNetworkSecurityRuleConfig -Name $nsgRuleName 
                        -Description $nsgRuleDescription -Access `
        $nsgRuleAccess -Protocol $nsgRuleProtocol -Direction $nsgRuleDirection 
            -Priority $nsgRulePriority -SourceAddressPrefix $nsgRuleSourceAddressPrefix `
        -SourcePortRange $nsgRuleSourcePortRange 
              -DestinationAddressPrefix $nsgRuleDestinationAddressPrefix 
              -DestinationPortRange $nsgRuleDestinationPortRange.split(";") -Verbose | 
        Set-AzNetworkSecurityGroup -Verbose
       }
    }

Points of Interest

There is an interesting error I came across during implementation of this, if we provide (,) separated list of ports in any of the Ports related columns in .CSV file, it gives following error while running the Powershell script:

Set-AzNetworkSecurityGroup : Security rule has invalid Port range. Value should be an
 integer OR integer range with '-' delimiter. Valid range 0-65535.
StatusCode: 400
ReasonPhrase: Bad Request

To resolve this, I needed to provide the port values in .CSV file in the following format (multiple ports as well as range):

 443;5300;1025-5000

and then in my Powershell script, I needed to use the split(";") function along with that particular parameter in the following way:

PowerShell
-DestinationPortRange $nsgRuleDestinationPortRange.split(";")

Please let me know your views on this tip and happy coding!

History

  • 3rd July, 2019: Initial publication

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)