Skip to content

Commit b5c1c4f

Browse files
Network - 27001 - TLS inspection bypass policies are regularly reviewed to prevent security protection gaps (#892)
* initial commit * made few improvements * Trigger validation with current main * resolved Aleks comments * updated comment with changed code * changed lastModifiedDateTime to string for consistancy --------- Co-authored-by: alexandair <alexandair@live.com>
1 parent ee8c8a8 commit b5c1c4f

File tree

2 files changed

+184
-0
lines changed

2 files changed

+184
-0
lines changed
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
When TLS inspection is enabled in Global Secure Access, traffic passing through the Security Service Edge undergoes decryption to enable deep packet inspection, URL categorization, and threat detection. Bypass rules are sometimes necessary for traffic that cannot be inspected due to technical constraints (certificate pinning) or compliance requirements. However, without regular review, bypass rules accumulate over time as temporary exceptions become permanent, applications are decommissioned while their bypass rules remain, or initial justifications become obsolete. Threat actors specifically target uninspected traffic channels, knowing that malware command-and-control communications, data exfiltration, and credential theft over HTTPS will evade detection when traffic bypasses TLS inspection. A policy that has not been modified in over 90 days may contain stale bypass rules that no longer serve a valid business purpose, effectively creating blind spots in the organization's network security posture. Organizations should maintain a review cadence where TLS inspection policies are audited quarterly at minimum, validating that each bypass rule remains necessary and appropriately scoped.
2+
3+
**Remediation action**
4+
5+
1. [Review and manage TLS inspection policies in the Microsoft Entra admin center under Global Secure Access > Secure > TLS inspection](https://learn.microsoft.com/en-us/graph/api/resources/networkaccess-tlsinspectionpolicy)
6+
2. [Understand TLS inspection rule configuration and bypass actions](https://learn.microsoft.com/en-us/graph/api/resources/networkaccess-tlsinspectionrule)
7+
3. Establish a quarterly review process for TLS inspection bypass rules, documenting business justification for each bypass rule and removing rules that are no longer necessary
8+
4. Required role: Global Secure Access Administrator or Security Administrator
9+
10+
<!--- Results --->
11+
%TestResult%
Lines changed: 173 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,173 @@
1+
<#
2+
.SYNOPSIS
3+
Validates that TLS inspection bypass policies are regularly reviewed to prevent security protection gaps.
4+
5+
.DESCRIPTION
6+
This test checks whether TLS inspection policies containing custom bypass rules have been
7+
reviewed within the last 90 days. Bypass rules that are not regularly reviewed can create
8+
security blind spots, as threat actors specifically target uninspected traffic channels.
9+
10+
.NOTES
11+
Test ID: 27001
12+
Category: Global Secure Access
13+
Required API: networkAccess/tlsInspectionPolicies
14+
#>
15+
16+
function Test-Assessment-27001 {
17+
[ZtTest(
18+
Category = 'Global Secure Access',
19+
ImplementationCost = 'Medium',
20+
MinimumLicense = 'Entra_Premium_Internet_Access',
21+
Pillar = 'Network',
22+
RiskLevel = 'Medium',
23+
SfiPillar = 'Protect networks',
24+
TenantType = ('Workforce'),
25+
TestId = 27001,
26+
Title = 'TLS inspection bypass policies are regularly reviewed to prevent security protection gaps',
27+
UserImpact = 'Low'
28+
)]
29+
[CmdletBinding()]
30+
param()
31+
32+
#region Data Collection
33+
Write-PSFMessage '🟦 Start' -Tag Test -Level VeryVerbose
34+
35+
$activity = 'Checking TLS inspection policy review status'
36+
37+
# Query 1: Retrieve all TLS Inspection Policies
38+
Write-ZtProgress -Activity $activity -Status 'Retrieving TLS inspection policies'
39+
40+
$tlsInspectionPolicies = $null
41+
$errorMsg = $null
42+
try {
43+
$tlsInspectionPolicies = Invoke-ZtGraphRequest -RelativeUri 'networkAccess/tlsInspectionPolicies?$expand=policyRules' -ApiVersion beta -ErrorAction Stop
44+
}
45+
catch {
46+
$errorMsg = $_
47+
Write-PSFMessage "Unable to retrieve TLS inspection policies: $errorMsg" -Level Warning
48+
}
49+
50+
if(-not $errorMsg){
51+
# Check if we got any policies
52+
if (-not $tlsInspectionPolicies -or $tlsInspectionPolicies.Count -eq 0) {
53+
Write-PSFMessage "No TLS inspection policies found." -Tag Test -Level Verbose
54+
Add-ZtTestResultDetail -SkippedBecause NotApplicable
55+
return
56+
}
57+
58+
# Process each policy's expanded policy rules
59+
$policiesWithCustomBypass = @()
60+
61+
foreach ($policy in $tlsInspectionPolicies) {
62+
Write-ZtProgress -Activity $activity -Status "Checking policy: $($policy.name)"
63+
64+
$policyRules = $policy.policyRules
65+
66+
if (-not $policyRules -or $policyRules.Count -eq 0) {
67+
continue
68+
}
69+
70+
# Filter out auto-created system rules (description starts with "Auto-created TLS rule")
71+
$customRules = $policyRules | Where-Object {
72+
$_.description -notlike "Auto-created TLS rule*"
73+
}
74+
75+
# Count custom bypass rules
76+
$customBypassRules = @($customRules | Where-Object { $_.action -eq 'bypass' })
77+
$customBypassCount = $customBypassRules.Count
78+
79+
# Skip policies with no custom bypass rules
80+
if ($customBypassCount -eq 0) {
81+
continue
82+
}
83+
84+
# Calculate days since last modified
85+
$daysSinceModified = ([datetime]::UtcNow - $policy.lastModifiedDateTime).Days
86+
87+
$policiesWithCustomBypass += [PSCustomObject]@{
88+
PolicyName = $policy.name
89+
LastModifiedDateTime = $policy.lastModifiedDateTime.ToString("yyyy-MM-ddTHH:mm:ss")
90+
DaysSinceModified = $daysSinceModified
91+
CustomBypassCount = $customBypassCount
92+
RequiresReview = $daysSinceModified -gt 90
93+
}
94+
}
95+
}
96+
97+
#endregion Data Collection
98+
99+
#region Assessment Logic
100+
$passed = $false
101+
102+
# Fail if there was an error retrieving policies
103+
if($errorMsg) {
104+
$passed = $false
105+
$testResultMarkdown = "❌ Unable to retrieve TLS inspection policies due to error:`n`n$errorMsg`n`n%TestResult%"
106+
}
107+
# Check if no policies with custom bypass rules were found
108+
elseif ($policiesWithCustomBypass.Count -eq 0) {
109+
$passed = $true
110+
$testResultMarkdown = "✅ No TLS inspection policies with custom bypass rules found.`n`n%TestResult%"
111+
}
112+
else {
113+
# Check if any policies require review
114+
$policiesRequiringReview = @($policiesWithCustomBypass | Where-Object { $_.RequiresReview -eq $true })
115+
116+
if ($policiesRequiringReview.Count -gt 0) {
117+
$passed = $false
118+
$testResultMarkdown = "❌ One or more TLS inspection policies with custom bypass rules have not been modified in over 90 days and require review.`n`n%TestResult%"
119+
}
120+
else {
121+
$passed = $true
122+
$testResultMarkdown = "✅ All TLS inspection policies with custom bypass rules have been reviewed within the last 90 days.`n`n%TestResult%"
123+
}
124+
}
125+
#endregion Assessment Logic
126+
127+
#region Report Generation
128+
$mdInfo = ''
129+
130+
if ($policiesWithCustomBypass.Count -gt 0) {
131+
$reportTitle = 'TLS inspection policies'
132+
$portalLink = 'https://entra.microsoft.com/#view/Microsoft_Azure_Network_Access/TLSInspectionPolicy.ReactView'
133+
134+
# Prepare table rows
135+
$tableRows = ''
136+
foreach ($item in $policiesWithCustomBypass) {
137+
$lastModifiedDisplay = Get-FormattedDate -DateString $item.LastModifiedDateTime
138+
$reviewStatus = if ($item.RequiresReview) { '' } else { '' }
139+
140+
$tableRows += "| $($item.PolicyName) | $lastModifiedDisplay | $($item.DaysSinceModified) | $($item.CustomBypassCount) | $reviewStatus |`n"
141+
}
142+
143+
$totalCount = $policiesWithCustomBypass.Count
144+
$oldPoliciesCount = $policiesRequiringReview.Count
145+
146+
$formatTemplate = @'
147+
148+
## [{0}]({1})
149+
150+
| Policy name | Last modified | Days since modified | Custom Bypass rule count | Status |
151+
| :---------- | :------------ | :------------------ | :----------------------- | :----- |
152+
{2}
153+
154+
**Summary:**
155+
- Total policies with custom bypass rules: {3}
156+
- Policies older than 90 days: {4}
157+
'@
158+
159+
$mdInfo = $formatTemplate -f $reportTitle, $portalLink, $tableRows, $totalCount, $oldPoliciesCount
160+
}
161+
162+
$testResultMarkdown = $testResultMarkdown -replace '%TestResult%', $mdInfo
163+
#endregion Report Generation
164+
165+
$params = @{
166+
TestId = '27001'
167+
Title = 'TLS inspection bypass policies are regularly reviewed to prevent security protection gaps'
168+
Status = $passed
169+
Result = $testResultMarkdown
170+
}
171+
172+
Add-ZtTestResultDetail @params
173+
}

0 commit comments

Comments
 (0)