Active Directory Group Nesting: Keeping It Manageable

Use AGDLP properly, avoid the nesting depth that makes permissions unauditable, and find circular and redundant group membership with PowerShell.

Active Directory Group Nesting: Keeping It Manageable

Group nesting is how permissions quietly become impossible to reason about. Nobody sets out to build a structure where a contractor ends up with finance access. It happens one reasonable-looking membership at a time, over years.

The fix is a convention applied consistently, plus a way to see what you’ve actually got.

Quick Facts

  • AGDLP is the convention worth following: Accounts into Global groups, Global into Domain Local, permissions on Domain Local.
  • Keep nesting to two or three levels. Beyond that nobody can answer “why does this person have access?”
  • Circular nesting is possible and breaks token calculation in confusing ways.
  • Kerberos tokens have a size limit. Users in hundreds of groups get authentication failures.
  • Name groups so the purpose is obvious without opening them.

AGDLP, briefly

The convention that stops this getting out of hand:

StepWhat goes where
AccountsUser accounts…
Global groups…go into global groups representing roles, e.g. GG-Finance-Staff
Domain Local groups…which go into domain local groups representing resources, e.g. DL-FinanceShare-Modify
Permissions…and permissions are assigned only to the domain local group

The value is that roles and resources stay separate. Someone changing department moves between global groups; a share changing its permission model changes domain local groups. Neither requires touching the other, and neither requires editing an ACL.

The failure mode people fall into is assigning permissions directly to global groups, or worse to individual users. It works immediately and becomes unmaintainable within a year.

Finding what you’ve actually got

# Everything a user is in, including nested
function Get-NestedGroups {
    param([string]$SamAccountName)
    $user = Get-ADUser $SamAccountName -Properties MemberOf
    $all = @{}
    function Walk($groups, $depth) {
        foreach ($g in $groups) {
            $grp = Get-ADGroup $g -Properties MemberOf
            if (-not $all.ContainsKey($grp.Name)) {
                $all[$grp.Name] = $depth
                Walk $grp.MemberOf ($depth + 1)
            }
        }
    }
    Walk $user.MemberOf 1
    $all.GetEnumerator() | Sort-Object Value, Name |
        Select-Object @{N='Group';E={$_.Key}}, @{N='Depth';E={$_.Value}}
}

Get-NestedGroups -SamAccountName jsmith

Run that against a long-serving employee and the result is usually surprising. Depth values above three are where auditing stops being practical.

Circular nesting

Group A contains Group B, which contains Group A. Active Directory permits it, and it produces membership that’s technically resolvable but impossible to reason about.

# Look for groups that are members of groups they contain
Get-ADGroup -Filter * -Properties MemberOf, Members | ForEach-Object {
    $g = $_
    foreach ($m in $g.Members) {
        if ($g.MemberOf -contains $m) {
            [PSCustomObject]@{ Group = $g.Name; CircularWith = (Get-ADObject $m).Name }
        }
    }
}

The token size problem

Every group membership adds to the Kerberos token. Users in a very large number of groups. Typically beyond about 1,000 SIDs, though the practical limit is lower. Start failing authentication in ways that look like anything but a group problem: HTTP 400 errors on internal sites, failed logons to specific applications, or connections that hang.

# Rough token size check
$user = Get-ADUser jsmith -Properties MemberOf, TokenGroups
"Direct groups : $($user.MemberOf.Count)"
"Total SIDs    : $((Get-ADUser jsmith -Properties TokenGroups).TokenGroups.Count)"

If that total is in the hundreds, you have a structural problem rather than a per-user one, and it will get worse.

Keeping it manageable

Quick Steps

  1. Adopt AGDLP and stick to it. Consistency matters more than which convention you pick.
  2. Name groups so purpose is obvious. A prefix for type, then role or resource, then permission level.
  3. Cap nesting at three levels and treat exceptions as things to fix.
  4. Never assign permissions to individual users. It’s always faster now and always costs more later.
  5. Review quarterly. Empty groups, circular nesting, and groups nobody can explain.
  6. Document why each group exists, in the group’s own description field. It’s the one place that travels with it.
# Groups with no members - usually leftovers
Get-ADGroup -Filter * -Properties Members, Description |
    Where-Object { $_.Members.Count -eq 0 } |
    Select-Object Name, Description, DistinguishedName

Glossary

TermWhat it means
AGDLPAccounts, Global, Domain Local, Permissions. The standard nesting convention.
Global groupContains accounts from its own domain. Represents a role.
Domain local groupCan contain groups from any domain. Represents access to a resource.
Token bloatExcessive group memberships causing authentication failures.
Circular nestingTwo groups each containing the other.
Effective permissionsThe access someone actually has once all nesting is resolved.

Frequently asked questions

How deep can group nesting go?

Technically very deep. Practically, three levels is where it stops being auditable. If you can’t explain someone’s access in one sentence, it’s too deep.

What’s the actual limit on group memberships?

There’s no hard cap, but Kerberos token size becomes a problem well before any theoretical limit, often around 1,000 SIDs, sometimes fewer depending on configuration.

Is AGDLP still relevant with cloud identity?

The principle is. Separating roles from resources. Entra ID uses different mechanics, but assigning access to roles rather than individuals is the same idea and just as important.

How do I find why someone has access to something?

Walk the nesting from the resource’s ACL back through the groups. The recursive function above does it from the user’s side; combine both to find the specific path.

Can I safely delete empty groups?

Usually, but check first. Some are placeholders for scheduled onboarding, and some are referenced by scripts or applications rather than by membership. Disable or rename before deleting if unsure.

🛠️

Gear We Recommend

Testing AD structure changes safely needs a lab. Here’s ours.

Browse our Home Lab picks on Amazon

As an Amazon Associate, TechyGeeksHome earns from qualifying purchases

Disclosure: this post may contain affiliate links. If you buy through one of them, we may earn a small commission at no extra cost to you. We only recommend products we’ve tested or genuinely rate.


Discover more from TechyGeeksHome

Subscribe to get the latest posts sent to your email.

Andrew Armstrong

Andrew Armstrong is a UK-based IT professional with 26+ years of hands-on experience in Windows, Windows Server, SCCM/ConfigMgr, Intune, Active Directory, PowerShell and enterprise infrastructure.

He founded TechyGeeksHome in 2010 and has published 770+ practical guides to real-world IT problems. He also builds free Windows utilities, including Ultimate Settings Panel, which has been downloaded over 850,000 times.

Leave a Reply

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