Migrating to Entra Cloud Sync in a hybrid environment (Cloud Sync and Connect Sync coexistence)

[ Originally published on sidorov.au, you can find the original post here ]

If you have an on-premises environment with Active Directory, you likely have Entra Connect Sync (formerly known as AAD Connect) synchronising your users, groups, and device objects between your on-premises environment and the cloud.

In 2025, you may be considering adopting a cloud-first approach, particularly for group memberships. This will enable you to fully utilise Entra ID’s Dynamic groups, Identity Governance, Access Packages, and other valuable tools.

If you’ve attempted this approach in the past, you may have heard about Connect Sync group writeback. This feature allowed you to source user records from your on-premises environment and some (or all) group memberships from the cloud, and then synchronise them back to your on-premises environment. Unfortunately, Microsoft has discontinued this functionality (source: https://learn.microsoft.com/en-us/entra/identity/hybrid/group-writeback-cloud-sync).

Microsoft’s recommended approach is to switch from Connect Sync to Cloud Sync (source: https://learn.microsoft.com/en-us/entra/identity/hybrid/cloud-sync/migrate-group-writeback). However, if you’re using Entra ID hybrid join with your on-premises workstations, a complete migration (replacing Connect Sync with Cloud Sync) isn’t feasible. Additionally, Pass-Through Authentication and several other crucial features aren’t supported.

https://learn.microsoft.com/en-us/entra/identity/hybrid/cloud-sync/what-is-cloud-sync#comparison-between-microsoft-entra-connect-and-cloud-sync

You might rightfully think that at some stage the gap between Entra Connect Sync and Cloud Sync will be bridged, and all functionality will be supported, and you can replace one with another. But if you, as many other customers, are waiting for that to happen since 2019 when Cloud Sync was first released, you might seriously consider a coexistence approach.

Coexistence

So, is it possible to have Connect Sync and Cloud Sync side by side? The official answer is yes – that is entirely possible as long as they are not syncing the same objects. There is already a built-in safety mechanism in place: Cloud Sync will detect objects synced by Connect Sync and won’t touch them.

At this stage you might think “great, let’s go ahead with the side-by-side” configuration! But before we do that, there are a couple of things to consider.

Cloud Sync – key limitations

  1. Security groups are supported, however mail-enabled security groups are not.
  2. Only cloud-created security groups are supported (i.e. groups created by Connect Sync are not, this is why the approach is to create new groups). This is an important limitation that prescribes re-creation of the cloud group.
  3. Entra ID Cloud Sync only works with Universal groups on-premises.
  4. Group nesting: only direct members will be synchronised.

What does it practically mean?

In Active Directory, Universal, Global and Domain local group scopes define a couple of things:

  • how Active Directory objects are replicated
  • if a foreign user (from another domain) can be a member (domain local groups)

In a simple scenario with one domain in one location, a conversion from a Global to Universal scope will be relatively straightforward. In a complex environment, moving foreign security principals from domain-local groups might be a separate preparation task (the approach is to move those objects to a specifically created group as they are unlikely to be in the scope of Cloud Sync).

To complicate things further, groups in our on-premises AD can already be nested one inside another. If one of those groups is in the scope of Cloud Sync, then it has to be converted to the Universal scope, and that has some implications.

Key AD limitations to consider before converting groups to the Universal scope:

  • A Global group can’t have Universal group as a member
  • A Universal group can’t have Domain Local group as a member
  • A Global group can’t have Domain local group as a member

https://learn.microsoft.com/en-us/previous-versions/windows/it-pro/windows-server-2003/cc755692(v=ws.10)?redirectedfrom=MSDN

We can see that group nesting coupled with Cloud Sync and AD limitations can quickly become complicated.

Another important pitfall to consider is that in Active Directory it is possible to create cyclic group nesting (e.g. “Group A is a member of Group B, which is a member of Group C, which is a member of Group A”).

In practice all these considerations most probably mean creating scripts:

  • to find potential issues that will prevent the conversion (e.g. foreign security principals, group nesting and cycle relationships)
  • to convert groups and their parents/children

This can be a showstopper during the migration, so it is important to identify and address the issues beforehand.

Access control 

To delegate access control in Active Directory, you can use the managedBy attribute of the group. An equivalent to that would be the Owner property in Entra ID; however, it is important to mention that managedBy supports groups, and the Owner property doesn’t.

The best option to approach access control is to implement Access Packages / Identity Governance. However, it is likely a separate project and a dependency, so a tactical solution could be extracting individual users from AD managedBy groups and assigning them as owners in Entra.

Important consideration regarding access control:

  • Entra ID connected applications (such as GitHub and Confluence) will likely use group GUIDs. This should be addressed (remapped) in those apps if Entra groups are re-created.
  • If AD groups are used for access control in external apps, it could also be the group’s SSID or group’s name, and should be addressed in the respective apps.

Matching new cloud groups to existing on-premises groups

What if you wanted to keep on-premises groups, would that be possible?

Yes, it is totally possible and supported. If you want to keep existing AD groups, all you need to do is set the adminDescription attribute to “Group_{cloud-group-guid}” and then Cloud sync will match the cloud group with the existing AD group. Keep in mind that depending on the Cloud Sync configuration, the AD group could be renamed (in fact it will be, by default). To change that behaviour, apply mapping to the cn attribute only during creation.

Planning

Let’s say you already have a list of cloud and on-premises groups managed by Entra ID Connect Sync. A high-level plan of migration activities can look like this:

  • deploy a dev/sandpit environment (1 x AD DC and 1 x temp Entra tenant)
  • use ldifde to copy users, groups and the OU structure from production AD
  • copy existing Entra ID groups across
  • develop scripts to analyse dependencies, cyclic relationships and convert group scopes
  • run the scripts and address the findings
  • prepare migration scripts
  • plan the roll-back
  • split the deployment in proper chunks to make sure that potential errors won’t cause business disruption

Although Entra ID allows you to have multiple groups with the same Display Name, you might want to consider a prefix to differentiate new groups from the old ones.

You might also consider changing the attribute mappings in Cloud Sync to make on-premises groups look nicer:

Technical aspects

Migration scripts will likely do the following:

  • Create new cloud groups
  • Populate adminDescription attribute of the corresponding on-prem groups
  • Replicate group members (users and groups)
  • Replicate the memberOf attribute
  • Add owners
  • Replicate Applications
  • Bring new groups in scope for Cloud Sync
  • Rename old groups and new groups
  • Delete old AD groups (note: deleting an AD group that is synced by Connect Sync will delete a corresponding cloud group in the next sync cycle)

Everything that is mentioned above is relatively straightforward, although it might be time-consuming if approached from scratch.

Cloud Sync scoping filters

How do we bring groups into the scope of Cloud Sync?

There are three options:

  • All groups
  • Selected groups (manual selection)
  • Scoping filters based on group attributes

Let’s say that neither ‘All groups’ nor the complexity of bringing an additional attribute from on-premises AD is our use case, and we would like to go with the ‘Selected groups’.

Manual selection might not be the best option when you have a lot of groups.

One thing that might not seem obvious is how to add groups in scope for Cloud Sync. One would have thought that adding one group and nesting all groups to include under it would be a neat solution, but unfortunately, that is not going to work (https://learn.microsoft.com/en-us/entra/identity/hybrid/cloud-sync/how-to-configure-entra-to-active-directory#scope-provisioning-to-specific-groups).

Can this be scripted? The answer is yes; however, this part is not well documented.

Let’s have a closer look at what Cloud Sync actually is and how scoping filters work.

Cloud Sync is an application; it has an appId and an App registration (service principal, spId) associated with it.

Here’s an example of a Cloud Sync page in a demo tenant.

Note the appId in the URL.

Now if we navigate to App registrations, we can find a service principal with the same appId:

Knowing that, all we need to do is to extract the AppRole ID, and we can script adding groups to the Cloud Sync scope.

Helper script to extract the App Role ID:

function ExtractAppRoleID {
    param (
        [string]$AppID
    )

    try {
        Write-Host "[ ExtractAppRoleID ] Extracting Service Principal ID for AppID : [$AppID]"
        $sp = Get-MgServicePrincipal -Filter "appId eq '$AppID'"
        $global:AppRoleID = $sp.appRoles.id
        $global:spId = $sp.id
        Write-Host "[ ExtractAppRoleID ] AppRoleID: $($global:AppRoleID)"
        Write-Host "[ ExtractAppRoleID ] SpID: $($global:spId)"    
        if ($sp) { return $true } else { return $false }
    } 
    catch {
        Write-Host "[ ExtractAppRoleID ] Error: failed to extract AppRoleID for AppID: $AppID. Error: $_" -ForegroundColor Red
        return $false
    }
}

Script to add the group to the Cloud Sync scope:

function Group-AddToCloudSyncScope {
    param (
        [string]$GroupName
    )

    Write-Host "[ Group-AddToCloudSyncScope ] Processing group [$GroupName]"

    if (-not $global:spId) {
        Write-Host "[ Group-AddToCloudSyncScope ] Error: Service Principal ID [ global:spId ] not set, run ExtractAppRoleID" -ForegroundColor Red
        return
    }
    if (-not $global:AppRoleID) {
        Write-Host "[ Group-AddToCloudSyncScope ] Error: App Role ID [ global:AppRoleID ] not set, run ExtractAppRoleID" -ForegroundColor Red
        return
    }

    $entraGroup = Get-MgGroup -Filter "displayName eq '$GroupName'" -Select Id
    if (-not $entraGroup) {
        Write-Host "[ Group-AddToCloudSyncScope ] Error: Group [$GroupName] not found in Entra" -ForegroundColor Red
        return
    }

    try {
        $json = @"
        {
            "principalId": "$($entraGroup.id)",
            "resourceId": "$global:spId",
            "appRoleId": "$global:AppRoleID"
        }
"@
        # $json

        Write-Host "[ Group-AddToCloudSyncScope ] Adding group $GroupName to CloudSync scope " -NoNewline
        Invoke-MgGraphRequest -Method POST -Uri "$baseURI/servicePrincipals/$spId/appRoleAssignedTo" -Body $json | Out-Null
        Write-Host "OK" -ForegroundColor Green
    } catch {
        Write-Host
        if ($_ -match "Permission being assigned already exists on the object") {
            Write-Host "[ Group-AddToCloudSyncScope ] Group $GroupName is already in scope of CloudSync" -ForegroundColor Yellow
        } else {
            Write-Host "[ Group-AddToCloudSyncScope ] Error adding group to scope: $_" -ForegroundColor Red
        }
    }
}

Conclusion

With the right approach and the right tools at hand, you can initiate Connect Sync to Cloud Sync migration today! I hope this article has useful things to consider and some ideas that could help with the migration.

Read more recent blogs

Get started on the right path to cloud success today. Our Crew are standing by to answer your questions and get you up and running.