Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions src/powershell/tests/Test-Assessment.25533.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
DDoS attacks remain a major security and availability risk for customers with cloud-hosted applications. These attacks aim to overwhelm an application's compute, network, or memory resources, rendering it inaccessible to legitimate users. Any public-facing endpoint exposed to the internet can be a potential target for a DDoS attack. Azure DDoS Protection provides always-on monitoring and automatic mitigation against DDoS attacks targeting public-facing workloads. Without Azure DDoS Protection (Network Protection or IP Protection), public IP addresses for services such as Application Gateways, Load Balancers, or virtual machines remain exposed to DDoS attacks that can overwhelm network bandwidth, exhaust system resources, and cause complete service unavailability. These attacks can disrupt access for legitimate users, degrade performance, and create cascading outages across dependent services.Azure DDoS Protection uses adaptive real-time tuning to profile normal traffic patterns and automatically detects anomalies indicative of an attack. When an attack is identified, mitigation is engaged at the Azure network edge to absorb and filter malicious traffic before it reaches your applications. This check verifies that Azure DDoS Protection is enabled for public IP addresses within a VNET, ensuring that applications are protected from DDoS attacks. If this check does not pass, your workloads remain significantly more vulnerable to downtime, customer impact, and operational disruption during an attack.

## Remediation Resources

- [Please check the articles below for guidance on how to enable DDoS Protection for Public IP addresses.](https://learn.microsoft.com/en-us/azure/ddos-protection/manage-ddos-protection)
- [Please check the articles below for guidance on how to enable DDoS Protection for Public IP addresses.](https://learn.microsoft.com/en-us/azure/ddos-protection/manage-ddos-ip-protection-portal)


<!--- Results --->
%TestResult%
130 changes: 130 additions & 0 deletions src/powershell/tests/Test-Assessment.25533.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
function Test-Assessment-25533 {
[ZtTest(
Category = 'Azure Network Security',
ImplementationCost = 'Low',
MinimumLicense = ('DDoS_Network_Protection', 'DDoS_IP_Protection'),
Pillar = 'Network',
RiskLevel = 'High',
SfiPillar = 'Protect networks',
TenantType = ('Workforce', 'External'),
TestId = 25533,
Title = 'DDoS Protection is enabled for all Public IP Addresses in VNETs',
UserImpact = 'Low'
)]
[CmdletBinding()]
param()

Write-PSFMessage 'Start DDoS Public IP Assessment' -Tag Test -Level VeryVerbose

if ((Get-MgContext).Environment -ne 'Global') {
Write-PSFMessage "This test is only applicable to the Global environment." -Tag Test -Level VeryVerbose
return
}

#region Azure Connection Verification
try {
$accessToken = Get-AzAccessToken -AsSecureString -ErrorAction Stop
}
catch {
Write-PSFMessage $_.Exception.Message -Tag Test -Level Error
Add-ZtTestResultDetail -SkippedBecause NoAzureAccess
return
}
#endregion

#region Data Collection
$subscriptions = Get-AzSubscription
$publicIpFindings = @()

foreach ($sub in $subscriptions) {

Set-AzContext -SubscriptionId $sub.Id | Out-Null

try {
$publicIps = Get-AzPublicIpAddress -ErrorAction Stop
}
catch {
Write-PSFMessage "Unable to list Public IPs in subscription $($sub.Name)." -Tag Test -Level Warning
continue
}

foreach ($pip in $publicIps) {

$protectionMode = $null
$source = 'None'

# Case 1: Explicit DDoS IP protection
if ($pip.DdosSettings -and $pip.DdosSettings.ProtectionMode) {
$protectionMode = $pip.DdosSettings.ProtectionMode
$source = 'PublicIP'
}

# Case 2: VNET inherited protection
elseif ($pip.IpConfiguration -and $pip.IpConfiguration.Id) {

try {
$vnet = Get-AzVirtualNetwork -ResourceGroupName $pip.ResourceGroupName -ErrorAction Stop
if ($vnet.EnableDdosProtection) {
$protectionMode = 'VirtualNetworkInherited'
$source = 'VNET'
$vnet.EnableDdosProtection
}
}
catch {
Write-PSFMessage "Failed to resolve VNET for Public IP $($pip.Name)" -Tag Test -Level Debug
}
}

$isCompliant = $protectionMode -in @('Enabled', 'VirtualNetworkInherited')

$publicIpFindings += [PSCustomObject]@{
PublicIpName = $pip.Name
PublicIpId = $pip.Id
Location = $pip.Location
AllocationMethod = $pip.PublicIpAllocationMethod
ProtectionMode = if ($protectionMode) { $protectionMode } else { 'NotEnabled' }
ProtectionSource = $source
IsCompliant = $isCompliant
SubscriptionId = $sub.Id
SubscriptionName = $sub.Name
}
}
}
#endregion

#region Assessment Logic
if ($publicIpFindings.Count -eq 0) {
Add-ZtTestResultDetail -TestId '25533' -Status $true -Result "No Public IP addresses found."
return
}

$nonCompliant = $publicIpFindings | Where-Object { -not $_.IsCompliant }
$passed = ($nonCompliant.Count -eq 0)

$testResultMarkdown = if ($passed) {
"DDoS Protection is enabled for all Public IP addresses.`n`n%TestResult%"
}
else {
"DDoS Protection is NOT enabled for one or more Public IP addresses.`n`n%TestResult%"
}
#endregion

#region Result Reporting
$mdInfo = "## Public IP Address DDoS Protection Status`n`n"
$mdInfo += "| Public IP | Location | Allocation | Protection Mode | Source | Status |`n"
$mdInfo += "| :--- | :--- | :--- | :--- | :--- | :--- |`n"

foreach ($item in $publicIpFindings | Sort-Object PublicIpName) {

$icon = if ($item.IsCompliant) { '✅' } else { '❌' }
$pipLink = "https://portal.azure.com/#@/resource$($item.PublicIpId)"
$safeName = Get-SafeMarkdown -Text $item.PublicIpName

$mdInfo += "| $icon [$safeName]($pipLink) | $($item.Location) | $($item.AllocationMethod) | $($item.ProtectionMode) | $($item.ProtectionSource) | $icon |`n"
}


$testResultMarkdown = $testResultMarkdown -replace "%TestResult%", $mdInfo
Add-ZtTestResultDetail -TestId '25533' -Status $passed -Result $testResultMarkdown
#endregion
}