Federal Modernization Workbook
Command Reference
The example kits in the repository’s examples folder hold 795 commands: 67 PowerShell scripts, 679 functions their PowerShell modules export, and 49 Python tools. This page lists each one with its synopsis and the pages that teach it. The text comes from each command’s own help, so the page and the help always agree.
Getting help for a command
| Kind | Full help | Examples only |
|---|---|---|
| PowerShell script | Get-Help ./Invoke-Example.ps1 -Full |
Get-Help ./Invoke-Example.ps1 -Examples |
| PowerShell function | Import-Module ./powershell/Module/Module.psm1, then Get-Help Verb-Noun -Full |
Get-Help Verb-Noun -Examples |
| Python tool | python tool.py --help |
the examples at the top of the file |
-? after any PowerShell script or function prints its syntax and synopsis. Windows’ /? isn’t a PowerShell or Python convention and isn’t supported. Run a kit’s commands from the kit’s folder, as its README says; the chapters walk through them in order.
Kits
| Kit | Scripts | Functions | Python tools | README |
|---|---|---|---|---|
| ansible | 0 | 0 | 1 | README |
| cisco-sdwan | 0 | 0 | 1 | README |
| dp-consolidation | 8 | 16 | 0 | README |
| drift-pipeline | 0 | 0 | 11 | README |
| dynamic-rules | 1 | 16 | 0 | README |
| group-policy-as-code | 1 | 12 | 0 | README |
| hcm-entra | 2 | 17 | 2 | README |
| hr-lifecycle | 0 | 0 | 13 | README |
| lifecycle-extensions | 0 | 0 | 1 | README |
| machine-configuration | 2 | 11 | 0 | README |
| ms-automation | 0 | 36 | 3 | README |
| non-person-identity | 22 | 240 | 0 | README |
| privileged-access | 15 | 137 | 0 | README |
| provider-notices | 8 | 46 | 0 | README |
| servicenow-sailpoint | 2 | 41 | 15 | README |
| start-kit | 1 | 51 | 0 | README |
| ttm-task-catalog | 0 | 0 | 2 | README |
| validation-kit | 1 | 49 | 0 | README |
| zta-results | 4 | 7 | 0 | README |
ansible
| Command | Kind | What it does | Taught in |
|---|---|---|---|
cmdb_inventory.py |
Python tool | Dynamic inventory from a CMDB export: the CMDB is the attribute source, Ansible reads it. | Chapter 08 — Ansible Beside Arc Ansible for Configuration Automation |
cisco-sdwan
| Command | Kind | What it does | Taught in |
|---|---|---|---|
sdwan_evidence.py |
Python tool | Read-only evidence collector for a Cisco Catalyst SD-WAN fabric (illustrative). | — |
dp-consolidation
| Command | Kind | What it does | Taught in |
|---|---|---|---|
Get-DpcSizing.ps1 |
Script | Step 1: size the hub tier from the inventory against Microsoft’s published limits, and order the offices into retirement waves by circuit readiness and renewal date. Read-only. | — |
Invoke-DpcInventory.ps1 |
Script | Step 0: read the existing content estate (distribution points, boundary groups, site system roles, distribution status, clients per boundary group, applications, packages, task sequence deployments) and write hashed, control-tagged evidence. Read-only. | — |
Invoke-DpcOfficeRetirement.ps1 |
Script | Step 6: retire one office distribution point in three steps: Check (read-only go/no-go), Drain (take it out of its boundary groups) and Remove (remove the DP role, then the site system server if nothing else is on it). Drain and Remove are dry runs unless -Apply. | — |
New-DpcHubTier.ps1 |
Script | Step 3: build the hub tier. Plan, and with -Apply make, the pull distribution points at each hub, one distribution point group per hub, and the content distributed to each group. Dry run by default. | — |
Set-DpcBoundaryGroups.ps1 |
Script | Step 4: point office boundary groups at their hub. Plan, and with -Apply make, the boundary group changes for one wave of offices: hub DPs added as content sources, peer download options set, and fallback to the other hubs. Dry run by default. | — |
Set-DpcPeerCache.ps1 |
Script | Step 5: plan, and with -Apply make, the client settings that keep content in the office: a peer cache source setting for chosen clients, and BranchCache, cache size and Delivery Optimization for every office client. Dry run by default. | — |
Test-DpcPackaging.ps1 |
Script | Step 7: check the application catalog against the packaging standard. For every application, report whether its source is wrapped in PSAppDeployToolkit (and which major version), and the action the standard asks for. Read-only. | — |
Test-DpcRetirementGates.ps1 |
Script | Step 9: judge the five retirement gates from an inventory run. Read-only. Exit code 0 when all five are closed, 2 when any is open. | — |
Module DpConsolidation
powershell/DpConsolidation/DpConsolidation.psm1
| Function | What it does | Taught in |
|---|---|---|
Get-DpcTag |
Return the controls and KSIs the kit tags an evidence file with. | — |
Get-DpcOsStandard |
Judge a Windows Server build number against the workbook’s Windows Server 2019 minimum. | — |
Get-DpcServerName |
Extract a server FQDN from a Configuration Manager NAL path or network OS path. | — |
Get-DpcSha256 |
SHA-256 of a file, lower-case hex. | — |
New-DpcRun |
Start an evidence run: create the output folder and return the run record. | — |
Write-DpcEvidence |
Write one evidence table as CSV and JSON, tagged with its controls and KSIs. | — |
Complete-DpcRun |
Finish a run: write manifest.json with the SHA-256 of every file the run wrote. | — |
Test-DpcManifest |
Re-hash every file a manifest lists and report any that changed. Returns $true when all match. | Distribution Point Consolidation: An Implementation Guide |
Read-DpcJson |
Read a JSON file as objects (an array stays an array). | — |
Read-DpcRows |
Read an evidence table the kit wrote (the rows of |
— |
Test-DpcSubnetMatch |
True when a client’s subnet ID matches an IP subnet boundary value (with or without a /prefix). | — |
Get-DpcPsadtInfo |
Detect whether a package source folder is wrapped in PSAppDeployToolkit, and which version. | — |
Format-DpcCommand |
Render a planned cmdlet call as the exact command line a reader could run. | — |
New-DpcPlanItem |
One planned change: the step, the target, the cmdlet and its parameters, and the rollback. | — |
Invoke-DpcPlan |
Run a change plan. Without -Apply it only records the plan (dry run); with -Apply it calls each cmdlet, honoring -WhatIf through the calling script’s ShouldProcess. | — |
Connect-DpcSite |
Import the ConfigurationManager module and change to the site drive, as Learn’s getting-started page shows. | — |
drift-pipeline
| Command | Kind | What it does | Taught in |
|---|---|---|---|
adm_deploy.py |
Python tool | One environment settings file for the Attribute-Driven Migration deployment runbook. | Chapter 10 — Deploying to Test and Production |
evidence.py |
Python tool | Evidence records for the Attribute-Driven Migration deployment runbook, and the check that each requirement has one. | Chapter 10 — Deploying to Test and Production Chapter 08 — Deploying to a Test Tenant, Then to Production |
preflight.py |
Python tool | Pre-flight checks before the Attribute-Driven Migration deploys to a test environment or production. | Chapter 10 — Deploying to Test and Production Chapter 08 — Deploying to a Test Tenant, Then to Production |
rollback.py |
Python tool | Record each change a deployment stage makes, and write the rollback for them, newest first. | Chapter 10 — Deploying to Test and Production Chapter 08 — Deploying to a Test Tenant, Then to Production |
smoke_test.py |
Python tool | Smoke test after an Attribute-Driven Migration deployment stage: read what the kits wrote and say go or no-go. | Chapter 10 — Deploying to Test and Production Chapter 08 — Deploying to a Test Tenant, Then to Production |
drift_pipeline.py |
Python tool | Drift pipeline: compare two validation kit runs, draft findings, and package evidence for the ISSO. | Chapter 09 — Drift Pipelines and Evidence to the ISSO Chapter 10 — Deploying to Test and Production |
hr_evidence.py |
Python tool | HR-driven identity evidence: package each lifecycle drift run for the ISSO with a SHA-256 per file, the | Chapter 09 — Drift Pipelines and Evidence to the ISSO Chapter 07 — Lifecycle Drift, Metrics and Evidence |
npi_evidence.py |
Python tool | Non-person identity evidence: package each drift run for the ISSO with a SHA-256 per file, the tenant | Chapter 09 — Drift Pipelines and Evidence to the ISSO Chapter 07 — Lifecycle Drift, Metrics and Evidence |
oscal_export.py |
Python tool | Turn a drift pipeline evidence package into NIST OSCAL JSON: Assessment Results and a POA&M. | Chapter 09 — Drift Pipelines and Evidence to the ISSO Appendix D — Security Assessment Report Template |
pa_evidence.py |
Python tool | Privileged access evidence: compare two evidence runs, draft findings without names, package each | Chapter 09 — Drift Pipelines and Evidence to the ISSO Chapter 07 — Lifecycle Drift, Metrics and Evidence |
workflow_lint.py |
Python tool | Offline checks for a GitHub Actions workflow that signs in to Azure with a federated credential. | Chapter 09 — Drift Pipelines and Evidence to the ISSO Chapter 10 — Deploying to Test and Production |
dynamic-rules
| Command | Kind | What it does | Taught in |
|---|---|---|---|
Invoke-DrLibraryCheck.ps1 |
Script | The pull request check for the rule library: lint every rule, run every rule’s membership tests, and for each rule file changed since -BaseRef, show whom the change adds and removes. | — |
Module DynamicRules
| Function | What it does | Taught in |
|---|---|---|
New-DrFinding |
Creates one finding row (Severity, Rule, Group, Issue, Detail), the shape the linter and the library tests return. | — |
Get-DrTokens |
Splits a dynamic membership rule into tokens: parentheses, brackets, commas, strings, operators (without the leading hyphen) and words such as property paths and literals. | — |
ConvertFrom-DrRule |
Parses a dynamic membership rule into a tree of nodes, with Learn’s precedence: comparisons, then -not, -and, -or. Throws when the rule doesn’t parse. | Chapter 04 — Dynamic Rules as Code |
Get-DrRuleNodes |
Returns every node of a parsed rule tree, depth first, starting with the root. | — |
Get-DrRuleObjectType |
Returns user, device, mixed or none, from the property prefixes a parsed rule reads. A direct reports rule is a user rule. | — |
Test-DrMember |
Returns whether one fixture object satisfies a rule, by the offline evaluator. An object whose objectType differs from the rule’s type is never a member. | Chapter 04 — Dynamic Rules as Code |
Get-DrMembers |
Returns the key of every population object a rule selects, by the offline evaluator. | Chapter 04 — Dynamic Rules as Code Attribute-Driven Migration, Module 3: Keep Dynamic Rules as Code |
Get-DrLibrary |
Reads every rules/*.json file in name order and adds its file name. Throws when displayName, kind, membershipRule or owner is missing, or kind isn’t user or device. | Chapter 04 — Dynamic Rules as Code Chapter 10 — Deploying to Test and Production |
Test-DrRule |
Lints one dynamic membership rule and returns finding rows for rules DR-01 to DR-10, such as a parse error, a missing guard, a display-name attribute or a slow operator. | Chapter 04 — Dynamic Rules as Code Attribute-Driven Migration, Module 3: Keep Dynamic Rules as Code |
Invoke-DrLibraryTest |
Lints every rule in the library and runs each rule’s membership tests against the population. Returns finding rows; DR-11 is a failed test. | — |
Compare-DrRule |
Shadow diff offline: returns who a proposed rule adds and removes compared with the current rule, over a fixture population, with both member counts. | Chapter 04 — Dynamic Rules as Code |
Get-DrGraphEndpoint |
Returns the Microsoft Graph host for a cloud: Global, USGov or USGovDoD. An unknown name throws; there is no default. | Chapter 02 — Graph Clients for the Government Clouds Chapter 04 — Dynamic Rules as Code |
Get-DrDynamicCollections |
Lists every dynamic group and dynamic administrative unit with its processing state, through the Graph script block in -Invoke, following @odata.nextLink. | Chapter 04 — Dynamic Rules as Code |
New-DrPauseManifest |
Records every dynamic group and administrative unit with its processing state before anything is paused, so a later resume touches only what the incident paused. | Chapter 04 — Dynamic Rules as Code |
Invoke-DrPause |
Pauses the collections that were On when the manifest was taken, except those in -Except, and records each in the manifest. Without -Apply it only returns what it would pause. | Chapter 04 — Dynamic Rules as Code |
Invoke-DrResume |
Resumes only collections this manifest paused: the -Ids given at any time, otherwise the next -BatchSize after -WaitHours have passed. Without -Apply it only returns what it would resume. | Chapter 04 — Dynamic Rules as Code |
group-policy-as-code
| Command | Kind | What it does | Taught in |
|---|---|---|---|
Invoke-GpcSync.ps1 |
Script | The pull request and release step for the settings catalog library: lint, read the tenant, diff, and with -Apply create the policies that are missing. | — |
Module GroupPolicyAsCode
powershell/GroupPolicyAsCode.psm1
| Function | What it does | Taught in |
|---|---|---|
Get-GpcCloud |
Returns the Graph host and Connect-MgGraph environment name for a cloud: gcc, global, gcchigh or dod. An unknown name throws. | Chapter 06 — Moving Group Policy as Code |
Get-GpcRequiredScope |
Returns the least-privileged delegated Graph permission for an action: DeviceManagementConfiguration.Read.All for Plan and DryRun, ReadWrite.All for Apply. | Chapter 06 — Moving Group Policy as Code |
Get-GpcMovePlan |
One row per imported Group Policy setting, from Intune’s Group Policy analytics (beta), with a disposition: Candidate, Conflict, EndpointSecurity, NoCatalogSetting, NotSupported, Deprecated or Unknown. GET only. | Chapter 06 — Moving Group Policy as Code Attribute-Driven Migration, Module 4: Move Group Policy as Code |
Read-GpcLibrary |
Reads every *.json file in the policy library folder, in name order, and returns each with its file name, path, SHA-256, data and policy body. Throws on a missing folder or invalid JSON. | Chapter 06 — Moving Group Policy as Code Attribute-Driven Migration, Module 4: Move Group Policy as Code |
Test-GpcLibrary |
Lint the policy library. Rules GPC-01 to GPC-10; the README lists them. | Chapter 06 — Moving Group Policy as Code Attribute-Driven Migration, Module 4: Move Group Policy as Code |
ConvertTo-GpcCanonical |
Returns one canonical JSON string for a setting instance, so a library file and the tenant’s copy compare equal when they mean the same thing. | Chapter 06 — Moving Group Policy as Code |
Get-GpcTenantPolicy |
The tenant’s settings catalog policies whose names are in -Name, with their settings. GET only. | Chapter 06 — Moving Group Policy as Code |
Compare-GpcPolicy |
Compares one library policy body with one tenant policy from Get-GpcTenantPolicy. Returns the settings added, removed and changed, the differing properties, and Same. | — |
Compare-GpcLibrary |
The diff between the library and the tenant: Create, NoChange, Drift or Duplicate per policy. | Chapter 06 — Moving Group Policy as Code |
Invoke-GpcSync |
Lint, read the tenant, diff, and (with -Apply) create the policies that are missing. | Chapter 06 — Moving Group Policy as Code Chapter 10 — Deploying to Test and Production |
New-GpcFixtureInvoke |
A fake Graph for labs and tests, served from a fixture tenant file. Nothing leaves the machine. | Chapter 06 — Moving Group Policy as Code Attribute-Driven Migration, Module 4: Move Group Policy as Code |
Invoke-GpcFakeGraph |
Answers one Graph call from the fixture tenant behind New-GpcFixtureInvoke and records it in the state’s Calls. Serves only the routes this example reads and the one POST it sends. | — |
hcm-entra
| Command | Kind | What it does | Taught in |
|---|---|---|---|
hcm_correlate.py |
Python tool | Correlate an Oracle Fusion Cloud HCM extract with Active Directory and Microsoft Entra ID on the person key. | Building Book 03’s HR Pipeline: Oracle Fusion Cloud HCM to Microsoft Entra ID |
hcm_to_scim.py |
Python tool | Convert an Oracle Fusion Cloud HCM extract (CSV) into SCIM bulk requests for | Chapter 01 — The HR-to-Entra Middleware Chapter 10 — Deploying to Test and Production |
Invoke-HcmCorrelation.ps1 |
Script | Correlate an HCM extract with Active Directory and Entra ID on the person key: matched, unmatched both ways, duplicates and conflicting values, with a quarantine report. | — |
Invoke-HcmToScim.ps1 |
Script | Dry-run-first wrapper: convert an HCM extract to SCIM bulk requests and, only with -Apply, POST them. | — |
Module HcmCorrelation
powershell/HcmCorrelation.psm1
| Function | What it does | Taught in |
|---|---|---|
Read-HcmEntraExport |
Read a saved Entra ID users export (a JSON array of Graph users, or a saved {“value”: […]} page) and return the member users; guests are left out. | — |
Invoke-HcmCorrelationJoin |
The join: every key’s status, conflicts and reasons, the counts and rates, and the quarantine entries. Rows are the extract and the AD export as Import-Csv reads them; EntraUsers is $null when no Entra export was given. | — |
Get-HcmCorrelationReport |
Build the correlation report’s content from a join result: keys, statuses, counts, rates and conflict field names, with no names and no values. | — |
Module HcmToScim
| Function | What it does | Taught in |
|---|---|---|
Get-HcmMapping |
Read the field mapping file (config/mapping.json) into a hashtable. | — |
Get-HcmSettings |
Read a settings JSON file and return it merged with the defaults and checked by Test-HcmSettings. A key that looks like a secret is refused. | — |
Test-HcmSettings |
Merge defaults, refuse secrets, and check formats. Returns the merged settings. | — |
Test-HcmEndpoint |
Return the endpoint unchanged when it is an https Microsoft Graph /bulkUpload URL for one provisioning job (graph.microsoft.com, graph.microsoft.us or dod-graph.microsoft.us); otherwise throw. | — |
ConvertTo-HcmCanonicalJson |
Convert a value to canonical JSON: sorted keys (ordinal), no whitespace, UTF-8 characters kept. Matches Python’s json.dumps(sort_keys=True, separators=(‘,’, ‘:’), ensure_ascii=False). | — |
Get-HcmSha256 |
Return the lowercase hex SHA-256 of a value’s canonical JSON. | — |
Get-HcmFileSha256 |
Return the SHA-256 of a file’s bytes, so the manifest names the exact extract and mapping used. | — |
Get-HcmProvenance |
Build the run’s provenance manifest: which inputs produced which batches, by hash and person key. No names and no payloads; each batch_sha256 matches apply-results.json for that batch. | — |
ConvertTo-HcmUtcIso |
Combine a date, a local time and a UTC offset into a UTC timestamp (yyyy-MM-ddTHH:mm:ssZ). | — |
ConvertTo-HcmScimOperation |
Validate one extract row and build its SCIM bulk operation. Fail closed: a row with any problem comes back quarantined, with its reasons and no operation. | Chapter 01 — The HR-to-Entra Middleware |
Convert-HcmExtract |
Convert all extract rows into SCIM bulk request batches: validate each row, settle duplicates (a separation wins), order leavers first and managers before their reports, and hold the run when disables or calls exceed the limits in the settings. | — |
Get-HcmReport |
Build the operational report from a conversion result: person key and payload hash only, never the payload. | — |
Get-HcmQuarantineEntry |
Return the quarantine entries (Book 03, Appendix A) from a conversion result. They contain personal data: write them only to the access-controlled audit store. | — |
Invoke-HcmBulkUpload |
POST each batch to the provisioning job’s /bulkUpload endpoint, paced below the documented limit, honoring Retry-After on 429 and 503. Stops at the first batch that isn’t accepted (202). | — |
hr-lifecycle
lifecycle-extensions
| Command | Kind | What it does | Taught in |
|---|---|---|---|
lcwext.py |
Python tool | Lifecycle Workflows custom task extensions as code: lint a Logic App workflow definition, | Chapter 05 — Lifecycle Workflows Custom Extensions Chapter 10 — Deploying to Test and Production |
machine-configuration
| Command | Kind | What it does | Taught in |
|---|---|---|---|
TlsServerProtocols.ps1 |
Script | Defines the TlsServerProtocols DSC configuration, which audits that the server side of TLS 1.0 and TLS 1.1 is disabled in the SCHANNEL registry keys. Dot-source it, then run it to compile a MOF. | Chapter 07 — Machine Configuration Packages Attribute-Driven Migration, Module 5: Build Machine Configuration Packages |
Invoke-McBuild.ps1 |
Script | Build one machine configuration release offline: compile, clean the MOF, package and write the policy definition with Learn’s GuestConfiguration cmdlets, check both, and write provenance.json. | — |
Module McPipeline
| Function | What it does | Taught in |
|---|---|---|
Get-McFileSha256 |
Returns the SHA-256 of a file’s bytes as lowercase hex, the form provenance.json uses. | — |
Get-McReleaseEntry |
Returns one configuration’s entry from the release registry (config/releases.json), with its name added. Throws when the entry is missing, incomplete, or has an unknown mode or a non-GUID policy ID. | — |
Get-McPackageType |
Returns the package type New-GuestConfigurationPackage needs for a policy mode: Audit for Audit, AuditAndSet for ApplyAndMonitor and ApplyAndAutoCorrect. | — |
ConvertTo-McCleanMof |
Rewrites a compiled MOF without build-host data and with each instance’s properties sorted, so the same configuration gives the same bytes on any host. Writes -Destination and returns the file. | Chapter 07 — Machine Configuration Packages |
Test-McMofText |
Checks MOF text for build-host data or an absolute build path (MC-PKG-04) and for anything that looks like a secret (MC-PKG-05). Returns finding rows. | Chapter 07 — Machine Configuration Packages Attribute-Driven Migration, Module 5: Build Machine Configuration Packages |
Get-McMofModules |
Returns the module name and version pairs a MOF’s resources import, sorted, excluding the configuration document. | — |
Test-McPackage |
Inspects a package .zip without expanding it and returns findings for rules MC-PKG-01 to MC-PKG-07. An empty result means the package passed. | Chapter 07 — Machine Configuration Packages Attribute-Driven Migration, Module 5: Build Machine Configuration Packages |
Get-McSasExpiry |
Returns the signed expiry (se=) of a SAS URI as a DateTimeOffset, or $null when it has none. | — |
Test-McPolicy |
Checks a policy definition New-GuestConfigurationPolicy wrote against its package and the release registry entry, and returns findings for rules MC-POL-01 to MC-POL-09. | Chapter 07 — Machine Configuration Packages |
Get-McProvenance |
Builds the provenance manifest for one build: what was built, the hashes of the cleaned MOF, package and definition, the module versions, and the finding counts. | — |
New-McFinding |
Creates one finding row (Severity, Rule, Issue, Detail), the shape the package and policy checks return. | — |
ms-automation
| Command | Kind | What it does | Taught in |
|---|---|---|---|
arc_tasks.py |
Python tool | Read-only Azure Arc and Azure Policy checks through Azure Resource Graph, for the workbook’s Module 4. | Microsoft Automation, Module 4: Azure Arc through Azure Resource Manager and Resource Graph |
entra_tasks.py |
Python tool | Read-only Microsoft Entra ID checks through Microsoft Graph, for the workbook’s Module 2. | Chapter 02 — Graph Clients for the Government Clouds Microsoft Automation, Module 2: Microsoft Entra ID through Microsoft Graph |
intune_tasks.py |
Python tool | Read-only Microsoft Intune checks through Microsoft Graph, for the workbook’s Module 3. | Microsoft Automation, Module 3: Intune through Microsoft Graph |
Module FmwArm
| Function | What it does | Taught in |
|---|---|---|
Connect-FmwAzure |
Signs in to the Azure cloud that matches the tenant, as an app with a certificate or as a managed identity. | Microsoft Automation, Module 4: Azure Arc through Azure Resource Manager and Resource Graph |
Get-FmwArgRows |
Runs a Resource Graph query and returns every row, paging with -SkipToken. | Microsoft Automation, Module 4: Azure Arc through Azure Resource Manager and Resource Graph |
Get-FmwArcLifecycleTable |
Reads the product lifecycle table (arc-lifecycle.json), longest product name first. | — |
Test-FmwArcExtension |
Arc servers missing a required extension, and extensions not in the Succeeded state. | — |
Test-FmwArcPrivateLink |
Arc servers not assigned to an Azure Arc private link scope, so they reach Azure over public endpoints. | Microsoft Automation, Module 4: Azure Arc through Azure Resource Manager and Resource Graph |
Test-FmwArcLifecycle |
Arc servers and SQL Server instances on products past, or near, the end of support. | Microsoft Automation, Module 4: Azure Arc through Azure Resource Manager and Resource Graph |
Test-FmwArcSql |
SQL Server instances enabled by Arc: counts by version and edition, and instances whose host isn’t a connected Arc machine in scope. | — |
Test-FmwArcPolicy |
Per policy assignment: enforcement mode and compliance counts; flags DoNotEnforce and noncompliant assignments. | — |
Invoke-FmwArcTask |
Runs one Arc check against Azure (after Connect-FmwAzure) and returns its result with the controls it evidences. Read-only. | Microsoft Automation, Module 4: Azure Arc through Azure Resource Manager and Resource Graph |
Module FmwGraph
| Function | What it does | Taught in |
|---|---|---|
Get-FmwCloud |
Returns the sign-in, Graph and Azure Resource Manager endpoints and the Connect-MgGraph environment name for a cloud. GCC uses the worldwide service; GCC High and DoD have their own. | Chapter 02 — Graph Clients for the Government Clouds Microsoft Automation, Module 1: Graph and Azure Foundations |
Connect-FmwGraph |
Signs in to Microsoft Graph app-only in the chosen cloud, with a certificate or a managed identity (never a client secret), and remembers the cloud for later calls. | Chapter 02 — Graph Clients for the Government Clouds Chapter 10 — Deploying to Test and Production |
Get-FmwGraphCollection |
Returns every item of a Graph collection, following @odata.nextLink. Each page is checked with Assert-FmwGraphCall (cloud host, declared calls) before it is sent. | Chapter 02 — Graph Clients for the Government Clouds |
Get-FmwGraphCall |
Returns the Graph calls declared in graph-calls.json, or only those for one task. Throws when no call is declared for the task. | — |
Get-FmwCallPermission |
Returns the least-privileged permissions a task’s declared Graph calls need, sorted and without duplicates. | Chapter 02 — Graph Clients for the Government Clouds Microsoft Automation, Module 1: Graph and Azure Foundations |
Assert-FmwGraphCall |
Checks one Graph call before it is sent: the URI must stay on the cloud’s Graph host, and the call must be declared in graph-calls.json for the task. Throws on a refused call; returns the matching call. | Chapter 02 — Graph Clients for the Government Clouds Microsoft Automation, Module 1: Graph and Azure Foundations |
Get-FmwBetaCollection |
Reads a beta collection without depending on it. A refused call, or a 400, 404 or 501 from Graph, returns available = false with the reason instead of an error. | Chapter 02 — Graph Clients for the Government Clouds |
Get-FmwTokenRole |
Returns the roles claim (application permissions) of an access token. The token is decoded, not validated: this is a pre-flight check only. | — |
Test-FmwTokenRole |
Compares a token’s roles with the permissions a task needs. Returns Missing (needed, not held) and Extra (held, not used). | Chapter 02 — Graph Clients for the Government Clouds |
Test-FmwSessionRole |
Compares the permissions of the current app-only Graph PowerShell session (Get-MgContext Scopes) with those a task needs, and returns Missing and Extra. Throws when there is no session or it is delegated. | Chapter 02 — Graph Clients for the Government Clouds |
Assert-FmwSessionRole |
Stops before a live task when the Graph session lacks a permission the task’s calls need, and warns for each permission the session holds that the task doesn’t use. | Chapter 02 — Graph Clients for the Government Clouds |
Test-FmwStaleUser |
Lists enabled member accounts with no interactive or non-interactive sign-in for -Days days as of -AsOf, skipping accounts created within that window. Makes no Graph call. | Microsoft Automation, Module 2: Microsoft Entra ID through Microsoft Graph |
ConvertTo-FmwCaExport |
Summarizes Conditional Access policies (name, state, grant controls, report-only) with counts by state, and keys the full policies and named locations by ID for export. Makes no Graph call. | — |
Test-FmwPim |
Checks role assignments against ScubaGear MS.AAD.7.1v1 (2 to 8 Global Administrators) and MS.AAD.7.4v1 (no permanent active assignment to a privileged role). Makes no Graph call. | Microsoft Automation, Module 2: Microsoft Entra ID through Microsoft Graph |
Test-FmwAppCredential |
Lists every application password and certificate with its lifetime and days left, flagged against ScubaGear MS.AAD.5.5v1, 5.6v1 and 5.7v1, and marked expired or expiring. Makes no Graph call. | — |
Test-FmwMfaRegistration |
Counts members who aren’t MFA registered or have no phishing-resistant method, and lists admins without one, toward ScubaGear MS.AAD.3.1v1. Makes no Graph call. | — |
Invoke-FmwEntraTask |
Runs one read-only Entra ID task after Connect-FmwGraph: checks the session’s permissions, reads the data from Graph and returns the findings. For ca-export, -OutDirectory also writes the policies as JSON. | Chapter 02 — Graph Clients for the Government Clouds Chapter 10 — Deploying to Test and Production |
ConvertTo-FmwUtc |
Converts a string, DateTime or DateTimeOffset to a UTC DateTimeOffset. Returns $null for an empty value. | — |
Format-FmwUtc |
Formats a date as a UTC ISO 8601 string ending in Z, such as 2026-07-01T00:00:00Z. Returns $null for $null. | — |
Get-FmwIntunePermission |
Returns the least-privileged application permissions for one Intune task, or the sorted union for all of them. | — |
Test-FmwIntuneNoncompliant |
Lists managed devices whose compliance state needs attention (noncompliant, in grace period, error or conflict) with the policies that report them failing, and counts by state. | — |
Test-FmwIntuneComplianceCoverage |
Finds compliance policies with no assignment or only exclusions, and managed devices that no compliance policy reports on. Also lists device names that aren’t unique. | — |
Test-FmwIntuneStaleCheckin |
Lists managed devices whose last Intune sync is at least -ValidityDays old, or that never synced, banded as beyondValidity, beyondCleanup (-CleanupDays) or noSync. | Microsoft Automation, Module 3: Intune through Microsoft Graph |
Test-FmwIntunePosture |
Lists devices that don’t report encryption on the platforms in -EncryptionOs, or whose OS version is below the floor for their platform in -OsFloors, with counts. | Microsoft Automation, Module 3: Intune through Microsoft Graph |
Test-FmwAutopilotProfile |
Counts Windows Autopilot registrations by deployment profile assignment status (a beta-only property) and lists every one that isn’t assignedInSync. | — |
Test-FmwVersionBelow |
Returns $true when a dotted version is lower than -Floor, compared part by part. A missing or non-numeric part counts as 0. | — |
Invoke-FmwIntuneTask |
Runs one read-only Intune task after Connect-FmwGraph: checks the session’s permissions, reads devices and compliance policies from Graph and returns the findings. autopilot-profiles reads beta. | Chapter 02 — Graph Clients for the Government Clouds Microsoft Automation, Module 3: Intune through Microsoft Graph |
non-person-identity
| Command | Kind | What it does | Taught in |
|---|---|---|---|
Invoke-NpiAgentCaAction.ps1 |
Script | Chapter 09: the separate write path for the agent Conditional Access plan. Creates only the report-only Block policies the reviewed plan lists, and only when the plan’s SHA-256 is the one a reviewer approved. Dry run unless -Apply. A live run is a person signed in with Conditional Access Administrator, never an unattended app. | — |
Invoke-NpiAgentId.ps1 |
Script | Chapter 09: read the AI agent identities and blueprints (or, where decision D-NP6 says agent identities aren’t available, the service principals the agents run as), check them against the program’s rules, fill in the sponsor fields Chapter 02 recorded, and write the findings, the orphan candidates for Chapter 02’s orphan rule, and a dry-run plan for the two agent Conditional Access policies with its SHA-256. Read only: the plan is applied, after review, by Invoke-NpiAgentCaAction.ps1. | — |
Invoke-NpiCredentialAction.ps1 |
Script | Chapter 04’s separate, reviewed write path: apply a policy plan or a rotation plan that a reviewer approved by its SHA-256. A dry run unless -Apply. Live runs are delegated only: a person signed in with Cloud Application Administrator (and, for a rotation, Key Vault Certificates Officer on the vault), never an unattended app. | — |
Invoke-NpiCredentialPolicy.ps1 |
Script | Chapter 04: read the tenant’s app management policies and each app registration’s app instance lock, compare them with the reviewed file (config/app-management-policy.json), and write the diff, the findings and the policy plan with its SHA-256 for review. Read only: the plan is applied, after review, by Invoke-NpiCredentialAction.ps1. | — |
Invoke-NpiDriftRun.ps1 |
Script | Chapter 10: one scheduled drift run. Runs Chapter 01’s inventory and Chapter 02’s ownership check unchanged, reads the credential and consent events in the directory audit log for the window and the service principal sign-in activity report, compares the register with the approved baseline by fingerprint, reads the review records and findings Chapters 03 to 09 hand over, and writes one run folder with run.json. Read only. examples/drift-pipeline/python/npi_evidence.py packages it. | — |
Invoke-NpiFederation.ps1 |
Script | Chapter 05: workload identity federation and managed identities, wave by wave. Plan (the default): read the tenant for each reviewed conversion, check each federated credential against what the workload’s issuer will present, run the token exchange test against the fake token endpoint, and write the plan, the findings, the conversion records and the parallel run status. Nothing is written to the tenant. Apply: the separate, delegated write path. A dry run unless -Apply; refuses a plan whose SHA-256 isn’t the approved one. | — |
Invoke-NpiInventory.ps1 |
Script | Chapter 01: read every non-person identity into one register (AD service accounts, MSAs, gMSAs, dMSAs, app registrations, service principals, managed identities, federated credentials, Graph application permissions and consent grants), classify it, report the findings, and write the run with a manifest. Read only. | — |
Invoke-NpiKerberosIsland.ps1 |
Script | Chapter 06: read the Kerberos accounts in Chapter 01’s register and the domain (the KDS root key, read-only; the managed service accounts and their retrievers; dMSA migration state; domain controllers and hosts), check them against the owners’ D-NP3 dispositions from Chapter 03’s run (checked against its manifest) and the program’s dates, and write the findings, the plan (dry run, for review), the island list for the program’s SPN retirement (P4.6) and the reconciliation with the provisional end state (D11). Read only: the plan is applied, after review, by Invoke-NpiKerberosIslandAction.ps1. | — |
Invoke-NpiKerberosIslandAction.ps1 |
Script | Chapter 06’s separate, reviewed write path: apply a Kerberos plan that a reviewer approved by its SHA-256. A dry run unless -Apply. A live run is a person’s session against a read-write domain controller, never a scheduled job or a service account, and never deletes, uninstalls, undoes or resets anything. | — |
Invoke-NpiLeastPrivilege.ps1 |
Script | Chapter 07: the permission sweep over Chapter 01’s register. Reads every service principal’s application permissions and delegated grants, its directory roles, and each managed identity’s Azure role assignments; checks broad permissions against the reviewed list and its exceptions; hands privileged service principals to the Privileged Access plan; writes the quarterly owner review packet and, from the owners’ decisions, a dry-run plan with its SHA-256. Read only: the plan is applied, after review, by Invoke-NpiLeastPrivilegeAction.ps1. | — |
Invoke-NpiLeastPrivilegeAction.ps1 |
Script | Chapter 07’s separate, reviewed write path: apply a least-privilege plan that a reviewer approved by its SHA-256. A dry run unless -Apply. It removes app role assignments (through the resource service principal) and narrows delegated grants; it never deletes a service principal or an application. Live runs are delegated only: a person signed in with Privileged Role Administrator, never an unattended app. | — |
Invoke-NpiMatrix.ps1 |
Script | Chapter 03: the migration path matrix as code. Reads Chapter 01’s register and Chapter 02’s ownership run (both checked against their manifests), proposes a target for every identity from config/migration-matrix.json (NP2.1), checks the application owners’ dispositions (D-NP3), sequences the waves with HIGH-risk accounts first and a rollback per wave (NP2.2), checks the Workload ID Premium scope decision (D-NP4) against the tenant’s subscriptions, and reports Gate 2. Read only: two declared GETs (config/calls-ch03.json); nothing is written to the tenant. | — |
Invoke-NpiOrphanAction.ps1 |
Script | Chapter 02’s separate, reviewed write path: apply an orphan plan that a reviewer approved by its SHA-256. A dry run unless -Apply. Live runs are delegated only: a person signed in with Cloud Application Administrator and the orphan-apply permissions, never an unattended app. | — |
Invoke-NpiOwnership.ps1 |
Script | Chapter 02: check every identity in Chapter 01’s register against the ownership rule, report the findings, record the AI sponsor fields for Chapter 09, and write the orphan rule as a dry-run plan with its SHA-256 for review. Read only: the plan is applied, after review, by Invoke-NpiOrphanAction.ps1. | — |
Invoke-NpiRotation.ps1 |
Script | Chapter 04: for every app registration in Chapter 01’s register, read its credentials and its Key Vault certificate, and write the rotation plan (raise, approve, renew in Key Vault, attach, verify, overlap, remove the old one), the requests for owners and the findings, with the plan’s SHA-256 for review. Read only: the plan is applied, after review, by Invoke-NpiCredentialAction.ps1. | — |
Invoke-NpiVintage.ps1 |
Script | Chapter 10: the annual AI use-case inventory vintage comparison (plan task NP7.4, M-25-21). Compares this year’s vintage with last year’s by use case ID, joins both to Chapter 01’s register through the use-case map and the service records, and writes the findings and changes with a manifest. Reads files only; nothing signs in. | — |
Invoke-NpiWorkloadCa.ps1 |
Script | Chapter 08: Conditional Access for workload identities. -Mode Check the pre-merge check on workload-ca/ and the scope file (no tenant; exit 1 on a Finding) -Mode Plan check the scope against the tenant, plan CA015 and CA037 per ring, and write the requests; a dry run unless -Apply, which needs a person’s delegated sign-in and -ApprovedPlanSha256, the SHA-256 of the reviewed dry run’s plan.json. New policies are created report-only; a ring is enforced only with -AllowEnforce, a D-NP5 record and the reviewed -SignInSummaryPath. -Mode SignIns read the service principal sign-in logs (Graph beta) and summarize the report-only results per principal and ring; prints the summary’s SHA-256 for the review record. | — |
Invoke-NpiDeployRollback.ps1 |
Script | Chapter 11: the rollback. -Mode Plan write rollback-plan.json from the settings and the preflight’s snapshot.json, and print its SHA-256 for the reviewer. Sends nothing. -Mode Apply check the plan’s approved SHA-256, tenant and age, then dry-run it, or send it with -Apply. Only PATCH, Enable-ADAccount and Disable-ADAccount: nothing is deleted. A live run is a person, delegated. -FixturePath serves Graph and Active Directory from a file and sends nothing anywhere. | — |
Invoke-NpiDeploySmokeTest.ps1 |
Script | Chapter 11: the smoke test with the synthetic service principal and service account. Reads the register run, then the tenant and the forest, and sends one write expected to fail: a new secret on the synthetic app, which the app management policy must refuse (if it isn’t refused, the secret is removed at once and the check fails; its value is never kept). Writes results.json and a manifest. Exit code 1 on any Fail. A live run is a person, delegated; -FixturePath sends nothing. | — |
Test-NpiDeployEvidence.ps1 |
Script | Chapter 11: the go/no-go’s evidence check. For every requirement row the stage must cover (config/requirements-ch11.json, “stages”), an evidence record for this environment and tenant whose result is Pass or Warn; and SHA256SUMS present, with every file unchanged and listed. Prints one row per step with its controls and KSIs, and exits 1 when any row is missing or failing. Reads only the evidence folder. | — |
Test-NpiDeployPreflight.ps1 |
Script | Chapter 11: the preflight before a stage. Reads only. Checks the settings file, the deployment identity’s credential, the licenses, the reader’s permissions, the operators’ roles, the objects the runbook touches, the VK-NPI baseline and (production) the test stage’s evidence, and writes results.json, snapshot.json (what the rollback restores) and a manifest. Exit code 1 on any Fail. -FixturePath serves Graph and Active Directory from a file and sends nothing anywhere. | — |
Write-NpiDeployEvidence.ps1 |
Script | Chapter 11: records one runbook step’s evidence. Copies the step’s run folders (the ones the earlier chapters’ scripts wrote) into the evidence folder under runs/ |
— |
Module NpiDeploy
| Function | What it does | Taught in |
|---|---|---|
Test-NpiDeploySettings |
Checks a settings hashtable and returns the problems found, one string each (none when it’s good): a secret-like name or value, an unreplaced |
— |
Read-NpiDeploySettings |
Reads the environment settings file, checks it with Test-NpiDeploySettings and returns it as a hashtable with its SHA-256 in _sha256. Throws, listing every problem, when the file isn’t usable. -AllowPlaceholders lets the template itself pass. | Chapter 11 — Deploying to Test and Production Module 11: Deploy to test, then production |
Get-NpiDeployCallList |
Reads Chapter 11’s call list (config/calls-ch11.json unless -Path names another file). | — |
Get-NpiDeployRequiredPermission |
The union of a Chapter 11 task’s calls: Graph permissions, AD rights and methods. | — |
New-NpiDeployClient |
A client for one Chapter 11 task, shaped like NpiCore’s reader so Invoke-NpiList and Invoke-NpiGetOne work on it. -Invoke is { param($Method, $Uri, $Body, $Headers) }; -AdInvoke is { param($Cmdlet, [hashtable]$Params) }. | — |
Invoke-NpiDeployWrite |
Sends one declared POST or PATCH on the cloud’s own Graph host and records it. A read task can’t write, and no call list entry here is a DELETE. | — |
Invoke-NpiDeployAd |
Runs one declared Active Directory call (Get-ADComputer, Get-ADGroup, Get-ADUser, Test-ADServiceAccount, and for the rollback Enable-ADAccount and Disable-ADAccount) and records it. The cmdlet comes from the call list, never from the caller. | — |
New-NpiDeployFixtureInvoker |
A fake Graph and Active Directory served from a fixture file: “graph” maps “METHOD /version/path” to a response body (or to { “__status”: 400, “error”: {…} }, which throws as Graph would); “ad” maps “Cmdlet|Identity” to a result. Writes not in the fixture succeed with an empty body. Every call is recorded in .Calls; nothing leaves the machine. | — |
New-NpiDeployLiveInvoker |
The live Graph invoker, through Invoke-MgGraphRequest. It refuses to start when the Graph session is in another cloud or tenant, and, for a write task, when the session isn’t a person’s delegated sign-in. Graph errors throw, as the fake’s do. | — |
New-NpiDeployLiveAdInvoker |
The live Active Directory invoker, with the ActiveDirectory module, against -Server. It runs only the cmdlets Chapter 11 declares for the task. | — |
Invoke-NpiDeployPreflight |
The checks before a stage starts, each with its gate, what it expects and what it found: PF-01 the settings file; PF-02 the deployment identity’s credential; PF-03 Workload ID Premium; PF-04 Entra ID P1 or P2; PF-05 the reader’s permissions are reads; PF-06 each operator holds, or is eligible for, the roles their steps need; PF-07 the pilot and synthetic apps exist with no secret; PF-08 the workload policies exist and are report-only or off; PF-09 the VK-NPI baseline; PF-10 the gMSA test host and retriever group; PF-11 (production only) the test stage’s smoke test passed in another tenant. Also returns the snapshot the rollback restores. | — |
Invoke-NpiDeploySmokeTest |
The smoke test with the synthetic service principal and service account, each check with what it expects: ST-01 the synthetic app is in the register with two owners and no secret; ST-02 the synthetic service account is in the register as HIGH (the detection works); ST-03 the app management policy refuses a new secret on the synthetic app (the probe; a secret that gets through is removed at once and the check fails); ST-04 its federated credential matches the settings exactly; ST-05 each workload policy assigns the synthetic service principal directly, in the expected state; ST-06 its sign-ins show the policy’s result (Graph beta); ST-07 the gMSA test host can retrieve the gMSA’s password. | Chapter 11 — Deploying to Test and Production Module 11: Deploy to test, then production |
New-NpiDeployRollbackPlan |
The rollback as a reviewed plan, from the settings and the preflight’s snapshot: each workload policy back to report-only (-To ReportOnly, a production ring) or off (-To Disabled, the test stage); the tenant default app management policy restored from the snapshot; the pilot’s app-specific policy turned off; each legacy account the conversion disabled re-enabled; and, with -IncludeSmokeCleanup, the synthetic service principal and account disabled. Nothing is deleted. Returns the plan; the caller writes it and a reviewer approves its SHA-256. | — |
Invoke-NpiDeployRollbackPlan |
Applies a rollback plan only when its SHA-256 is the one a reviewer approved, it’s for this tenant and it’s at most seven days old. A dry run unless -Apply. Each Conditional Access action re-reads the policy first and skips it when it’s already in the target state. | — |
Export-NpiDeployRun |
Writes a run’s files and a manifest: task, mode, stage, cloud, tenant, change record, the settings file’s SHA-256, the permissions the task holds, every request, and each file’s SHA-256. | — |
Write-NpiDeploySummary |
Prints one line of counts and one line per result, the way the other chapters’ scripts do. | — |
Get-NpiDeployRequirements |
Reads Chapter 11’s requirements catalog (config/requirements-ch11.json): the SP 800-53 controls, other requirements and FedRAMP 20x KSIs for each check and each runbook step, and the steps each stage’s evidence must cover. | — |
Update-NpiDeployEvidenceSums |
Rewrites SHA256SUMS in the evidence folder: one “sha256 relative/path” line per file, LF line endings, so the ISSO can check the folder with sha256sum -c SHA256SUMS. Returns the line count. | Chapter 11 — Deploying to Test and Production |
Write-NpiDeployEvidence |
Writes one evidence record for a runbook step to the evidence folder: when, which environment, tenant and change record, the command, the result, each check with the SP 800-53 controls, other requirements and FedRAMP 20x KSIs it supports (from config/requirements-ch11.json), and each run folder it covers (copied under runs/ |
Chapter 11 — Deploying to Test and Production |
Test-NpiDeployEvidence |
The go/no-go’s evidence check: for every step the stage’s catalog row lists, an evidence record for this environment and tenant whose result is Pass (or Warn, which the go/no-go record must explain); and SHA256SUMS present, with every file it lists unchanged and every file listed. Returns one row per step, plus EVIDENCE for the folder’s integrity. | Chapter 11 — Deploying to Test and Production Module 11: Deploy to test, then production |
Module NpiAgentId
powershell/NpiAgentId/NpiAgentId.psm1
| Function | What it does | Taught in |
|---|---|---|
Get-NpiAgentConfig |
Reads the Chapter 09 configuration and returns the call list, the program’s rules and the D-NP6 capability table as hashtables, with the folder they were read from. | — |
Get-NpiAgentCall |
Returns the declared Chapter 09 calls, narrowed to one task (agent-id or agent-ca-apply) with -Task. | — |
Get-NpiAgentRequiredPermission |
Returns the Graph permissions, methods and API versions a Chapter 09 task needs, the union of its declared calls. | Chapter 09 — AI Agent Identities Module 9: Govern AI agent identities |
Get-NpiAgentCapability |
D-NP6 for one cloud: Mode ‘AgentId’ where agent identities are available, else ‘Fallback’ (service principals and managed identities under the same governance), with the stage and watch flag of each capability. | Chapter 09 — AI Agent Identities Module 9: Govern AI agent identities |
New-NpiAgentReader |
A read-only client for the agent-id task, shaped like NpiCore’s reader so Invoke-NpiList and Invoke-NpiGetOne page and host-check its GETs, but holding this chapter’s calls. | — |
Import-NpiAgentRuns |
Chapter 01’s register and Chapter 02’s sponsor fields, each checked against its own manifest, and the ownership run checked against the register it was made from. | — |
Import-NpiAgentInputs |
Reads the reviewed input files in -InputPath (AI use case inventory, handshakes, creation setting, sponsor events and confirmations, pipeline changes) and returns each one, with the SHA-256 of every file found in Hashes. A missing file comes back empty. | — |
Read-NpiAgentEstate |
Read what the checks need. In AgentId mode: blueprints with sponsors, owners, federated credentials and inheritable permissions; agent identities with sponsors (expanded), owners, custom security attributes, app role assignments and directory roles. In both modes: the authorization policy, the agent Conditional Access policies (beta), the Lifecycle Workflows and their tasks, the credential audit events, and the directory roles of each fallback service principal named in the inventory. | Chapter 09 — AI Agent Identities |
Get-NpiBusinessDayDeadline |
Returns the date that is -Days business days after -Start, skipping Saturdays, Sundays and the holidays given as yyyy-MM-dd strings. | Chapter 09 — AI Agent Identities |
Test-NpiAgentCaPolicyShape |
Check one agent Conditional Access policy body against the program’s design. Kind ‘Unapproved’: all agent identities, all resources, Block, report-only, and approved agents excluded only by the custom security attribute filter. Kind ‘HighRisk’: all agent identities, all resources, Block, report-only, agent risk high. Returns the problems. | — |
Get-NpiAgentCredentialKind |
The blueprint’s credential, in the program’s order: ManagedIdentity (a federated credential whose issuer is this tenant’s own login endpoint), Federation (any other issuer), Certificate, Secret, or None. Every kind present is returned; the first is the best. | — |
Test-NpiAgentId |
Check the AI identities against the program’s rules and return @{ Identities (the sponsor fields Chapter 02 recorded, filled); Findings NPI-AI-01 to NPI-AI-23 with stable IDs; OrphanCandidates for Chapter 02’s orphan rule; Capability }. | — |
New-NpiAgentCaPlan |
A dry-run plan for the two agent policies: Create (report-only) where the tenant has no policy of that name, InPlace or Differs where it has one. Nothing here writes. Refuses a reviewed policy file that isn’t report-only Block, and a cloud where D-NP6 says agent Conditional Access isn’t available. | Chapter 09 — AI Agent Identities |
New-NpiAgentCaWriter |
The only code in this chapter that can write. Its calls are the agent-ca-apply task’s: re-read the policies, then POST a report-only Block policy. A live run is a person, delegated, with Conditional Access Administrator. | — |
Invoke-NpiAgentCaPlan |
Apply an approved plan. Refuses a plan whose SHA-256 isn’t the approved one, for another tenant or cloud, older than seven days, or with a body that isn’t report-only Block. Before each POST it re-reads the policies and skips if one with that name now exists. Without -Apply it reports WouldSend. | — |
Export-NpiAgentRun |
Write a run’s files and a manifest with the task, cloud, tenant, D-NP6 mode, the permissions the task holds, every request, the SHA-256 of each file, and of each input. | — |
New-NpiAgentFixtureInvoker |
A fake Microsoft Graph for Chapter 09, served from tests/fixtures/ch09/agent-estate.json. GET only unless -AllowWrite, which accepts the POSTs Learn’s samples send (create a blueprint, add a federated credential or a password, add inheritable permissions, create a Conditional Access policy) and changes the estate so a test can check the result. Every call is recorded in .Calls. | — |
Invoke-NpiAgentFake |
The request handler behind New-NpiAgentFixtureInvoker: answers one Graph request from the fixture estate in -State, applies a POST it accepts when writes are allowed, records the call in State.Calls, and throws as Graph would for a request it refuses. Normally called through the invoker’s .Invoke script block. | — |
Module NpiCore
powershell/NpiCore/NpiCore.psm1
| Function | What it does | Taught in |
|---|---|---|
Get-NpiCloud |
Endpoints for global, gcc, gcchigh or dod. Any other name throws: there is no default. Returns an object with the Graph, Resource Manager and sign-in URLs and the Graph and Azure environment names for that cloud. | Chapter 01 — Non-Person Identity Inventory as Code Chapter 11 — Deploying to Test and Production |
Get-NpiCallList |
Reads the declared call list (config/calls.json unless -Path names another file) and returns it as a hashtable with its calls and tasks. | — |
Get-NpiCall |
The declared calls, optionally for one task or one id. Returns an array of call entries from config/calls.json. | — |
Get-NpiTask |
A task’s declaration from calls.json: mode, permissions, Azure roles, AD rights. Throws for a task the call list doesn’t declare. | — |
Get-NpiRequiredPermission |
The union of a task’s calls: Graph permissions, Azure roles and Active Directory rights. Returns an object with Task, GraphPermissions, AzureRoles, AdRights and Methods. | Chapter 01 — Non-Person Identity Inventory as Code Chapter 02 — Ownership and the Orphan Rule |
New-NpiReader |
A read-only client for one read task in one cloud. -Invoke is { param($Method, $Uri, $Body, $Headers) } and returns the parsed JSON body as a hashtable; -AdInvoke is { param($Cmdlet, [hashtable]$Params) } and returns Active Directory objects. A write task can’t have a reader. | Chapter 01 — Non-Person Identity Inventory as Code Module 1: Inventory every non-person identity |
Resolve-NpiUri |
Builds the full URL for one declared Graph or Resource Manager call on the reader’s cloud and returns @{ Call; Uri; Host }. Throws for an undeclared call, a method not in -AllowedMethods (GET by default), an Active Directory call or an unbound placeholder. | — |
Assert-NpiHost |
Throws unless -Uri starts with -ExpectedHost and a slash, so a token (or a next link) never goes to another host. Returns nothing when the host matches. | — |
Invoke-NpiList |
GET a declared collection and follow every page (@odata.nextLink for Graph, nextLink for Resource Manager), only on the cloud’s own host. Records each request in the evidence. | Chapter 01 — Non-Person Identity Inventory as Code Module 1: Inventory every non-person identity |
Invoke-NpiGetOne |
GETs one declared object on the cloud’s own host, records the request in the reader’s evidence, and returns the parsed body. It doesn’t follow next links. | — |
Invoke-NpiAdRead |
Run a declared Active Directory read. The cmdlet comes from the call list, never from the caller, and must be a Get-AD* cmdlet; the parameters are recorded in the evidence. | — |
New-NpiLiveInvoker |
The live invoker: Graph through Invoke-MgGraphRequest, Resource Manager through Invoke-AzRestMethod. It refuses to start if either session is in another cloud, or signed in to a tenant other than -TenantId. -AllowWrite is for NpiOwnership’s writer only. | Chapter 01 — Non-Person Identity Inventory as Code |
New-NpiLiveAdInvoker |
The live Active Directory invoker. It runs only the Get-AD* cmdlets the call list declares (and Disable-ADAccount when -AllowWrite), against -Server, with the ActiveDirectory module. | Chapter 01 — Non-Person Identity Inventory as Code |
New-NpiFixtureInvoker |
A fake Microsoft Graph and Resource Manager served from a fixture estate file, for labs and tests. GET only unless -AllowWrite, which accepts only the two writes Chapter 02 declares. Collections come in pages of -PageSize with a next link on the same host. Every call is recorded in .Calls, and writes change .Estate so a test can read the result back. | Chapter 01 — Non-Person Identity Inventory as Code Module 1: Inventory every non-person identity |
Invoke-NpiFake |
The fake’s request handler, called through the scriptblock New-NpiFixtureInvoker returns. It records the call in -State.Calls, serves the Graph and Resource Manager routes the chapters use from the fixture estate in pages, and applies the two declared writes only when the state allows writes. Returns the response body as a hashtable; throws for a route it doesn’t know. | — |
Test-NpiLdapFilter |
The fake’s LDAP evaluator: (&…), (|…), (attr=), (attr=value) with wildcards, and the bitwise-AND matching rule 1.2.840.113556.1.4.803. Anything else throws, so a query the fake can’t evaluate fails a test instead of returning a wrong answer. Returns $true when -Object (a fixture AD object) matches -Filter, else $false. | — |
New-NpiFixtureAdInvoker |
A fake Active Directory served from the fixture’s “ad” section: Get-ADUser with -LDAPFilter or -Identity, Get-ADServiceAccount with -Filter * or -Identity, and Disable-ADAccount only with -AllowWrite. Every call is recorded in .Calls. | Chapter 01 — Non-Person Identity Inventory as Code |
Invoke-NpiFakeAd |
The fake Active Directory’s handler, called through the scriptblock New-NpiFixtureAdInvoker returns. It records the call, answers Get-ADUser and Get-ADServiceAccount from the fixture’s “ad” section with the properties the real cmdlets compute, and runs Disable-ADAccount only when the state allows writes. Throws for any other cmdlet or parameter set. | — |
New-NpiFinding |
A finding with a stable ID, Rule:ObjectKey, so the same gap keeps its ID from run to run. Returns an object with Id, Rule, Severity, ObjectKey, Object and Issue. | — |
Write-NpiJson |
Writes -Value to -Path as JSON (depth 20), UTF-8 without a byte order mark and with LF line endings on every platform, so a manifest’s hashes are the same on Windows and Linux. Returns nothing. | — |
Get-NpiFileHash |
Returns the lowercase hexadecimal SHA-256 of one file, the form every manifest records. | — |
Export-NpiRun |
Write a run’s outputs and a manifest: the task, mode, cloud, tenant ID, domain, as-of date, the permissions and rights the task holds, every request or AD read, and the SHA-256 of each file, so the ISSO can check what the evidence is and how it was read. | — |
Module NpiCredentialPolicy
powershell/NpiCredentialPolicy/NpiCredentialPolicy.psm1
| Function | What it does | Taught in |
|---|---|---|
ConvertFrom-NpiIsoDuration |
Converts an ISO 8601 duration in days and time only (such as P180D or P4DT12H30M5S) to a TimeSpan. Throws for years or months, whose length varies. | — |
ConvertTo-NpiCanonicalJson |
Returns compact JSON for a value, with keys sorted at every level and dates as ISO strings, so two reads of the same object give the same text and the same hash. | — |
ConvertTo-NpiSortedNode |
Returns a copy of a value with the keys of every dictionary and object sorted (as ordered hashtables) and dates as ISO 8601 UTC strings, so its JSON is the same on every run. | — |
Write-NpiSortedJson |
Writes a value to a JSON file whose bytes depend only on its data: keys sorted, dates as ISO strings, LF line endings, UTF-8 without a BOM. Returns nothing. | — |
Format-NpiDate |
Formats a date or date string as ISO 8601 UTC (yyyy-MM-ddTHH:mm:ssZ), or as yyyy-MM-dd with -DateOnly. Returns an empty string for an empty value. | — |
ConvertFrom-NpiX5t |
Converts Key Vault’s x5t value (the base64url SHA-1 thumbprint of a certificate) to an upper-case hex thumbprint. Returns $null for an empty value. | — |
ConvertFrom-NpiCustomKeyIdentifier |
Converts Graph’s customKeyIdentifier on a keyCredential (base64 of the thumbprint bytes) to an upper-case hex thumbprint. Returns $null if the value is empty or isn’t base64. | — |
Get-NpiCh04CallList |
Reads the Chapter 04 call list (config/calls-ch04.json unless -Path is given) and returns it as a hashtable of tasks and calls. | — |
Get-NpiCh04Task |
Returns one Chapter 04 task’s declaration from the call list (app-policy, policy-apply, rotation or rotation-apply), including its mode. Throws for an unknown task. | — |
Get-NpiCh04Call |
Returns the declared Chapter 04 calls as an array, narrowed to one task with -Task and to one call with -Id. | — |
Get-NpiCh04RequiredPermission |
Returns what a Chapter 04 task needs: the union of its calls’ Graph permissions, Azure roles (Resource Manager and Key Vault data plane), AD rights and methods, with the task’s mode and delegated role. | Chapter 04 — App Management Policies and Certificate Rotation Module 4: Set the credential rules |
Get-NpiVaultHost |
Returns the Key Vault data-plane URL for a vault in a cloud: https:// |
— |
New-NpiCh04Client |
A client for one Chapter 04 task in one cloud. A read task’s client sends only its declared GETs; a write task’s client is the only object that can send this chapter’s PATCHes and POSTs, and only through Invoke-NpiCredentialPlan. -Invoke is { param($Method, $Uri, $Body, $Headers) }. | — |
Resolve-NpiCh04Uri |
Builds the request URL for a declared Chapter 04 call: binds the path placeholders, adds the query, and uses the cloud’s Graph host or the vault’s host. Returns the call, the URI and the host; throws for an undeclared call or an unbound placeholder. | — |
Invoke-NpiCh04Get |
GET a declared call and follow @odata.nextLink pages on the same host. Returns the items of a collection, or the object itself. Every request is recorded in the client’s evidence. | — |
New-NpiCh04LiveInvoker |
Graph through Invoke-MgGraphRequest; Key Vault’s data plane through Invoke-AzRestMethod with -ResourceId set to the vault audience of this cloud (research gaps, row 38). Refuses to start if either session is in another cloud or tenant. -AllowWrite for the writer only. | — |
New-NpiCh04FixtureInvoker |
A fake Microsoft Graph (the app management policy routes, applications, owners, users) and a fake Key Vault data plane, served from tests/fixtures/ch04/tenant.json and the shared estate. GET only unless -AllowWrite. It evaluates the restriction types Learn lists for v1.0 (beta adds more), replaces a restriction collection as a PATCH does, enforces one app management policy per app and the certificate lifetime cap on a new keyCredential, and completes a Key Vault create on the first poll. Every call is recorded in .Calls; writes change .Tenant. | — |
Invoke-NpiCh04Fake |
The request handler behind New-NpiCh04FixtureInvoker: answers one request from the fake Graph and Key Vault state, records it in State.Calls, and throws as the service would for a request it refuses. Normally called through the invoker’s .Invoke script block. | — |
ConvertFrom-NpiFakeCert |
Decodes a test certificate blob made by New-NpiFakeCertBlob and returns its thumbprint, validity dates and subject. Throws if the blob isn’t one. Used by the fake only. | — |
New-NpiFakeCertBlob |
Builds a test certificate blob, the base64 text the fake Graph and Key Vault accept as a certificate key, from a thumbprint, validity dates and subject. Not a real certificate. | — |
Import-NpiCh04Register |
Reads Chapter 01’s register.json from an inventory run and checks it against the run’s manifest. Returns the rows, the manifest and the register’s SHA-256; throws if a file is missing, the run isn’t an inventory run, or the register has changed. | — |
Import-NpiCh04Input |
Reads one reviewed CSV input (certificate bindings, rotation approvals or verifications) and returns its rows. Returns an empty array if the path is empty or the file doesn’t exist. | — |
Export-NpiCh04Run |
Writes each of a run’s files as sorted JSON under -OutputPath, then manifest.json with the task, mode, cloud, tenant, the permissions the task needs, every request made and a SHA-256 per file. Returns the manifest file. | — |
Get-NpiAppPolicyState |
Read the tenant default policy, every app management policy with what it applies to, and, for each app registration in the register, its creation date and app instance lock. | Chapter 04 — App Management Policies and Certificate Rotation |
Compare-NpiAppPolicy |
Compare the tenant default policy with the reviewed file. Returns the rows of the diff and the merged PATCH body: every restriction the tenant already has is carried, the program’s are added or tightened, and none is ever loosened or dropped (Design guidance). | Chapter 04 — App Management Policies and Certificate Rotation |
New-NpiPolicyPlan |
The policy plan: PATCH the tenant default when it differs, create and assign each exception that’s in force, and lock every app registration that isn’t fully locked. No write weakens a restriction, drops one, or deletes anything. Same inputs, same plan, byte for byte. | Chapter 04 — App Management Policies and Certificate Rotation |
New-NpiRotationPlan |
For every app registration in the register: secrets reported for replacement; each certificate checked against its Key Vault binding, the owner’s approval and verification, and given one step: wait, renew in Key Vault, attach the new certificate, wait out the overlap, or remove the old one. Same inputs, same plan, byte for byte. | Chapter 04 — App Management Policies and Certificate Rotation |
Assert-NpiCh04PlannedWrite |
Every write must be a declared call of the writer’s task, with the declared method, on this cloud’s host, with a body this function allows. DELETE and PUT are never sent. | — |
Test-NpiNoWeakening |
Checks a PATCH body for the tenant default policy against the live policy. Returns the first restriction the body would drop or loosen (as scope.restrictionType), or $null when every enabled restriction is kept at least as strict. | — |
Invoke-NpiCredentialPlan |
Apply a reviewed policy or rotation plan. Without -Apply it’s a dry run: it checks the plan and runs every precheck, and sends nothing. With -Apply it sends only the plan’s writes, only if the plan file’s SHA-256 is the one approved, the plan is for this tenant, cloud and task, no older than seven days, and each precheck still holds. | — |
Module NpiDrift
powershell/NpiDrift/NpiDrift.psm1
| Function | What it does | Taught in |
|---|---|---|
Get-NpiDriftCallList |
Chapter 10’s call list, config/calls-ch10.json, in calls.json’s schema. Returns it as a hashtable with its calls, tasks and runs. | — |
Get-NpiDriftPolicy |
Thresholds and Learn’s activity names, config/drift-ch10.json. Returns the policy as a hashtable, with the resolved file path added as _path so a run can record the policy’s SHA-256. | — |
Get-NpiDriftPermission |
What a task needs: drift (this chapter’s calls), or drift-run, the union of Chapter 01’s inventory, Chapter 02’s ownership and this chapter’s drift task. | Chapter 10 — Drift and Evidence for the ISSO Module 10: Find drift and file the evidence |
New-NpiDriftReader |
A read-only client for the drift task: NpiCore’s reader shape with this chapter’s call list, so Invoke-NpiList sends only declared GETs to the cloud’s own host and follows every page. | — |
ConvertTo-NpiUtc |
Returns -Value as a UTC DateTime, whether it is a DateTime (as ConvertFrom-Json parses it), a DateTimeOffset or an ISO 8601 string, without applying the local offset. $null or an empty string returns $null. | — |
New-NpiDriftFixtureInvoker |
A fake Microsoft Graph for the drift task: the directory audit log from -AuditPath (a JSON file with a ‘directoryAudits’ array in Graph’s shape) and the service principal sign-in activity report from -SignInPath (‘servicePrincipalSignInActivities’). It evaluates only the filter terms this chapter sends and refuses any other, serves pages of -PageSize with a next link on the same host, and records every call. | — |
Invoke-NpiDriftFake |
The fake’s request handler, called through the scriptblock New-NpiDriftFixtureInvoker returns. It records the call, serves the directory audit log and the sign-in activity report from the fixtures, applies only the activityDateTime and activityDisplayName filter terms, and returns one page with a next link on the same host. Throws for a non-GET, another host or another route. | — |
ConvertTo-NpiActivityName |
Returns an audit activity name with any en or em dash replaced by a hyphen and the ends trimmed, so it matches the activity names in the policy. | — |
Get-NpiKeyDescription |
Parses a KeyDescription value from an audit event’s modified properties (a JSON array string or a list of entries) and returns one object per credential with KeyId, KeyType and KeyUsage. The display name is dropped. $null or an empty value returns an empty array. | — |
ConvertTo-NpiAuditEvent |
One directoryAudit item as an evidence row: the activity and its class, the initiator and the target as IDs, and the credentials added or removed (key ID, type, usage). No names. | — |
Get-NpiAuditEvent |
Read the directory audit log for one window: one filtered, paged GET for each activity name in the policy (credential changes on applications and service principals, consent, delegated grants, app role assignments). Events are de-duplicated by ID and sorted by time. Refuses a window that starts more than 30 days before -AsOf: the log keeps 30 days with P1 or P2. | Chapter 10 — Drift and Evidence for the ISSO |
Get-NpiSignInActivity |
The service principal sign-in activity report (beta): the last sign-in per app ID. Learn lists it in the global service only, so in gcchigh or dod it isn’t sent and Status is NotAvailable. | Chapter 10 — Drift and Evidence for the ISSO |
Get-NpiFingerprint |
A finding’s fingerprint: the first 16 hex characters of SHA-256(“ |
— |
New-NpiDriftFinding |
Builds one Chapter 10 finding: NpiCore’s finding (ID Rule:ObjectKey) with Chapter set to 10 and the finding’s fingerprint added. Returns an object with Id, Rule, Severity, Chapter, ObjectKey, Object, Issue and Fingerprint. | — |
Get-NpiRowFingerprint |
SHA-256 over the row’s governance columns, as name=value lines in a fixed order. Returns the lowercase hexadecimal digest; the baseline compares register rows by it. | — |
New-NpiDriftBaseline |
A baseline candidate from one register: each identity’s fingerprint and governance columns, with the tenant, cloud, run and the register’s SHA-256. It becomes the approved baseline when a reviewer passes its SHA-256 to the next run as -ApprovedBaselineSha256. | — |
Import-NpiDriftBaseline |
The approved baseline: its SHA-256 must be the one the reviewer approved, and it must be for this tenant and cloud, or the run refuses to compare against it. | — |
Read-NpiContractFile |
Read and check one file another chapter wrote for this one. Three schemas: fmp-npi-findings/1 (findings with id, rule, severity, chapter, objectKey, fingerprint), fmp-npi-review/1 (review records) and fmp-npi-credential-log/1 (credentials a pipeline added). Returns @{ Schema; Chapter; Data } or throws with the reason. | — |
Import-NpiContract |
Every *.json file in -Path, read through Read-NpiContractFile. A file that fails its check is refused and listed with the reason, never half-read. Returns @{ Findings; Reviews; CredentialLog; Chapters; Refused; Files }. | — |
Test-NpiRegisterDrift |
The register drift findings, NPI-DRF-01 to NPI-DRF-09, each with a stable ID and fingerprint. 01 new since the approved baseline; 02 changed or removed since it; 03 ownerless (an orphan candidate in Chapter 02’s run); 04 unused for 90 days by the sign-in activity report; 05 a credential expiring within 30 days; 06 a password that never expires; 07 a credential added outside the pipeline; 08 a new consent grant or application permission; 09 an evidence gap. | — |
Test-NpiReviewCycle |
The review cycle record (plan task NP7.2) from the outputs of Chapters 07 and 09, read only. NPI-REV-01: an app registration holding Graph permissions with no owners’ permission review in the last quarter. NPI-REV-02: an agent identity or blueprint with no sponsor attestation in the last 12 months. NPI-REV-03: an agent’s access assignment with no end date, an end past the maximum, or still active after it. NPI-REV-04: a kind of review record not received. Returns @{ Findings; Record }. | — |
Compare-NpiAiVintage |
Compare this year’s AI use-case inventory vintage with last year’s by use case ID (Book 17, Chapter 09’s four changes), joined to the register through the use-case map and the service records. NPI-VIN-01 a new piloted or deployed entry with no identity; 02 an entry retired whose identities are still enabled; 03 an authorization answer changed; 04 an entry that left the inventory without being retired; 05 an AI identity whose record maps to no use case in this vintage. Returns @{ Findings; Changes }. | — |
Export-NpiDriftTask |
Write one task folder of this chapter (drift or vintage): its files and a manifest in the shape Chapters 01 and 02 write (task, mode, cloud, tenant, permissions, every request sent, a SHA-256 per file), plus -Extra. | — |
Write-NpiDriftJson |
Writes -Value to -Path as JSON (depth 20), UTF-8 without a byte order mark and with LF line endings on every platform, so the files a run hashes are the same everywhere. Returns nothing. | — |
Get-NpiRunId |
A sortable run ID from the as-of time and the mode, for example 2026-10-30T0600Z-fixture. | — |
Write-NpiRunIndex |
run.json: the run’s ID, as-of time, cloud, tenant, mode, audit window, approved baseline, the permissions, and each task’s status (OK or Error, with the message) with the SHA-256 of its manifest. A task that failed has no folder: its findings are unverified, never resolved. | — |
Module NpiFederation
powershell/NpiFederation/NpiFederation.psm1
| Function | What it does | Taught in |
|---|---|---|
Get-NpiWifCallList |
Reads Chapter 05’s call list (config/calls-ch05.json unless -Path names another file) and returns it as a hashtable with its calls and tasks. | — |
Get-NpiWifTask |
Returns one task’s declaration from config/calls-ch05.json: its mode and the permissions, roles and rights it holds. Throws for a task the call list doesn’t declare. | — |
Get-NpiWifRequiredPermission |
The union of a task’s calls: Graph permissions, Azure roles, AD rights and methods. Returns an object with Task, GraphPermissions, AzureRoles, AdRights and Methods. | Chapter 05 — Workload Identity Federation and Managed Identities Module 7: Convert to managed identities and federation |
New-NpiWifClient |
A client for one Chapter 05 task in one cloud. -Invoke is { param($Method, $Uri, $Body, $Headers) } for Graph and Resource Manager; -AdInvoke is { param($Cmdlet, [hashtable]$Params) }; -TokenEndpoint is a fake from New-NpiWifFakeTokenEndpoint, the only place the token exchange test is ever sent. | — |
Resolve-NpiWifUri |
Builds the full URL for one declared Graph, Resource Manager or sign-in call on the client’s cloud and returns @{ Call; Uri; Host }. Throws for an undeclared call, an Active Directory call or an unbound placeholder; the caller checks the method. | — |
Invoke-NpiWifGet |
GET a declared call and follow every page on the cloud’s own host. Returns the items of a collection, or the object. With -AllowNotFound a 404 returns $null instead of throwing. | — |
Invoke-NpiWifAdRead |
Runs one declared Active Directory read (a Get-AD* cmdlet named by the call list, never by the caller) through the client’s AD invoker, records the cmdlet and its parameters in the evidence, and returns what the cmdlet returns. | — |
Get-NpiWifPresentedClaims |
The iss, sub and aud the workload’s issuer will put in its token, from the workload record. GitHub’s subject is derived from Learn’s formats (environment, branch, tag) only for the name-based subject format; a pull request subject, an immutable subject or any other platform needs the subject captured from a test run (capturedSubject). Kubernetes uses system:serviceaccount: |
Chapter 05 — Workload Identity Federation and Managed Identities |
Test-NpiWifCredential |
The static checks for one federated identity credential: Learn’s rules (name, lengths, no wildcards, exactly one audience, the recommended audience, issuer and subject that match the token exactly) and the program’s (no preview flexible credentials). Returns a list of @{ Rule; Issue }; empty means it passes. | — |
Test-NpiWifOrder |
The plan’s order: a managed identity where the host is in Azure, else a federated credential where it has an OIDC issuer, else a certificate. Returns $null when the conversion’s target kind fits, or a sentence naming the kind that should come first. | — |
New-NpiWifTestAssertion |
An unsigned test assertion with the claims the workload’s issuer will present. For the fake token endpoint only: it has no valid signature, and Microsoft Entra ID would refuse it. | — |
New-NpiWifFakeTokenEndpoint |
A fake Microsoft identity platform token endpoint for the client credentials request with a federated credential. It decodes the assertion and matches it as Learn describes: issuer, subject and audience exactly and case-sensitively, an issuer with leading or trailing whitespace blocked, an expired assertion refused. It checks no signature and no issuer keys. -Credentials is @{ ClientId; Name; Id; Issuer; Subject; Audiences }. | Chapter 05 — Workload Identity Federation and Managed Identities |
Test-NpiWifTokenExchange |
The client credentials request with a federated credential (Learn’s third case), sent only to the fake token endpoint on the client: the code refuses to send an assertion anywhere else. Passes only if the named credential is the one that matched. | Chapter 05 — Workload Identity Federation and Managed Identities |
Import-NpiWifConversions |
The reviewed conversion file, with its SHA-256. Returns @{ Data; Conversions; Sha256 } and throws if two conversions share an ID. | — |
Import-NpiWifCutoverLog |
Reads the cutover log CSV and returns @{ Rows; Sha256 }, with Rows keyed by ConversionId. | — |
New-NpiWifPlan |
Read the tenant for each reviewed conversion and build the plan: the order check, the credential checks against what the workload presents, the token exchange test against the fake endpoint, the diff (create, no change, review, unmanaged), managed identities created or recorded with their role assignments, and the parallel run from sign-in evidence. The plan only describes writes; nothing here sends one. | Chapter 05 — Workload Identity Federation and Managed Identities |
Assert-NpiWifPlannedWrite |
Every write must be a declared federation-apply call with its method, its target on the cloud’s host, and only the body it allows. A federated credential’s body goes through Test-NpiWifCredential again. Throws with the reason; returns nothing when the write is allowed. | — |
Invoke-NpiWifPlan |
Apply a reviewed plan. Without -Apply it is a dry run: every check and precheck, nothing sent. With -Apply it sends the plan’s writes in order, one at a time, only if the plan file’s SHA-256 is the approved one, the plan is for this tenant and cloud and no older than seven days, and each precheck still holds. | — |
New-NpiWifLiveInvoker |
The live invoker: Graph through Invoke-MgGraphRequest, Resource Manager through Invoke-AzRestMethod. Refuses a session in another cloud or tenant, refuses anything but GET unless -AllowWrite, and never sends DELETE. | — |
New-NpiWifFake |
A fake Microsoft Graph, Resource Manager and Active Directory for Chapter 05, served from tests/fixtures/ch05/tenant.json. GET only unless -AllowWrite. It enforces the creation rules Learn documents (exactly one audience, the name rules, a unique issuer and subject, 20 per parent, an existing parent identity) and nothing else: a wrong subject or audience is accepted at creation, as Learn says the service accepts it. | — |
Invoke-NpiWifFakeHttp |
The fake’s HTTP handler, called through New-NpiWifFake’s Invoke scriptblock. It records the call, serves the Graph and Resource Manager routes Chapter 05 uses from the fixture tenant in pages, and creates a credential or identity only when the state allows writes, with Learn’s creation errors. Returns the response body; throws for a route it doesn’t know. | — |
Invoke-NpiWifFakeAd |
The fake Active Directory handler, called through New-NpiWifFake’s AdInvoke scriptblock. It records the call, returns SamAccountName, ObjectGUID, Enabled and LastLogonDate for one fixture account on Get-ADUser, and runs Disable-ADAccount only when the state allows writes. | — |
Export-NpiWifRun |
Write a run’s files and a manifest: task, mode, cloud, tenant, as-of, the task’s permissions, every request, and a SHA-256 per file. Returns the manifest.json file. | — |
ConvertFrom-NpiWifBase64Url |
Decodes a base64url string (the encoding of a JWT’s header and claims) and returns the UTF-8 text. | — |
Format-NpiWifTime |
Returns a time as an ISO 8601 UTC string (yyyy-MM-ddTHH:mm:ssZ), whether JSON parsing turned it into a DateTime or left a string. $null or an empty value returns $null. | — |
ConvertTo-NpiWifDate |
Parses a date or date-time string as UTC (a value with no offset is taken as UTC) and returns a DateTime. An empty string returns $null. | — |
Module NpiInventory
powershell/NpiInventory/NpiInventory.psm1
| Function | What it does | Taught in |
|---|---|---|
Get-NpiRegisterConfig |
Reads the register settings (config/register.json unless -Path names another file) and returns them as a hashtable, with the resolved file path added under the _path key. | — |
Get-NpiServiceUserLdapFilter |
Returns the LDAP filter string that Get-NpiAdServiceAccount passes to Get-ADUser to find user accounts that may be service accounts, built from the naming patterns and description pattern in the register settings. | — |
Get-NpiAdServiceAccount |
The Active Directory side of the register: one Get-ADUser LDAP query for user accounts that match any of Learn’s criteria or the naming convention, and one Get-ADServiceAccount for MSAs, gMSAs and dMSAs. Computer accounts aren’t read (research gaps, row 8). | — |
Get-NpiEntraWorkloadIdentity |
The Microsoft Entra side of the register: app registrations with owners and federated credentials, every service principal by type, managed identities (user-assigned ones with their federated credentials from Resource Manager), Microsoft Graph application permissions and delegated consent grants. | — |
Get-NpiRisk |
Classifies one register row as HIGH, MEDIUM or LOW risk and returns an object with Risk and Reasons. | Chapter 01 — Non-Person Identity Inventory as Code |
Get-NpiCandidateTarget |
Returns the candidate migration target for one register row as text, chosen by the row’s type and facts. It is a candidate only; Chapter 03 makes the decision. | Chapter 01 — Non-Person Identity Inventory as Code |
Get-NpiRegister |
The whole register: AD and Entra rows, each with a risk, a candidate target and a Data Platform hand-off where it applies. Returns @{ Rows; Evidence }. | Chapter 01 — Non-Person Identity Inventory as Code |
Test-NpiRegister |
The register’s findings, NPI-INV-01 to NPI-INV-09, each with a stable ID (rule:identity). | Chapter 01 — Non-Person Identity Inventory as Code |
New-NpiRow |
Returns one register row with every register column, filled from the -Values hashtable and defaulted otherwise. It throws on a column name the register doesn’t have. | — |
Module NpiKerberosIsland
powershell/NpiKerberosIsland/NpiKerberosIsland.psm1
| Function | What it does | Taught in |
|---|---|---|
Get-NpiKrbCallList |
Reads Chapter 06’s call list (config/calls-ch06.json unless -Path names another file) and returns it as a hashtable of tasks and calls. | — |
Get-NpiKrbCall |
Returns the calls in Chapter 06’s call list as an array, narrowed to those declared for -Task and to the call with ID -Id when either is given. | — |
Get-NpiKrbTask |
Returns one task’s declaration from Chapter 06’s call list, such as its mode (read or write). Throws if the task isn’t declared. | — |
Get-NpiKrbRequiredRight |
Returns the Active Directory rights, cmdlets and methods that a Chapter 06 task’s declared calls need, combined into one object. | Chapter 06 — gMSAs, dMSAs and the Kerberos Island Module 8: Convert Kerberos accounts to gMSAs and dMSAs |
New-NpiKrbReader |
A read-only Active Directory client for the kerberos-island task. -AdInvoke is { param($Cmdlet, [hashtable]$Params) } and returns AD objects. A write task can’t have a reader. | — |
Invoke-NpiKrbAdRead |
Runs one declared Get-AD* read through a reader (or writer) client, records it in the client’s Evidence and returns the AD objects. The cmdlet comes from the call list; an undeclared call or one that isn’t a Get-AD* read throws. | — |
Import-NpiKrbRegister |
Reads Chapter 01’s register from a run folder and returns @{ Rows; Manifest; Sha256 }. Throws if register.json’s SHA-256 isn’t the one manifest.json records. | — |
Import-NpiKrbMatrixRun |
Chapter 03’s run, checked against its manifest: decisions.json must have the SHA-256 the manifest records, and the run must have decided on this very register. Returns @{ Decisions; Manifest; Sha256 }. The owners’ D-NP3 dispositions (Retire, Replatform, Keep, KeepKerberos) and the authorizing official’s acceptance come from here, not from a second file. | — |
Get-NpiKrbPath |
What this chapter does with a D-NP3 disposition from Chapter 03: Convert (Replatform to a gMSA or a dMSA), WorkloadIdentity (Replatform to a managed identity or an app registration, which Chapter 05 moves), Island (Keep or KeepKerberos, or a gMSA kept beside an app registration: it stays on Kerberos) or Retire. Empty for a disposition or target it doesn’t know. | — |
Import-NpiKrbInput |
The inputs: Chapter 03’s decisions (the D-NP3 disposition, target, end date, SPN owner and the authorizing official’s acceptance for each AD account), this chapter’s two reviewed files (kerberos-replatform.csv and password-retrievers.json) and the program’s one program-dates.json, each with its SHA-256. Returns @{ Dispositions; Retrievers; ProgramDates; Hashes }, one Dispositions record per account. A missing input throws, and so does a program-dates.json that isn’t the one Chapter 03’s run read: there is no default end state. | — |
Get-NpiKdsRootKeyState |
The KDS root key prerequisite, read-only: whether a root key exists and when it became usable (msKds-UseStartTime), never the key data. Ready once the earliest key has been usable for 10 hours (Learn: domain controllers wait up to 10 hours for replication). | — |
Get-NpiKrbScope |
Returns the register rows this chapter covers: AD rows that are enabled traditional accounts with at least one SPN, and every MSA, gMSA and dMSA. | — |
Read-NpiKrbDomain |
Everything the plan reads from the domain, through the reader: the KDS root key state, the managed service accounts with their retrievers and dMSA migration state, the accounts to be superseded, the domain controllers and the hosts named for a dMSA. | Chapter 06 — gMSAs, dMSAs and the Kerberos Island |
Test-NpiKerberosIsland |
Check the Kerberos accounts against the reviewed dispositions and build the plan, the island list for the program’s SPN retirement (P4.6) and the reconciliation of every gMSA and dMSA with the provisional end state (D11). Returns @{ Findings; Plan; IslandList; Reconciliation }. Findings NPI-KRB-01 to NPI-KRB-09, each with a stable ID (rule:account). Nothing here writes. | Chapter 06 — gMSAs, dMSAs and the Kerberos Island |
New-NpiKrbWriter |
The writer for kerberos-apply: the only object in this chapter that can run New-, Set-, Start-, Complete- or Disable- cmdlets, and only the calls calls-ch06.json declares for it. | Chapter 06 — gMSAs, dMSAs and the Kerberos Island |
Assert-NpiKrbPlannedWrite |
Throws unless a plan action is a write declared for kerberos-apply, with the declared cmdlet, only that call’s allowed parameters and the values its rule requires. A Remove-, Uninstall-, Undo-, Reset- or Clear- cmdlet always throws. Returns nothing when the action passes. | — |
Invoke-NpiKrbPlan |
Apply a reviewed Kerberos plan. Without -Apply it is a dry run: it checks the plan and runs every precheck, and runs nothing. With -Apply it runs only the plan’s writes, only if the plan file’s SHA-256 is the one the reviewer approved, the plan is for this tenant and domain and no older than seven days, and each precheck still holds. | — |
Export-NpiKrbRun |
Writes each entry of -Files into -OutputPath (CSV for a .csv name, JSON otherwise) plus a manifest.json with the task’s AD rights, every request and each file’s SHA-256, and returns the manifest file. | — |
New-NpiKrbLiveAdInvoker |
The live Active Directory invoker: only the cmdlets calls-ch06.json declares for -Task, against -Server, with the ActiveDirectory module. Removes, uninstalls, undoes and resets never run. | — |
New-NpiKrbFixtureAdInvoker |
A fake Active Directory for Chapter 06: the fixture estate’s accounts plus ad-kerberos.json (KDS root keys, domain controllers, hosts, dMSA state). Reads: Get-ADObject (the KDS root keys only, and never msKds-RootKeyData), Get-ADServiceAccount, Get-ADUser, Get-ADDomainController, Get-ADComputer. Writes only with -AllowWrite: New-ADServiceAccount, Set-ADServiceAccount, Start- and Complete-ADServiceAccountMigration, Disable-ADAccount. Every call is recorded. | — |
Invoke-NpiKrbFakeAd |
The fake Active Directory’s dispatcher: records the cmdlet and parameters in the state’s Calls, then answers the cmdlet from the fixture state, or throws for a cmdlet it doesn’t serve and for a write when the state doesn’t allow writes. New-NpiKrbFixtureAdInvoker’s Invoke calls it. | — |
Module NpiLeastPrivilege
powershell/NpiLeastPrivilege/NpiLeastPrivilege.psm1
| Function | What it does | Taught in |
|---|---|---|
Get-NpiLpCallList |
Reads Chapter 07’s call list (config/calls-ch07.json unless -Path names another file) and returns it as a hashtable of tasks and calls. | — |
Get-NpiLpTask |
Returns one task’s declaration from Chapter 07’s call list, such as its mode (read or write). Throws if the task isn’t declared. | — |
Get-NpiLpCall |
Returns the calls in Chapter 07’s call list, narrowed to those declared for -Task when it is given. | — |
Get-NpiLpRequiredPermission |
Returns the Microsoft Graph permissions, Azure roles and methods that a Chapter 07 task’s declared calls need, combined into one object. | Chapter 07 — Least Privilege for Service Principals Module 5: Cut the privilege of service principals |
Get-NpiLpConfig |
Reads the least-privilege settings (config/least-privilege.json unless -Path names another file): the reviewed list of broad permissions, their proposed replacements, directory role names and privileged Azure roles. Returns them as a hashtable. | — |
New-NpiLpReader |
A read-only client for the least-privilege task, shaped like NpiCore’s reader so its Invoke-NpiList and Invoke-NpiGetOne send only these declared GETs, on the cloud’s own hosts. | — |
Import-NpiLpRegister |
Reads Chapter 01’s register from a run folder and returns @{ Rows; Manifest; Sha256 }. Throws if register.json’s SHA-256 isn’t the one manifest.json records. | — |
Import-NpiLpInput |
Reads a CSV input file and returns its rows. Returns an empty array when the path is empty or the file doesn’t exist, so an optional input can be left out. | — |
Get-NpiLpScopeLevel |
Returns the level of an Azure role assignment scope as text: Root, ManagementGroup, Subscription, ResourceGroup, Resource, or Unknown when the string matches none of them. | — |
Get-NpiLpSweep |
Read every in-scope service principal’s permissions: app role assignments on every resource, delegated grants, directory roles, and for managed identities their Azure role assignments at the scopes listed. Returns @{ Identities; Grants; Skipped; Evidence }. | Chapter 07 — Least Privilege for Service Principals |
Test-NpiLeastPrivilege |
Findings NPI-LP-01 to NPI-LP-09 over a sweep, the privileged service principals handed to the Privileged Access plan, and a proposal for each broad grant. Returns @{ Grants (each with Broad, Class, Proposal, Exception); Findings; Handoff }. | Chapter 07 — Least Privilege for Service Principals |
Get-NpiLpQuarter |
Returns the calendar quarter that contains -AsOf: its name (for example 2026-Q4) and its start and end as UTC dates. The owner review uses it to tell this quarter’s decisions from older ones. | — |
New-NpiLpOwnerReview |
The quarterly owner review (NP4.3): one row per grant of every service principal this chapter sweeps, with its owners, whether it’s broad, its exception and the proposal, and the owner’s decision this quarter if there is one. Privileged service principals aren’t in it: their review is the Privileged Access plan’s. Returns @{ Rows; Status }. | Chapter 07 — Least Privilege for Service Principals |
New-NpiLpPlan |
Turn the owners’ decisions into one action per broad grant and per decided change. Only two actions write: RemoveAppRole (DELETE the assignment through the resource service principal) and NarrowGrant (PATCH a delegated grant’s scope to a non-empty subset). Nothing in it writes. | Chapter 07 — Least Privilege for Service Principals |
New-NpiLpWriter |
The writer for least-privilege-apply: the only object in this chapter that can send a DELETE or a PATCH, and only the two calls calls-ch07.json declares for that task. | Chapter 07 — Least Privilege for Service Principals |
Assert-NpiLpPlannedWrite |
Throws unless a plan action is a write declared for least-privilege-apply, with the declared method, the expected target shape and an allowed body. Returns nothing when the action passes. | — |
Invoke-NpiLpPlan |
Apply a reviewed least-privilege plan. Without -Apply it is a dry run: it checks the plan and runs every precheck, and sends nothing. With -Apply it sends only the plan’s writes, only if the plan file’s SHA-256 is the one the reviewer approved, the plan is for this tenant and cloud and no older than seven days, and each precheck still holds. | — |
Export-NpiLpRun |
Writes each entry of -Files into -OutputPath (CSV for a .csv name, JSON otherwise) plus a manifest.json with the task’s permissions, every request and each file’s SHA-256, and returns the manifest file. | — |
New-NpiLpFixtureInvoker |
A fake Microsoft Graph and Resource Manager for this chapter, served from the Chapter 07 fixture: app role assignments by principal, delegated grants by client, resource service principals, directory role assignments by principal, Azure role assignments by scope and assignedTo, and role definitions. GET only unless -AllowWrite, which accepts the DELETE of an app role assignment through its resource service principal (404 through any other), the DELETE of a delegated grant (Learn’s sample) and a PATCH of a grant’s scope. Collections come in pages of -PageSize; every call is recorded in .Calls. | — |
Invoke-NpiLpFake |
The Chapter 07 fake’s dispatcher: records the request in the state’s Calls, then answers it from the fixture by host, method and path (paging collections), or throws for a request it doesn’t serve and for a write when the state doesn’t allow writes. New-NpiLpFixtureInvoker’s Invoke calls it. | — |
Module NpiMatrix
powershell/NpiMatrix/NpiMatrix.psm1
| Function | What it does | Taught in |
|---|---|---|
Get-NpiMatrixCallList |
Reads Chapter 03’s call list (config/calls-ch03.json unless -Path names another file) and returns it as a hashtable of tasks and calls. | — |
Get-NpiMatrixRequiredPermission |
Returns the Microsoft Graph permissions, Azure roles, AD rights and methods that a task’s declared calls in Chapter 03’s call list need, combined into one object. | Chapter 03 — The Migration Path Matrix as Code Module 3: Decide each identity’s target |
New-NpiMatrixReader |
A read-only client for the migration-matrix task, shaped like NpiCore’s reader so its Invoke-NpiGetOne and Invoke-NpiList work, but with Chapter 03’s own call list. | — |
New-NpiMatrixFixtureInvoker |
NpiCore’s fake Graph for the estate, plus a GET /subscribedSkus route served from a Chapter 03 fixture. GET only; every call is recorded in .Calls. | — |
Import-NpiMatrixConfig |
Reads the migration matrix (config/migration-matrix.json unless -Path names another file), checks that every row names a known target, and returns it as a hashtable with the file’s SHA-256 under the sha256 key. | — |
Import-NpiOwnershipRun |
Chapter 02’s run, checked against its manifest: ownership.json and orphan-plan.json must have the SHA-256 the manifest records, and the run must have checked this very register. | — |
Import-NpiMatrixJson |
Reads a JSON input file and returns it as a hashtable. Returns $null when the path is empty or the file doesn’t exist, so an optional input can be left out. | — |
Get-NpiMatrixProposal |
A proposed target for every identity in the register (NP2.1): Retire for an unowned or disabled one, otherwise the first matrix row that matches its type, its workload’s location and facts, and its credential kind. Identities outside the matrix get a reason, not a row. | Chapter 03 — The Migration Path Matrix as Code |
Test-NpiMigrationDecision |
Check each owner’s disposition (D-NP3) against the matrix’s proposal, sequence the waves (NP2.2) and return @{ Decisions; Waves; Findings }. Findings NPI-MAT-01 to NPI-MAT-08, each with a stable ID (rule:identity, or rule:wave-N). | Chapter 03 — The Migration Path Matrix as Code |
Get-NpiWorkloadIdScope |
The Workload ID Premium licensing scope (D-NP4) as a decision file checked against the register, the decisions and the tenant’s subscriptions: which identities Conditional Access and ID Protection for workload identities can cover, now and after conversion, how many each option scopes, and whether the tenant holds the license. Finding NPI-MAT-09. | Chapter 03 — The Migration Path Matrix as Code |
Test-NpiGate2 |
Gate 2, “every account has a decision”: every account in scope has a disposition and a target from the matrix; HIGH-risk accounts in the first wave; every kept Kerberos account has an SPN owner; waves and their rollback recorded; the D-NP4 scope decided. | Chapter 03 — The Migration Path Matrix as Code |
Export-NpiMatrixRun |
Write the run’s files and a manifest: task, mode, cloud, tenant, as-of date, the permissions the task holds (from calls-ch03.json), every request, the SHA-256 of the register, the ownership run, the matrix and each input, and of each file written. | — |
Module NpiOwnership
powershell/NpiOwnership/NpiOwnership.psm1
| Function | What it does | Taught in |
|---|---|---|
Import-NpiRegister |
Chapter 01’s register, checked against its run manifest: the file’s SHA-256 must be the one manifest.json records, so the ownership check runs on the evidence the ISSO received. | Chapter 03 — The Migration Path Matrix as Code |
Import-NpiInput |
Reads a CSV input file and returns its rows. Returns an empty array when the path is empty or the file doesn’t exist, so an optional input can be left out. | — |
Test-NpiOwnership |
Check every identity in the register against the program’s ownership rule and return @{ Identities; Findings; AiSponsorFields; Evidence }. Findings NPI-OWN-01 to NPI-OWN-09, each with a stable ID (rule:identity). | Chapter 02 — Ownership and the Orphan Rule |
New-NpiOrphanPlan |
The orphan rule (D-NP2) as a dry-run plan. An orphan candidate is disabled, never deleted, only after the identity governance officer confirms it in the confirmations log; the claim window is 30 days from the disable. Owner nominations become AddOwner actions for app registrations, after the nominee is checked. Nothing here writes. | Chapter 02 — Ownership and the Orphan Rule |
New-NpiWriter |
The writer for the orphan-apply task: the only object in this example that can send a PATCH, a POST or Disable-ADAccount, and only the calls calls.json declares for that task. | Chapter 02 — Ownership and the Orphan Rule |
Assert-NpiPlannedWrite |
Throws unless a plan action is a write declared for the orphan-apply task, with the declared method, the expected target shape and, for a disable, the only allowed body. Returns nothing when the action passes. | — |
Invoke-NpiOrphanPlan |
Apply a reviewed orphan plan. Without -Apply it is a dry run: it checks the plan and runs every precheck, and sends nothing. With -Apply it sends only the plan’s writes, only if the plan file’s SHA-256 is the one the reviewer approved, the plan is for this tenant and cloud and no older than seven days, and each precheck still holds. | — |
Module NpiWorkloadCa
powershell/NpiWorkloadCa/NpiWorkloadCa.psm1
| Function | What it does | Taught in | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
Get-NpiWcaPlanSha256 |
Returns the lowercase SHA-256 of the plan exactly as a run writes it to plan.json, so it is the same value manifest.json records for plan.json and a reviewer can approve it from the dry run’s output. | — | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Assert-NpiWcaApprovedPlan |
Throws unless -ApprovedSha256 is given and equals the SHA-256 of the plan about to be applied. Writes to a tenant are a person’s reviewed run: the reviewer approves the hash of a dry run’s plan.json, and any change to the plan or the tenant since then refuses the run. | — | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Get-NpiWcaCallList |
Reads the Chapter 08 call list (config/calls-ch08.json unless -Path is given) and returns it as a hashtable of tasks and calls. | — | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Get-NpiWcaCall |
Returns the declared Chapter 08 calls as an array, narrowed to one task (wca-read, wca-signins or wca-apply) with -Task. | — | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Get-NpiWcaRequiredPermission |
Returns the Graph permissions and methods a Chapter 08 task needs, the union of its declared calls, with the task’s mode. | Chapter 08 — Conditional Access for Workload Identities Module 6: Conditional Access for workload identities |
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
New-NpiWcaClient |
A Graph client for one Chapter 08 task in one cloud. -Invoke is { param($Method, $Uri, $Body, $Headers) } and returns the parsed body as a hashtable. Only the wca-apply task can write. | Chapter 08 — Conditional Access for Workload Identities Module 6: Conditional Access for workload identities |
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Resolve-NpiWcaRequest |
Builds the request for a declared Chapter 08 call on the cloud’s Graph host and returns the call, its method and the URI. Throws for an undeclared call, a write from a read task, DELETE, or a bound value that isn’t an object ID. | — | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Invoke-NpiWcaGet |
Sends a declared Chapter 08 GET to the cloud’s own Graph host, follows every @odata.nextLink, and returns all the items; -One returns the single response body. Each request is recorded in the client’s evidence. | — | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
New-NpiWcaFixtureInvoker |
A fake Microsoft Graph for Chapter 08, served from a fixture tenant: policies, named locations, service principals and the beta sign-in log, paged with a next link on the same host. It refuses what Learn documents Graph refuses (a policy state outside the three values, a service principal entry that isn’t an ID or ServicePrincipalsInMyTenant), serves only interactive sign-ins unless the filter asks for service principals, and returns the report-only results as unknownFutureValue unless the request carries Prefer: include-unknown-enum-members. DELETE throws. Every call is recorded in .Calls. | Chapter 08 — Conditional Access for Workload Identities Module 6: Conditional Access for workload identities |
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Invoke-NpiWcaFake |
The request handler behind New-NpiWcaFixtureInvoker: answers one Graph request from the fixture tenant in -State, applies a POST or PATCH to it, records the call in State.Calls, and throws as Graph would for a request it refuses. Normally called through the invoker’s .Invoke script block. | — | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Read-NpiWcaScope |
Reads the reviewed scope file and returns it as a hashtable, with the file’s SHA-256 added under the _sha256 key. | Chapter 08 — Conditional Access for Workload Identities Module 6: Conditional Access for workload identities |
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Read-NpiWcaRepository |
Reads the policy templates, named locations and alert definitions under workload-ca/ (or -Path) and returns each file’s kind, path, name, text and parsed body. | Chapter 08 — Conditional Access for Workload Identities Module 6: Conditional Access for workload identities |
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Read-NpiWcaLearnSample |
The Graph JSON sample from the pinned Learn page “Conditional Access for workload identities”, unmodified: its one json block. Throws if the page no longer has exactly one. | Chapter 08 — Conditional Access for Workload Identities Module 6: Conditional Access for workload identities |
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
ConvertTo-NpiWcaCidr |
Parses a CIDR range such as 198.51.100.32/29 and returns its text, address family, address bytes and prefix length, or $null if it isn’t a valid range. | — | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Test-NpiWcaIpInRange |
Returns $true when an IP address is inside any of the CIDR ranges given, and $false when it isn’t or the address doesn’t parse. | — | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Test-NpiWcaPolicyBody |
NPI-WCA-01, -07 and -08 on one policy body: a repository template, a rendered policy, or Learn’s sample. Reads the body only. | Chapter 08 — Conditional Access for Workload Identities Module 6: Conditional Access for workload identities |
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Test-NpiWcaRepository |
The pre-merge check: NPI-WCA-01 to -09 over the policy templates, the named location and the scope file. Reads files only, and runs in the pull request pipeline. A Finding stops -Apply. | Chapter 08 — Conditional Access for Workload Identities Module 6: Conditional Access for workload identities |
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Test-NpiWcaTenantScope |
Confirm the scope against the tenant: each in-scope object ID is a service principal (not an app registration’s object ID), an Application registered in this tenant, single-tenant and enabled (NPI-WCA-02 to -04), and every managed identity, multitenant, SaaS, agent or legacy service principal in the tenant is recorded out of scope (NPI-WCA-06). Reads only. | Chapter 08 — Conditional Access for Workload Identities | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Get-NpiWcaEnforcement |
Which rings may be enforced on this run. A ring is enforced only when the scope marks it, D-NP5 is recorded, -AllowEnforce was given, the sign-in summary at -SignInSummaryPath has the SHA-256 the ring’s record cites and shows the ring ready, and every earlier ring is enforced too. Anything else holds the ring in report-only, with the reason. | Chapter 08 — Conditional Access for Workload Identities Module 6: Conditional Access for workload identities |
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Get-NpiWcaDesiredLocation |
Returns the named location body from the repository with its ipRanges set from the scope’s egress ranges, in Graph’s iPv4CidrRange and iPv6CidrRange shape. Throws if no location file matches the scope’s egress name. | — | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Get-NpiWcaDesiredPolicy |
Each policy template rendered once per ring: ‘-Compare-NpiWcaValue
Compares a value from the repository with the tenant’s and returns the dotted path of each difference, walking the repository’s keys. Arrays compare as sets. Returns nothing when they match.
—
Get-NpiWcaTenant
Reads the tenant’s Conditional Access policies and named locations, every page, and returns them as Policies and Locations.
Chapter 08 — Conditional Access for Workload IdentitiesModule 6: Conditional Access for workload identities Get-NpiWcaPlan
Compare the repository and scope with the tenant and say what would change: the named location first, then each ring’s policies. Create (a policy always report-only), Update, NoChange, Blocked (its named location doesn’t exist yet), Held (an enforcement that isn’t allowed on this run) and NotInRepository (a workload policy nobody’s files name: reported, never deleted). Sends nothing.
Chapter 08 — Conditional Access for Workload IdentitiesModule 6: Conditional Access for workload identities Invoke-NpiWcaPlan
Carry out a plan. A dry run unless the client is the wca-apply task: it returns each request it would send with Sent = $false. With wca-apply it refuses to start if the pre-merge or tenant check has a Finding, and refuses any policy write that assigns anything but object IDs, grants anything but block, creates a policy that isn’t report-only, or enables one the plan didn’t mark as an allowed enforcement.
Chapter 08 — Conditional Access for Workload IdentitiesModule 6: Conditional Access for workload identities Get-NpiWcaSignIn
Service principal sign-ins between -From and -To, from Graph beta (List signIns), with the filter Learn gives for service principal sign-ins and the Prefer header that returns the report-only results. Throws if a result still comes back as unknownFutureValue.
Chapter 08 — Conditional Access for Workload Identities
Get-NpiWcaSignInSummary
Summarize report-only evidence per in-scope service principal and per ring. For each principal: sign-ins, the results our CA015 and CA037 policies recorded, the addresses outside the reviewed egress ranges, and a status: NoSignIns, NotEvaluated (no result from our policies yet), WouldBlock (a report-only failure, a block, or an address outside the ranges) or Clear. A ring is ready when every principal is Clear and the window is at least 14 days (Design guidance). Same inputs, same file, byte for byte.
Chapter 08 — Conditional Access for Workload Identities
New-NpiWcaAlertRule
The block-event alert for security operations, rendered from the reviewed definition in workload-ca/alerts with the scope’s service principal IDs. A definition for a reviewed deployment; this code doesn’t write to Azure Monitor.
Chapter 08 — Conditional Access for Workload Identities
Export-NpiWcaRun
Writes each of a run’s files as JSON under -OutputPath, then manifest.json with the task, mode, cloud, tenant, the Graph permissions the task holds, every request made and a SHA-256 per file. Returns the manifest file.
—
privileged-access
Module PaDeploy
Module PaAccessReviews
Module PaAzurePim
Module PaConditionalAccess
Module PaEvidence
Module PimEntraRoles
Module PimGroups
Module PrivilegedAccess
provider-notices
Module PnDeploy
Module ProviderNotices
servicenow-sailpoint
Module IdentityKit
start-kit
Module FMPADAssessment
Module FMPAttributeSurvey
Module FMPNpsInventory
Module FMPSqlEstate
Module FMPTransactionProfile
ttm-task-catalog
validation-kit
Module ValidationKit
Module ValidationKit
Module ValidationKit
Module ValidationKit
Module ValidationKit
Module ValidationKit
Module ValidationKit
Module ValidationKit
Module ValidationKit
Module ValidationKit
zta-results
Module ZtaResults
Command Reference – Federal Modernization Workbook Command Reference – Federal Modernization Workbook Command Reference – Federal Modernization Workbook Federal Modernization Workbook Federal Modernization Workbook Every command in the example kits: what it does, the pages that teach it, and how to get its help. Every command in the example kits: what it does, the pages that teach it, and how to get its help. |