-
Notifications
You must be signed in to change notification settings - Fork 138
Expand file tree
/
Copy pathTest-Assessment.00000.ps1
More file actions
226 lines (188 loc) Β· 8.38 KB
/
Test-Assessment.00000.ps1
File metadata and controls
226 lines (188 loc) Β· 8.38 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
<#
.SYNOPSIS
High-risk web categories are blocked by Azure Firewall application rules.
.DESCRIPTION
Verifies that Azure Firewall Policies have at least one application rule in a Deny
rule collection that targets high-risk (Liability group) web categories.
Web categories allow administrators to block access to inherently dangerous website
categories such as malware, phishing, hacking, and other liability-group content.
This check applies to both Standard and Premium SKU firewalls.
.NOTES
Test ID: 00000 (placeholder β replace with assigned spec ID)
Category: Azure Network Security
Required API: Azure Resource Graph
#>
function Test-Assessment-00000 {
[ZtTest(
Category = 'Azure Network Security',
ImplementationCost = 'Low',
Service = ('Azure'),
MinimumLicense = ('Azure_Firewall_Standard', 'Azure_Firewall_Premium'),
Pillar = 'Network',
RiskLevel = 'High',
SfiPillar = 'Protect networks',
TenantType = ('Workforce', 'External'),
TestId = 00000,
Title = 'High-risk web categories are blocked by Azure Firewall application rules',
UserImpact = 'Low'
)]
[CmdletBinding()]
param()
Write-PSFMessage 'π¦ Start Azure Firewall Web Categories evaluation' -Tag Test -Level VeryVerbose
$activity = 'Checking Azure Firewall web category filtering configuration'
#region Data Collection
# 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.' -Level Warning
Add-ZtTestResultDetail -SkippedBecause NotConnectedAzure
return
}
# Check the supported environment β 'AzureCloud' maps to 'Global'
Write-ZtProgress -Activity $activity -Status 'Checking Azure environment'
if ($azContext.Environment.Name -ne 'AzureCloud') {
Write-PSFMessage 'This test is only applicable to the Global (AzureCloud) environment.' -Tag Test -Level VeryVerbose
Add-ZtTestResultDetail -SkippedBecause NotSupported
return
}
# Q1: Query all firewall policies (Standard + Premium) via Azure Resource Graph
Write-ZtProgress -Activity $activity -Status 'Querying Azure Firewall policies via Resource Graph'
$policyQuery = @"
resources
| where type =~ 'microsoft.network/firewallpolicies'
| where tostring(properties.sku.tier) in ('Standard', 'Premium')
| join kind=leftouter (
resourcecontainers
| where type =~ 'microsoft.resources/subscriptions'
| project subscriptionName=name, subscriptionId
) on subscriptionId
| project
PolicyName=name,
PolicyId=id,
SubscriptionName=subscriptionName,
SubscriptionId=subscriptionId,
SkuTier=tostring(properties.sku.tier),
FirewallCount=coalesce(array_length(properties.firewalls), 0)
"@
$allPolicies = @()
try {
$allPolicies = @(Invoke-ZtAzureResourceGraphRequest -Query $policyQuery)
Write-PSFMessage "ARG returned $($allPolicies.Count) firewall policy(ies)" -Tag Test -Level VeryVerbose
}
catch {
Write-PSFMessage "Azure Resource Graph query failed: $($_.Exception.Message)" -Tag Test -Level Warning
Add-ZtTestResultDetail -SkippedBecause NotSupported
return
}
# No firewall policies at all β Skipped
if ($allPolicies.Count -eq 0) {
Write-PSFMessage 'No Azure Firewall policies found in any subscription.' -Tag Test -Level VeryVerbose
Add-ZtTestResultDetail -SkippedBecause NotApplicable
return
}
# Q2: Find policies with at least one Deny application rule targeting web categories
Write-ZtProgress -Activity $activity -Status 'Checking application rules for web category deny rules'
$webCatPolicyIds = @()
$webCatQuery = @"
resources
| where type =~ 'microsoft.network/firewallpolicies/rulecollectiongroups'
| mvexpand ruleCollection = properties.ruleCollections
| where ruleCollection.ruleCollectionType =~ 'FirewallPolicyFilterRuleCollection'
and ruleCollection.action.type =~ 'Deny'
| mvexpand rule = ruleCollection.rules
| where rule.ruleType =~ 'ApplicationRule'
and array_length(rule.webCategories) > 0
| extend lowerId = tolower(id)
| extend policyId = substring(lowerId, 0, indexof(lowerId, '/rulecollectiongroups/'))
| distinct policyId
"@
try {
$webCatPolicyIds = @(Invoke-ZtAzureResourceGraphRequest -Query $webCatQuery | ForEach-Object { $_.policyId })
Write-PSFMessage "ARG found $($webCatPolicyIds.Count) policy(ies) with web category deny rules" -Tag Test -Level VeryVerbose
}
catch {
Write-PSFMessage "Web category rule query failed: $($_.Exception.Message)" -Tag Test -Level Warning
Add-ZtTestResultDetail -SkippedBecause NotSupported
return
}
#endregion Data Collection
#region Assessment Logic
# Build evaluation results for each policy
$evaluationResults = @()
foreach ($policy in $allPolicies) {
$policyIdLower = $policy.PolicyId.ToLower()
$attachedToFirewall = $policy.FirewallCount -gt 0
$hasWebCatDenyRules = $policyIdLower -in $webCatPolicyIds
$portalUrl = "https://portal.azure.com/#@/resource$($policy.PolicyId)"
$evaluationResults += [PSCustomObject]@{
SubscriptionName = $policy.SubscriptionName
SubscriptionId = $policy.SubscriptionId
PolicyName = $policy.PolicyName
SkuTier = $policy.SkuTier
PortalUrl = $portalUrl
AttachedToFirewall = $attachedToFirewall
HasWebCatDenyRules = $hasWebCatDenyRules
PassesCriteria = $attachedToFirewall -and $hasWebCatDenyRules
}
}
# Separate attached (evaluable) policies from unattached ones
$attachedResults = @($evaluationResults | Where-Object { $_.AttachedToFirewall })
$passed = $false
$testResultMarkdown = ''
if ($attachedResults.Count -eq 0) {
# All policies are not attached to any firewall β Not applicable
Write-PSFMessage 'All firewall policies are not attached to any Azure Firewall.' -Tag Test -Level VeryVerbose
Add-ZtTestResultDetail -SkippedBecause NotApplicable
return
}
elseif (($attachedResults | Where-Object { -not $_.PassesCriteria }).Count -eq 0) {
$passed = $true
$testResultMarkdown = @"
β
All Azure Firewall policies have application rules that deny traffic to high-risk web categories. This provides defense-in-depth against threats delivered through inherently dangerous website categories.
%TestResult%
"@
}
else {
$testResultMarkdown = @"
β One or more Azure Firewall policies do not have application rules that deny traffic to high-risk web categories. Without web category filtering, users can access malware distribution sites, phishing pages, and other liability-group content through the firewall.
%TestResult%
"@
}
#endregion Assessment Logic
#region Report Generation
$formatTemplate = @'
## Azure Firewall policies web category filtering status
| Subscription name | Firewall policy name | SKU | Attached to Firewall | Web category deny rules | Result |
| :--- | :--- | :--- | :--- | :--- | :--- |
{0}
'@
$tableRows = ''
foreach ($result in ($evaluationResults | Sort-Object PolicyName)) {
$policyName = Get-SafeMarkdown -Text $result.PolicyName
$policyNameWithLink = "[$policyName]($($result.PortalUrl))"
$subName = Get-SafeMarkdown -Text $result.SubscriptionName
$attached = if ($result.AttachedToFirewall) { 'Yes' } else { 'No' }
$webCatDeny = if ($result.HasWebCatDenyRules) { 'Yes' } else { 'No' }
if (-not $result.AttachedToFirewall) {
$icon = 'β¬'
}
elseif ($result.PassesCriteria) {
$icon = 'β
'
}
else {
$icon = 'β'
}
$tableRows += "| $subName | $policyNameWithLink | $($result.SkuTier) | $attached | $webCatDeny | $icon |`n"
}
$mdInfo = $formatTemplate -f $tableRows
$testResultMarkdown = $testResultMarkdown -replace '%TestResult%', $mdInfo
#endregion Report Generation
$params = @{
TestId = '00000'
Title = 'High-risk web categories are blocked by Azure Firewall application rules'
Status = $passed
Result = $testResultMarkdown
}
Add-ZtTestResultDetail @params
}