Azure NSGs: export rules by source prefix

Overview

This PowerShell script searches all Azure subscriptions accessible to the current account, inspects every network security group, and exports only the NSG rules whose source address starts with a specific value.

In its current form, the filter is:

10.114.

This is useful when you need to quickly identify:

  • Which NSGs contain rules for a given source range.
  • Which subscription and resource group own those NSGs.
  • The rule direction, access action, priority, and destination settings for each match.

What the script does

  • Retrieves all accessible subscriptions with Get-AzSubscription.
  • Switches context into each subscription with Set-AzContext.
  • Reads NSGs with Get-AzNetworkSecurityGroup.
  • Checks each rule source prefix for values beginning with 10.114..
  • Prints matching rules immediately to the console.
  • Collects all matches and exports them to CSV.

Prerequisites

Install the Azure PowerShell modules if needed:

Install-Module Az -Scope CurrentUser

Connect to Azure before running the script:

Connect-AzAccount

The account must have permission to read NSGs in the subscriptions being checked.

Output

The CSV is written to:

$HOME/NSG_Rules_10.114.csv

Each row includes:

  • SubscriptionName
  • SubscriptionId
  • ResourceGroup
  • NSGName
  • NSGLocation
  • RuleName
  • Priority
  • Direction
  • Access
  • Protocol
  • SourceAddress
  • SourcePort
  • DestinationAddress
  • DestinationPort
  • RuleDescription

PowerShell script

$OutputFile = "$HOME/NSG_Rules_10.114.csv"
 
$Results = @()
 
$Subscriptions = Get-AzSubscription
 
Write-Host ""
Write-Host "Found $($Subscriptions.Count) accessible subscriptions." -ForegroundColor Cyan
Write-Host "Searching NSGs for source addresses matching 10.114.x.x..." -ForegroundColor Cyan
Write-Host ""
 
foreach ($Subscription in $Subscriptions) {
 
    Write-Host "============================================================" -ForegroundColor DarkGray
    Write-Host "Subscription: $($Subscription.Name)" -ForegroundColor Yellow
    Write-Host "Subscription ID: $($Subscription.Id)" -ForegroundColor DarkYellow
 
    try {
        Set-AzContext -SubscriptionId $Subscription.Id -ErrorAction Stop | Out-Null
 
        $NSGs = Get-AzNetworkSecurityGroup -ErrorAction Stop
 
        Write-Host "NSGs found: $($NSGs.Count)" -ForegroundColor Gray
 
        foreach ($NSG in $NSGs) {
 
            foreach ($Rule in $NSG.SecurityRules) {
 
                $SourcePrefixes = @($Rule.SourceAddressPrefix)
 
                foreach ($Source in $SourcePrefixes) {
 
                    if ($Source -match '^10\.114\.') {
 
                        $Row = [PSCustomObject]@{
                            SubscriptionName   = $Subscription.Name
                            SubscriptionId     = $Subscription.Id
                            ResourceGroup      = $NSG.ResourceGroupName
                            NSGName            = $NSG.Name
                            NSGLocation        = $NSG.Location
                            RuleName           = $Rule.Name
                            Priority           = $Rule.Priority
                            Direction          = $Rule.Direction
                            Access             = $Rule.Access
                            Protocol           = $Rule.Protocol
                            SourceAddress      = $Source
                            SourcePort         = ($Rule.SourcePortRange -join ', ')
                            DestinationAddress = ($Rule.DestinationAddressPrefix -join ', ')
                            DestinationPort    = ($Rule.DestinationPortRange -join ', ')
                            RuleDescription    = $Rule.Description
                        }
 
                        $Results += $Row
 
                        Write-Host ""
                        Write-Host "MATCH FOUND" -ForegroundColor Green
                        Write-Host "  Subscription : $($Subscription.Name)"
                        Write-Host "  ResourceGroup: $($NSG.ResourceGroupName)"
                        Write-Host "  NSG          : $($NSG.Name)" -ForegroundColor Cyan
                        Write-Host "  Rule         : $($Rule.Name)" -ForegroundColor Cyan
                        Write-Host "  Source       : $Source" -ForegroundColor Green
                        Write-Host "  Direction    : $($Rule.Direction)"
                        Write-Host "  Access       : $($Rule.Access)"
                        Write-Host "  Priority     : $($Rule.Priority)"
                        Write-Host "  Protocol     : $($Rule.Protocol)"
                    }
                }
            }
        }
    }
    catch {
        Write-Warning "Could not process subscription '$($Subscription.Name)': $($_.Exception.Message)"
    }
}
 
Write-Host ""
Write-Host "============================================================" -ForegroundColor Cyan
Write-Host "SEARCH COMPLETE" -ForegroundColor Cyan
Write-Host "============================================================" -ForegroundColor Cyan
 
if ($Results.Count -gt 0) {
 
    $Results |
        Sort-Object SubscriptionName, ResourceGroup, NSGName, Priority |
        Format-Table `
            SubscriptionName,
            ResourceGroup,
            NSGName,
            RuleName,
            Priority,
            Direction,
            Access,
            SourceAddress `
            -AutoSize
 
    $Results |
        Sort-Object SubscriptionName, ResourceGroup, NSGName, Priority |
        Export-Csv `
            -Path $OutputFile `
            -NoTypeInformation `
            -Encoding UTF8
 
    Write-Host ""
    Write-Host "Total matching rules: $($Results.Count)" -ForegroundColor Green
    Write-Host "CSV exported to: $OutputFile" -ForegroundColor Green
}
else {
    Write-Host "No NSG rules found with a source beginning with 10.114." -ForegroundColor Yellow
}

Notes

  • The current match uses -match '^10\.114\.', so it matches string prefixes such as host IPs, CIDR ranges, and explicit ranges that begin with 10.114..
  • SourceAddressPrefix may contain one or multiple values, so the script normalizes it into an array before checking.
  • If you want a reusable variant, move the source prefix and output file into parameters.
  • If one subscription cannot be queried, the script warns and continues with the rest.