All product names, logos, and brands used in this post are property of their respective owners.
I recently stumbled across a nifty PowerShell LDAP module that allows you to programmatically query directories (OpenLDAP, Active Directory, etc.) via the LDAP protocol. The description states “non-AD LDAP environments,” but in the absence of the AD PowerShell module (for example, PowerShell Core on macOS, Linux, Azure Cloud Shell, etc.), the LDAP module happily queries Active Directory as well. And as it turns out, I spend more time reading ADDS than writing to it.
A common thread in my Active Directory data mining is group membership (members) - especially huge AD groups with many members (tens of thousands of users). With the Active Directory PowerShell module (RSAT tools), I use the following:
|
|
The LDAP module can produce identical results (albeit a little slower and with a caveat) as follows. The snippet is also available as a Gist.
Install the LDAP module
|
|
Create an LDAP connection using the Get-LdapConnection cmdlet
|
|
Enumerate members of the group using the Get-LdapObject cmdlet
|
|
This is where things get interesting. The caveat I mentioned is how the LDAP module returns the member attribute for groups with more than 1,500 members. You will notice the module returns an additional member attribute (something like member;range=0-1499) for large AD groups.
PS C:\Temp> Get-LdapObject -LdapConnection $connection -LdapFilter "(&(objectClass=group)(samaccountname=$group))" -SearchBase $searchBase -Property "member"
DistinguishedName member member;range=0-1499
----------------- ------ -------------------
CN=All-Contoso-Users-Global,OU=Groups,DC=ad,DC=contoso,DC=com {CN=someuser1,OU=Use...
That is a result of the “range tag” feature of the LDAP protocol, documented here. The Microsoft code sample is C++, which was not particularly useful for a PowerShell user like me. But it was not too difficult to implement something similar with PowerShell (using a Do…While loop):
Enumerate ALL members of the group using the Get-LdapObject cmdlet (and range tag)
|
|
With $allmembers populated, perform whatever tasks you need to
|
|
PS C:\Temp> $allmembers | Sort | Select -First 5
CN=someuser1,OU=Users,DC=ad,DC=contoso,DC=com
CN=someuser2,OU=Users,DC=ad,DC=contoso,DC=com
CN=someuser3,OU=Users,DC=ad,DC=contoso,DC=com
CN=someuser4,OU=Users,DC=ad,DC=contoso,DC=com
CN=someuser5,OU=Users,DC=ad,DC=contoso,DC=com
PS C:\Temp> $allmembers | Measure-Object
Count : 2371
Average :
Sum :
Maximum :
Minimum :
Property :
If nothing else, I hope this post serves as a PowerShell example of “range tag” enumeration of LDAP objects. However, the LDAP module itself is worth a look. Especially if you need to query Active Directory from a non-Windows device (Mac, Linux, Cloud Shell, etc.). You can even create functions that mimic the common Get- AD PowerShell module cmdlets (like Get-ADUser, Get-ADGroup, etc.) using LDAP searches…