AD Export of Groups / Members of Each group and Email Addresses - powershell

I would like to ask if anyone could help me with a script to extract all the AD groups with their members and their email addresses. I'm running the script bellow which I found it in one of the posts which extracts all the AD Groups and their members but I don't know how to include their email addresses also. Thank you very much for your help.
$Groups = Get-ADGroup -Filter * -SearchBase 'OU,OU,OU,OU,OU,DC,DC,DC' #creates a variable with the name Groups and stores all the groups into it
$Results = foreach( $Group in $Groups ){ #looks for members in each group and stores them in Results
Get-ADGroupMember -Identity $Group | foreach {
[pscustomobject]#{
GroupName = $Group.Name
Name = $_.Name
}
}
}
$Results| sort -Property GroupName | Export-Csv -Path c:\temp\groups.csv -NoTypeInformation #stores results in a csv

You'll need to capture the user's email address in your foreach loop, and you'll need to do that by looking up the user properties - a listing of group members only has the member DN and name.
Get-ADGroupMember -Identity $Group | foreach {
$u = get-aduser $_ -properties mail ##plus any other user properties you need
[pscustomobject]#{
GroupName = $Group.Name
Name = $u.Name
Email = $u.mail
}
}

Related

Get user group memberships from SID

I'm querying AD groups outside our local domain. When searching for the groups in PS I've got all the members that are displayed with their SID and not with their User ID.
What I basically want is to enter the user ID and get all the group memberships the user's SID is linked with.
Below is what I've already tried but with no result...
Write-Host "enter user id"
$user = Read-Host
# Forrest were groups are nested
$LDAPServer = 'wwg00m.rootdom.net'
# Get SID from user
$adUsr = Get-ADUser $user -Properties SID | Select-Object SID
# Get all groups from Query in AD
$Groups = Get-ADObject -server $LDAPServer -LDAPFilter '(&(objectCategory=group)(name=*_EN))' | Select Name
# Get all Members from each group, replacing characters to get equal SID ID like $adUser
$Members = (Get-ADGroup -Identity $Groups -Server $LDAPServer -Properties Members).Members -Replace ("CN=", "") -Replace (",ForeignSecurityPrincipals,DC=wwg00m,DC=rootdom,DC=net", "")
foreach ($adUsr in $members) {
[pscustomobject]#{
GroupName = $Members.Name
}
}
Based on conversation in comments this might work. Basically, first we get the SID of the user in the Current Domain, then once we get it we can get the user's DistinguishedName on the Trusted Domain and finally with this information we can perform an LDAP Query searching for all Groups this DN is a member.
try {
# Get user input
$user = Read-Host "Enter User ID"
# Forrest were groups are nested
$LDAPServer = 'wwg00m.rootdom.net'
# Get the SID of the user in the Current Domain
$sid = Get-ADUser $user
# Get the DistinguishedName of the user in the other Domain
$dn = (Get-ADUser $sid.SID -Server $LDAPServer).DistinguishedName
# Search for all groups where this DN is a member
Get-ADGroup -LDAPFilter "(member=$dn)" -Server $LDAPServer | ForEach-Object {
# here we can combine the user's data in the Current and Trusted Domain
# change the output as needed
[pscustomobject]#{
GroupName = $_.Name
UserName = $sid.Name
UserDistinguishedName = $dn
}
}
}
catch {
# Error handling here...
Write-Error $_
}

PowerShell - Create Custom Object to Export as CSV

