|
| 1 | +<# |
| 2 | +.SYNOPSIS |
| 3 | + Checks if Microsoft 365 traffic is actively flowing through Global Secure Access. |
| 4 | +
|
| 5 | +.DESCRIPTION |
| 6 | + This test validates that the Microsoft 365 traffic forwarding profile is enabled and |
| 7 | + that Microsoft 365 traffic is actively being tunneled through Global Secure Access. |
| 8 | +
|
| 9 | +.NOTES |
| 10 | + Test ID: 25376 |
| 11 | + Category: Traffic Acquisition |
| 12 | + Required API: networkAccess/reports (beta) |
| 13 | +#> |
| 14 | + |
| 15 | +function Test-Assessment-25376 { |
| 16 | + [ZtTest( |
| 17 | + Category = 'Traffic Acquisition', |
| 18 | + ImplementationCost = 'Medium', |
| 19 | + MinimumLicense = ('P1','E3'), |
| 20 | + Pillar = 'Network', |
| 21 | + RiskLevel = 'High', |
| 22 | + SfiPillar = 'Protect networks', |
| 23 | + TenantType = ('Workforce'), |
| 24 | + TestId = 25376, |
| 25 | + Title = 'Microsoft 365 traffic is actively flowing through Global Secure Access', |
| 26 | + UserImpact = 'Low' |
| 27 | + )] |
| 28 | + [CmdletBinding()] |
| 29 | + param() |
| 30 | + |
| 31 | + #region Data Collection |
| 32 | + Write-PSFMessage '🟦 Start' -Tag Test -Level VeryVerbose |
| 33 | + |
| 34 | + $activity = 'Checking Microsoft 365 traffic through Global Secure Access' |
| 35 | + Write-ZtProgress -Activity $activity -Status 'Verifying M365 traffic forwarding profile' |
| 36 | + |
| 37 | + # Define evaluation time window (last 7 days) |
| 38 | + $endDateTime = (Get-Date).ToUniversalTime() |
| 39 | + $startDateTime = $endDateTime.AddDays(-7) |
| 40 | + $startDateTimeStr = $startDateTime.ToString('yyyy-MM-ddTHH:mm:ssZ') |
| 41 | + $endDateTimeStr = $endDateTime.ToString('yyyy-MM-ddTHH:mm:ssZ') |
| 42 | + |
| 43 | + # Query 3: Verify Microsoft 365 traffic forwarding profile is enabled |
| 44 | + $m365Profile = $null |
| 45 | + try { |
| 46 | + $allProfiles = Invoke-ZtGraphRequest -RelativeUri "networkAccess/forwardingProfiles" -ApiVersion beta |
| 47 | + $m365Profile = $allProfiles | Where-Object { $_.trafficForwardingType -eq 'm365' } |
| 48 | + } catch { |
| 49 | + Write-PSFMessage "Unable to retrieve M365 forwarding profile: $_" -Level Warning |
| 50 | + } |
| 51 | + |
| 52 | + # Query 1 & 2: Execute in parallel conceptually, but sequentially due to tool constraints |
| 53 | + Write-ZtProgress -Activity $activity -Status 'Retrieving traffic statistics' |
| 54 | + |
| 55 | + # Query 1: Get transaction summaries |
| 56 | + $transactionSummary = $null |
| 57 | + try { |
| 58 | + $transactionSummary = Invoke-ZtGraphRequest -RelativeUri "networkAccess/reports/transactionSummaries(startDateTime=$startDateTimeStr,endDateTime=$endDateTimeStr)" -ApiVersion beta |
| 59 | + } catch { |
| 60 | + Write-PSFMessage "Unable to retrieve transaction summaries: $_" -Level Warning |
| 61 | + } |
| 62 | + |
| 63 | + # Query 2: Get device usage summary |
| 64 | + $deviceUsage = $null |
| 65 | + try { |
| 66 | + $deviceUsage = Invoke-ZtGraphRequest -RelativeUri "networkAccess/reports/getDeviceUsageSummary(startDateTime=$startDateTimeStr,endDateTime=$endDateTimeStr)" -ApiVersion beta |
| 67 | + } catch { |
| 68 | + Write-PSFMessage "Unable to retrieve device usage summary: $_" -Level Warning |
| 69 | + } |
| 70 | + #endregion Data Collection |
| 71 | + |
| 72 | + #region Assessment Logic |
| 73 | + $passed = $true |
| 74 | + $warnings = [System.Collections.Generic.List[string]]::new() |
| 75 | + |
| 76 | + # Extract M365 profile state |
| 77 | + $profileEnabled = $false |
| 78 | + $profileState = 'Not found' |
| 79 | + $profileName = 'N/A' |
| 80 | + if ($m365Profile -and $m365Profile.Count -gt 0) { |
| 81 | + $m365ProfileData = $m365Profile | Select-Object -First 1 |
| 82 | + $profileName = $m365ProfileData.name |
| 83 | + $profileState = $m365ProfileData.state |
| 84 | + $profileEnabled = ($m365ProfileData.state -eq 'enabled') |
| 85 | + } |
| 86 | + |
| 87 | + # Extract M365 transaction data |
| 88 | + $m365TotalCount = 0 |
| 89 | + $m365BlockedCount = 0 |
| 90 | + if ($transactionSummary) { |
| 91 | + $m365Entry = $transactionSummary | Where-Object { $_.trafficType -eq 'microsoft365' } | Select-Object -First 1 |
| 92 | + if ($m365Entry) { |
| 93 | + $m365TotalCount = [int]$m365Entry.totalCount |
| 94 | + $m365BlockedCount = [int]$m365Entry.blockedCount |
| 95 | + } |
| 96 | + } |
| 97 | + |
| 98 | + # Extract device usage data |
| 99 | + $totalDeviceCount = 0 |
| 100 | + $activeDeviceCount = 0 |
| 101 | + $inactiveDeviceCount = 0 |
| 102 | + if ($deviceUsage) { |
| 103 | + $totalDeviceCount = [int]$deviceUsage.totalDeviceCount |
| 104 | + $activeDeviceCount = [int]$deviceUsage.activeDeviceCount |
| 105 | + $inactiveDeviceCount = [int]$deviceUsage.inactiveDeviceCount |
| 106 | + } |
| 107 | + |
| 108 | + # Evaluation logic |
| 109 | + if (-not $profileEnabled) { |
| 110 | + $passed = $false |
| 111 | + } |
| 112 | + |
| 113 | + if ($m365TotalCount -eq 0) { |
| 114 | + $passed = $false |
| 115 | + } |
| 116 | + |
| 117 | + # Warning conditions |
| 118 | + if ($profileEnabled -and $m365TotalCount -gt 0 -and $m365TotalCount -lt 1000) { |
| 119 | + $warnings.Add("Low Microsoft 365 transaction count ($m365TotalCount) may indicate deployment issues") |
| 120 | + } |
| 121 | + |
| 122 | + if ($activeDeviceCount -eq 0 -and $totalDeviceCount -gt 0) { |
| 123 | + $warnings.Add("No active devices detected despite $totalDeviceCount total devices registered") |
| 124 | + } |
| 125 | + |
| 126 | + if ($activeDeviceCount -lt 10 -and $profileEnabled) { |
| 127 | + $warnings.Add("Low active device count ($activeDeviceCount) - verify client deployment across endpoints") |
| 128 | + } |
| 129 | + |
| 130 | + # Generate result message |
| 131 | + if ($passed -and $warnings.Count -eq 0) { |
| 132 | + $testResultMarkdown = "✅ Microsoft 365 traffic forwarding is enabled and a healthy volume of Microsoft 365 traffic is flowing through Global Secure Access.`n`n%TestResult%" |
| 133 | + } |
| 134 | + elseif ($passed -and $warnings.Count -gt 0) { |
| 135 | + $testResultMarkdown = "⚠️ Microsoft 365 traffic is flowing through Global Secure Access, but some concerns were detected.`n`n%TestResult%" |
| 136 | + } |
| 137 | + else { |
| 138 | + $testResultMarkdown = "❌ Microsoft 365 traffic forwarding is disabled or no Microsoft 365 traffic is being tunneled through Global Secure Access.`n`n%TestResult%" |
| 139 | + } |
| 140 | + #endregion Assessment Logic |
| 141 | + |
| 142 | + #region Report Generation |
| 143 | + $mdInfo = '' |
| 144 | + |
| 145 | + # Summary Section |
| 146 | + $mdInfo += "`n## Summary`n`n" |
| 147 | + $mdInfo += "| Metric | Value |`n" |
| 148 | + $mdInfo += "| :--- | ---: |`n" |
| 149 | + $mdInfo += "| Profile Enabled | $(if ($profileEnabled) { '✅ Yes' } else { '❌ No' }) |`n" |
| 150 | + |
| 151 | + # Only show transaction and device counts if profile is enabled |
| 152 | + if ($profileEnabled) { |
| 153 | + $mdInfo += "| M365 Transactions (7 days) | $($m365TotalCount.ToString('N0')) |`n" |
| 154 | + $mdInfo += "| M365 Blocked Transactions | $($m365BlockedCount.ToString('N0')) |`n" |
| 155 | + $mdInfo += "| Active Devices | $activeDeviceCount |`n" |
| 156 | + $mdInfo += "| Total Devices | $totalDeviceCount |`n" |
| 157 | + } |
| 158 | + $mdInfo += "`n" |
| 159 | + |
| 160 | + # Traffic Forwarding Profile Section |
| 161 | + $mdInfo += "`n## Traffic Forwarding Profile`n`n" |
| 162 | + $mdInfo += "| Property | Value |`n" |
| 163 | + $mdInfo += "| :--- | :--- |`n" |
| 164 | + $mdInfo += "| Profile Name | $(Get-SafeMarkdown -Text $profileName) |`n" |
| 165 | + $mdInfo += "| State | $profileState |`n" |
| 166 | + $mdInfo += "| Traffic Type | m365 |`n`n" |
| 167 | + |
| 168 | + # Only show transaction and device data if profile is enabled |
| 169 | + if ($profileEnabled) { |
| 170 | + # Transaction Summary Section |
| 171 | + $mdInfo += "`n## Transaction Summary`n`n" |
| 172 | + $mdInfo += "| Traffic Type | Total Count | Blocked Count |`n" |
| 173 | + $mdInfo += "| :--- | ---: | ---: |`n" |
| 174 | + if ($transactionSummary) { |
| 175 | + foreach ($entry in $transactionSummary | Sort-Object trafficType) { |
| 176 | + $total = [int]$entry.totalCount |
| 177 | + $blocked = [int]$entry.blockedCount |
| 178 | + $mdInfo += "| $($entry.trafficType) | $($total.ToString('N0')) | $($blocked.ToString('N0')) |`n" |
| 179 | + } |
| 180 | + } else { |
| 181 | + $mdInfo += "| - | No data available | - |`n" |
| 182 | + } |
| 183 | + $mdInfo += "`n" |
| 184 | + $mdInfo += "*Evaluation Period: $($startDateTime.ToString('yyyy-MM-dd')) to $($endDateTime.ToString('yyyy-MM-dd'))*`n`n" |
| 185 | + |
| 186 | + # Device Usage Section |
| 187 | + $mdInfo += "`n## Device Usage`n`n" |
| 188 | + $mdInfo += "| Metric | Count |`n" |
| 189 | + $mdInfo += "| :--- | ---: |`n" |
| 190 | + $mdInfo += "| Total Devices | $totalDeviceCount |`n" |
| 191 | + $mdInfo += "| Active Devices | $activeDeviceCount |`n" |
| 192 | + $mdInfo += "| Inactive Devices | $inactiveDeviceCount |`n`n" |
| 193 | + } |
| 194 | + |
| 195 | + # Warnings Section |
| 196 | + if ($warnings.Count -gt 0) { |
| 197 | + $mdInfo += "`n## ⚠️ Warnings`n`n" |
| 198 | + foreach ($warning in $warnings) { |
| 199 | + $mdInfo += "- $warning`n" |
| 200 | + } |
| 201 | + $mdInfo += "`n" |
| 202 | + } |
| 203 | + |
| 204 | + # Portal Link |
| 205 | + $portalLink = "https://entra.microsoft.com/#view/Microsoft_Azure_Network_Access/ForwardingProfile.ReactView" |
| 206 | + $mdInfo += "`n[$(Get-SafeMarkdown -Text 'View in Entra Portal: Traffic forwarding')]($portalLink)" |
| 207 | + |
| 208 | + # Replace placeholder with detailed information |
| 209 | + $testResultMarkdown = $testResultMarkdown -replace '%TestResult%', $mdInfo |
| 210 | + #endregion Report Generation |
| 211 | + |
| 212 | + $params = @{ |
| 213 | + TestId = '25376' |
| 214 | + Title = 'Microsoft 365 traffic is actively flowing through Global Secure Access' |
| 215 | + Status = $passed |
| 216 | + Result = $testResultMarkdown |
| 217 | + } |
| 218 | + |
| 219 | + Add-ZtTestResultDetail @params |
| 220 | +} |
0 commit comments