Public/Assert-SqlAccountStandard.ps1
|
# ============================================================================= # Script : Assert-SqlAccountStandard.ps1 # Author : Keith Ramsey # ============================================================================= # Change Log # ----------------------------------------------------------------------------- # 2026-05-09 Keith Ramsey Phase 2 release polish - DR-202 standard header applied. # ============================================================================= function Assert-SqlAccountStandard { <# .SYNOPSIS Validates an Active Directory account against a named compliance policy. .DESCRIPTION Looks up the account in AD and asserts three policy invariants: - ObjectClass matches the policy's Type (user, computer, gMSA). - SamAccountName starts with the policy's Prefix when one is defined. - DistinguishedName lives under the policy's OU. Throws on first failure with all violations joined into the exception message. Returns $true on full compliance. Designed to be called as a pre-flight check inside Start-SqlSpnConfiguration; can also be called standalone for ad-hoc validation. .PARAMETER SamAccountName SAM account name to validate (e.g., svc_sql_prod or SQLFCI01$). .PARAMETER PolicyName Policy key from Get-SqlAccountPolicy (e.g., Std_Engine, Std_FCI_VNN, Std_SSAS, Std_Engine_gMSA). .EXAMPLE Assert-SqlAccountStandard -SamAccountName svc_sql_prod -PolicyName Std_Engine .EXAMPLE Resolve-SqlPolicyFromContext -Scenario FCI -Role Engine | ForEach-Object { Assert-SqlAccountStandard -SamAccountName 'SQLFCI01$' -PolicyName $_ } .OUTPUTS [bool]. Returns $true on success. Throws a terminating error on any compliance violation. .NOTES The policy table lives in Get-SqlAccountPolicy. Adding a new role/scenario requires extending that table. Phase 0 ships with Std_Engine, Std_Engine_gMSA, Std_FCI_VNN, and Std_SSAS; other policies are Phase 1 work. #> [CmdletBinding()] param( [Parameter(Mandatory=$true)][string]$SamAccountName, [Parameter(Mandatory=$true)][string]$PolicyName ) $policy = Get-SqlAccountPolicy -PolicyName $PolicyName if (-not $policy) { throw "Unknown policy [$PolicyName]. See Get-SqlAccountPolicy for valid keys." } $adObject = Get-ADObject -Filter "SamAccountName -eq '$SamAccountName'" -Properties DistinguishedName, ObjectClass if (-not $adObject) { throw "Account [$SamAccountName] not found in Active Directory." } $failures = @() if ($adObject.ObjectClass -ne $policy.Type) { $failures += "TYPE: Expected $($policy.Type), got $($adObject.ObjectClass)" } if ($policy.Prefix -and -not $SamAccountName.StartsWith($policy.Prefix)) { $failures += "PREFIX: Missing required prefix '$($policy.Prefix)'" } if ($adObject.DistinguishedName -notmatch [regex]::Escape($policy.OU)) { $failures += "OU: Account is not located under '$($policy.OU)'" } if ($failures.Count -gt 0) { throw "Compliance Failure for [$SamAccountName] under policy [$PolicyName]: $($failures -join ' | ')" } return $true } |