I'm trying to pull a report using PowerShell and export it as CSV. I want to grab an AD Group, get the "Members" and "Members Of", then export it.
The final export, I want it to look like this:
Group Name Member Of Member ID Member Name Member Email
Finance Group AD Group 1 User 1 John Smith JSmith#example.com
Finance Group AD Group 2 User 2 Ryan Smith RSmith#example.com
Finance Group AD Group 3 User 3 Amanda Smith ASmith#example.com
Finance Group AD Group 4
Finance Group AD Group 5
I have the following script to get the AD Group Members and Member Of:
$Groups = "Finance Group"
$Object = New-Object PSObject
ForEach ($Group in $Groups) {
$MemberOf = Get-ADPrincipalGroupMembership -Identity $Group
ForEach ($Access in $MemberOf.Name) {
$Object | Add-Member -NotePropertyName "Group Name" -NotePropertyValue $Group
$Object | Add-Member -NotePropertyName "Member Of" -NotePropertyValue "$MemberOf
}
}
I'm just trying to make the first 2 columns, however, Add-Member seems to just replace the current values, and I can't seem to find a way to append the values. Afterwards I will try to add in the users information columns. The reason I want the "Group Name" to repeat is because I want to use a Pivot Table to group "Finance Group" to its respective "Member Of" and "Members". Am I going about this the right way or is there some better way to do this?
Thanks in advance.
Following Abraham's helpful answer which just needs a slight modification to get the user's DisplayName and Mail properties:
$Groups = "Finance Group"
$export = foreach ($Group in $Groups)
{
$thisGroup = Get-ADGroup $Group -Properties MemberOf
$memberOf = $thisGroup.MemberOf
$member = #(Get-ADGroupMember $group).where({
$_.objectClass -eq 'user'
}) | Get-ADuser -Properties DisplayName, mail
$max = [Math]::Max($memberOf.Count, $member.Count)
for ($i = 0; $i -lt $max; $i++)
{
[PSCustomObject]#{
GroupName = $thisGroup.Name
MemberOf = $memberOf[$i] -replace '^CN=(.*?)(?<!\\),.*','$1'
MemberID = $member[$i].Name
MemberName = $member[$i].DisplayName
MemberEmail = $member[$i].mail
}
}
}
$export | Export-Csv .... -NoTypeInformation
The use of -replace on MemberOf is because the MemberOf property of AD Group are DistinguishedName and this would get their CN (Common Name). See https://regex101.com/r/jrbwVb/1 for more details.
If I'm not mistaken, this is your intentions:
$Groups = "Finance Group"
foreach ($Group in $Groups)
{
$groupObj = Get-ADGroup -Identity $Group -Properties Members, MemberOf
for ($i = 0; $i -lt [Math]::Max($groupObj.Members, $groupObj.MemberOf; $i++)
{
[PSCustomObject]#{
GroupName = $Group
MemberOf = $groupObj[$i].MemberOf
Members = $groupObj[$i].Members # here you can substitute this field, or add new ones, with a new Get-ADUser call -
# to get the display name or other properties.
}
}
}
. . .as noted in the in-line comment, you can substitute the returned field for a call to AD using Get-ADUser to swap for a display name or other fields instead.
Unfortunately, I do not have AD installed on my computer, nor have access to an AD environment anymore so this was all based off what I though is correct. I believe that Get-ADGroup returns it's membersof property as well; so only one call would be needed in that aspect.

Export the AD Group Membership of a list of users from a CSV Powershell

