Skip to content
Open
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
11 changes: 11 additions & 0 deletions src/powershell/tests/Test-Assessment.25537.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
Azure Firewall Threat intelligence-based filtering alerts and denies traffic from/to known malicious IP addresses, FQDNs, and URLs. The IP addresses, domains, and URLs are sourced from the Microsoft Threat Intelligence feed, which includes multiple sources including the Microsoft Cyber Security team. When threat intelligence-based filtering is enabled, Azure Firewall evaluates traffic against the threat intelligence rules before applying NAT, network, or application rules.

This check verifies that Threat Intelligence feature is enabled in “Alert and Deny” mode in the Azure Firewall policy configuration. The check will fail if Threat Intelligence is either “Disabled” or if it is not configured in “Alert and Deny” mode, in the firewall policy attached to the firewall.

**Remediation action**

Please check this article for guidance on how to enable Threat Intelligence in “Alert and Deny” mode in the Azure Firewall Policy:
Comment on lines +3 to +7
Copy link

Copilot AI Jan 19, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The documentation states the check will fail if Threat Intelligence is "not configured in 'Alert and Deny' mode". This is inconsistent with Azure Firewall terminology. The correct mode is "Deny", not "Alert and Deny". The text should state "not configured in 'Deny' mode" to accurately reflect the requirement.

Suggested change
This check verifies that Threat Intelligence feature is enabled in “Alert and Deny” mode in the Azure Firewall policy configuration. The check will fail if Threat Intelligence is either “Disabled” or if it is not configured in “Alert and Deny” mode, in the firewall policy attached to the firewall.
**Remediation action**
Please check this article for guidance on how to enable Threat Intelligence in “Alert and Deny” mode in the Azure Firewall Policy:
This check verifies that Threat Intelligence feature is enabled in “Deny” mode in the Azure Firewall policy configuration. The check will fail if Threat Intelligence is either “Disabled” or if it is not configured in “Deny” mode, in the firewall policy attached to the firewall.
**Remediation action**
Please check this article for guidance on how to enable Threat Intelligence in “Deny” mode in the Azure Firewall Policy:

