Forum Discussion
See groups menbership of a list of users
- Aug 22, 2022
Hi,
The easy answer is that you're trying to get the UserPrincipalName of the Group rather than the user, which returns null because the group doesn't have a UserPrincipalName.
As the variable $_. has already been overwritten by Get-AzureAdUsermembership you can't really reference back.
I have written a Powershell script that would do the job and shared it on Github:
https://github.com/Raindrops-dev/RAIN-TechCommunityContributions/blob/main/Get-AzureAdGroupMembership.ps1
Check it out and let me know if it fits your requirements.
EDIT: Apparently I was too slow and LainRobertson already came with a more modern solution!
Basically, you need to capture the user's details such as id, userPrincipalName, etc. in the outer loop, before proceeding to the inner loop to fetch the group/object details.
I started earlier with one answer but decided to switch Azure modules (to a more "recent" one) and have a play. The example below is the result, where it pulls any kind of membership - not just groups. I've also added a flag called IsDynamicGroup since that's usually something you want to know when figuring out how someone ended up in (or out) of scope for a given group.
The key additional inclusion from testing in my tenant is that it pulls Azure AD role memberships - which is quite nifty to know when working with PIM-style auditing. You can always filter this out client-side (or just take it out of the script altogether if you like.)
For context, this script uses the following first-party Microsoft Azure modules:
- Microsoft.Graph.Authentication
- Microsoft.Graph.DirectoryObjects
- Microsoft.Graph.Users
It uses the Graph beta endpoint, which you can select using the following command:
Select-MgProfile -Name "beta";
Example script
Get-Content -Path "D:\Data\Temp\Test.txt" |
ForEach-Object { Get-MgUser -UserId "$_" -ExpandProperty TransitiveMemberOf -Select Id, UserPrincipalName, TransitiveMemberOf } |
ForEach-Object {
# We're now in your per user "outer" loop.
$User = $_;
$User.TransitiveMemberOf.Id |
ForEach-Object {
# Whereas now, we're in your per user membership inner loop. Here, we're iterating through each one of their memberships and pulling the Azure AD object details below.
Get-MgDirectoryObject -DirectoryObjectId "$_" |
ForEach-Object {
# This is yet another nested level we reach after having pulled the object for which the user is a member.
[PSCustomObject] @{
UserId = $User.Id;
UserPrincipalName = $User.UserPrincipalName;
ObjectId = $_.id;
ObjectType = $_.AdditionalProperties["@odata.type"].Split('.')[-1];
ObjectName = $_.AdditionalProperties["displayName"];
MailEnabled = $_.AdditionalProperties["mailEnabled"];
SecurityEnabled = $_.AdditionalProperties["securityEnabled"];
IsDynamicGroup = if ($null -ne $_.AdditionalProperties["groupTypes"]) { $_.AdditionalProperties["groupTypes"].Contains("DynamicMembership") } else { $null };
}
}
}
} |
Export-Csv -Path "D:\Data\Temp\test.csv" -NoTypeInformation -Encoding Unicode;
Example output (having removed the Export-Csv in order to see this)
Cheers,
Lain