Private/03.Principal.ps1
|
<#
SPDX-License-Identifier: Apache-2.0 Copyright (c) 2025 Stefan Ploch #> #region Principal Modeling # ---------------------------------------------------------------------- # # # Principal Modeling # # ---------------------------------------------------------------------- # function New-PrincipalDescriptor { <# .SYNOPSIS Create a principal descriptor (components, realm, name-type) used by the writer. #> param( [Parameter(Mandatory)][string[]]$Components, [Parameter(Mandatory)][string]$Realm, [Parameter(Mandatory)][int]$NameType, [string[]]$Tags ) $Tags = $Tags -join ',' [pscustomobject]@{ Components = $Components Realm = $Realm NameType = $NameType Tags = $Tags Display = ("{0}@{1}" -f ($Components -join '/'), $Realm) } } function Get-ComputerPrincipalDescriptors { <# .SYNOPSIS Build principal descriptors from a computer account's SPNs. #> [CmdletBinding()] param( [Parameter(Mandatory)][string]$ComputerName, [Parameter(Mandatory)][string]$DomainFQDN, [switch]$IncludeShortHost ) $adComp = Get-ADComputer -Identity $ComputerName -Properties servicePrincipalName -Server $DomainFQDN -ErrorAction Stop $realm = $DomainFQDN.ToUpperInvariant() $set = New-Object System.Collections.Generic.List[object] $spns = @() if ($adComp.servicePrincipalName) { $spns = $adComp.servicePrincipalName | Sort-Object -Unique } foreach ($spn in $spns) { if ($spn -notmatch '/') { continue } $parts = $spn.Split('/',2) $svc = $parts[0].ToLowerInvariant() $right = $parts[1].Split(':')[0].Split('/')[0].ToLowerInvariant() if (-not $right) { continue } $comp = New-PrincipalDescriptor -Components @($svc, $right) -Realm $realm -NameType $script:NameTypes.KRB_NT_SRV_HST -Tags @('SPN') $set.Add($comp) if ($IncludeShortHost) { $short = $right.Split('.')[0] if ($short -and $short -ne $right) { $set.Add( (New-PrincipalDescriptor -Components @($svc, $short) -Realm $realm -NameType $script:NameTypes.KRB_NT_SRV_HST -Tags @('SPN','ShortHost')) ) } } } # Deduplicate $unique = @{} foreach ($principal in $set) { $key = "$($principal.Components -join '|')|$($principal.Realm)|$($principal.NameType)" if (-not $unique.ContainsKey($key)) { $unique[$key] = $principal } } $unique.Values } function Get-UserPrincipalDescriptor { <# .SYNOPSIS Build a user principal descriptor from sAMAccountName and realm. #> param( [Parameter(Mandatory)][string]$SamAccountName, [Parameter(Mandatory)][string]$Realm ) $base = $SamAccountName.TrimEnd('$') New-PrincipalDescriptor -Components @($base) -Realm $Realm -NameType $script:NameTypes.KRB_NT_PRINCIPAL -Tags @('User') } function Get-KrbtgtPrincipalDescriptor { <# .SYNOPSIS Build the krbtgt principal descriptor for a realm. #> param( [Parameter(Mandatory)][string]$Realm ) New-PrincipalDescriptor -Components @('krbtgt') -Realm $Realm -NameType $script:NameTypes.KRB_NT_PRINCIPAL -Tags @('Krbtgt') } function Get-RiskLevelForPrincipal { <# .SYNOPSIS Compute a coarse risk level for a principal (for UX warnings). #> param( [string]$SamAccountName, [string]$PrincipalType, [boolean]$isDC ) if ($SamAccountname -eq 'KRBTGT') { return 'krbtgt' } if ($PrincipalType -eq 'Computer' -and $isDC) { return 'High' } if ($PrincipalType -eq 'Computer') { return 'Medium' } if ($PrincipalType -eq 'User') { return 'Medium' } if ($PrincipalType -eq 'Krbtgt') { return 'krbtgt' } return 'Medium' } #endregion |