M365 ● Sealed v1.0

Cloud Sync

Entra Cloud Sync Discovery - enumerates the modern lightweight provisioning

What it does

Microsoft ships two architecturally distinct directory-sync products that both set onPremisesSyncEnabled = true on user objects: - Azure AD Connect Sync (legacy) -> on-prem ADSync service (AADConnectHealthDiscovery) - Entra Cloud Sync (modern) -> lightweight provisioning agent (THIS module) Calls documented MS Graph endpoints and writes three CSVs: 1. GET /beta/onPremisesPublishingProfiles('provisioning')/agents?$expand=agentGroups -> CloudSyncAgents.csv (ProvisioningAgent rows) 2. GET /v1.0/servicePrincipals?$filter=applicationTemplateId eq '{AD2AAD|AAD2AD}' -> (pivot: SyncServicePrincipal rows; drives 3 & 4) 3. GET /beta/servicePrincipals/{id}/synchronization/jobs -> CloudSyncJobs.csv (SyncJob rows) 4. GET /beta/servicePrincipals/{id}/synchronization/templates -> CloudSyncTemplates.csv (SyncTemplate rows) Cloud Sync configuration service principals use fixed application templates: - AD -> Entra ID : 1a4721b3-e57f-4451-ae87-ef078703ec94 - Entra ID -> AD : fb81332f-3eca-4ecf-a939-4278e501d330 Pattern: identical to AzureIdentityDiscovery.psm1 (SPEC-106, shipped). Pagination, retry, and beta-URL handling are provided by Invoke-GraphAPIWithPaging (DiscoveryBase.psm1). Agents API is delegated-only per Graph docs (Policy.Read.HybridAuthentication); under app-only auth a 401/403 is recorded as AUTH_FAILURE for that section, and discovery continues with service-principal + sync-job enumeration (app permissions). Empty value arrays after a successful Graph call are honest EMPTY_RESULT ΓÇö never invented rows. Required Graph application permissions (primary path): - Application.Read.All / Directory.Read.All for Cloud Sync service principals - Synchronization.Read.All for synchronization jobs + templates Agents (optional / delegated): Policy.Read.HybridAuthentication Token acquisition scope: https://graph.microsoft.com/.default

How the app exposes it

The module feeds into the ACQI app's dedicated results view. From there, conflicts, dependencies, and readiness scores roll up into the deal workspace.

Route in app:
/discovered/cloud-sync

Outputs

Each module produces a CSV with readiness and risk scores, evidence-source counts, and last-seen timestamps. The exact columns vary by module — the app's results view shows the live schema.