DEV Community

AdminPackStudio
AdminPackStudio

Posted on

The 30-minute Monday habit — weekly read-only Intune device + compliance CSV snapshots

The 30-minute Monday habit: weekly read-only Intune snapshots

"Are we healthier than last month?" is a hard question to answer from the Intune portal. Portal views show now. They don't version-control, they don't diff, and nobody remembers what the noncompliant count was three Mondays ago.

The fix is boring: export device and compliance state to a dated CSV once a week, read-only, and compare. Here's the pattern we use.

Related reading:


1. Read-only, least privilege, on purpose

A snapshot job should never be able to change anything. Set it up so it can't.

Choice Starter setting
Entra role for the person running it Intune Reader or Global Reader if that's sufficient in your tenant — not Global Admin for a weekly export
Graph scope — devices DeviceManagementManagedDevices.Read.All
Graph scope — compliance policies DeviceManagementConfiguration.Read.All
Where it runs A dedicated admin workstation or hardened jump box — not a shared PC
Auth Interactive delegated sign-in to start; automate later with app permissions + certificate only once you've thought it through

If Connect-MgGraph fails with insufficient privileges, stop and get consent the proper way. Don't "fix" it by borrowing a more powerful session.


2. The export (one-time setup, then copy-paste)

Install-Module Microsoft.Graph.Authentication -Scope CurrentUser
Install-Module Microsoft.Graph.DeviceManagement -Scope CurrentUser
Enter fullscreen mode Exit fullscreen mode

(If your org blocks PSGallery, use your internal module distribution.)

Each Monday:

$week = Get-Date -Format 'yyyy-MM-dd'
$out  = ".\snapshots\$week"
New-Item -ItemType Directory -Path $out -Force | Out-Null

Connect-MgGraph -Scopes 'DeviceManagementManagedDevices.Read.All','DeviceManagementConfiguration.Read.All'

# Managed devices: a small, useful property set
Get-MgDeviceManagementManagedDevice -All -Property `
    'deviceName','operatingSystem','osVersion','complianceState','lastSyncDateTime',`
    'enrolledDateTime','userPrincipalName','isEncrypted','azureADDeviceId','id' |
  Select-Object DeviceName, OperatingSystem, OsVersion, ComplianceState,
                LastSyncDateTime, EnrolledDateTime, UserPrincipalName,
                IsEncrypted, AzureADDeviceId, Id |
  Export-Csv "$out\intune-devices.csv" -NoTypeInformation -Encoding UTF8
Enter fullscreen mode Exit fullscreen mode

Then export your compliance policy list (names, platform, last modified) into the same folder. That second file is what tells you "someone edited a live policy on Thursday" — the device CSV alone won't.

Testing on a big tenant? Use -Top 50 instead of -All for a pilot-sized sample first.

You end up with:

snapshots/
  2026-09-28/intune-devices.csv
  2026-09-28/compliance-policies.csv
  2026-10-05/intune-devices.csv
  2026-10-05/compliance-policies.csv
Enter fullscreen mode Exit fullscreen mode

3. What to track week over week

Don't build a dashboard. Track five numbers in a ticket or wiki table:

Metric Why it matters
Total managed devices Sudden drops = enrollment or licensing problem; sudden jumps = someone enrolled personal devices
Noncompliant count (and %) The headline trend. Should fall as pilots mature
Stale sync (LastSyncDateTime > ~7 days) Usually powered-off laptops or broken enrollment — not compliance logic
IsEncrypted false on Windows rows Cross-check vs a BitLocker requirement; treat odd/null values on non-Windows rows carefully
Compliance policy count / last-modified changes Unannounced policy edits are the #1 cause of "nothing changed but everything broke"

A quick comparison of two weeks:

$prev = Import-Csv .\snapshots\2026-09-28\intune-devices.csv
$curr = Import-Csv .\snapshots\2026-10-05\intune-devices.csv

'Last week:'; $prev | Group-Object ComplianceState | Select-Object Name, Count
'This week:'; $curr | Group-Object ComplianceState | Select-Object Name, Count

# Devices that went from compliant to anything else
$prevState = @{}; $prev | ForEach-Object { $prevState[$_.Id] = $_.ComplianceState }
$curr | Where-Object { $prevState[$_.Id] -eq 'compliant' -and $_.ComplianceState -ne 'compliant' } |
  Select-Object DeviceName, ComplianceState, LastSyncDateTime | Format-Table -AutoSize

# Stale sync this week
$cutoff = (Get-Date).AddDays(-7)
$curr | Where-Object { $_.LastSyncDateTime -and [datetime]$_.LastSyncDateTime -lt $cutoff } |
  Measure-Object | Select-Object Count
Enter fullscreen mode Exit fullscreen mode

The "went from compliant to noncompliant" list is the one worth 5 minutes of human attention. Everything else is trend.


4. The ritual (≤30 minutes)

  1. Run the device export → save under yyyy-mm-dd/
  2. Run the compliance policy export
  3. Write down the five numbers next to last week's
  4. Spot-check 1–2 weird devices on the endpoint itself (dsregcmd /status, encryption status)
  5. Open a ticket only if the trend worsens — or if Conditional Access report-only "would block" numbers spike

That's it. After a month you have real evidence for "ready to move CA from report-only to enforce?" instead of a gut feeling.


5. Where NOT to put these CSVs

These files contain device names, user principal names, and tenant-linked IDs. Treat them like internal data:

  • ❌ Public Teams/Slack channels with guests, Discord servers, community forums
  • ❌ Pasted into public AI chat tools or GitHub issues
  • ❌ Attached to vendor tickets without trimming to the rows they need
  • ❌ Product reviews or blog screenshots (redact names/UPNs/IDs first)
  • ✅ An access-controlled share or repo your org approves, with a retention rule (e.g. keep 12 weeks)

If you need help from a forum, share the counts or a redacted row — never the file.


6. Common snags

Symptom Likely cause
Missing module Microsoft.Graph.* Installed under a different PowerShell edition/host than the one running the script
Consent prompt loop Admin consent required once per tenant
Empty device list Wrong tenant — check Get-MgContext — or scope too weak
Graph 403 Role doesn't cover Intune read; assign Intune Reader or an appropriate role
Execution policy blocks .ps1 Use process-scoped bypass or signed scripts per IT policy — don't weaken machine policy casually

Want this ready-made?

This post is the short version. The Intune & M365 Admin Starter Pack ($19 during launch week; normally $29) includes the full inventory-snapshot module plus enrollment hygiene, baseline compliance, M365 admin hygiene, and break/fix cards — and three read-only PowerShell scripts: a local enrollment snapshot (no Graph), a Graph managed-device snapshot, and a compliance policy summary. The scripts only read; they take no device actions and make no policy changes.

👉 https://cashflow4375.gumroad.com/l/joonf


Not affiliated with Microsoft. Operational guidance for admins authorized to manage their tenant. Pilot first.

Top comments (0)