tests/Test-Assessment.27019.ps1
|
<#
.SYNOPSIS Validates that JavaScript challenge is enabled in Azure Front Door WAF policies. .DESCRIPTION This test evaluates Azure Front Door WAF policies across all subscriptions to verify that at least one custom rule with JavaScript challenge action (JSChallenge) is configured and enabled. Only policies attached to an Azure Front Door are evaluated. .NOTES Test ID: 27019 Category: Azure Network Security Required APIs: Azure Resource Graph (Front Door WAF policies) #> function Test-Assessment-27019 { [ZtTest( Category = 'Azure Network Security', ImplementationCost = 'Low', MinimumLicense = 'Azure WAF', Pillar = 'Network', RiskLevel = 'Medium', SfiPillar = 'Protect networks', TenantType = ('Workforce'), TestId = 27019, Title = 'JavaScript Challenge is Enabled in Azure Front Door WAF', UserImpact = 'Low' )] [CmdletBinding()] param() #region Data Collection Write-PSFMessage '🟦 Start' -Tag Test -Level VeryVerbose $activity = 'Checking Azure Front Door WAF JavaScript challenge configuration' # Check if connected to Azure Write-ZtProgress -Activity $activity -Status 'Checking Azure connection' $azContext = Get-AzContext -ErrorAction SilentlyContinue if (-not $azContext) { Write-PSFMessage 'Not connected to Azure.' -Tag Test -Level Warning Add-ZtTestResultDetail -SkippedBecause NotConnectedAzure return } # Check the supported environment Write-ZtProgress -Activity $activity -Status 'Checking Azure environment' if ($azContext.Environment.Name -ne 'AzureCloud') { Write-PSFMessage 'This test is only applicable to the AzureCloud environment.' -Tag Test -Level VeryVerbose Add-ZtTestResultDetail -SkippedBecause NotSupported return } # Query all Front Door WAF policies attached to an Azure Front Door via Azure Resource Graph Write-ZtProgress -Activity $activity -Status 'Querying Azure Front Door WAF policies' $argQuery = @" resources | where type =~ 'microsoft.network/frontdoorwebapplicationfirewallpolicies' | where array_length(properties.frontendEndpointLinks) > 0 or array_length(properties.securityPolicyLinks) > 0 | join kind=leftouter ( resourcecontainers | where type =~ 'microsoft.resources/subscriptions' | project subscriptionId, subscriptionName=name ) on subscriptionId | project PolicyName = name, PolicyId = id, SubscriptionName = subscriptionName, SubscriptionId = subscriptionId, EnabledState = tostring(properties.policySettings.enabledState), WafMode = tostring(properties.policySettings.mode), JsChallengeCookieExpirationInMins = toint(properties.policySettings.javascriptChallengeExpirationInMinutes), CustomRules = properties.customRules.rules "@ $policies = @() try { $policies = @(Invoke-ZtAzureResourceGraphRequest -Query $argQuery) Write-PSFMessage "ARG Query returned $($policies.Count) records" -Tag Test -Level VeryVerbose } catch { Write-PSFMessage "Failed to query Azure Front Door WAF policies via Resource Graph: $($_.Exception.Message)" -Tag Test -Level Warning Add-ZtTestResultDetail -SkippedBecause NotSupported return } #endregion Data Collection #region Assessment Logic if ($policies.Count -eq 0) { Write-PSFMessage 'No Azure Front Door WAF policies attached to Azure Front Door found.' -Tag Test -Level Verbose Add-ZtTestResultDetail -SkippedBecause NotApplicable -Result 'No Azure Front Door WAF policies attached to Azure Front Door found.' return } # Fail if any policy is disabled, not in Prevention mode, or has no enabled JSChallenge custom rule $failingPolicies = $policies | Where-Object { $_.EnabledState -ne 'Enabled' -or $_.WafMode -ne 'Prevention' -or @($_.CustomRules | Where-Object { $_.action -eq 'JSChallenge' -and $_.enabledState -eq 'Enabled' }).Count -eq 0 } $passed = $failingPolicies.Count -eq 0 if ($passed) { $testResultMarkdown = "✅ All Azure Front Door WAF policies attached to Azure Front Door are enabled in Prevention mode and have at least one JavaScript Challenge rule configured and enabled.`n`n%TestResult%" } else { $testResultMarkdown = "❌ One or more Azure Front Door WAF policies attached to Azure Front Door are disabled, running in Detection mode, have no JavaScript challenge rules configured, or have JavaScript challenge rules configured but all set to Disabled state, leaving applications without browser verification against automated bots at the global edge.`n`n%TestResult%" } #endregion Assessment Logic #region Report Generation $portalWafBrowseLink = 'https://portal.azure.com/#browse/Microsoft.Network%2FfrontdoorWebApplicationFirewallPolicies' $portalResourceBaseLink = 'https://portal.azure.com/#resource' $portalSubscriptionBaseLink = 'https://portal.azure.com/#resource/subscriptions' $mdInfo = "`n## [Azure Front Door WAF policies]($portalWafBrowseLink)`n`n" $tableRows = '' $formatTemplate = @' | Policy name | Subscription name | Enabled state | WAF mode | JS challenge rules count | Rule state | Cookie expiration (mins) | Status | | :--- | :--- | :--- | :--- | :--- | :--- | :--- | :--- | {0} '@ foreach ($policy in ($policies | Sort-Object SubscriptionName, PolicyName)) { $policyLink = "[$(Get-SafeMarkdown $policy.PolicyName)]($portalResourceBaseLink$($policy.PolicyId))" $subscriptionLink = "[$(Get-SafeMarkdown $policy.SubscriptionName)]($portalSubscriptionBaseLink/$($policy.SubscriptionId)/overview)" $allJsRules = @($policy.CustomRules | Where-Object { $_.action -eq 'JSChallenge' }) $enabledJsRules = @($allJsRules | Where-Object { $_.enabledState -eq 'Enabled' }) $jsRuleCountDisplay = if ($enabledJsRules.Count -gt 0) { "✅ $($enabledJsRules.Count)" } elseif ($allJsRules.Count -gt 0) { "⚠️ $($allJsRules.Count) (disabled)" } else { '❌ 0' } $ruleStateDisplay = if ($allJsRules.Count -eq 0) { 'N/A' } elseif ($enabledJsRules.Count -ge 1) { '✅ Enabled' } else { '❌ Disabled' } $cookieExpiration = if ($policy.JsChallengeCookieExpirationInMins) { $policy.JsChallengeCookieExpirationInMins } else { 'N/A' } $enabledStateDisplay = if ($policy.EnabledState -eq 'Enabled') { '✅ Enabled' } else { '❌ Disabled' } $wafModeDisplay = if ($policy.WafMode -eq 'Prevention') { '✅ Prevention' } else { '❌ Detection' } $statusText = if ($policy.EnabledState -eq 'Enabled' -and $policy.WafMode -eq 'Prevention' -and $enabledJsRules.Count -ge 1) { '✅ Pass' } else { '❌ Fail' } $tableRows += "| $policyLink | $subscriptionLink | $enabledStateDisplay | $wafModeDisplay | $jsRuleCountDisplay | $ruleStateDisplay | $cookieExpiration | $statusText |`n" } $mdInfo += $formatTemplate -f $tableRows $testResultMarkdown = $testResultMarkdown -replace '%TestResult%', $mdInfo #endregion Report Generation $params = @{ TestId = '27019' Title = 'JavaScript Challenge is Enabled in Azure Front Door WAF' Status = $passed Result = $testResultMarkdown } Add-ZtTestResultDetail @params } |