Skip to content

Entra ID & Intune Cloud Security Audit Scripts

Essential PowerShell automation scripts utilizing the official Microsoft.Graph and Microsoft.Graph.DeviceManagement modules for cloud identity hygiene, privilege escalation detection, and Intune compliance auditing.


Audits all active and eligible assignments to Tier-0 Entra ID administrative roles (Global Administrator, Privileged Role Administrator, Security Administrator, Intune Administrator).

Terminal window
# Connect to Microsoft Graph
Connect-MgGraph -Scopes "RoleManagement.Read.Directory", "User.Read.All"
$targetRoles = @(
"Global Administrator",
"Privileged Role Administrator",
"Security Administrator",
"Intune Administrator",
"Authentication Administrator",
"Cloud Application Administrator"
)
$auditReport = foreach ($roleName in $targetRoles) {
$roleDef = Get-MgRoleManagementDirectoryRoleDefinition -Filter "displayName eq '$roleName'"
if ($roleDef) {
Get-MgRoleManagementDirectoryRoleAssignment -Filter "roleDefinitionId eq '$($roleDef.Id)'" -ExpandProperty "principal" | ForEach-Object {
[PSCustomObject]@{
RoleName = $roleName
PrincipalType = $_.Principal.AdditionalProperties["@odata.type"] -replace '#microsoft.graph.', ''
DisplayName = $_.Principal.AdditionalProperties["displayName"]
UserPrincipal = $_.Principal.AdditionalProperties["userPrincipalName"]
AppId = $_.Principal.AdditionalProperties["appId"]
AssignmentId = $_.Id
}
}
}
}
$auditReport | Sort-Object RoleName, DisplayName | Format-Table -AutoSize

๐Ÿ“ฑ 2. High-Risk App Registrations & Over-Permissioned Service Principals

Section titled โ€œ๐Ÿ“ฑ 2. High-Risk App Registrations & Over-Permissioned Service Principalsโ€

Identifies Enterprise Applications and Service Principals possessing sensitive Microsoft Graph Application permissions (daemon rights that bypass user MFA and access tenant-wide data):

Terminal window
# Hunt for apps with tenant-wide administrative Graph API permissions
$dangerousScopes = @(
"Application.ReadWrite.All",
"RoleManagement.ReadWrite.Directory",
"Mail.ReadWrite",
"Mail.ReadWrite.Shared",
"Files.ReadWrite.All",
"Directory.ReadWrite.All",
"User.ReadWrite.All"
)
Get-MgServicePrincipal -All | ForEach-Object {
$sp = $_
$appRoles = $sp.AppRoleAssignments | Where-Object { $_.ResourceDisplayName -eq "Microsoft Graph" }
foreach ($role in $appRoles) {
# Match role IDs to permission names
[PSCustomObject]@{
AppDisplayName = $sp.DisplayName
AppId = $sp.AppId
Publisher = $sp.PublisherName
PrincipalId = $sp.Id
}
}
}

๐Ÿ”‘ 3. Expiring & Long-Lived Service Principal Secrets

Section titled โ€œ๐Ÿ”‘ 3. Expiring & Long-Lived Service Principal Secretsโ€

Audits client secrets and certificates configured on App Registrations, identifying keys valid for over 2 years or already expired:

Terminal window
# Audit credential hygiene on App Registrations
Get-MgApplication -All | ForEach-Object {
$app = $_
# Check Password Secrets
foreach ($secret in $app.PasswordCredentials) {
[PSCustomObject]@{
AppName = $app.DisplayName
AppId = $app.AppId
Type = "ClientSecret"
KeyName = $secret.DisplayName
CreatedDate = $secret.StartDateTime
ExpiryDate = $secret.EndDateTime
IsExpired = ($secret.EndDateTime -lt (Get-Date))
}
}
# Check Certificates
foreach ($cert in $app.KeyCredentials) {
[PSCustomObject]@{
AppName = $app.DisplayName
AppId = $app.AppId
Type = "Certificate"
KeyName = $cert.DisplayName
CreatedDate = $cert.StartDateTime
ExpiryDate = $cert.EndDateTime
IsExpired = ($cert.EndDateTime -lt (Get-Date))
}
}
} | Format-Table -AutoSize

๐Ÿ’ป 4. Intune Device Compliance Audit (Windows & macOS)

Section titled โ€œ๐Ÿ’ป 4. Intune Device Compliance Audit (Windows & macOS)โ€

Scans the managed endpoint fleet in Microsoft Intune, highlighting non-compliant, jailbroken, or unmanaged devices:

Terminal window
# Connect to Microsoft Graph Device Management
# Connect-MgGraph -Scopes "DeviceManagementManagedDevices.Read.All"
Get-MgDeviceManagementManagedDevice -All | Select-Object DeviceName,
OperatingSystem,
OSVersion,
ComplianceState,
JailBroken,
ManagementAgent,
UserPrincipalName,
LastSyncDateTime |
Where-Object { $_.ComplianceState -ne "compliant" } |
Sort-Object OperatingSystem, DeviceName |
Format-Table -AutoSize

Locates external guest accounts (#EXT#) and internal users who have not authenticated in over 90 days:

Terminal window
# Find inactive cloud users and stale guest collaborators
$cutoffDate = (Get-Date).AddDays(-90)
Get-MgUser -All -Property DisplayName, UserPrincipalName, UserType, AccountEnabled, SignInActivity | ForEach-Object {
$lastSign = $_.SignInActivity.LastSignInDateTime
if ($_.AccountEnabled -eq $true -and ($lastSign -lt $cutoffDate -or $null -eq $lastSign)) {
[PSCustomObject]@{
DisplayName = $_.DisplayName
UPN = $_.UserPrincipalName
UserType = $_.UserType
LastSignIn = $lastSign
DaysIdle = if ($lastSign) { ( (Get-Date) - $lastSign ).Days } else { "Never" }
}
}
} | Sort-Object DaysIdle -Descending | Format-Table -AutoSize

๐Ÿ›ก๏ธ 6. User Authentication Methods Audit (Phishing-Resistant MFA)

Section titled โ€œ๐Ÿ›ก๏ธ 6. User Authentication Methods Audit (Phishing-Resistant MFA)โ€

Audits which users have registered hardware-bound phishing-resistant credentials (FIDO2 keys, Windows Hello for Business) vs. legacy methods:

Terminal window
# Audit MFA method adoption across all enabled users
Get-MgUser -All -Property Id, DisplayName, UserPrincipalName -Filter "accountEnabled eq true" | ForEach-Object {
$methods = Get-MgUserAuthenticationMethod -UserId $_.Id
$methodTypes = $methods.AdditionalProperties["@odata.type"] -replace '#microsoft.graph.', ''
[PSCustomObject]@{
DisplayName = $_.DisplayName
UPN = $_.UserPrincipalName
HasFIDO2 = ($methodTypes -contains "fido2AuthenticationMethod")
HasWindowsHello = ($methodTypes -contains "windowsHelloForBusinessAuthenticationMethod")
HasAuthenticator = ($methodTypes -contains "microsoftAuthenticatorAuthenticationMethod")
HasPhoneSMS = ($methodTypes -contains "phoneAuthenticationMethod")
}
} | Format-Table -AutoSize