From 9d5754fc56a01ded935cc17e95057ef3ecbf5d88 Mon Sep 17 00:00:00 2001 From: Kshitiz Sharma Date: Tue, 6 Jan 2026 09:20:19 +0530 Subject: [PATCH] 25533 --- src/powershell/tests/Test-Assessment.25533.md | 10 ++ .../tests/Test-Assessment.25533.ps1 | 130 ++++++++++++++++++ 2 files changed, 140 insertions(+) create mode 100644 src/powershell/tests/Test-Assessment.25533.md create mode 100644 src/powershell/tests/Test-Assessment.25533.ps1 diff --git a/src/powershell/tests/Test-Assessment.25533.md b/src/powershell/tests/Test-Assessment.25533.md new file mode 100644 index 000000000..3afeea209 --- /dev/null +++ b/src/powershell/tests/Test-Assessment.25533.md @@ -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) + + + +%TestResult% diff --git a/src/powershell/tests/Test-Assessment.25533.ps1 b/src/powershell/tests/Test-Assessment.25533.ps1 new file mode 100644 index 000000000..00828a66a --- /dev/null +++ b/src/powershell/tests/Test-Assessment.25533.ps1 @@ -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 +}