-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathTest-ServicePrincipalNameFromADUser.ps1
More file actions
128 lines (94 loc) · 4.28 KB
/
Copy pathTest-ServicePrincipalNameFromADUser.ps1
File metadata and controls
128 lines (94 loc) · 4.28 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
#Requires -Modules ActiveDirectory, DnsClient
<#PSScriptInfo
.DESCRIPTION Gets the ServicePrincipalName from ADUser Objects, and validates this
.VERSION 1.0.0.0
.GUID c2a3cd35-7919-4455-89da-15bece2fb794
.AUTHOR Tom Stryhn
.COMPANYNAME Tom Stryhn
.COPYRIGHT 2022 (c) Tom Stryhn
.TAGS Microsoft Active Directory ServicePrincipalName ADUser
.LICENSEURI https://github.com/tomstryhn/PowerShell/blob/main/LICENSE
.PROJECTURI https://github.com/tomstryhn/PowerShell/ActiveDirectory/Test-ServicePrincipalNameFromADUser/
#>
function Test-ServicePrincipalNameFromADUser {
<#
.SYNOPSIS
Gets the ServicePrincipalName from ADUser Objects, and validates this.
.DESCRIPTION
Gets the ServicePrincipalNames from a given ADUser Object, and will try and resolve the FQDN, assuming the SPN is in
the correct syntax, for the User Objects, which only should consist of Service Accounts, there are som requirements
for the SPNs, which differ a little from the SPNs found on the Computer Objects:
ServiceName/Fully.Qualified.Domain.Name(:Port)
The ServiceName is mandatory, and so is the FQDN, not saying it wont work with the ComputerName alone, but the correct
definition is with FQDN, which is why this function will flag nonFQDN's as invalid. The Port number on the other hand,
is optional.
.PARAMETER DistinguishedName
The DistinguishedName of the ADUser Object you want to test the ServicePrincipalName(s) on.
.EXAMPLE
PS C:\> Test-ServicePrincipalNameFromADUser -DistinguishedName "CN=ServiceAccountA,OU=UserAccounts,DC=Domain,DC=local"
DistinguishedName : CN=ServiceAccountA,OU=UserAccounts,DC=Domain,DC=local
ServicePrincipalName : http/webserver-a.domain.local:80
ServiceName : http
FullyQualifiedDomainName : webserver-a.domain.local
Resolvable : True
DistinguishedName : CN=ServiceAccountA,OU=UserAccounts,DC=Domain,DC=local
ServicePrincipalName : http/webserver-b.domain.local
ServiceName : http
FullyQualifiedDomainName : webserver-b.domain.local
Resolvable : True
.NOTES
FUNCTION: Test-ServicePrincipalNameFromADUser
AUTHOR: Tom Stryhn
GITHUB: https://github.com/tomstryhn/
.INPUTS
[string]
.OUTPUTS
[PSCustomObject]
#>
[CmdletBinding()]
param (
# DistinguishedName of ADUser Object
[Parameter(
Mandatory = $true,
ValueFromPipelineByPropertyName = $true
)]
[string]
$DistinguishedName
)
begin {}
process {
try{
Write-Verbose -Message "Fetching: [$DistinguishedName]"
$adUser = Get-ADUser -Identity $DistinguishedName -Properties ServicePrincipalName -ErrorAction Stop
}
catch {
Write-Error -Message "UserObject not found: [$DistinguishedName]"
}
Write-Verbose -Message "SPN Count: [$(($adUser.ServicePrincipalName).Count)]"
[regex]$spnRegex = "^(?'spnString'(?'serviceName'[A-Za-z0-9\-\.]{1,25})\/(?'fqdn'(?'computerName'[A-Za-z0-9\-]{1,63})(?:(?:\.[A-Za-z0-9\-]{1,63})){2,5})(?:\:(?'portNumber'[0-9]{1,5})){0,1})$"
foreach($servicePrincipalName in $adUser.ServicePrincipalName) {
$isValidSPN = $servicePrincipalName -match $spnRegex
if($isValidSPN) {
try {
$dnsResolve = Resolve-DnsName $Matches.fqdn -ErrorAction Stop
if($dnsResolve) {
$isResolvable = $true
}
}
catch {
$isResolvable = $false
}
}
$output = [PSCustomObject]@{
DistinguishedName = $DistinguishedName
ServicePrincipalName = if($isValidSPN) { $Matches.spnString } else { $servicePrincipalName }
ServiceName = if($isValidSPN) { $Matches.serviceName } else { 'N/A' }
FullyQualifiedDomainName = if($isValidSPN) { $Matches.fqdn } else { 'N/A' }
Resolvable = if($isValidSPN) { $isResolvable } else { 'N/A' }
}
$output
}
Write-Verbose -Message "Complete: [$DistinguishedName]`n"
}
end {}
}