Exporting AD group memberships of users in PowerShell - powershell

I need to export a list of all groups a user is assigned to. This command works fine for my needs:
Get-ADPrincipalGroupMembership username | select name | Export-Csv filepath
However I have to review about 100 users in my company, so I would like to to merge those CSVs in an Excel spreadsheet. My problem is that when I merge the CSVs, I just have a random list of AD groups.
A solution for this problem would be to export a CSV with two columns while column 1 consists of the AD username and column 2 of the AD groupname, eg.
User A | Group A; User A | Group B; User A | Group C
I already have figured out that this probably won't be possible with Get -ADPrincipalGroupMembership but unfortunately I haven't found any solution yet.

The format you're considering is terrible for both viewing and processing. Either build a list mapping the user to each group (one mapping per line)
$users = 'userA', 'userB', ...
foreach ($user in $users) {
$groups = Get-ADPrincipalGroupMembership $user |
Select-Object -Expand Name
$groups | ForEach-Object {
New-Object -Type PSObject -Property #{
'User' = $user
'Group' = $_
}
}
} | Export-Csv 'output.csv' -NoType
or join the list of groups with a secondary delimiter and map a user to all of its groups like that:
$users = 'userA', 'userB', ...
foreach ($user in $users) {
$groups = Get-ADPrincipalGroupMembership $user |
Select-Object -Expand Name
New-Object -Type PSObject -Property #{
'User' = $user
'Group' = $groups -join '|'
}
} | Export-Csv 'output.csv' -NoType

Related

PowerShell compare two objects and output equals

I have a text file with different user names inside.
Now I want to get all groups where the users are inside, compare the user and only output the groups where ALL users are inside.
$users = Get-Content -path "C:\users.txt"
foreach($user in $users)
{
write-host "Group Membership for: " $user
Get-ADPrincipalGroupMembership -Identity $user | Select name
}
If the user list is not huge, the following is a simple way to group all groups that are common among the users:
$users = Get-Content -path "C:\users.txt"
$users | Foreach-Object {
# Grouping groups based on distinguishedName
# List groups that appear as many times as the number of users
Get-ADPrincipalGroupMembership -Identity $_
} | Group-Object DistinguishedName | Where {$_.Count -eq $users.Count} |
Select-Object #{n='Name';e={$_.Group[0].Name}}

get list of DLs few users are member of

I am beginner in powershell and trying to create a script.
I have list of users, for them I need to know in which DLs they are added.
The problem I am facing is, it shows the list of DLs only, is there any way I can get DLs under the usernames? or a better way to accomplish this.
Note: we name all our DLs in capital letter thats why I have used "\b[A-Z0-9_]+\b" in where-object.
$users = import-csv C:\Test\users.csv | ForEach-Object {$_.users = $_.users.Trim(); $_} | Select-Object -ExpandProperty users
foreach ( $user in $users)
{get-ADPrincipalGroupMembership $user | select name |
Where-Object { $_.name -cmatch "\b[A-Z0-9_]+\b"} | Export-CSV "C:\test\output_file.csv" -NoTypeInformation -Append
}
Now I get the following outcome:
Group1
Group2
Group3
Group2
Group3
Group4
My ideal out put would be something along the lines of:
User MemberOf
---- --------
Bob Group1, Group2, Group3....
Jim Group2, Group3, Group4....
Thanks alot.
Assuming you're looking for Distribution Lists, you can tell if a group is a Security Group or a Distribution List by looking at the GroupCategory property of an ADGroup object.
Instead of looking at the user's memberOf attribute and finding out which ones are Distribution you can search for ADGroups that are GroupCategory -eq 'Distribution' where each user is a member:
$users = (Import-CSV C:\Test\users.csv | ForEach-Object {
$_.users.Trim()
}).users
$result = foreach ($user in $users)
{
$userDN = (Get-ADUser $user).DistinguishedName
$groups = Get-ADGroup -Filter "member -eq '$userDN' -and groupCategory -eq 'Distribution'"
[pscustomobject]#{
User = $user
MemberOf = $groups.Name -join ', '
}
}
$result | Export-CSV "C:\test\output_file.csv" -NoTypeInformation
If you want to use the code you already have, with this minor update you should be getting the result you are looking for:
$users = (Import-CSV C:\Test\users.csv | ForEach-Object {
$_.users.Trim()
}).users
$result = foreach ($user in $users)
{
$membership = Get-ADPrincipalGroupMembership $user |
Where-Object {
$_.name -cmatch "\b[A-Z0-9_]+\b"
}
[pscustomobject]#{
User = $user
MemberOf = $membership.Name -join ', '
}
}
$result | Export-CSV "C:\test\output_file.csv" -NoTypeInformation

Powershell - CSV Export formatting

