Aug 22 2022 03:32 AM
Hello,
I'm trying to get a list from all groups that a user is part of, on a single file (DL, Teams groups, ...)
This is what I'm doing:
What am i doing wrong?
Thank you.
Aug 22 2022 05:33 AM
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:
It uses the Graph beta endpoint, which you can select using the following command:
Select-MgProfile -Name "beta";
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;
Cheers,
Lain
Aug 22 2022 05:43 AM
I also meant to add that you mentioned Exchange groups, however, if you use dynamic Exchange groups, you can't pull that from Azure AD. You'd need to use the Exchange Online module to fetch those and their memberships.
Cheers,
Lain
Aug 22 2022 06:26 AM
Aug 22 2022 06:37 AM
Aug 22 2022 07:26 AM
If your account has the necessary rights, you can just leave -Scopes out.
That said, you can run Connect-MgGraph as many times in a row as you like to change the -Scopes specification (i.e. you don't have to keep disconnecting and logging back on.)
If leaving -Scopes out doesn't work for you, then put it back in with the following scope:
You don't really need write access for this script, and neither of the two scopes you provided are broad enough for running Get-MgDirectoryObject.
Cheers,
Lain
Aug 22 2022 07:51 AM - edited Aug 22 2022 07:53 AM
Solution
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:
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!
Aug 22 2022 08:05 AM
Aug 23 2022 05:37 AM - edited Aug 23 2022 05:38 AM
I'm happy my code was helpful!
That said, be aware that the AzureAd module will reach end of life at the end of this year, so it's strongly discouraged to put anything new in production using it.
To assist I've also prepared a Graph API version of that same script and updated the Azure AD with parameters to customize input and output paths and filename:
Strong recommendation NOT to just use it as is though. Read it and understand why everything was one as is and learn it so you can do it yourself next time for the next task you need to do with MgGraph.
P.S: to find equivalent cmdlets you can use this table: https://docs.microsoft.com/en-us/powershell/microsoftgraph/azuread-msoline-cmdlet-map?view=graph-pow...
Aug 22 2022 07:51 AM - edited Aug 22 2022 07:53 AM
Solution
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:
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!