Problem Break-Down
So I'm trying to return a list of all the security user groups a user is in but have it be broken up by manager. I take a couple of steps to do this:
- Get all users into UserList
- Gather a list of managers using the list of users.
- Sort the list of managers into a unique list.
- Get Manager SamAccountNames.
- Get directreports attribute from the managers to create the list of subordinates.
- Get their SamAccountNames
- Use SamAccountNames to pull AD Security Groups and Descriptions.
Everything works when used in little pieces. If you declare some names for $DirectReports and then run the final for loop it returns everything appropriately.
When running the script however, it returns only the Manager name, the direct report name, and all the lines for the security groups but nothing is in the lines for the security groups.
No relevant error message. Thanks in advance for the help.
Code
#Search Organizational Unit to find all Users
$UserList = @(Get-ADUser -Filter * -SearchBase "COMPANY'S ORG UNITS").SamAccountName
#For every user found in OU, select their manager
foreach ($User in $UserList) {
$Manager = @(Get-ADUser $User -Properties * | Select-Object @{Name = "Manager";Expression = {($_.manager -split ',*..=')[1]}})
$Managers = $Manager
}
#Sort and Select Unique Managers
$Managers = $Managers | Sort-Object -Property Manager -Unique
#Get SamAccountName From Manager Name
for ($a = 0; $a -lt $Managers.Count; $a ) {
$FilterString = "Name -eq '{0}'" -f $Managers[$a].Manager
$SAM = @(Get-ADUser -Filter "$FilterString" | Select SamAccountName)
$SAMs = $SAM
}
#Get subordinates for each manager
for ($b=0; $b -lt 1; $b ) {
#Get direct reporting individuals, second line cleans up output.
$DirectReports = @(Get-ADUser $SAMs[$b].SamAccountName -Properties directreports | select-object -ExpandProperty DirectReports)
$DirectReports = $DirectReports -replace "(CN=)(.*?),.*",'$2'
$Managers[$b 1]
Write-Output "`n"
#Get SAM names for direct reporting individuals and use to get user properties
for ($c = 0; $c -lt $DirectReports.Count; $c ) {
$FilterString2 = "Name -eq '{0}'" -f $DirectReports[$c]
$DirectReports[$c]
$SAM2 = @(Get-ADUser -Filter "$FilterString2")
$SAM2.SamAccountName
Get-ADPrincipalGroupMembership -Identity $SAM2.SamAccountName | Get-ADGroup -Properties * | select name, description
Write-Output "`n"
}
}
CodePudding user response:
Alright, couple of things we need to improve in your solution, but you are in the right path.
You're doing:
- Get all AD users
- Get all managers uniquely
- Get managers AD info
- Get managers direct report
- Get group membership of all direct reports
If you just want to return a list of SG per user, you could just go with:
$users = Get-ADUser -Filter * -Properties MemberOf
foreach ($membership in $users.MemberOf) {
Get-ADGroup -Identity $membership
}
If you want something from the managers themselves, you could go:
## Get list of managers (DirectReports not null)
$managers = Get-ADUser -Filter { -not (DirectReports -like '*') } -Properties DirectReports
#Get subordinates for each manager
foreach ($manager in $managers) {
foreach ($user in $manager.DirectReports) {
$groupMembership = Get-ADUser -Identity $user -Properties MemberOf
foreach ($membership in $groupMembership.MemberOf) {
Get-ADGroup -Identity $membership | Select-Object Name, Description
}
}
}
But for me this is just extra redundant work.
You can also use the Get-ADGroup cmdlet to list all groups.
Now let me explain what I changed from your script.
foreach loops instead of for loops. This makes object management easier
DistinguishedName is an identity together with SamAccountName, SID, ObjectGUId... Parsing DN for the CN is not reliable.
Instead of getting the users, then getting the managers, then getting the users again, then getting the groups, why not just get all groups?
No need to use the Get-ADPrincipalGroupMembership, there is an attribute called 'MemberOf' on the user object.
Things worth mentioning while using the ActiveDirectory PS module:
Be careful with the '-Filter *', some AD structures are too big and you'll end up with a timeout.
Use the '-Properties *' the least possible. Adding properties to the LDAP query slows it down considerably! and you may end up with a timeout. You can go for specific attributes instead, like '-Properties MemberOf'.
Even when specifying a single attribute, the standard ones always comes together. These are: DistinguishedName, Enabled, GivenName, Name, ObjectClassm ObjectGUID, SamAccountName, SID, Surname, UserPrincipalName.
I hope it helps!