Created
March 3, 2021 06:05
-
-
Save IMJLA/3e5fa452af8948e5d97e91207a08baba to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
param ( | |
# Name of the group whose members to retrieve | |
[string]$GroupName | |
) | |
function Search-Directory { | |
# Uses the .NET System.DirectoryServices Namespace to perform an LDAP search | |
param ( | |
# LDAP Path to the node to search | |
[string]$DirectoryPath = (([adsisearcher]'').SearchRoot.Path), | |
# LDAP filter | |
[string]$Filter, | |
# LDAP result page size for large numbers of results | |
[int]$PageSize = 1000, | |
# LDAP attributes to return for the objects found in the search | |
[string[]]$PropertiesToLoad, | |
# Credentials to use to perform the LDAP bind | |
[pscredential]$Credential, | |
# LDAP search scope (Base, OneLevel, or Subtree [default]) | |
[string]$SearchScope = 'Subtree' | |
) | |
if ($Credential) { | |
$DirectoryEntry = [System.DirectoryServices.DirectoryEntry]::new($DirectoryPath,$($Credential.UserName),$($Credential.GetNetworkCredential().password)) | |
} | |
else { | |
$DirectoryEntry = [System.DirectoryServices.DirectoryEntry]::new($DirectoryPath) | |
} | |
$DirectorySearcher = [System.DirectoryServices.DirectorySearcher]::new($DirectoryEntry) | |
if ($Filter) { | |
$DirectorySearcher.Filter = $Filter | |
} | |
$DirectorySearcher.PageSize = $PageSize | |
$DirectorySearcher.SearchScope = $SearchScope | |
ForEach ($Property in $PropertiesToLoad) { | |
$null = $DirectorySearcher.PropertiesToLoad.Add($Property) | |
} | |
$SearchResultCollection = $DirectorySearcher.FindAll() | |
$null = $DirectorySearcher.Dispose() | |
$null = $DirectoryEntry.Dispose() | |
$Output = [System.DirectoryServices.SearchResult[]]::new($SearchResultCollection.Count) | |
$SearchResultCollection.CopyTo($Output,0) | |
$null = $SearchResultCollection.Dispose() | |
Write-Output $Output | |
} | |
function Get-DirectoryGroupMember { | |
# Uses the .NET System.DirectoryServices Namespace to perform an LDAP search to recursively find all members of a group | |
param ( | |
# Groups (returned from an LDAP search) whose members need to be retrieved | |
[Parameter(Mandatory=$true,ValueFromPipeline=$true)] | |
[System.DirectoryServices.SearchResult[]]$Group | |
) | |
begin{ | |
<# | |
1.2.840.113556.1.4.1941 is the OID for LDAP_MATCHING_RULE_IN_CHAIN aka LDAP_MATCHING_RULE_TRANSITIVE_EVAL | |
LDAP_MATCHING_RULE_IN_CHAIN is a special Extensible Match operator that walks the chain of ancestry in objects all the way to the root until it finds a match. | |
This reveals group nesting. | |
LDAP_MATCHING_RULE_IN_CHAIN will only work when used with Distinguished Name (DN) type attributes. | |
LDAP_MATCHING_RULE_IN_CHAIN is available only on domain controllers with Windows Server 2003 R2 (or above). | |
LDAP_MATCHING_RULE_TRANSITIVE_EVAL may be the new name as it is in current MS documentation and supports Windows Server 2008 (or above) domain controllers | |
#> | |
$OID = '1.2.840.113556.1.4.1941' | |
} | |
process{ | |
foreach ($ThisGroup in $Group) { | |
$GroupMemberSearch = Search-Directory -Filter "(memberof:$($OID):=$($ThisGroup.Properties['distinguishedname']))" -PropertiesToLoad @('operatingSystem','objectSid','samAccountName') | |
if ($GroupMemberSearch.Count -gt 0) { | |
$CurrentADGroupMembers = $GroupMemberSearch.GetDirectoryEntry() | |
} | |
Write-Debug "$($ThisGroup.Properties.name) has $(($CurrentADGroupMembers | Measure-Object).Count) members" | |
$ThisGroup | | |
Add-Member -MemberType NoteProperty -Name FullMembers -Value $CurrentADGroupMembers -Force -PassThru | |
} | |
} | |
end{} | |
} | |
$SearchParams = @{ | |
Filter = "(&(objectClass=group)(cn=$GroupName))" | |
PropertiesToLoad = @('objectClass','distinguishedName','name','grouptype','description','managedby','member','objectClass') | |
} | |
Search-Directory @SearchParams | | |
Get-DirectoryGroupMember |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment