Teams: Recover deleted team memberships
We recently had to perform the year-end tasks in Teams/SchoolDataSync which should be easy really - run through the cleanup process to archive all of last year's teams, then update the SDS profiles with the new term dates, and resume syncing with the new data. Unfortunately ours messed up and removed all members from the archived teams - presumably as I forgot to hit "Reset Sync" before feeding it the new year's data.
Luckily there's a solution to get these memberships back - we need to go and search the Azure AD audit log for group membership removal events. Head to the Compliance Admin Centre > Audit > Audit Search, and search for the activity "Azure AD group administration: Removed member from group". Put the date range in, and click Search. You should hopefully get some results, all performed by the ServicePrincipal account. If you click onto one of these results and examine the data, you'll notice we can discover the username, team name and the team's group ID, which is all contained in the JSON formatted data associated with the log entry.
From this view, we can then Export to CSV - this will export everything returned by the search, not just the 150 or so items which load on the screen. In my case there were over 8,100 group membership actions to undo. The download appeared to freeze a few times but if you leave it alone it eventually completes.
Looking at the CSV in Notepad++ (or whatever your editor of choice is) you'll see four columns - time, userID, operation and AuditData. In this case the data we want is entirely contained within AuditData - the userID column is the user who removed the member from the group, in this case ServicePrincipal_GUID as it was removed by SDS in the background.
AuditData is in JSON format and contains the UPN of the user who was removed, and the group ID and display name, but not whether they were a member or owner. One row of the CSV is shown below:
2021-08-17T14:14:50.0000000Z,ServicePrincipal_8ca6586c-b428-4174-9f4c-805c018815a0,Remove member from group.,"{""CreationTime"":""2021-08-17T14:14:50"",""Id"":""844d8a4e-ec5a-4ffe-8258-03582ed3d409"",""Operation"":""Remove member from group."",""OrganizationId"":""82214f68-930d-4882-94b3-eaadd02287af"",""RecordType"":8,""ResultStatus"":""Success"",""UserKey"":""Not Available"",""UserType"":4,""Version"":1,""Workload"":""AzureActiveDirectory"",""ObjectId"":""[email protected]"",""UserId"":""ServicePrincipal_8ca6586c-b428-4174-9f4c-805c018815a0"",""AzureActiveDirectoryEventType"":1,""ExtendedProperties"":[{""Name"":""additionalDetails"",""Value"":""{}""},{""Name"":""extendedAuditEventCategory"",""Value"":""Group""}],""ModifiedProperties"":[{""Name"":""Group.ObjectID"",""NewValue"":"""",""OldValue"":""8e73e6b3-b8f6-4c2a-b4dd-a76e60e5fe8b""},{""Name"":""Group.DisplayName"",""NewValue"":"""",""OldValue"":""11_PEX_C_2020_21""},{""Name"":""Group.WellKnownObjectName"",""NewValue"":"""",""OldValue"":""""}],""Actor"":[{""ID"":""Microsoft.Azure.SyncFabric"",""Type"":1},{""ID"":""00000014-0000-0000-c000-000000000000"",""Type"":2},{""ID"":""ServicePrincipal_8ca6586c-b428-4174-9f4c-805c018815a0"",""Type"":2},{""ID"":""8ca6586c-b428-4174-9f4c-805c018815a0"",""Type"":2},{""ID"":""ServicePrincipal"",""Type"":2}],""ActorContextId"":""82214f68-930d-4552-94b3-eaadd02287af"",""InterSystemsId"":""8453cb73-2e25-4dca-a449-a65772fb7655"",""IntraSystemId"":""85c7023c-2ee0-4fcf-8748-7f9bd5d89cef"",""SupportTicketId"":"""",""Target"":[{""ID"":""User_8793ef47-4eee-4736-b900-7d557be34b73"",""Type"":2},{""ID"":""8793ef47-4eee-4736-b900-7d557be34b73"",""Type"":2},{""ID"":""User"",""Type"":2},{""ID"":""[email protected]"",""Type"":5},{""ID"":""80033FFFAFF0E924"",""Type"":3}],""TargetContextId"":""82214f68-930d-4552-94b3-eaadd02287af""}"
From this I've built a PowerShell script to add the users back into the teams. Unfortunately it doesn't tell us if they were an owner or just a member when removed, so you'll have to use your own code to determine this based on username. In my case, pupil usernames start with numbers, and pupils are team members. Staff are team owners, and usernames start with letters.
In this script we pull the username and team's group ID from the JSON encoded data, then insert those into the Add-TeamUser cmdlet.
Connect-MicrosoftTeams
$CSV = Import-CSV "C:\Users\katy\downloads\AuditLog_2021-07-31_2021-08-18.csv"
$CSV | foreach-object {
$ItemData = ConvertFrom-Json($_.AuditData)
$User = $ItemData.ObjectId
$GroupID = ($ItemData.ModifiedProperties | Where {$_.Name -eq "Group.ObjectID"}).OldValue
$Type = "Owner"
if ($User -match "^\d+.*$") {
$Type = "Member"
}
Add-TeamUser -GroupId $GroupID -User $User -Role $Type
Write-Host "Add $User to $GroupID"
}