Keeping track of configuration changes inside Microsoft Intune can feel like chasing ghosts. One day a policy behaves normally, the next day something is different, and no one knows who touched what.
Instead of spending your mornings digging through logs, here’s a much cleaner solution:
A fully automated Intune change alert system using Azure Automation, Managed Identity, and Microsoft Graph.
This guide shows you every technical detail, every permission, every command, and the full working script — ready for production.
If you want real-time visibility of every Intune modification, this is the way.

What This Automation Actually Does
Every X minutes/hours (your schedule):
- The script connects to Graph using the Automation Account Managed Identity
- It checks Intune audit logs for anything new since the last run
- It extracts:
- Who made the change
- What object they modified
- What was changed (before/after values)
- When it happened
- It converts this into a clean HTML report
- then sent emails your admin team via Graph’s Mail.Send
- also It saves a timestamp so no duplicate alerts are sent
The result:
Instant intelligence on all changes happening in your Intune environment.
for more info check the ms learn from Microsoft
Prerequisites — and Why You Need Each One
To run the script, your Automation Account Managed Identity must have application permissions to Microsoft Graph.
Here are the required ones:
Microsoft Graph Application Permissions
| Permission | Reason |
|---|---|
AuditLog.Read.All | Required to read audit events (Intune changes). |
DeviceManagementConfiguration.Read.All | Required to resolve object names (policies, profiles, etc.). |
DeviceManagementApps.Read.All | Needed for app-related Intune changes. |
Group.Read.All | Needed because many Intune changes involve groups. |
Mail.Send | Allows the Automation Account to send alert emails. |
You must grant admin consent in Entra ID for these App permissions.
Giving the Automation Account the Proper Graph API Access
1. Find your Automation Account Managed Identity Object ID
Run this from Azure Cloud Shell or local PowerShell:
az account set --subscription "<YOUR_SUBSCRIPTION_ID>"
az automation account show `
--resource-group "<RESOURCE_GROUP>" `
--name "<AUTOMATION_ACCOUNT>" `
--query identity.principalId `
-o tsv
This returns the Object ID of the System-Assigned Managed Identity.
2. Assign the Graph API permissions
Use the following commands:
Add Required Permissions:
# DeviceManagementConfiguration.Read.All
az ad app permission add --id <MANAGED_IDENTITY_OBJECT_ID> --api 00000003-0000-0000-c000-000000000000 --api-permissions 5b567255-7703-4780-807c-7be8301ae99b=Role
# DeviceManagementApps.Read.All
az ad app permission add --id <MANAGED_IDENTITY_OBJECT_ID> --api 00000003-0000-0000-c000-000000000000 --api-permissions 9e3f62cf-6bd8-4ab8-b2d4-a2ce46c643c0=Role
# AuditLog.Read.All
az ad app permission add --id <MANAGED_IDENTITY_OBJECT_ID> --api 00000003-0000-0000-c000-000000000000 --api-permissions e48d8a35-e77a-4285-8440-f9ff79f1e49f=Role
# Group.Read.All
az ad app permission add --id <MANAGED_IDENTITY_OBJECT_ID> --api 00000003-0000-0000-c000-000000000000 --api-permissions 5b567255-7703-4780-807c-7be8301ae99b=Role
# Mail.Send
az ad app permission add --id <MANAGED_IDENTITY_OBJECT_ID> --api 00000003-0000-0000-c000-000000000000 --api-permissions 07f59a12-8361-4f14-b33d-402d5b1f6ca9=Role
Grant Admin Consent
az ad app permission grant --id <MANAGED_IDENTITY_OBJECT_ID> --api 00000003-0000-0000-c000-000000000000 --scope /
az ad app permission admin-consent --id <MANAGED_IDENTITY_OBJECT_ID>
After this → your Automation Account has the correct Graph permissions.
The Complete, Fully Featured PowerShell Script
This script:
- Connects via Managed Identity
- Reads Intune audit logs
- Maps IDs → readable names
- Detects changes
- Builds a clean HTML report
- Emails the summary
- Stores the timestamp for incremental scanning
Paste this directly inside your Azure Automation Account PowerShell Runbook.
🔥 FULL SCRIPT -COPY -PASTE
<#
.SYNOPSIS
Intune Change Alerts — Automated Email Notifications
.DESCRIPTION
Pulls Intune audit logs via Microsoft Graph, identifies new changes,
formats them into an HTML report, and emails them to admins.
Uses system-assigned managed identity (no secrets).
#>
Connect-MgGraph -Identity -NoWelcome
Select-MgProfile -Name "beta"
# Timestamp file
$timestampFile = "$PSScriptRoot/lastRun.txt"
if (Test-Path $timestampFile) {
$lastRun = Get-Content $timestampFile | Out-String
} else {
$lastRun = (Get-Date).AddHours(-24).ToString("o")
Set-Content -Path $timestampFile -Value $lastRun
}
Write-Output "Last run: $lastRun"
# Fetch audit logs since last run
$auditLogs = Get-MgDeviceManagementAuditEvent -Filter "activityDateTime gt $lastRun" -All
if (-not $auditLogs) {
Write-Output "No changes. Exiting."
Set-Content -Path $timestampFile -Value (Get-Date).ToString("o")
return
}
# Resolve names for objects referenced by ID
function Resolve-ObjectName {
param($id)
try {
$config = Get-MgDeviceManagementConfigurationPolicy -PolicyId $id -ErrorAction SilentlyContinue
if ($config) { return $config.Name }
$group = Get-MgGroup -GroupId $id -ErrorAction SilentlyContinue
if ($group) { return $group.DisplayName }
$app = Get-MgDeviceAppManagementMobileApp -MobileAppId $id -ErrorAction SilentlyContinue
if ($app) { return $app.DisplayName }
return $id
} catch {
return $id
}
}
# Build HTML Report
$report = "<h2>Intune — Changes Detected</h2>"
foreach ($entry in $auditLogs) {
$target = ""
if ($entry.TargetResources.Count -gt 0) {
$res = $entry.TargetResources[0]
$resolvedName = Resolve-ObjectName $res.Id
$target = "$resolvedName ($($res.Type))"
}
$report += "<div style='padding:10px;border:1px solid #ccc;margin-top:10px;border-radius:8px'>"
$report += "<p><strong>User:</strong> $($entry.Actor?.UserPrincipalName)</p>"
$report += "<p><strong>Action:</strong> $($entry.Activity)</p>"
$report += "<p><strong>Target:</strong> $target</p>"
$report += "<p><strong>Date:</strong> $($entry.ActivityDateTime)</p>"
if ($entry.ModifiedProperties) {
$report += "<p><strong>Modified Properties:</strong></p><ul>"
foreach ($prop in $entry.ModifiedProperties) {
$report += "<li><strong>$($prop.DisplayName)</strong>: '$($prop.OldValue)' → '$($prop.NewValue)'</li>"
}
$report += "</ul>"
}
$report += "</div>"
}
# Send the email
Send-MgUserMail -UserId "alerts-mailbox@domain.com" -Message @{
Subject = "Intune Change Alert — $(Get-Date -Format 'yyyy-MM-dd HH:mm')"
Body = @{
ContentType = "HTML"
Content = $report
}
ToRecipients = @(
@{EmailAddress = @{Address = "admin-team@domain.com"}}
)
}
# Update timestamp
Set-Content -Path $timestampFile -Value (Get-Date).ToString("o")
Write-Output "Report sent and timestamp updated."
What the Email Looks Like
The script sends an HTML report similar to:
- User: john.doe@domain.com
- Action: Updated Device Configuration
- Target: Windows Compliance Policy – Production
- Modified:
- PasswordRequired: false → true
- MinimumOSVersion: 10.0.19045 → 10.0.19047
- Timestamp: 2025-02-14 14:21 UTC
Readable. Clean. No GUIDs. No walls of JSON.
Why This Monitoring Setup Is Actually Worth It
This automation detects:
✓ Policy updates
✓ Compliance changes
✓ App assignments
✓ Group modifications tied to Intune
✓ Enrollment changes
✓ Device management configuration tweaks
And it alerts you before users start calling.
This is exactly the kind of proactive monitoring every Intune admin should have in place.
Please check my post about Azure Automation acount troubleshooting process here
Retour de ping : How to Verify Your Azure Automation Account Permissions Using PowerShell - MSEndpoint