Public/Add-NSPADForestUPNSuffix.ps1
|
function Add-NSPADForestUPNSuffix { <# .SYNOPSIS Previews a forest suffix plan; explicitly applies one additive change and verifies it. .DESCRIPTION Apply requires RSAT's Set-ADForest and separate owner authorization for the live forest. Rereads the pinned DC before and after confirmation, checks configuration GUID and snapshot, adds only the selected suffix and verifies on that DC. Never replaces the suffix list, changes a user, verifies an Entra domain or starts synchronization. .EXAMPLE Add-NSPADForestUPNSuffix -Plan $plan .EXAMPLE Add-NSPADForestUPNSuffix -Plan $plan -Apply #> [CmdletBinding(SupportsShouldProcess, ConfirmImpact='High')] [OutputType('NSP.ActiveDirectory.ForestUPNSuffixResult')] param([Parameter(Mandatory)][ValidateNotNull()]$Plan, [switch]$Apply) if ($Plan.Blocked) { throw 'Suffix plan is blocked.' } if (-not $Apply -or $WhatIfPreference) { if ($Apply) { [void]$PSCmdlet.ShouldProcess($Plan.ForestDNSRoot, "Add UPN suffix $($Plan.Suffix)") } return [pscustomobject]@{PSTypeName='NSP.ActiveDirectory.ForestUPNSuffixResult'; Result='Preview'; Plan=$Plan} } $ErrorActionPreference = 'Stop' $current = Get-NSPADForestInfo -Server $Plan.Server $fresh = Get-NSPADForestUPNSuffixPlan -ForestInfo $current -Suffix $Plan.Suffix Assert-NSPADForestSuffixPlanCurrent -Plan $Plan -Current $fresh if (-not $fresh.Changed) { return [pscustomobject]@{PSTypeName='NSP.ActiveDirectory.ForestUPNSuffixResult'; Result='AlreadyAvailable'; ForestInfo=$current; Suffix=$fresh.Suffix} } Assert-NSPADCommand -Name Set-ADForest $result = 'Skipped' $message = '' $observed = $null if ($PSCmdlet.ShouldProcess("$($fresh.ForestDNSRoot) on $($fresh.Server)", "Add UPN suffix $($fresh.Suffix)")) { # Do not hold a stale snapshot while an operator is deciding at a confirmation prompt. $current = Get-NSPADForestInfo -Server $fresh.Server $latest = Get-NSPADForestUPNSuffixPlan -ForestInfo $current -Suffix $fresh.Suffix Assert-NSPADForestSuffixPlanCurrent -Plan $Plan -Current $latest $writeStarted = $false try { $writeStarted = $true Set-ADForest -Identity $latest.ForestDNSRoot -Server $latest.Server -UPNSuffixes @{Add=$latest.Suffix} -ErrorAction Stop $observed = Get-NSPADForestInfo -Server $latest.Server $missingBefore = @($latest.Before | Where-Object { $observed.AlternateUPNSuffixes -inotcontains $_ }) if ($observed.ConfigurationGUID -eq $latest.ConfigurationGUID -and $observed.ConfigurationDN -ieq $latest.ConfigurationDN -and $observed.AvailableUPNSuffixes -icontains $latest.Suffix -and $missingBefore.Count -eq 0) { $result = 'Verified' } else { $result='VerificationFailed'; $message='Read-back did not verify the selected suffix on the same forest.' } } catch { $result = if ($writeStarted) { 'WriteUnverified' } else { 'Failed' } $message = $_.Exception.Message } } [pscustomobject]@{ PSTypeName='NSP.ActiveDirectory.ForestUPNSuffixResult'; Result=$result; Message=$message ForestDNSRoot=$fresh.ForestDNSRoot; ConfigurationGUID=$fresh.ConfigurationGUID Server=$fresh.Server; Suffix=$fresh.Suffix; Before=$fresh.Before; After=$fresh.After Observed=$observed; TimestampUtc=[datetime]::UtcNow } } |