How to list a user's forest-wide group memberships in Active Directory using PowerShell. It's not as easy as you think. Sure, you can just get the contents of the user's memberOf attribute, but that only contains groups from the domain that the user belongs to. What if your AD forest has multiple domains, and the user belongs to groups from more than one domain? In that case, you have to get the user's tokenGroups attribute.
The tokenGroups attribute is a multi-valued attribute that contains a list of SIDs of the groups the user belongs to, stored as byte arrays. The attribute is populated behind the scenes by AD. To get the list of token groups, you first have to explicitly retrieve the contents of the attribute by calling GetInfoEX. Then, for each token in the list, we create a security principal object that we can translate into a user name. I toss the results into a hashtable so that I can sort the output.
The Perl version (see Enumerate TokenGroups using Perl) is slightly more complicated in that you have to convert the bytes yourself. PowerShell does the conversion for you automatically.
$username=$args[0]
if($args.count -lt 1){ "Usage: ./tokenGroups.ps1 <username>" }
$groups=@{}
$gc="GC://" + $([adsi] "LDAP://RootDSE").Get("RootDomainNamingContext")
$filter = "(&(objectCategory=User)(|(cn=" + $username + ")(samaccountname=" + $username + ")(displayName=" + $username + ")(distinguishedName=" + $username + ")))" $domain = New-Object System.DirectoryServices.DirectoryEntry($gc) $searcher = New-Object System.DirectoryServices.DirectorySearcher $searcher.SearchRoot = $domain $searcher.Filter = $filter $results = $searcher.FindAll() if($results.count -eq 0){ "User Not Found"; }else{ foreach ($result in $results){ $user=$result.GetDirectoryEntry(); $user.GetInfoEx(@("tokenGroups"),0) $tokenGroups=$user.Get("tokenGroups") foreach ($token in $tokenGroups){ $principal = New-Object System.Security.Principal.SecurityIdentifier($token,0) $group = $principal.Translate([System.Security.Principal.NTAccount]) $groups[$group]=1 } } }
$groups.keys | sort-object
Related Posts:
- Backup DFS Namespaces Using PowerShell
- Translate Active Directory Name Formats Using PowerShell
- List Linux Users in Active Directory Using PowerShell
- Enable Trust for Delegation in Active Directory Using PowerShell
- TCP/IP Subnet Math with PowerShell - What AD Site is that Server in?
- List Sites and Subnets in Active Directory with PowerShell
- Find Disabled Users in Active Directory with PowerShell
- List Forest-wide Group Memberships with PowerShell
- Find Old Computer Accounts in AD with PowerShell
- List SPNs in Active Directory with PowerShell
- List Domain Controllers in Active Directory
4 comments:
I have not been able to successfully run this PowerShell script. I understand the explanation of why it is difficult to gather cross-domain memberships, but I am struggling with running the PowerShell.
Please excuse my ignorance, but would you be so kind as to provide instructions on how I need to save and execute this script?
Thank you!
Sorry, posting the script in html broke the code. It's fixed now.
Marvelous script it is ! , thanks a lot.
Very handy script. Thanks a lot.
Post a Comment