Public/Start-NSPEntraPairingUpnSuffixReview.ps1
|
function Start-NSPEntraPairingUpnSuffixReview { <# .SYNOPSIS Reviews verified cloud domains missing as AD UPN suffixes, with explicit selected additions. .DESCRIPTION Default is review/preview. Apply enables an explicit add action after showing the AD plan; confirmation is required for that forest change. The AD module owns planning and writing. Every addition refreshes the domain/forest comparison. No users or cloud domains change. .EXAMPLE Start-NSPEntraPairingUpnSuffixReview -ExpectedTenantId $queue.tenantId -ExpectedForest $queue.forest -Server $server .EXAMPLE Start-NSPEntraPairingUpnSuffixReview -ExpectedTenantId $queue.tenantId -ExpectedForest $queue.forest -Server $server -Apply #> [CmdletBinding(SupportsShouldProcess, ConfirmImpact='High')] param([Parameter(Mandatory)][guid]$ExpectedTenantId, [Parameter(Mandatory)][string]$ExpectedForest, [Parameter(Mandatory)][string]$Server, [switch]$Apply) Import-NSPToolkitModule -Name 'NSP.ActiveDirectory' Import-NSPToolkitModule -Name 'NSP.Console' -MinimumVersion '0.1.1' foreach ($command in 'Get-NSPADForestInfo','Get-NSPADForestUPNSuffixPlan','Add-NSPADForestUPNSuffix') { if (-not (Get-Command $command -ErrorAction SilentlyContinue)) { throw 'The AD forest/suffix APIs are not available yet. Install the AD specialist delivery before using this gate.' } } $results = [System.Collections.Generic.List[object]]::new() $failure = $null try { while ($true) { $forest = Get-NSPADForestInfo -Server $Server if ([string]$forest.ForestDNSRoot -ine $ExpectedForest) { throw 'The AD forest differs from the expected forest.' } if ($null -eq $forest.PSObject.Properties['AvailableUPNSuffixes']) { throw 'AD did not return available UPN suffixes; availability is unknown.' } $comparison = @(Get-NSPEntraPairingUpnSuffixComparison -ExpectedTenantId $ExpectedTenantId -Forest $ExpectedForest -AvailableSuffix @($forest.AvailableUPNSuffixes)) foreach ($item in $comparison) { Write-NSPConsoleLine -Message "$($item.Suffix) [$($item.Status)]" } $missing = @($comparison | Where-Object Status -eq Missing) if (-not $missing.Count) { break } $choices = @($missing | ForEach-Object { [pscustomobject]@{ Label="Review missing suffix $($_.Suffix)"; Value=$_.Suffix } }) $suffix = Read-NSPMenu -Prompt 'Choose a missing verified domain to preview; nothing is added automatically' -Choices $choices -CancelLabel 'Back to user preparation' if ($null -eq $suffix) { break } if ($suffix -notin @($missing.Suffix)) { throw 'Selected suffix was not in the missing verified-domain list.' } $plan = Get-NSPADForestUPNSuffixPlan -ForestInfo $forest -Suffix $suffix Write-NSPConsoleLine -Message ($plan | ConvertTo-Json -Depth 8) if (-not $Apply -or $plan.Blocked -or -not $plan.Changed) { continue } $action = Read-NSPMenu -Prompt 'Review the additive forest change above' -Choices @( [pscustomobject]@{Label='Return without adding';Value='back'} [pscustomobject]@{Label="Add only $suffix to $ExpectedForest";Value='add'} ) if ($action -ne 'add') { continue } # Check Graph again just before applying; the AD writer independently rejects stale forest plans. $current = @(Get-NSPEntraPairingUpnSuffixComparison -ExpectedTenantId $ExpectedTenantId -Forest $ExpectedForest -AvailableSuffix @($forest.AvailableUPNSuffixes)) if ($suffix -notin @($current.Suffix)) { throw 'The suffix is no longer a verified domain in this tenant.' } if ($PSCmdlet.ShouldProcess("$ExpectedForest via $($forest.Server)", "Add UPN suffix $suffix")) { $result = Add-NSPADForestUPNSuffix -Plan $plan -Apply -Confirm:$false $results.Add($result) Write-NSPConsoleLine -Message ($result | ConvertTo-Json -Depth 8) if ($result.Result -notin @('Verified','AlreadyAvailable')) { break } } } } catch { if (-not $results.Count) { throw } $failure = $_.Exception.Message } [pscustomobject]@{ Comparison=$comparison; Results=$results.ToArray(); Error=$failure } } |