M365Con 2027 – free online conference · 11–22 Jan 2027 · 120 sessions→ m365con.net

2025-08-05

Find Missing Microsoft 365 Compliance Data with Graph

Find Missing Microsoft 365 Compliance Data with Graph
Your Compliance Dashboard Is Lying to You: The Microsoft Graph Endpoints That Expose Hidden Risk (and How to Wire Them into Purview) If your M365 compliance reports always feel a step behind, you’re missing entire categories of incidents that never hit the default dashboards. In this episode, we…

Compliance Blindspots in M365: The Graph Endpoints Your Dashboards Don’t Show—and How to Pipe Them into Purview

Overview

Default compliance dashboards are summaries, not truth. Critical signals (DLP hits, eDiscovery actions, security alerts) often live behind Graph endpoints with separate permissions. We map the exact APIs, scopes, and scripting patterns to extract full-fidelity evidence and centralize it in Purview for clear, defensible reporting.

Who This Helps

  • Compliance/Legal/Risk owners who need audit-ready evidence

  • M365/Entra admins building reporting and automation

  • Security teams correlating DLP, eDiscovery, and alert telemetry

The Blindspots (why OOTB dashboards miss)

  • Aggregation & lag: UI summaries omit nested incident details and recent activity

  • Scope gaps: eDiscovery actions/DLP matches may be outside standard exports

  • Split permissions: /security & /compliance endpoints require different scopes

  • No joins: Dashboards rarely correlate incidents with users/custodians/case steps

The High-Value Graph Endpoints (copy-this list)

  • Security alerts (breadth)

    • Endpoint: /security/alerts or /security/alerts_v2

    • App perms (examples): SecurityEvents.Read.All (or Alerts.Read.All in newer models)

    • Use for: Alert timelines, severity, status, assignments

  • DLP policies & activity (data loss)

    • Endpoints (tenant varies by availability):

      • /security/dataLossPreventionPolicies (policy inventory)

      • /security/dlpIncidents or advanced DLP incident endpoints in security namespace (tenant dependent)

    • App perms: SecurityEvents.Read.All (and/or specific DLP read scopes as available)

    • Use for: Matches, locations (Exchange/SharePoint/Teams), disposition

  • eDiscovery (cases & actions)

    • /compliance/ediscovery/cases

    • Child paths: /custodians, /searches, /reviewSets, /noncustodialDataSources, /operations

    • App perms: eDiscovery.Read.All (and write if managing cases)

    • Use for: Case status, holds, custodians, exports, reviewer actions

  • Audit & sign-in context (supporting evidence)

    • /auditLogs/directoryAudits, /auditLogs/signIns

    • App perms: AuditLog.Read.All, Directory.Read.All

    • Use for: Who changed what/when, session context

Tip: Many compliance payloads are deeply nested—plan to use $expand, page via @odata.nextLink, and join with /users/{id} for display names and departments.

Auth & Permissions (zero-drama path)

  • Use Application permissions (service principal) for unattended jobs

  • Register separate apps for security vs. core Graph if your org requires split privilege

  • Consent only the least-privilege scopes; store secrets/certs in Key Vault

  • Implement exponential backoff for 429/503 and capture x-ms-request-id in logs

Scripting Patterns (PowerShell or Python)

  • Select & expand: request only needed fields, $select=…, $expand=… for nested entities

  • Filter & time-box: $filter=createdDateTime ge {ISO8601} for deltas

  • Paginate: loop on @odata.nextLink; never assume single-page results

  • Normalize: map user/object IDs to names and departments up front for readable outputs

  • Join for context: enrich incidents with user, site, team, or case metadata before export

Wiring It Into Purview (turn data into decisions)

  1. Standardize output: CSV/JSON with consistent field names (tenant, incidentId, workload, userId, userUPN, severity, status, created, lastAction, caseId)

  2. Ingest: land files in a secured storage location Purview can read (e.g., ADLS Gen2)

  3. Tag & label: apply sensitivity labels or custom tags (e.g., “DLP-PII-High”) for routing

  4. Dashboards: Purview (or Power BI over Purview data) for trends, owners, SLA aging

  5. Automations: rules to notify case owners on repeats/escalations; weekly PDF digests

30-Minute Pilot (step-by-step)

  • 0–10 min: App registration + SecurityEvents.Read.All / eDiscovery.Read.All; create secret/cert

  • 10–20 min: Script one endpoint (alerts or cases) with paging + $filter for last 7 days

  • 20–30 min: Enrich with /users, export CSV, drop to ADLS path, visualize a basic chart

KPIs That Prove Value

  • % of incidents with owner & disposition populated

  • Mean time from incident → case (or reviewer)

  • Repeat-offender accounts/locations per 30 days

  • Delta vs. OOTB dashboard counts (gap closure)

  • Audit cycle time (evidence prep hours saved)

Common Pitfalls (and fixes)

  • Empty results → wrong scopes or using Delegated where Application is required

  • Missing detail → forgot $expand / nested collections not parsed

  • Partial data → no pagination; only first page captured

  • Name mismatches → no enrichment join with /users or HR data

  • Stale dashboards → no scheduled runs; add job + alerting on failures

Quick Wins This Week

  • Pull last 7 days from /security/alerts and compare counts to the portal

  • Export open eDiscovery cases + custodians; share with Legal for validation

  • Run a DLP incident sweep and tag repeats; open follow-ups in Purview

  • Schedule a weekly evidence bundle (CSV + PDF) to a compliance mailbox

FAQ

  • Do I need to be a developer? No—PowerShell or short Python scripts are enough.

  • Why app perms? Most /security and /compliance endpoints require headless, high-trust access.

  • Can I stay in PowerShell? Yes—use the Microsoft Graph PowerShell SDK and handle $top, $filter, $expand, pagination.

  • Is Purview required? Not strictly—but it turns raw JSON into auditable workflows and dashboards.

Conclusion

Dashboards summarize; Graph tells the whole story. Pull the right endpoints, fix auth, page and expand, then centralize in Purview. You’ll move from checkbox compliance to provable, real-time visibility—without drowning in manual exports.

YouTube

Host: Mirko Peters

Related articles

← PowerShell vs Microsoft Graph API for AutomationFix Microsoft Entra B2B Direct Connect Issues →