All scripts
Governance 542

Get-AzureNSGRuleAuditReport

Exports every custom inbound rule from every network security group in the subscription to a single CSV, flagging any rule that allows traffic from any source on a sensitive port.

Get-AzureNSGRuleAuditReport.ps1
<#
.SYNOPSIS
    Audits inbound NSG rules across the subscription.

.DESCRIPTION
    Exports every custom inbound rule from every network security group
    to a single CSV and flags any rule allowing traffic from any source
    on a commonly targeted port like RDP or SSH, so risky rules are
    found in one pass instead of reviewing each NSG separately.

.PARAMETER ExportPath
    Path to write the CSV to. Defaults to the current directory.

.EXAMPLE
    .\Get-AzureNSGRuleAuditReport.ps1

.NOTES
    Requires the Az.Network module and an active Connect-AzAccount session.

.AUTHOR
    Shehryar Hassan
#>

param(
    [string]$ExportPath = (Get-Location).Path
)

$sensitivePorts = @("22", "3389", "1433", "3306")
$nsgs = Get-AzNetworkSecurityGroup

$report = foreach ($nsg in $nsgs) {
    foreach ($rule in $nsg.SecurityRules | Where-Object { $_.Direction -eq "Inbound" -and $_.Access -eq "Allow" }) {
        [pscustomobject]@{
            NSG          = $nsg.Name
            RuleName     = $rule.Name
            SourceRange  = $rule.SourceAddressPrefix -join ","
            DestPort     = $rule.DestinationPortRange -join ","
            OpenToAny    = $rule.SourceAddressPrefix -contains "*" -or $rule.SourceAddressPrefix -contains "Internet"
            SensitivePort = ($rule.DestinationPortRange | Where-Object { $_ -in $sensitivePorts }).Count -gt 0
        }
    }
}

$file = Join-Path $ExportPath "nsg-rule-audit_$(Get-Date -Format yyyyMMdd_HHmmss).csv"
$report | Export-Csv -Path $file -NoTypeInformation

$risky = $report | Where-Object { $_.OpenToAny -and $_.SensitivePort }
Write-Warning "$($risky.Count) rule(s) allow open access to a sensitive port. Full report at $file"

Read it before you run it, and test in a safe tenant first.