I am trying to get a CSV output of all the users in the 'VPN Users' group that are also in the 'Domain Users' group. I'd like it to give their name and then their group membership. Each member should only be in the VPN group. I am looking to identify who is in both groups.
To achieve this I have first exported a list of the users in the VPN Group to a CSV which works fine. Second part of the code is meant to go through the list of users in the CSV from that AD group and export an output as a CSV containing the users and their group membership which isn't working for me. For each user in the CSV it returns the error: Get-ADUser : Cannot find an object with identity: '"User001_vpn"'.....
I'm not sure if the way I'm going about it is the best way to achieve the task in hand or if any of you might be able to help me make it work? It seems like Get-ADUser isn't finding the users from the CSV.
#Retrieves list of users that are in the VPN Users group and exports them into a CSV
(Get-ADGroupMember "VPN Users" -Recursive | Get-ADUser -Properties * |
Select-Object SamAccountName |
ConvertTo-Csv -NoTypeInformation) |
Select-Object -Skip 1 |
Set-Content -Path "C:\Documents\VPN Users Report\VPNUsers.csv”
Get-Content “C:\Documents\VPN Users Report\VPNUsers.csv” | Get-ADUser | ForEach{
$user = $_
$groups = Get-ADPrincipalGroupMembership $user
$groups | %{ New-Object PSObject -Property #{ User = $user.SamAccountName; Group = $_.SamAccountName } }
} | Export-Csv "C:\VPN Users Report\Results\Output.csv"
I believe the problem is with the quotes, since you are using ConvertTo-Csv while retrieving the users, all user SamAccountNames will be quoted.
Afterwards you read this csv file using Get-Content, not Import-Csv, so the quotes will not be removed and you have user names like "User001_vpn" instead of User001_vpn
You do not have to use this 'in-between' cvs at all and on second thought, you can leave out Get-ADUser too unless you want other properties from these users than what Get-ADGroupMember already returns (i.e. distinguishedName, name, objectClass, objectGUID, SamAccountName, SID)
Try
# Retrieves list of users that are in the VPN Users group
(Get-ADGroupMember "VPN Users" -Recursive | Where-Object { $_.objectClass -eq 'user' }).SamAccountName | ForEach-Object {
foreach ($group in (Get-ADPrincipalGroupMembership -Identity $_)) {
[PsCustomObject]#{
User = $_
Group = $group.SamAccountName
}
}
} | Export-Csv "C:\VPN Users Report\Results\Output.csv" -NoTypeInformation
I have added Where-Object { $_.objectClass -eq 'user' }, because the Get-ADGroupMember cmdlet can return users, groups, and/or computer objects
As per your latest comment:
If you want more properties from the user, you need Get-ADUser, which by default returns objects with these properties:
DistinguishedName, Enabled, GivenName, Name, ObjectClass, ObjectGUID, SamAccountName, SID, Surname, UserPrincipalName
If you still need more, like for instance the users email address, you need to ask for it by adding -Properties EmailAddress
# demo to include the users first and last name
Get-ADGroupMember "VPN Users" -Recursive | Where-Object { $_.objectClass -eq 'user' } | ForEach-Object {
$user = Get-ADUser -Identity $_.DistinguishedName
foreach ($group in (Get-ADPrincipalGroupMembership -Identity $user.DistinguishedName)) {
[PsCustomObject]#{
User = $user.SamAccountName
FirstName = $user.GivenName
LastName = $user.Surname
Group = $group.SamAccountName
}
}
} | Export-Csv "C:\VPN Users Report\Results\Output.csv" -NoTypeInformation
I propose an alternative to Theo's helpful answer letting LDAP handle the filtering of users.
The result of this query would be those users which are members of GroupX and members of GroupY:
$groupX = (Get-ADGroup 'VPN Users').DistinguishedName
$groupY = (Get-ADGroup 'Domain Users').DistinguishedName
Get-ADUser -LDAPFilter "(&(memberOf=$groupX)(memberOf=$groupY))"
If you were looking for indirect members of one of the groups or both groups, meaning, possible members of nested groups in those groups you could use memberOf:1.2.840.113556.1.4.1941:. Example:
Get-ADUser -LDAPFilter "(&(memberOf:1.2.840.113556.1.4.1941:=$groupX)(memberOf=$groupY))"
Would bring all members (recursive) of GroupX which are also direct members of GroupY.

Powershell - Get User information from AD list

I'm a beginner in programming in general..
What I'm trying to do is to create a powershell script that will:
Get information on each user on an Active Directory group.
Inside each group there may be another group, so I would want it to get the list of users from each nested group as well.
Only give me the information for each group once.
This is what I have so far:
$list = Get-ADGroupMember Admins
foreach($u in $list) {
Get-ADObject $u
}
foreach ($_ in $u) {
if ($u.ObjectClass -eq 'user') {
Get-ADUser $u -Properties * | select givenname, surname, samaccountname | ft -autosize
} else {
Get-ADGroupMember $u -Recursive | select name, samaccountname | ft -autosize
}
}
So far I'm trying to get it to work with that one group 'Admins' and then if it does I would want to run the code for more groups at the same time.
Any help or guidance would be appreciated.
You seem to want only properties that are returned by default by Get-ADUser aswell as Get-ADGroup, so in both cases, there is no need to specify the -Properties parameter.
Get-ADGroupMember can return user, computer and group objects, so at the moment, your else condition expects groups, where you could end up with a computer object..
In your code, you output to console with ft -autosize both in the if and the else, but it would be simpler to capture both types of resulting objects in a variable at the start of the loop and output it as a whole afterwards:
# you can load a list of group names from a predefined array:
$Groups = 'Admins', 'Users'
# or load from a file, each group name listed on a separate line:
# $Groups = Get-Content -Path 'D:\Test\ADGroups.txt'
# or get all AD groups in the domain:
# $Groups = (Get-ADGroup -Filter *).Name
$result = foreach ($group in $Groups) {
Get-ADGroup -Filter "Name -eq '$group'" | ForEach-Object {
# we could use the $group variable, but this ensures correct casing
$groupName = $_.Name
$members = $_ | Get-ADGroupMember -Recursive
foreach ($member in $members) {
if ($member.objectClass -eq 'user') {
Get-ADUser -Identity $member.DistinguishedName |
Select-Object #{Name="GroupName"; Expression={$groupName}},
#{Name="MemberType";Expression={'User'}},
Name,
GivenName,
Surname,
SamAccountName
}
elseif ($member.objectClass -eq 'group') {
Get-ADGroup -Identity $member.DistinguishedName |
Select-Object #{Name="GroupName";Expression={$groupName}},
#{Name="MemberType";Expression={'Group'}},
Name,
#{Name="GivenName";Expression={''}}, # groups don't have this property
#{Name="Surname";Expression={''}}, # groups don't have this property
SamAccountName
}
}
}
}
# output is console
$result | Format-Table -AutoSize
# write to CSV file
$result | Export-Csv -Path 'D:\Test\GroupsInfo.csv' -NoTypeInformation
The trick is here to output objects with equal properties for both a user and a group object

