2
votes

I'm trying to make a PS script which would list all Active Directory user group membership (recursive).

I already have working script:

import-module activedirectory

$users = get-aduser -Filter {Name -Like "*"} -Searchbase "ou=Users, dc=Domain" | Where-Object { $_.Enabled -eq 'True' } 

$targetFile = "D:\users.csv"
rm $targetFile
Add-Content $targetFile "User;Group"


foreach ($user in $users)
{
    $groups = Get-ADPrincipalGroupMembership $user

    foreach ($group in $groups)
    {
        $username = $user.samaccountname
        $groupname = $group.name
        $line = "$username;$groupname"
        Add-Content $targetFile $line
    }
}

But script doesn't list groups recursively, i.e., if group listed in the output file is part of another group.

Example:

Group1: User

Group2: Group3: User

Script shows only Group1 and 3 but not 2.

What should I add to the first script that it writes group membership recursively?

5
You should recursively query Get-ADPrincipalGroupMembership for a group, for those group you haven't queried yet.Vesper

5 Answers

5
votes

Sorry I am publishing an answer for a question from 3 years ago but if someone will see it, it can help.
Credit to:
How to get ALL AD user groups (recursively) with Powershell or other tools?

You can use the LDAP_MATCHING_RULE_IN_CHAIN:

Get-ADGroup -LDAPFilter "(member:1.2.840.113556.1.4.1941:=CN=User,CN=USers,DC=x)"

You can use it anywahere that you can use an LDAP filter.

Example:

$username = 'myUsername'
$dn = (Get-ADUser $username).DistinguishedName
Get-ADGroup -LDAPFilter ("(member:1.2.840.113556.1.4.1941:={0})" -f $dn) | select -expand Name | sort Name  

Fix in your script:

import-module activedirectory

$users = get-aduser -Filter {Name -Like "*"} -Searchbase "ou=Users, dc=Domain" | Where-Object { $_.Enabled -eq 'True' } 

$targetFile = "D:\users.csv"
rm $targetFile
Add-Content $targetFile "User;Group"

foreach ($user in $users)
{
$dn = $user.DistinguishedName
    $groups = Get-ADGroup -LDAPFilter ("(member:1.2.840.113556.1.4.1941:={0})" -f $dn) | select -expand Name | sort Name

    foreach ($group in $groups)
    {
        $username = $user.samaccountname
        $groupname = $group.name
        $line = "$username;$groupname"
        Add-Content $targetFile $line
    }
}
2
votes

If you make it a function you can call it recursively. Check this out, I think you'll be pleased with the results:

Function Get-ADGroupsRecursive{
Param([String[]]$Groups)
    Begin{
        $Results = @()
    }
    Process{
        ForEach($Group in $Groups){
            $Results+=$Group
            ForEach($Object in (Get-ADGroupMember $Group|?{$_.objectClass -eq "Group"})){
                $Results += Get-ADGroupsRecursive $Object
            }
        }
    }
    End{
        $Results | Select -Unique
    }
}

Toss that at the top of your script, and then call it for each user. Something like:

import-module activedirectory

$users = get-aduser -Filter {Name -Like "*"} -Searchbase "ou=Users, dc=Domain" -Properties MemberOf | Where-Object { $_.Enabled -eq 'True' } 

$targetFile = "D:\users.csv"
rm $targetFile
Add-Content $targetFile "User;Group"


foreach ($user in $users)
{
    $Groups = $User.MemberOf
    $Groups += $Groups | %{Get-ADGroupsRecursive $_}
$Groups | %{New-Object PSObject -Property @{User=$User;Group=$_}}|Export-CSV $targetfile -notype -append
}

Now, depending on the size of your AD structure that may take quite a while, but it will get you what you were looking for.

1
votes

It is very easy. Just use ActiveRoles Management Shell for Active Directory. Cmdlet Get-QADMemberOf with parameter Indirect is the one you are looking for. Example:

Get-QADMemberOf john.smith -Indirect

1
votes

The Quest object returned already include All Recursive groupes (and first level users) in properties $_.AllMembers

Add-PSSnapin Quest.ActiveRoles.ADManagement
$UsersFirstLevel = ($Members | Get-QADObject -Type Group -DontUseDefaultIncludedProperties | Get-QADGroupMember -DontUseDefaultIncludedProperties | ?{$_.type -eq 'user'})
$UsersSubGroup = ($Members | Get-QADObject -Type Group -DontUseDefaultIncludedProperties | Get-QADGroupMember -DontUseDefaultIncludedProperties | ?{$_.type -eq 'group'}).Allmembers | Get-QADObject -DontUseDefaultIncludedProperties | ?{$_.type -eq 'user'}

$RecursiveUsers = $UsersFirstLevel
$RecursiveUsers += $UsersSubGroup
$RecursiveUsers = $RecursiveUsers | Sort-Object -Unique
1
votes

Newer versions of PowerShell (AD Module) do have -Recursive switch. So you can easily use Get-ADGroupMember.

Example: Get-ADGroupMember -Identity My_Group -Recursive