Public/Test-NSPEntraUserHardMatch.ps1
|
function Test-NSPEntraUserHardMatch { <# .SYNOPSIS Checks every selected pair of a queue against the live tenant. Read-only. .DESCRIPTION Refuses another tenant before reading anything. Each selected pair comes back Ready, AlreadySet, Linked or Blocked with its reasons. Nothing is written, including the queue. Blocked when: the queue is not freshly revalidated, the anchor is not Verified, the pair is stale, the cloud user is gone, synced, was synced, is a guest or holds a different immutable ID, an AD user or anchor maps to several cloud users, another cloud user or a soft-deleted user holds the anchor, the user holds or is eligible for a directory role, or the tenant blocks hard match. Revalidation has to be recent, -MaxRevalidationAgeMinutes, because it is what proves the AD side: this command reads only Entra. A failed eligibility read blocks. If the tenant has no licence for PIM, and so no eligible roles, say so with -AssumeNoRoleEligibility; the result records that you did. Needs a session from Connect-NSPEntraPairingGraph -Purpose Preflight. .EXAMPLE $check = Test-NSPEntraUserHardMatch -Queue $queue $check.Items | Group-Object Outcome #> [CmdletBinding()] [OutputType('NSP.M365.UserPairing.HardMatchPreflight')] param( [Parameter(Mandatory)]$Queue, [ValidateRange(1, 1440)][int]$MaxRevalidationAgeMinutes = 60, [switch]$AssumeNoRoleEligibility ) Import-NSPM365Graph Assert-NSPEntraPairingTenant -ExpectedTenantId $Queue.tenantId | Out-Null Assert-NSPEntraPairingSession -Purpose Preflight -TenantId $Queue.tenantId $queueBlocks = @(Get-NSPEntraHardMatchQueueBlock -Queue $Queue -MaxRevalidationAgeMinutes $MaxRevalidationAgeMinutes) $tenantState = Get-NSPEntraHardMatchTenantState -AssumeNoRoleEligibility:$AssumeNoRoleEligibility $usersById = @{} $holders = @{} foreach ($user in @(Invoke-NSPGraphCollection -Uri 'users?$select=id,userPrincipalName,userType,onPremisesImmutableId,onPremisesSyncEnabled&$top=999')) { if ($null -eq $user) { continue } $id = [string]$user['id'] $usersById[$id] = $user $anchor = [string]$user['onPremisesImmutableId'] if ($anchor) { if (-not $holders.ContainsKey($anchor)) { $holders[$anchor] = @() } $holders[$anchor] += $id } } $items = foreach ($pair in @($Queue.pairs | Where-Object decision -eq 'selected')) { $id = [string]$pair.cloudObjectId $check = @{ Pair = $pair Queue = $Queue QueueBlock = $queueBlocks TenantState = $tenantState CloudUser = $usersById[$id] ObjectIdentifier = $(if ($usersById.ContainsKey($id)) { Get-NSPEntraObjectIdentifierState -CloudObjectId $id } else { 'Unknown' }) } $anchor = [string]$pair.desiredImmutableId if ($anchor -and $holders.ContainsKey($anchor)) { $check.OtherAnchorHolder = @($holders[$anchor]) } Test-NSPEntraHardMatchPair @check } [pscustomobject]@{ PSTypeName = 'NSP.M365.UserPairing.HardMatchPreflight' TenantId = [string]$Queue.tenantId CheckedAtUtc = [datetime]::UtcNow.ToString('o') QueueBlocks = $queueBlocks TenantBlocks = @($tenantState.Blocks) Warnings = @($tenantState.Warnings) Items = @($items) TenantState = $tenantState } } |