Copilot uses AI. Check for mistakes.
- [Azure Firewall threat intelligence configuration | Microsoft Learn](https://learn.microsoft.com/en-us/azure/firewall-manager/threat-intelligence-settings)

<!--- Results --->
%TestResult%
137 changes: 137 additions & 0 deletions src/powershell/tests/Test-Assessment.25537.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@

<#
.SYNOPSIS
Validates Threat intelligence is Enabled in Deny Mode on Azure Firewall.
.DESCRIPTION
This test validates that Azure Firewall Policies have Threat Intelligence enabled in Deny mode.
Checks all firewall policies in the subscription and reports their threat intelligence status.
.NOTES
Test ID: 25537
Category: Azure Network Security
Required API: Azure Firewall Policies
#>

function Test-Assessment-25537 {
[ZtTest(
Category = 'Azure Network Security',
ImplementationCost = 'Low',
MinimumLicense = ('Azure_Firewall_Standard', 'Azure_Firewall_Premium'),
Pillar = 'Network',
RiskLevel = 'High',
SfiPillar = 'Protect networks',
TenantType = ('Workforce'),
TestId = 25537,
Title = 'Threat intelligence is Enabled in Deny Mode on Azure Firewall',
UserImpact = 'Low'
)]
[CmdletBinding()]
param()

Write-PSFMessage '🟦 Start' -Tag Test -Level VeryVerbose

#region Data Collection
$activity = 'Azure Firewall Threat Intelligence'
Write-ZtProgress `
-Activity $activity `
Comment on lines +33 to +35
Copy link

Copilot AI Jan 28, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is inconsistent indentation on this line. The line has leading spaces before Write-ZtProgress, which breaks the consistent indentation pattern. This should align with the standard 4-space indentation used for code within the function body.

Suggested change
$activity = 'Azure Firewall Threat Intelligence'
Write-ZtProgress `
-Activity $activity `
$activity = 'Azure Firewall Threat Intelligence'
Write-ZtProgress `
-Activity $activity `

Copilot uses AI. Check for mistakes.
-Status 'Enumerating Firewall Policies'

# Query 1: List all subscriptions
$resourceManagerUrl = (Get-AzContext).Environment.ResourceManagerUrl.TrimEnd('/')
$subscriptionsUri = "$resourceManagerUrl/subscriptions?api-version=2020-01-01"

try {
$subscriptionsResponse = Invoke-AzRestMethod -Method GET -Uri $subscriptionsUri -ErrorAction Stop
}
catch {
if ($_.Exception.Response.StatusCode -eq 403 -or $_.Exception.Message -like '*403*' -or $_.Exception.Message -like '*Forbidden*') {
Add-ZtTestResultDetail -SkippedBecause NoAzureAccess
return
}
}

$subscriptions = ($subscriptionsResponse.Content | ConvertFrom-Json).value

if (-not $subscriptions) {
Add-ZtTestResultDetail -SkippedBecause NoResults
return
}
$results = @()
foreach ($sub in $subscriptions) {

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

# Query 1: List Azure Firewall Policies
try {
$policiesUri = "$resourceManagerUrl/subscriptions/$($sub.subscriptionId)/providers/Microsoft.Network/firewallPolicies?api-version=2023-04-01"
Write-ZtProgress -Activity $activity -Status "Enumerating policies in subscription $($sub.displayName)"

$policyResponse = (Invoke-AzRestMethod -Method GET -Uri $policiesUri -ErrorAction Stop ).Content | ConvertFrom-Json
$policies = $policyResponse.value

}
catch {
Write-PSFMessage "Unable to enumerate firewall policies in subscription $($sub.displayName): $($_.Exception.Message)" -Tag Firewall -Level Warning
continue
}

if (-not $policies) { continue }

# Query 2: Get details for each firewall policy and check threatIntelMode
foreach ($policyResource in $policies) {

$threatIntelMode = $policyResource.Properties.threatIntelMode

$subContext = Get-AzContext

$results += [PSCustomObject]@{
PolicyName = $policyResource.Name
SubscriptionName = $subContext.Subscription.Name
SubscriptionId = $subContext.Subscription.Id
ThreatIntelMode = $threatIntelMode
PolicyID = $policyResource.Id
Passed = $threatIntelMode -eq 'Deny'
}
}
}
#endregion Data Collection

#region Assessment Logic


$passed = ($results | Where-Object { -not $_.Passed }).Count -eq 0
$allAlert = ($results | Where-Object { $_.ThreatIntelMode -ne 'Alert' }).Count -eq 0
Copy link

Copilot AI Jan 28, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The variable $allAlert is computed on line 103 but is never used in the subsequent code. This creates unnecessary maintenance burden. If this variable is intended for future use or debugging, consider removing it or documenting its purpose.

Copilot uses AI. Check for mistakes.

$testResultMarkdown = if ($passed) {
"Threat Intel is enabled in **Alert and Deny** mode .`n`n%TestResult%"
} elseif ($allAlert) {
"Threat Intel is enabled in **Alert** mode .`n`n%TestResult%"
} else {
"Threat Intel is not enabled in **Alert and Deny** mode for all Firewall policies.`n`n%TestResult%"
}
#endregion Assessment Logic

#region Report Generation
$mdInfo = "## Firewall policies`n`n"
$mdInfo += "| Policy name | Subscription name | Threat Intel mode | Result |`n"
$mdInfo += "| :--- | :--- | :--- | :--- |`n"

foreach ($item in $results | Sort-Object PolicyName) {
$policyLink = "https://portal.azure.com/#resource$($item.PolicyID)"
$subLink = "https://portal.azure.com/#resource/subscriptions/$($item.SubscriptionId)"
$policyMd = "[$(Get-SafeMarkdown -Text $item.PolicyName)]($policyLink)"
$subMd = "[$(Get-SafeMarkdown -Text $item.SubscriptionName)]($subLink)"
$icon = if ($item.Passed) { '✅' } else { '❌' }
$mdInfo += "| $policyMd | $subMd | $($item.ThreatIntelMode) | $icon |`n"
}

$testResultMarkdown = $testResultMarkdown -replace '%TestResult%', $mdInfo
#endregion Report Generation
$params = @{
TestId = '25537'
Title = 'Threat intelligence is Enabled in Deny Mode on Azure Firewall'
Status = $passed
Result = $testResultMarkdown
}

Add-ZtTestResultDetail @params
}