-
-
Notifications
You must be signed in to change notification settings - Fork 9
Expand file tree
/
Copy pathGet-ADUserTransitiveGroupMembership.ps1
More file actions
93 lines (77 loc) · 4.26 KB
/
Copy pathGet-ADUserTransitiveGroupMembership.ps1
File metadata and controls
93 lines (77 loc) · 4.26 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
function Get-ADUserTransitiveGroupMembership {
<#
.SYNOPSIS
Get the full transitive group membership of an Active Directory user.
.DESCRIPTION
Get the full transitive group membership of an Active Directory user by searching the global catalog. This performs
a transitive LDAP query which effectively flattens the group membership hierarchy more efficiently than a recursive
memberOf lookup could.
.PARAMETER UserDN
The distinguished name of the user to search for. This is required and it accepts input from the pipeline.
.PARAMETER Server
A global catalog domain controller to connect to. This will get a GC in the current forest if none is specified.
.PARAMETER Port
Port to connect to the global catalog service on. Defaults to 3269 (using TLS).
.EXAMPLE
Get-ADUser -Identity JaneDoe | Get-ADUserTransitiveGroupMembership
Gets the transitive group membership of the user JaneDoe (include all effective nested group memberships).
.EXAMPLE
Get-ADUserTransitiveGroupMembership -UserDN 'CN=Jane Doe,OU=Users,DC=example,DC=com'
Gets the transitive group membership of the user Jane Doe (include all effective nested group memberships).
.NOTES
Author: Sam Erde
Company: Sentinel Technologies, Inc
Version: 1.0.0
Date: 2025-02-27
#>
[CmdletBinding()]
param (
[Parameter(Mandatory, ValueFromPipeline, HelpMessage = 'The distinguished name of the user to search for.')]
[string]$UserDN,
[Parameter(HelpMessage = 'A global catalog domain controller to connect to.')]
[ValidateScript({ (Test-NetConnection -ComputerName $_ -InformationLevel Quiet -ErrorAction SilentlyContinue).PingSucceeded })]
[string]$Server = ([System.DirectoryServices.ActiveDirectory.GlobalCatalog]::FindOne([System.DirectoryServices.ActiveDirectory.DirectoryContextType]::Forest)).Name,
# Port to connect to the global catalog service on.
[Parameter(HelpMessage = 'Port to connect to the global catalog service on. Default is 3268, or 3269 for using TLS.')]
[ValidateSet(3268, 3269)]
[int]$Port = 3269
)
begin {
if ($Port -eq 3269) {
$AltPort = 3268
} else {
$AltPort = 3269
}
$CurrentProgressPreference = Get-Variable -Name ProgressPreference -ValueOnly
try {
Set-Variable -Name ProgressPreference -Value 'SilentlyContinue' -Force -Scope Global -ErrorAction SilentlyContinue
# Check if the global catalog server is available on the specified port.
if (-not (Test-NetConnection -ComputerName $Server -Port $Port -InformationLevel Quiet -ErrorAction SilentlyContinue)) {
if (-not (Test-NetConnection -ComputerName $Server -Port $AltPort -InformationLevel Quiet -ErrorAction SilentlyContinue)) {
throw "Unable to connect to the global catalog server '$Server' on port '$Port' or '$AltPort.'"
}
}
} finally {
Set-Variable -Name ProgressPreference -Value $CurrentProgressPreference -Force -Scope Global -ErrorAction SilentlyContinue
}
}
process {
# Set the searcher parameters
$Filter = "(&(objectClass=group)(member:1.2.840.113556.1.4.1941:=$UserDN))"
$Searcher = New-Object System.DirectoryServices.DirectorySearcher
$Searcher.SearchRoot = New-Object System.DirectoryServices.DirectoryEntry("LDAP://$Server`:$Port")
$Searcher.Filter = $Filter
$Searcher.PageSize = 1000
$Searcher.PropertiesToLoad.Add('DistinguishedName') | Out-Null
$Results = $Searcher.FindAll()
Write-Verbose "Found $($Results.Count) groups for ${UserDN}."
$TransitiveMemberOfGroupDNs = foreach ($result in ($results.properties)) {
$result['distinguishedname']
}
# Emit deduplicated results per user in process block so pipeline results are not overwritten.
$TransitiveMemberOfGroupDNs | Sort-Object -Unique
}
end {
Remove-Variable Filter, TransitiveMemberOfGroupDNs, Results, Searcher, Server, Port, UserDN -ErrorAction SilentlyContinue
}
} # end function Get-ADUserTransitiveGroupMembership