From 75df61b19c967f0770340d1b40770b2e3711204c Mon Sep 17 00:00:00 2001 From: Rephl3x Date: Wed, 24 Sep 2025 00:47:08 +0000 Subject: [PATCH] Find and correct SPN issues for SQL team --- Darth-SPooN.ps1 | 111 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 111 insertions(+) create mode 100644 Darth-SPooN.ps1 diff --git a/Darth-SPooN.ps1 b/Darth-SPooN.ps1 new file mode 100644 index 0000000..0dc7414 --- /dev/null +++ b/Darth-SPooN.ps1 @@ -0,0 +1,111 @@ +param( + [Parameter(Mandatory = $true)] + [string]$MachineName, + + [Parameter(Mandatory = $true)] + [string]$ServiceAccount, + + [int]$SqlPort = 1433, + + [string[]]$HadrListeners +) + +Import-Module ActiveDirectory + +Write-Host "=== MSSQLSvc + HADR SPN Validation Tool ===" -ForegroundColor Cyan +Write-Host "Machine: $MachineName" +Write-Host "Service Account: $ServiceAccount" +Write-Host "SQL Port: $SqlPort" +if ($HadrListeners) { + Write-Host "HADR Listener(s): $($HadrListeners -join ', ')" +} +Write-Host "-------------------------------------------" + +# Get domain FQDN +$domainFQDN = (Get-ADDomain).DNSRoot + +# Lookup service account (user or computer) +try { + $svcObj = Get-ADUser -Identity $ServiceAccount -Properties ServicePrincipalName -ErrorAction Stop +} catch { + try { + $svcObj = Get-ADComputer -Identity $ServiceAccount -Properties ServicePrincipalName -ErrorAction Stop + } catch { + Write-Host "ERROR: Service account '$ServiceAccount' not found in AD." -ForegroundColor Red + exit + } +} + +# Build expected MSSQLSvc SPNs for machine and HADR listeners +$namesToCheck = @($MachineName) +if ($HadrListeners) { + $namesToCheck += $HadrListeners +} +$expectedSPNs = foreach ($name in $namesToCheck) { + "MSSQLSvc/${name}.${domainFQDN}:$SqlPort" + "MSSQLSvc/${name}:$SqlPort" +} + +Write-Host "`nExpected MSSQLSvc SPNs:" -ForegroundColor Yellow +$expectedSPNs | ForEach-Object { Write-Host " $_" } + +# Case-insensitive missing SPN check (fixed grouping) +$missingSPNs = $expectedSPNs | Where-Object { + $expectedLower = $_.ToLower() + -not (( $svcObj.ServicePrincipalName | ForEach-Object { $_.ToLower() } ) -contains $expectedLower) +} + +if ($missingSPNs) { + Write-Host "`n[!] Missing MSSQLSvc SPNs on service account:" -ForegroundColor Red + $missingSPNs | ForEach-Object { Write-Host " $_" -ForegroundColor Red } + + $addPrompt = Read-Host "`nDo you want to add the missing SPNs now? (Y/N)" + if ($addPrompt -match '^[Yy]$') { + foreach ($spn in $missingSPNs) { + Write-Host "Adding SPN: $spn" -ForegroundColor Green + # Use -S to avoid duplicates, requires running as an account with permission + setspn -S $spn $ServiceAccount + } + Write-Host "`n[OK] Missing SPNs have been added." -ForegroundColor Green + } else { + Write-Host "Skipping SPN creation." -ForegroundColor Yellow + } +} else { + Write-Host "`n[OK] All expected MSSQLSvc SPNs are present." -ForegroundColor Green +} + +# Pull all SPNs in the domain +$allSPNs = Get-ADObject -Filter {ServicePrincipalName -like "*"} -Properties ServicePrincipalName | + ForEach-Object { + foreach ($spn in $_.ServicePrincipalName) { + [PSCustomObject]@{ + SPN = $spn + ADObject = $_.SamAccountName + DN = $_.DistinguishedName + } + } + } + +# Check for duplicates of MSSQLSvc SPNs +Write-Host "`nChecking for duplicate MSSQLSvc SPNs in the domain..." -ForegroundColor Yellow +foreach ($spn in $svcObj.ServicePrincipalName | Where-Object { $_ -like "MSSQLSvc/*" }) { + $owners = $allSPNs | Where-Object { $_.SPN -eq $spn } + if ($owners.Count -gt 1) { + Write-Host "[DUPLICATE] SPN '$spn' is owned by multiple objects:" -ForegroundColor Red + $owners | ForEach-Object { Write-Host " -> $($_.ADObject) ($($_.DN))" } + } +} + +# Check for MSSQLSvc SPNs on service account that aren't expected +$expectedLowerList = $expectedSPNs | ForEach-Object { $_.ToLower() } +$wrongSPNs = $svcObj.ServicePrincipalName | Where-Object { + $_ -like "MSSQLSvc/*" -and ($_.ToLower() -notin $expectedLowerList) +} +if ($wrongSPNs) { + Write-Host "`n[!] Warning: Service account has MSSQLSvc SPNs not in expected list:" -ForegroundColor Red + $wrongSPNs | ForEach-Object { Write-Host " $_" } +} else { + Write-Host "`n[OK] No unexpected MSSQLSvc SPNs found." -ForegroundColor Green +} + +Write-Host "`n=== MSSQLSvc + HADR SPN Check Complete ==="