I am trying to get list of AD groups a user is part of and I have a script that works. But I need to show it in a different manner. Currently the script shows a record in one line with username and then multiple group names in the next cell delimited by a semi-colon.
I would like it in a way that all groups are in each seperate row and the username gets repeated.
Example:
DavidChow - Server Admin Group
DavidChow - Desktop Admin Group
DavidChow - Azure Admin Group
NinaChow - Desktop User Group
This is my script:
$UnameList= Import-Csv C:\temp\users_full_list.csv
ForEach ($username in $UnameList){
$groups=Get-ADPrincipalGroupMembership -Identity $username.Identity | select -expand name
$data = [PSCustomObject]#{
samaccountname = $username.Identity
count = $groups.count
memberOf = ($groups -join ';')}
Write-Output $data | Export-Csv C:\Temp\users_full_list_memberships.csv -Delimiter ";" -NoTypeInformation -Append
}
You could create a "data" object for each group of each user, and then export all to CSV at the end:
Import-Csv C:\temp\users_full_list.csv | foreach {
$identity = $_.Identity
Get-ADPrincipalGroupMembership -Identity $identity | foreach {
[PSCustomObject]#{
SamAccountName = $identity
GroupName = $_.Name
}
}
} | Export-Csv C:\Temp\users_full_list_memberships.csv -Delimiter ";" -NoTypeInformation

Grouping data from Active Directory

wondering if i could get some help with my powershell script. I am halfway (or maybe even 3/4 of the way there) but im just struggling to get my groups grouped on one line per user....
Ill explain
Right now i'm able to get ALL users from Multiple AD groups, took a bit of playing around but i got there in the end...
However it displays CSV like this:
first_name,last_name,email,group_list
John,Smith,JSmith#email.com,Group1
John,Smith,JSmith#email.com,Group2
Emily,Rogers,ERogers#email.com,Group1
Emily,Rogers,ERogers#email.com,Group3
Whilst thats OK, i would really like to format the data like this:
first_name,last_name,email,group_list
John,Smith,JSmith#email.com,Group1~Group2
Emily,Rogers,ERogers#email.com,Group1~Group3
This is my code so far
## Define the groups, This includes a wildcard which gets all users in groups with that pattern
$Groups = (Get-AdGroup -filter * | Where {$_.name -like "GroupName*"} | select name -expandproperty name)
## Var for array, empty
$Array = #()
## Var for data
$Data = [ordered]#{
}
## For Each loop to get members of each group
Foreach ($Group in $Groups)
{
## Define the search criteria for AD Search
$Members = Get-ADGroupMember -identity $Group | Get-ADUser -Properties * | select givenName,sn,sAMAccountName,mail
foreach ($Member in $Members)
{
$Data."first_name" = $Member.givenName
$Data."last_name" = $Member.sn
$Data."email" = $Member.mail
$Data."group_list" = $Group
## Store in PSObject
$DataPSObject = New-Object PSObject -property $Data
## Add to array so it is no longer empty
$Array += $DataPSObject
}
}
## Export array into CSV
$Array | export-csv "C:\temp\DataFromArray.csv" -NoTypeInformation
As the email is the unique identifier, i tried to Group-Object on the email property but the output is not useful for me
## Export array into CSV
$Array | Group-Object -Property email | export-csv "C:\temp\DataFromArray.csv" -NoTypeInformation
Also i tried to join the groups using a defined separator -join '~' but this just seemed to create one long string of joined groups (makes sense when i put it that way)
Hoping anyone has some ideas?
Thanks
You need to do a little more processing on the output of Group-Object, but you're almost there!
$Array |Group-Object -Property email |ForEach-Object {
[pscustomobject]#{
first_name = $_.Group[0].first_name
last_name = $_.Group[0].last_name
email = $_.Group[0].email
groups = $_.Group.group_list -join '~' # join all the group names together
}
} |Export-Csv "C:\temp\DataFromArray.csv" -NoTypeInformation
Just a quick thingy to get what you want:
## Define the groups, This includes a wildcard which gets all users in groups with that pattern
$Groups = Get-AdGroup -Filter 'Name -like "GroupName*"' | Select-Object -ExpandProperty Name
## For Each loop to get members of each group
$Array = foreach ($Group in $Groups) {
## Define the search criteria for AD Search and capture in variable $Array
Get-ADGroupMember -Identity $Group |
Get-ADUser -Properties GivenName,Surname,SamAccountName,EmailAddress |
Select-Object #{Name = 'first_name'; Expression = {$_.GivenName}},
#{Name = 'last_name'; Expression = {$_.Surname}},
#{Name = 'email'; Expression = {$_.EmailAddress}},
#{Name = 'GroupName'; Expression = {$Group}}
}
$out = $Array | Group-Object email | ForEach-Object {
# join the GroupName property of this user to get a delimited string
$grouplist = $_.Group.GroupName -join '; '
# output a new object with the 'group_list' property
# this will create duplicates objects, so we need Select-Object * -Unique at the end
$_.Group | Select-Object first_name, last_name, email, #{Name = 'group_list'; Expression = {$grouplist}}
} | Select-Object * -Unique
$out | Export-Csv "C:\temp\DataFromArray.csv" -NoTypeInformation
Hope that helps