Powershell command to compare AD user group memberships to a baseline

I'm trying to figure out the logic to do something like this:
Query all AD groups in a specific OU
Query all the users in a specific OU
Query all the user's group memberships
If any user belongs to one or more groups in the initial group query, output that information
If any user belongs to none of the groups in the initial group query, also output that information
I've dug around on this site and found a script that works for the most part, but I'm stuck on how I can compare the user's group membership to the original group query that I'm pulling. It looks like I could use the compare-object cmdlet but the parameters don't seem to include anything that would let me keep track of how many groups the two objects have in common.
The code I found online is below:
$groups = Get-ADGroup -Filter * | where {$_.distinguishedname -like "*,OU=TUNE_TEST_GROUPS,OU=TUNE_TEST,DC=tune,DC=priv"}
$users = Get-ADUser -Filter * | where {$_.distinguishedname -like "*,OU=TUNE_TEST_USERS,OU=TUNE_TEST,DC=tune,DC=priv"}
foreach ( $User in $Users ) {
$userGroups = Get-ADPrincipalGroupMembership $User
if ( $userGroups.Count -gt 1 ) {
"{0} is a member of the following {1} groups:" -f $User.SamAccountName, $userGroups.Count
foreach ( $group in $userGroups ) {
"`t{0}" -f $group.Name
}
} elseif ( $userGroups.Count -lt 1 ) {
"{0} is a member of the following {1} groups:" -f $User.SamAccountName, $userGroups.Count
foreach ( $group in $userGroups ) {
"`t{0}" -f $group.Name
}
}
}
The problem with this is that I don't have a way of comparing the user group names to the names of the group query in line 1. I also can't determine that a user belongs to 1 or more groups from that list. I'm not sure if I can use the same count method.
You can validate that accounts are member of at least one group from your reference list by using Compare-Object:
foreach ( $User in $Users ) {
$userGroups = Get-ADPrincipalGroupMembership $User
if (!(Compare-Object $userGroups $groups -IncludeEqual -ExcludeDifferent)) {
"{0} doesn't belong to any reference group." -f $User.SamAccountName
}
}
Side note: use the -SearchBase parameter instead of filtering the results of Get-ADUser and Get-ADGroup by a wildcard match on the distinguished name:
$groups = Get-ADGroup -Filter * -SearchBase 'OU=TUNE_TEST_GROUPS,OU=TUNE_TEST,DC=tune,DC=priv' -SearchScope Subtree
$users = Get-ADUser -Filter * -SearchBase 'OU=TUNE_TEST_USERS,OU=TUNE_TEST,DC=tune,DC=priv' -SearchScope Subtree
I ended up doing the following and it works well for what I need. In case anyone is interested, sample code is below:
#gets a list of all groups in a given OU and stores the objects in the $groups variable
$groups = Get-ADGroup -Filter * -SearchBase 'OU=TUNE_TEST_GROUPS,OU=TUNE_TEST,DC=tune,DC=priv' -Properties name | select name
#pipe each group object into a foreach loop and output a string value of the same group name and stores it into the $groups_string variable
$groups_string = $groups | % {$_.name}
#gets a list of all users in a given OU and stores the objects in the $users variable
$users = Get-ADUser -Filter * -SearchBase 'OU=TUNE_TEST_USERS,OU=TUNE_TEST,DC=tune,DC=priv'
$results=#{
"Username" = ""
"Groupname" = ""
}
$table=#()
#iterates through every user in the $users variable and retrieves their group memberships
foreach ($user in $users) {
#selects each group name and stores it in the $groupMembership variable
$groupMembership = Get-ADPrincipalGroupMembership $user | select name
#compares the names of each user's group to the baseline group name.
$groupMembership | foreach ($_) {
#If there is a match add the group name and the username to the $results hash table
if ($groups_string -contains $_.name) {
$results."Groupname" = $_.name
$results."Username" = $user.Name
#create a new PS object and supply the properties of the $results hash table to each object
$objresults = New-Object psobject -Property $results
#add each object to the $table array
$table += $objresults
}
}
}
#display/output the $table array and format it to fit
$table | ft -AutoSize