Root Cause
Imagine you have on-premises Active Directory synced to AzureAD through ADConnect. You do not delete users during leave process. Those account are disabled cause of various reasons (Jira, I’m looking at you). Now you need to clean up any Office Online groups user belongs to, like Exchange Groups, Teams etc.
How
This is rather simple task.
- First get all disabled users from given OUs
- Export them into CSV for further processing/change management/ whatever reason
- Connect to Azure AD
- Loop through each user, get their group membership and return a custom object with data – also for further processing/change management/whatever reason
- Loop through the data and remove user membership from any online groups.
We could remove user’s membership in step 4 in one loop but reporting and executing are two different tasks, so I prefer to keep it that way.
Things to remember
- Online account needs to have proper permissions!
- We require AzureAD module to perform online operations!
- We will be enumerating only online groups. That is why we’re looking at DirSyncEnabled attribute being empty (not present).
- We also want to process only if the user really does belong to any online group.
- We will create a custom object to export the data. We will export into two different files – json and csv. CSV is a flat file, meaning we cannot store arrays in one column. Those arrays (of groups) will be flattened into one string with coma separator. To allow further processing we will use JSON file which handles nested arrays perfectly!
The Code
First let’s get all disabled Users from an array of OUs:
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
$userOUs = @('OU=Leavers,OU=Site1,OU=Contoso Users,DC=Contoso,DC=com','OU=Leavers,OU=Site2,OU=Contoso Users,DC=Contoso,DC=com') | |
$disabledUsers = foreach ($ou in $userOUs) { | |
get-aduser -filter {Enabled -eq $false} -SearchBase $ou | |
} | |
$disabledUsers | Export-Csv -Path C:\AdminTools\disabled_users.csv -NoTypeInformation |
Now let’s connect to AzureAD and get each user’s group membership. To do that we will use Get-AzureADUserMembership cmdlet which requires ObjectID of a user. We want to proceed only if any online group was found (-not {$_.DirSyncEnabled})
Then we will create custom object with all the information we require.
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
#Get Credentials to O365 tenant | |
$credential = Get-Credential | |
Connect-AzureAD -Credential $credential | |
$disabled_OnlineMembership = foreach ($user in $disabledUsers) { | |
if ($user.UserPrincipalName) { | |
$userObjectId = Get-Msoluser -UserPrincipalName $user.UserPrincipalName | Select-Object -ExpandProperty ObjectId | |
$group = Get-AzureADUserMembership -ObjectId $userObjectId | Select-Object * | Where-Object {-not ($_.DirSyncEnabled)} | |
if ($group) { | |
[pscustomobject]@{ | |
UserName = $user.SamAccountName | |
DisplayName = $user.Name | |
Enabled = $user.Enabled | |
UserDN = $user.DistinguishedName | |
AADUserObjecID = $userObjectId | |
GroupName = $group.DisplayName | |
GroupMail = $group.Mail | |
AADGroupID = $group.ObjectID | |
} | |
} | |
} | |
} |
Export time.
JSON is easy. Depth parameter will make sure nothing gets lost in translation.
Before exporting to excel we need to flatten arrays of group (name and Mail).
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
$disabled_OnlineMembership | ConvertTo-Json -Depth 99| Out-File c:\AdminTools\disabled_onlinemembership.json | |
#Export For further 'human' processing through excel: | |
$disabled_OnlineMembership | Select-Object UserName,DisplayName,Enabled,UserDN,AADUserObjectID, | |
@{n='Groups';e={$_.GroupName -join ','}}, | |
@{n='GroupMail';e={$_.GroupMail -join ','}} | | |
Export-Csv -Path c:\AdminTools\disabled_onlinemembership.csv -NoTypeInformation | |
And finally let’s clean up the mess:
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
$UsersToClean = Get-Content -Path 'c:\AdminTools\disabled_onlinemembership.json ' -RAW | ConvertFrom-Json | |
#Remove from groups | |
foreach ($onlineUser in $UsersToClean) { | |
Write-Host "Processing user {$($onlineUser.DisplayName)}" | |
foreach ($group in $onlineUser.AADGroupID) { | |
Write-Host " Processing group {$($group)}" | |
Remove-AzureADGroupMember -ObjectId $group -MemberId $onlineUser.AADUserObjectID | |
} | |
} |