This repository was archived by the owner on Sep 1, 2026. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 182
Expand file tree
/
Copy pathInvoke-ZtTests.ps1
More file actions
157 lines (127 loc) · 5.92 KB
/
Copy pathInvoke-ZtTests.ps1
File metadata and controls
157 lines (127 loc) · 5.92 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
function Invoke-ZtTests {
<#
.SYNOPSIS
Runs all the Zero Trust Assessment tests.
.DESCRIPTION
Runs all the Zero Trust Assessment tests.
.PARAMETER Database
The Database object where the cached tenant data is stored
.PARAMETER Tests
The IDs of the specific test(s) to run. If not specified, all tests will be run.
.PARAMETER Pillar
The Zero Trust pillar to assess.
Defaults to: All.
.PARAMETER ThrottleLimit
Maximum number of tests processed in parallel.
Defaults to: 5
.PARAMETER LogsPath
Optional path to output logs for each test. If not specified, logs will not be written
to disk but will still be available in the database.
.PARAMETER Timeout
The maximum time to wait for all tests to complete before giving up and writing a warning message.
Defaults to: 24 hours. Adjust this value if you have a large number of tests or expect some tests to take a long time.
.PARAMETER ConnectedService
The services that are connected and can be used for testing.
This is used to skip tests that require a service connection when the service is not connected.
If not specified, it will use the value from $script:ConnectedService, which is set based on the
connected services populated by Connect-ZtAssessment.
.PARAMETER TestTimeout
Maximum time in minutes a single test is allowed to run.
Defaults to: 60. Set to 0 to disable.
For Data pillar tests and external-module/remoting-heavy operations,
this is a best-effort interruption rather than a guaranteed hard stop.
.EXAMPLE
PS C:\> Invoke-ZtTests -Database $database -Tests $Tests -Pillar $Pillar -ThrottleLimit $TestThrottleLimit
Executes all tests specified.
#>
[CmdletBinding()]
param (
[DuckDB.NET.Data.DuckDBConnection]
$Database,
[string[]]
$Tests,
[ValidateSet('All', 'Identity', 'Devices', 'Network', 'Data', 'Infrastructure', 'SecOps', 'AI')]
[string]
$Pillar = 'All',
[int]
$ThrottleLimit = 5,
[string]
$LogsPath,
[Parameter(DontShow)]
[ValidateSet('Graph', 'Azure', 'AipService', 'ExchangeOnline', 'SecurityCompliance', 'SharePointOnline')]
[string[]]
$ConnectedService = $script:ConnectedService,
[TimeSpan]
$Timeout = '1.00:00:00',
[int]
$TestTimeout = 60
)
# Get Tenant Type (AAD = Workforce, CIAM = EEID)
$org = Invoke-ZtGraphRequest -RelativeUri 'organization'
$tenantType = $org.TenantType
Write-PSFMessage "$tenantType tenant detected. This will determine the tests that are run."
# Map input parameters to config file values
$tenantTypeMapping = @{
"AAD" = "Workforce"
"CIAM" = "External"
}
$testsToRun = Get-ZtTest -Tests $Tests -Pillar $Pillar -TenantType $tenantTypeMapping[$TenantType]
# Store the requested pillar so Get-ZtAssessmentResults can restrict TestPillar on cross-ref tests
$script:__ZtSession.RequestedPillar = $Pillar
# Filter based on preview feature flag
if (-not $script:__ZtSession.PreviewEnabled) {
# Non-preview mode: Only include stable/released pillars
$stablePillars = @('Identity', 'Devices', 'Network', 'Data')
$testsToRun = $testsToRun.Where{ ($_.Pillar | Where-Object { $_ -in $stablePillars }) }
}
# Filter based on Compatible licenses
$skippedTestsForLicense = $testsToRun.Where{$_.CompatibleLicense.Count -gt 0 -and (-not (Test-ZtLicense -CompatibleLicense $_.CompatibleLicense)) }
$skippedTestsForLicense.ForEach{
Write-PSFMessage -Message ('Test {0} is skipped because no compatible license was found' -f $_.TestId) -Level Verbose
Add-ZtTestResultDetail -SkippedBecause NoCompatibleLicenseFound -TestId $_.TestId
}
$testsToRun = $testsToRun.Where{ $_.TestId -notin $skippedTestsForLicense.TestId }
# Filter based on service connection. If no service is specified in the test metadata, it will be run.
$skippedTestsForService = $testsToRun.Where{ $_.Service.count -gt 0 -and $_.Service.Count -notin $_.Service.Where{ $_ -in $ConnectedService}.count }
$skippedTestsForService.ForEach{
$notConnectedService = ($_).Service.Where{ $_ -notin $ConnectedService }
# Mark the test as skipped.
Add-ZtTestResultDetail -SkippedBecause NotConnectedToService -TestId $_.TestId -NotConnectedService $notConnectedService
}
$testsToRun = $testsToRun.Where{ $_.TestId -notin $skippedTestsForService.TestId }
# Separate Sync Tests (Compliance/ExchangeOnline/SharePointOnline) from Parallel Tests (because of DLL order to manage in runspaces & remoting into WPS)
# Tests that depend on SecurityCompliance remoting must run on the main thread regardless of pillar.
[int[]]$syncTestIds = $testsToRun.Where{
$_.Pillar -eq 'Data' -or $_.Service -contains 'SecurityCompliance'
}.TestId
$syncTests = $testsToRun.Where{ $_.TestId -in $syncTestIds }
$parallelTests = $testsToRun.Where{ $_.TestId -notin $syncTestIds }
[dateTime] $startTime = [datetime]::Now
$workflow = $null
try {
# Convert timeout minutes to timespan (0 = disabled)
$timeoutSpan = if ($TestTimeout -gt 0) { [timespan]::FromMinutes($TestTimeout) } else { [timespan]::Zero }
# Run Sync Tests in the main thread
foreach ($test in $syncTests) {
$null = Invoke-ZtTest -Test $test -Database $Database -LogsPath $LogsPath -TestTimeout $timeoutSpan
}
# Then run Parallel Tests
if ($parallelTests) {
$workflow = Start-ZtTestExecution -Tests $parallelTests -DbPath $Database.Database -ThrottleLimit $ThrottleLimit -LogsPath $LogsPath -TestTimeout $timeoutSpan
Wait-ZtTest -Workflow $workflow -StartedAt $startTime -Timeout $Timeout
$workflow.Queues['Input'].ForEach{
Write-PSFMessage -Level Debug -Message "Test $_ was not processed before timeout was reached."
Add-ZtTestResultDetail -SkippedBecause TimeoutReached -TestId $_
}
}
}
finally {
if ($workflow) {
# Disable CTRL+C to prevent impatient users from finishing the cleanup. Failing to do so may lead to a locked database, preventing a clean restart.
Invoke-ZtSafeConsoleInterruptToggle -Disable
$workflow | Stop-PSFRunspaceWorkflow
$workflow | Remove-PSFRunspaceWorkflow
Invoke-ZtSafeConsoleInterruptToggle -Enable
}
}
}