Skip to content

Instantly share code, notes, and snippets.

@jschlackman
Last active May 22, 2024 01:58
Show Gist options
  • Save jschlackman/98b913ebc8c5eb68030a4f4b91d4a27f to your computer and use it in GitHub Desktop.
Save jschlackman/98b913ebc8c5eb68030a4f4b91d4a27f to your computer and use it in GitHub Desktop.
<#
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