Training module · Draft
Module 1: Evidence, not a verdict
Status — Draft
This page is still being written. Expect gaps and changes; it is not part of the workbook's production guidance. Last reviewed 2026-11-11.
Part of the Zero Trust Assessment learning path. Guide Step 1 and Step 6. About 40 minutes.
Introduction (3 minutes)
The Zero Trust Assessment is a PowerShell module that tests a tenant against hundreds of configuration items drawn from Microsoft’s configuration guidance for Entra, Intune, Azure networking and Purview. Release 3.1.0, the current release, holds 364 tests in seven pillars. It is read-only, it is free, and it is the assessment component of Microsoft’s Zero Trust Workshop.
What it produces is a reading of the configuration on one day. In this module you learn what that reading can and can’t tell you, and you see, on a fictional export, why the tool’s six statuses have to be sorted before anyone counts them.
The federal requirement. Scoping and reading the assessment supports NIST SP 800-53 CA-2 (control assessments) and CA-7 (continuous monitoring). The full table is the guide’s Step 1.
| Requirement | KSI | Evidence |
|---|---|---|
| CA-2: plan the assessment and its scope | KSI-PIY-RIS | The approved decision record |
| CA-2: assessment results reviewed by the owners | KSI-PIY-RIS | Each pillar owner’s reading notes |
| CA-7: the frequency of assessment | KSI-MLA-EVC | The calendar entry and its owner |
KSIs are FedRAMP 20x indicators for cloud service providers. The agency lines its own evidence up with them; it doesn’t report KSIs itself (Book 00, Appendix B).
Learning objectives (1 minute)
After this module, you’ll be able to:
- say what the Zero Trust Assessment checks and name the four things it isn’t;
- explain why it doesn’t replace ScubaGear under BOD 25-01;
- read the Risk Level, User Impact and Implementation Cost rubric;
- name the six statuses a test can end in, and sort a skip reason into Book 11’s taxonomy.
Prerequisites (1 minute)
- Book 11, Chapter 05. Read it in Unit 1.
- PowerShell 7.1 or later, and the kit’s folder
examples/zta-results.
Unit 1: What it checks, and what it isn’t (8 minutes)
Read Book 11, Chapter 05, sections The two tools at a glance and Where they overlap, and where they don’t. Then read the guide’s Step 1. Four points to take away:
- Not a verdict. A finding is evidence for a decision a named person makes; a pass rate isn’t a maturity stage.
- Not a substitute for ScubaGear. BOD 25-01 names CISA’s SCuBA tools, and ScubaGear covers Exchange Online mail flow, Teams, SharePoint sharing and Power Platform, which the Zero Trust Assessment doesn’t test.
- Not a supported product. It is a community project maintained by Microsoft employees, provided as is.
- Not a detector. Microsoft’s own operations guidance calls it a configuration-posture check, to be paired with alerts.
The decision record in the guide’s template writes each of these down, with the scope, the run account, the cadence and the pinned version.
Unit 2: Reading the report (8 minutes)
Read the guide’s Step 6. Each test carries three ratings from Microsoft’s rubric: Risk Level (High means potential environment-wide exposure), User Impact (how many non-privileged users act or are told) and Implementation Cost (from targeted actions to programs). Each test ends in one of six statuses:
| Status | What it means |
|---|---|
| Passed | The configuration matched |
| Failed | It didn’t |
| Investigate | The tool needs a person to look before it’s a finding or not |
| Skipped | The test didn’t run, with a reason: not licensed, not connected, not applicable, not supported, timed out |
| Planned | The test is still under construction in the tool |
| Error | The test couldn’t be evaluated |
A pillar owner reads their tab with those filters and notes every Investigate, Skipped and Error result, and every Failed result whose feature may not exist in the tenant’s cloud. The guide’s example: Microsoft’s Exchange Online service description says impersonation protection and spoof intelligence aren’t yet available in GCC High and DoD, so a failed impersonation test there is a boundary finding.
Unit 3: Why skipped isn’t failed (6 minutes)
Read Book 11, Chapter 10, A normalized result taxonomy. The program records every result twice: the tool’s value, unchanged, and one of seven normalized results. A test skipped for a missing license is a licensing decision; one skipped because a service wasn’t connected is a gap in the run; neither is a failed control, and neither is a pass. Investigate counts as a finding until a person reviews it.
Exercise: Lab 1, fixtures, no tenant (12 minutes)
You read a fictional export the way the kit does, and sort its statuses. Work in examples/zta-results, with PowerShell 7.1 or later. The export is tests/fixtures/run-2026-10-27: a fictional Contoso tenant, in the shape release 3.1.0 writes.
Every command in this lab, in order, from examples/zta-results. Each step below says what it does and what to look for.
# Step 1: Read the export's metadata
$e = Get-Content -Raw tests/fixtures/run-2026-10-27/zt-export/ZeroTrustAssessmentReport.json | ConvertFrom-Json
$e | Select-Object CurrentVersion, TenantName, @{ n = 'Tests'; e = { $_.Tests.Count } }, EndOfJson | Format-List
# Step 2: Count the tool's statuses
$e.Tests | Group-Object TestStatus -NoElement | Sort-Object Name | Format-Table Name, Count
# Step 3: List what didn't run, with its reason
$e.Tests | Where-Object TestStatus -In 'Skipped', 'Planned' | Sort-Object TestId | Format-Table TestId, TestStatus, TestSkipped
# Step 4: Sort the reasons into the taxonomy
Import-Module ./powershell/ZtaResults/ZtaResults.psm1
foreach ($s in 'NotLicensedEntraWorkloadID', 'NotConnectedToService', 'NotApplicable', 'TimeoutReached') { '{0,-28} {1}' -f $s, (ConvertTo-ZtaResult -Test @{ TestId = '0'; TestStatus = 'Skipped'; TestSkipped = $s }).normalized }
'{0,-28} {1}' -f 'Investigate', (ConvertTo-ZtaResult -Test @{ TestId = '0'; TestStatus = 'Investigate' }).normalizedRead the export’s metadata. The file is the one the tool writes in its report folder, under
zt-export.$e = Get-Content -Raw tests/fixtures/run-2026-10-27/zt-export/ZeroTrustAssessmentReport.json | ConvertFrom-Json $e | Select-Object CurrentVersion, TenantName, @{ n = 'Tests'; e = { $_.Tests.Count } }, EndOfJson | Format-ListExpected output:
CurrentVersion : 3.1.0 TenantName : Contoso Tests : 33 EndOfJson : EndOfJsonEndOfJsonis the marker the tool writes last; a file without it is incomplete.Count the tool’s statuses.
$e.Tests | Group-Object TestStatus -NoElement | Sort-Object Name | Format-Table Name, CountExpected output:
Name Count ---- ----- Error 1 Failed 16 Investigate 1 Passed 8 Planned 1 Skipped 6A pass rate taken from these numbers would divide 8 by a total that moves with licensing and connections. That is why the program doesn’t report one.
List what didn’t run, with its reason.
$e.Tests | Where-Object TestStatus -In 'Skipped', 'Planned' | Sort-Object TestId | Format-Table TestId, TestStatus, TestSkippedExpected output:
TestId TestStatus TestSkipped ------ ---------- ----------- 21800 Planned UnderConstruction 21883 Skipped NotLicensedEntraWorkloadID 25416 Skipped NotApplicable 27018 Skipped NotApplicable 35005 Skipped NotConnectedToService 41050 Skipped TimeoutReached 61009 Skipped NoCompatibleLicenseFoundSort the reasons into the taxonomy with the kit’s own function.
Import-Module ./powershell/ZtaResults/ZtaResults.psm1 foreach ($s in 'NotLicensedEntraWorkloadID', 'NotConnectedToService', 'NotApplicable', 'TimeoutReached') { '{0,-28} {1}' -f $s, (ConvertTo-ZtaResult -Test @{ TestId = '0'; TestStatus = 'Skipped'; TestSkipped = $s }).normalized } '{0,-28} {1}' -f 'Investigate', (ConvertTo-ZtaResult -Test @{ TestId = '0'; TestStatus = 'Investigate' }).normalizedExpected output:
NotLicensedEntraWorkloadID Skipped-Licensing NotConnectedToService Skipped-Disconnected NotApplicable Skipped-Not-Applicable TimeoutReached Unable-to-Evaluate Investigate FailFour skips, four different meanings, and none of them a failure. The Investigate result is a finding until someone reviews it (Module 3).
Knowledge check (5 minutes)
- An agency already runs the Zero Trust Assessment monthly. Can it stop running ScubaGear?
- Yes: the Zero Trust Assessment covers identity, which is most of the SCuBA baselines.
- No: BOD 25-01 names CISA’s SCuBA tools, and ScubaGear covers Exchange Online, Teams, SharePoint and Power Platform policies the Zero Trust Assessment doesn’t test.
- Only in GCC High.
- A test is Skipped with
NotLicensedEntraIDP2. How is it counted?- As a failed control.
- As a pass, because nothing was found.
- As Skipped-Licensing: a licensing decision, neither a failure nor a pass.
- What does Investigate mean?
- The test failed and the tool wants a ticket opened.
- The tool needs a person to look; it counts as a finding until the review confirms or dismisses it.
- The test is under construction.
- A failed anti-phishing impersonation test in a GCC High tenant is most likely:
- a boundary finding, because Microsoft’s service description says the feature isn’t yet available there;
- a configuration change to make today;
- a reason to report the tenant to CISA.
- Which of these does the Zero Trust Assessment do?
- Detect an attack in real time.
- Read the tenant’s configuration and compare it with Microsoft’s guidance, without changing anything.
- Close a finding when the next run passes.
- b. See Book 11, Chapter 05 and Unit 1.
- c. See Unit 3 and the guide’s Step 7.
- b. See Unit 2.
- a. See Unit 2 and the guide’s Step 6.
- b. It is read-only and a posture check; closure is the authorizing official’s or assessor’s decision (Book 11, Chapter 10).
Summary (2 minutes)
You saw what the Zero Trust Assessment checks and what it isn’t, read its rubric and statuses, and sorted a fictional export’s skips into Book 11’s taxonomy. Evidence an ISSO keeps from this module: the approved decision record, and each pillar owner’s dated reading notes.