Microsoft Intune
Microsoft Intune is the MDM / device-management source. The integration talks to the Microsoft Graph API to pull managed devices, the tenant’s detected-app catalog, and the per-device installed apps, and writes them into MongoDB. It follows the shared integration lifecycle.
- Router:
app/api/v1/endpoints/intune.py, mounted at/api/v1/intune - Client:
app/services/intune_client.py(IntuneClient) - Config collection:
intune_config(keyed bytenant_id)
Authentication
Intune authenticates to Graph via MSAL client-credentials against an Azure app registration. Two auth methods are supported:
auth_method | Required fields |
|---|---|
certificate | cert_thumbprint + cert_private_key (PEM text) |
secret | client_secret |
Both methods also need azure_tenant_id and azure_client_id. The client builds
an msal.ConfidentialClientApplication and requests the
https://graph.microsoft.com/.default scope. On save, the router validates that
the fields for the chosen method are present (422 otherwise).
Required Graph application permissions (admin consent on the app registration):
DeviceManagementManagedDevices.Read.AllDeviceManagementApps.Read.All
Env seeding (_seed_intune_config) reads INTUNE_TENANT_ID, INTUNE_CLIENT_ID,
INTUNE_CERT_THUMBPRINT and a PEM at INTUNE_CERT_KEY_PATH, and seeds the
default tenant with certificate auth. (The same app registration and cert are
reused by the Entra ID integration.)
test-connection fetches one managed device to validate both credentials and
consent.
What the sync pulls
The background _run_sync fetches everything in a thread-pool executor so auth
stays responsive, then bulk-upserts:
| Data | Source call | Written to |
|---|---|---|
| Managed devices | get_managed_devices (/deviceManagement/managedDevices) | intune_devices |
| Detected apps (deduped catalog) | get_detected_apps → deduplicate_apps | intune_apps |
| Per-device apps | get_device_apps_batch (Graph $batch) | inventory_items (source=intune) |
- Devices capture OS/version, compliance state, owner type, enrolled/last-sync
timestamps, manufacturer/model/serial, and the owner —
user_upnanduser_display_name. Other integrations key off the device name and the owner UPN to reconcile machines and link users to assets. - Per-device apps are fetched with Graph JSON batching (
get_device_apps_batch): up to 20 requests per$batchcall, with per-response pagination re-batched in follow-up rounds and exponential-backoff retry on429throttling. The resulting device→app rows are upserted into the sharedinventory_itemscollection taggedsource="intune", carrying the device name, OS, and owner email/name so software reconciles and links to the right person.
Stale devices, apps and inventory rows are deleted, then rebuild_applications
refreshes the Software rollup.
Routes
| Method | Path | Purpose |
|---|---|---|
POST | /api/v1/intune/config | Save credentials (validates per-method fields) |
GET | /api/v1/intune/config | Get config (secrets redacted) |
DELETE | /api/v1/intune/config | Remove config + synced data |
POST | /api/v1/intune/test-connection | Live Graph credential + consent test |
POST | /api/v1/intune/sync | Start a background sync |
GET | /api/v1/intune/sync-status | Poll sync status |
GET | /api/v1/intune/stats | Summary counts + OS / compliance breakdowns |
GET | /api/v1/intune/devices | List managed devices (OS / compliance filters) |
GET | /api/v1/intune/apps | List deduplicated detected apps by device count |
See the overview for the lifecycle these routes share.