Public/ConvertTo-NSPEntraPairingQueue.ps1
|
function ConvertTo-NSPEntraPairingQueue { <# .SYNOPSIS Builds a review queue from candidate records, bound to one tenant and forest. Offline. .DESCRIPTION One pair per record, each undecided. Identity is held as the Graph object ID and the AD objectGUID and SID; UPNs and distinguished names are labels from the time of review. The queue holds no credentials or tokens, but it does hold personal data: keep it in local state. .EXAMPLE $queue = ConvertTo-NSPEntraPairingQueue -Candidate $records -TenantId $inventory.TenantId -Forest 'contoso.example' -Domain $inventory.Domains -SourceAnchor $anchor #> [CmdletBinding()] [OutputType('NSP.M365.UserPairing.Queue')] param( [Parameter(Mandatory)][AllowEmptyCollection()][object[]]$Candidate, [Parameter(Mandatory)][guid]$TenantId, [Parameter(Mandatory)][ValidateNotNullOrEmpty()][string]$Forest, [Parameter(Mandatory)][AllowEmptyCollection()][string[]]$Domain, $SourceAnchor ) $linked = @(foreach ($record in $Candidate) { if ($record.Status -ne 'Linked') { continue } foreach ($item in $record.Candidates) { if ($item.Confidence -eq 'Linked') { [string]$item.ObjectGUID } } }) $pairs = foreach ($record in $Candidate) { $snapshots = foreach ($item in $record.Candidates) { [pscustomobject]@{ adObjectGuid = [string]$item.ObjectGUID adSid = [string]$item.ObjectSID samAccountName = [string]$item.SamAccountName userPrincipalName = [string]$item.UserPrincipalName displayName = [string]$item.DisplayName distinguishedName = [string]$item.DistinguishedName domain = [string]$item.DomainDNSRoot enabled = [bool]$item.Enabled passwordLastSetUtc = $item.PasswordLastSetUtc confidence = [string]$item.Confidence score = [int]$item.Score evidence = @($item.Evidence) desiredImmutableId = $item.DesiredImmutableId } } [pscustomobject]@{ cloudObjectId = [string]$record.CloudObjectId cloudLastPasswordChangeUtc = $record.CloudLastPasswordChangeUtc roleReview = [string]$record.RoleReview cloudUpnAtReview = [string]$record.CloudUserPrincipalName cloudDisplayNameAtReview = [string]$record.CloudDisplayName cloudImmutableIdAtReview = [string]$record.CloudImmutableId cloudStateAtReview = [string]$record.CloudState status = [string]$record.Status candidates = @($snapshots) decision = 'undecided' adObjectGuid = $null adSid = $null adDistinguishedNameAtReview = $null adUserPrincipalNameAtReview = $null adEnabledAtReview = $null matchEvidence = @() desiredImmutableId = $null decidedAtUtc = $null decidedBy = $null note = $null history = @() executionState = 'pending' execution = $null revalidation = $null } } $anchorVerified = $SourceAnchor -and $SourceAnchor.Provenance -eq 'Verified' -and $SourceAnchor.Strategy -ne 'Unknown' [pscustomobject]@{ PSTypeName = 'NSP.M365.UserPairing.Queue' schemaVersion = 1 tenantId = [string]$TenantId forest = $Forest domains = @($Domain) sourceAnchor = [pscustomobject]@{ strategy = if ($SourceAnchor) { [string]$SourceAnchor.Strategy } else { 'Unknown' } status = if ($anchorVerified) { 'verified' } else { 'unverified' } syncServer = if ($SourceAnchor) { [string]$SourceAnchor.ComputerName } else { $null } collectedAtUtc = if ($SourceAnchor) { [string]$SourceAnchor.CollectedAtUtc } else { $null } } createdAtUtc = [datetime]::UtcNow.ToString('o') revalidatedAtUtc = $null needsRevalidation = $false linkedAdObjectGuids = $linked pairs = @($pairs) } } |