Finding nested Active Directory groups faster with PowerShell

Finding nested groups in large Active Directory groups can be a challenging task. Active Directory includes the cmdlet Get-ADGroupMember for finding group members, but it cannot be used to query groups with over 5000 members. The cmdlet also suffers from performance bottlenecks. I'd like to share with you a tool I built that solves both those problems.

The problem with nested groups ^

Active Directory supports the concept of "nesting" groups inside one another. For example, consider two groups: GroupA and GroupB. GroupB can be a member of GroupA. If I assign GroupA write permissions to Folder1, then the members of GroupB also have write access to Folder1. Nesting groups inside each other can be a powerful way to assign access dynamically. There is no limit to the amount of nesting in Active Directory. For example, this scenario is valid (but not recommended):

  • GroupE is a member of GroupD
  • GroupD is a member of GroupC
  • GroupC is a member of GroupB
  • GroupB is a member of GroupA

That scenario can be challenging to unwind and report on. A circular reference can occur if an administrator is not careful. This occurs when groups are nested inside each other, creating an endless loop.

  • GroupC is a member of GroupB
  • GroupB is a member of GroupA
  • GroupA is a member of GroupC

Get-ADGroupMember basics ^

Microsoft created the Get-ADGroupMember cmdlet to return lists of group members. For everyday tasks, it works as advertised. If I want to see the members of a group called ParentGroup05, the syntax is straightforward.

The results show that there are three group members and a nested group named NestedGroup05.

Get ADGroupMember syntax

Get ADGroupMember syntax

The cmdlet also supports recursive lookups, which return users from all nested groups. Here, we can see that it shows six users: three in the parent group and three in the nested group.

Get ADGroupMember recursive lookup

Get ADGroupMember recursive lookup

But if you look closely, we have a potential problem. The cmdlet so far has shown the number of users OR a list of users and groups. If we perform a recursive search, it returns the data in one format (a flat list of users without group membership info). If we perform a non-recursive search, it returns the data in another format (a list of parent group users and a list of nested groups).

  • What if I need to know how many users are in each nested group?
  • What if I need to know which members belong to which group?

Get-ADGroup ^

In the examples above, there were criteria that could be useful: the presence of nested groups, the number of users in a nested group, and the concept of recursion or finding groups within groups. Get-ADGroupMember has trouble returning this information. However, Get-ADGroup can return the information we're looking for.

You may wonder how it is possible that Get-ADGroup can return group member information. Remember that when looking at group information in Active Directory Users and Computers, you can see MemberOf information. This means that there is a relationship between the group and the group members that Active Directory tracks. If we look at the same information with PowerShell, we can see that Get-ADGroup knows about the group member information.

Viewing Get ADGroup properties

Viewing Get ADGroup properties

Why is this important? There are two important aspects here that make this significant. We said earlier that Get-ADGroupMember isn't returning the data we want, so we need to look elsewhere. Get-ADGroup offers an alternate way to get the data we are looking for, and we can use PowerShell to access the data. If it's available via PowerShell, then we should be able to grab the data and format it as we wish.

Get-NestedGroup ^

Get-ADGroup can access the required information, but to do so requires using LDAP filters. If you have any experience using LDAP filters, then you know that their syntax can be challenging for users to understand. We can access most of the information required using one line of code:

This line instructs Active Directory to return only the groups that are members of $ADGrp. I saved the output to a variable and then the rest of the information was available by grabbing various properties. From there, I built a function that allows me to pass in a group (or multiple groups) to query and then format the results as I wish.

Here's what the output of my function Get-NestedGroup looks like when I query a group called ParentGroup05. The group has one nested group inside it, which has three members.

Get NestedGroup output results

Get NestedGroup output results

I designed the tool to look for nested group members two levels deep. That means that if we search for nested groups in ParentGroup01, then it will return any nested groups and then check those nested groups for nested groups.

Get NestedGroup Returning two levels of nested groups

Get NestedGroup Returning two levels of nested groups

The group ParentGroup01 was searched and returned two groups: NestedGroup01 and NestedGroup02.

The tool then checked those two groups and found one more nested group named LargeGroup3000. Each group that is found also displays the number of group members and some basic group information.

The Get-NestedGroup tool can be used with a Server parameter. This gives the ability to query results against a specific DC (or a dc in a different domain). If no server is input, the tool finds a DC in the same site that the query is run from. This guarantees that searches remain fast.

The tool can query multiple parent groups at a time like this:

I prefer the Format-Table output for more complex lookups, but the default view can be useful.

One thing I haven't mentioned yet is how fast this tool is! It returns results in about 15 milliseconds. If a similar recursive group lookup is done with Get-ADGroupMember, the results take anywhere from 5 to 20 seconds to complete.

Get NestedGroup Querying two parent groups

Get NestedGroup Querying two parent groups

I built this tool to help me get around the limits of Get-ADGroupMember when working with large groups. I needed a solution to pull out the nested groups from parent groups and give me the relevant information about those nested groups. Keep an eye out for my sister tool for grabbing the nested user information from parent groups.

The latest version of this tool is always available in my PowerShell GitHub Repo.


Join the 4sysops PowerShell group!

Your question was not answered? Ask in the forum!

  1. PshMike 2 months ago

    I believe there may be a slight error in your code. I entered an issue in GitHub for you to look at if you like.


    • Author

      Hi Mike, 

      I saw the github issue you opened. Thank you for reaching out. I am going to paste my response I left on github here as well. 

      so let's go through the question together.... for those unfamilar with the issue Mike raised. you can look here:

      I believe lines 115-124 should be inside of the foreach loop bound by lines 111-113


      I am sorry the line numbers dont line up, but i copied lines 110-125 here....

      this IF loop is only used if there is a nested group found in the earlier lookup...

      • it says IF NOT NULL then continue...
      • then it says foreach group in $nestedqueryresult > do the $subgrouplookup
      • then we create an pscustomobject
      • then we return the object
        ... and then it goes back through the foreach if there are more nestedgroups in $nestedqueryresult

      if I move object inside the foreach, then the next time the loop runs, it will overwrite the first result (if there are more than one).

      PowerShell keeps track of the pscustomobject for me. When I come through the second time, it adds to the existing results on output. It took me a long time to understand that logic, but that's Powershell stepping in and doing the work for me ... the next run of the loop ADDS to $SubNestedGroupInfo - it doesn't overwrite it. 

      does that make sense?


Leave a reply

Your email address will not be published. Required fields are marked *


© 4sysops 2006 - 2020


Please ask IT administration questions in the forums. Any other messages are welcome.


Log in with your credentials


Forgot your details?

Create Account