Last active
May 22, 2024 01:58
-
-
Save jschlackman/98b913ebc8c5eb68030a4f4b91d4a27f to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<# | |
Name: Get-UserExchangeGroupMembership.ps1 | |
Author: James Schlackman | |
Last Modified: May 21 2024 | |
Displays all Exchange Online distribution lists and Office 365 groups that a specified user is a member of, | |
and optionally removes them from any groups that are not synced from on-prem AD. | |
#> | |
#Requires -Modules ExchangeOnlineManagement | |
Param( | |
# User to list group membership for | |
[Parameter(Mandatory=$true)] [String]$UserIdentity | |
) | |
Import-Module ExchangeOnlineManagement | |
# Connect to Exchange Online if not already connected | |
If (![bool](Get-ConnectionInformation)) { | |
Connect-ExchangeOnline | |
} | |
# Find user's Exchange Online entry | |
$rcpt = Get-ExoRecipient -Identity $UserIdentity -Properties WindowsLiveId | |
If ([bool]$rcpt) { | |
$rcpt | Select WindowsLiveId,EmailAddresses | Format-List | |
# Formats group lists with a common output | |
$DisplayProperties = @( | |
'DisplayName', | |
'PrimarySmtpAddress', | |
'RecipientTypeDetails', | |
# Resolve the manager identity into display names | |
@{Name='ManagedBy'; Expression={If ($_.RecipientTypeDetails -eq 'GroupMailbox') { | |
(Get-UnifiedGroupLinks -Identity $_ -LinkType Owners | Select -ExpandProperty DisplayName | Sort-Object) -join ', ' | |
} Else { | |
($_.ManagedBy | Get-ExoRecipient | Select -ExpandProperty DisplayName | Sort-Object) -join ', ' | |
} | |
}}, | |
@{Name='Capabilities'; Expression={$_.Capabilities -join ', '}} | |
) | |
# Get all the unified groups that the user is the sole OWNER of | |
$OwnedGroups = Get-ExoRecipient -Filter "ManagedBy -eq '$($rcpt.DistinguishedName)'" -RecipientTypeDetails GroupMailbox -Properties ManagedBy | Where-Object {($_.ManagedBy).Count -eq 1} | Select -Property $DisplayProperties | |
If ([bool]$OwnedGroups) { | |
Write-Host 'User is the sole owner of the following groups:' | |
$OwnedGroups | ft DisplayName,PrimarySmtpAddress,ManagedBy | |
} Else { | |
Write-Host "`nNo groups owned only by this user." | |
} | |
# Get all the groups the user is a MEMBER of | |
$UserGroups = Get-ExoRecipient -Filter "Members -eq '$($rcpt.DistinguishedName)'" -Properties ManagedBy,Capabilities | Sort-Object DisplayName | |
Write-Host "User is a member of $(@($UserGroups).Count) groups, review grid output for details.`n" | |
# Display list of groups | |
$SelectedGroups = ($UserGroups | Select -Property $DisplayProperties | Out-GridView -OutputMode Multiple -Title "Group memberships for $($rcpt.DisplayName). Select groups to act upon.") | |
If ([bool]$SelectedGroups) { | |
# Restore full details of selected groups | |
$SelectedGroups = $UserGroups | Where-Object -Property PrimarySmtpAddress -In ($SelectedGroups | Select -ExpandProperty PrimarySmtpAddress) | |
Write-Host 'Copy summary of selected groups to clipboard? ' -ForegroundColor Cyan -NoNewline | |
If ((Read-Host '[y/N]').ToUpper() -eq 'Y') { | |
$SelectedGroups | ForEach-Object {$_.DisplayName + "`t" + $_.PrimarySmtpAddress} | Set-Clipboard | |
} | |
Write-Host 'Do you want to remove the user from the selected groups now? ' -ForegroundColor Red -NoNewline | |
If ((Read-Host '[y/N]').ToUpper() -eq 'Y') { | |
# Remove all group memberships (excluding groups synced from on-premise Active Directory) | |
Write-Host "`nRemoving user from..." -ForegroundColor Cyan | |
# Remove distribution group memberships | |
$SelectedGroups | ForEach-Object { | |
Write-Host $_.DisplayName -NoNewline | |
# Skip AD-synced groups | |
If ($_.Capabilities -contains 'MasteredOnPremise') { | |
Write-Host ' - Skipped (AD-Synced Group)' -ForegroundColor DarkYellow | |
} Else { | |
Try | |
{ | |
# If not a unified group | |
If ($_.RecipientTypeDetails -ne 'GroupMailbox' ) { | |
Remove-DistributionGroupMember -Identity $_.Identity -Member $rcpt.DistinguishedName -Confirm:$false -ErrorAction Stop | |
} | |
Else { | |
# If the user is a group owner, attempt to demote them first. Will fail if there are no other owners, which will need to be resolved manually. | |
If ($_.ManagedBy -contains $rcpt.Name) { | |
Remove-UnifiedGroupLinks -Identity $_.Identity -LinkType Owners -Links $rcpt.DistinguishedName -Confirm:$false -ErrorAction Stop | |
} | |
# Now remove the actual group membership | |
Remove-UnifiedGroupLinks -Identity $_.Identity -LinkType Members -Links $rcpt.DistinguishedName -Confirm:$false -ErrorAction Stop | |
} | |
Write-Host ' - OK' -ForegroundColor Green | |
} | |
Catch | |
{ | |
# If remove failed because this is a dynamic group, mark this as 'skipped' | |
If ($Error[0].CategoryInfo.Reason -eq 'DynamicGroupMembershipChangeDeniedException') { | |
Write-Host ' - Skipped (Dynamic Group)' -ForegroundColor DarkYellow | |
} Else { | |
# Otherwise report the error message | |
Write-Host ' - FAILED' -ForegroundColor Red | |
Write-Warning $Error[0] | |
} | |
} | |
} | |
} | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment