For years, moving security groups from on-premises Active Directory to Microsoft Entra ID has been one of the more frustrating parts of a cloud migration. Organizations either had to recreate groups manually, build custom migration scripts, or accept downtime while replacing existing objects.
Microsoft’s introduction of Group Source of Authority (SOA) conversion changes that. Instead of creating new cloud-native groups, you can transfer management of existing synchronized groups from Active Directory to Entra ID while preserving the group’s identity, memberships, and permissions. This makes it much easier to modernize identity management without breaking existing workloads.
The challenge is scale. Converting a handful of groups through Microsoft Graph or the admin experience is manageable. Converting hundreds—or thousands—of groups quickly becomes repetitive and error-prone.
In this post, I’ll show you how to use PowerShell to perform a bulk conversion of AD-synced groups to Entra ID-managed groups. We’ll automate the process, add error handling and logging, and discuss the prerequisites and limitations you should be aware of before running the script in production.
Step 1 – Determining groups to convert
In my example, I will be converting all groups that matches a certain pattern in the dispalyName. Quite simple, but you can of course do this many ways. The point is to get a list of groups in the $groups variable:
$groups = Get-MgGroup -All -PageSize 999 | ? displayName -match "^G_[A-Z]+_EL_Trinn_[0-9]+$"
Write-Host "Found $($groups.Count) groups"
Step 2 – Converting to cloud managed
We are now ready to update the onPremisesSyncBehavior of our groups, which can be done like this:
$groups | ForEach-Object {
Write-Host "Converting group '$($_.displayName)' ($($_.id))"
Invoke-MgGraphRequest -Method PATCH -Uri "https://graph.microsoft.com/v1.0/groups/$($_.id)/onPremisesSyncBehavior" -Body (@{isCloudManaged = $true}|ConvertTo-Json)
}
That’s it, they are now cloud managed!
Step 3 – Back to AD…
In case you need to roll back the same groups, you have a reverse script here:
$groups | ForEach-Object {
Write-Host "Converting group '$($_.displayName)' ($($_.id))"
Invoke-MgGraphRequest -Method PATCH -Uri "https://graph.microsoft.com/v1.0/groups/$($_.id)/onPremisesSyncBehavior" -Body (@{isCloudManaged = $false}|ConvertTo-Json)
}
Good luck!