How to get list of selected AD Groups, that a large list of users are members of?

I have the below working script that checks if a large list of users in a CSV file are a member of an AD group and writes the results to results.csv.
Not sure how to convert the script so I can change $group = "InfraLite" to $group = DC .\List_Of_AD_Groups.CSV.
So the script doesn't just return matches for one AD group but so it returns matches for the 80 AD groups contained in the List_of_AD_groups.csv also. Writing a YES/NO for each AD group in a new column in the CSV (or if that's not possible creating a seperate .csv file for each group with results would do also.
I could do this manually by changing the value of $group and export file name, and re-running the script 80 times but must be a quick was with PS to do this?
e.g. results.csv:
NAME AD_GROUP1 AD_GROUP2 AD_GROUP80 etc etc.
user1 yes no yes
user2 no no yes
user3 no yes no
echo "UserName`InfraLite" >> results.csv
$users = GC .\user_list.csv
$group = "InfraLite"
$members = Get-ADGroupMember -Identity $group -Recursive |
Select -ExpandProperty SAMAccountName
foreach ($user in $users) {
if ($members -contains $user) {
echo "$user $group`tYes" >> results.csv
} else {
echo "$user`tNo" >> results.csv
}
}
I played with this for a while, and I think I found a way to get you exactly what you were after.
I think Ansgar was on the right path, but I couldn't quite get it to do what you were after. He mentioned that he didn't access to an AD environment at the time of writing.
Here is what I came up with:
$UserArray = Get-Content 'C:\Temp\Users.txt'
$GroupArray = Get-Content 'C:\Temp\Groups.txt'
$OutputFile = 'C:\Temp\Something.csv'
# Setting up a hashtable for later use
$UserHash = New-Object -TypeName System.Collections.Hashtable
# Outer loop to add users and membership to UserHash
$UserArray | ForEach-Object{
$UserInfo = Get-ADUser $_ -Properties MemberOf
# Strips the LPAP syntax to just the SAMAccountName of the group
$Memberships = $UserInfo.MemberOf | ForEach-Object{
($_.Split(',')[0]).replace('CN=','')
}
#Adding the User=Membership pair to the Hash
$UserHash.Add($_,$Memberships)
}
# Outer loop to create an object per user
$Results = $UserArray | ForEach-Object{
# First create a simple object
$User = New-Object -TypeName PSCustomObject -Property #{
Name = $_
}
# Dynamically add members to the object, based on the $GroupArray
$GroupArray | ForEach-Object {
#Checking $UserHash to see if group shows up in user's membership list
$UserIsMember = $UserHash.($User.Name) -contains $_
#Adding property to object, and value
$User | Add-Member -MemberType NoteProperty -Name $_ -Value $UserIsMember
}
#Returning the object to the variable
Return $User
}
#Convert the objects to a CSV, then output them
$Results | ConvertTo-CSV -NoTypeInformation | Out-File $OutputFile
Hopefully that all makes sense. I commented as much of it as I could. It would be very simple to convert to using ADSI if you didn't have RSAT installed on whatever machine you're running this on. If you need that let me know, and I'll make some quick modifications.
I've also tossed a slightly modified version of this in a Gist for later reference.
The trivial solution to your problem would be to wrap your existing code in another loop and create an output file for each group:
$groups = Get-Content 'C:\groups.txt'
foreach ($group in $groups) {
$members = Get-ADGroupMember ...
...
}
A more elegant approach would be to create a group mapping template, clone it for each user, and fill the copy with the user's group memberships. Something like this should work:
$template = #{}
Get-Content 'C:\groups.txt' | ForEach-Object {
$template[$_] = $false
}
$groups = #{}
Get-ADGroup -Filter * | ForEach-Object {
$groups[$_.DistinguishedName] = $_.Name
}
Get-ADUser -Filter * -Properties MemberOf | ForEach-Object {
$groupmap = $template.Clone()
$_.MemberOf |
ForEach-Object { $groups[$_] } |
Where-Object { $groupmap.ContainsKey($_) } |
ForEach-Object { $groupmap[$_] = $true }
New-Object -Type PSObject -Property $groupmap
} | Export-Csv 'C:\user_group_mapping.csv' -NoType