Overview
Device compliance policies in Microsoft Intune help ensure that devices meet your organization's security requirements before accessing corporate resources. This guide covers creating, managing, and monitoring compliance policies using PowerShell and Microsoft Graph API.
Prerequisites
- Microsoft Intune license and appropriate admin permissions
- Microsoft Graph PowerShell SDK installed
- Azure AD application registration with required Graph API permissions
- PowerShell 5.1 or PowerShell 7+ with appropriate execution policy
Installing Required Modules
First, install the Microsoft Graph PowerShell SDK:
# Install Microsoft Graph PowerShell SDK
Install-Module Microsoft.Graph -Scope CurrentUser -Force
# Install specific modules for Intune management
Install-Module Microsoft.Graph.DeviceManagement -Scope CurrentUser -Force
Install-Module Microsoft.Graph.Identity.DirectoryManagement -Scope CurrentUser -Force
Connecting to Microsoft Graph
Connect to Microsoft Graph with the required permissions for Intune management:
# Connect to Microsoft Graph with required scopes
$Scopes = @(
"DeviceManagementConfiguration.ReadWrite.All",
"DeviceManagementManagedDevices.ReadWrite.All",
"Directory.Read.All"
)
Connect-MgGraph -Scopes $Scopes
# Verify connection
Get-MgContext | Select-Object -Property Account, Scopes
Creating a Windows Compliance Policy
Create a comprehensive Windows device compliance policy with security requirements:
# Define Windows compliance policy settings
$WindowsCompliancePolicy = @{
"@odata.type" = "#microsoft.graph.windows10CompliancePolicy"
displayName = "Corporate Windows Compliance Policy"
description = "Standard compliance requirements for corporate Windows devices"
# OS Version Requirements
osMinimumVersion = "10.0.19041" # Windows 10 version 2004
osMaximumVersion = "10.0.99999" # Allow future versions
# Security Settings
passwordRequired = $true
passwordMinimumLength = 8
passwordMinutesOfInactivityBeforeLock = 15
passwordRequiredType = "alphanumeric"
passwordPreviousPasswordBlockCount = 5
passwordExpirationDays = 90
# Device Health Requirements
requireHealthyDeviceReport = $true
secureBootEnabled = $true
codeIntegrityEnabled = $true
# Encryption
bitLockerEnabled = $true
storageRequireEncryption = $true
# Antivirus Requirements
antivirusRequired = $true
antiSpywareRequired = $true
defenderEnabled = $true
defenderVersion = "1.1.18000.0" # Minimum Defender version
# System Requirements
tpmRequired = $true
deviceThreatProtectionEnabled = $true
deviceThreatProtectionRequiredSecurityLevel = "medium"
}
# Create the compliance policy
try {
$CreatedPolicy = New-MgDeviceManagementDeviceCompliancePolicy -BodyParameter $WindowsCompliancePolicy
Write-Host "✓ Successfully created compliance policy: $($CreatedPolicy.DisplayName)" -ForegroundColor Green
Write-Host "Policy ID: $($CreatedPolicy.Id)" -ForegroundColor Cyan
} catch {
Write-Error "❌ Failed to create compliance policy: $($_.Exception.Message)"
}
Creating an iOS Compliance Policy
Create a compliance policy specifically for iOS devices:
# Define iOS compliance policy settings
$iOSCompliancePolicy = @{
"@odata.type" = "#microsoft.graph.iosCompliancePolicy"
displayName = "Corporate iOS Compliance Policy"
description = "Standard compliance requirements for corporate iOS devices"
# OS Version Requirements
osMinimumVersion = "15.0"
osMaximumVersion = "99.0"
# Security Settings
passcodeRequired = $true
passcodeMinimumLength = 6
passcodeMinutesOfInactivityBeforeLock = 15
passcodeRequiredType = "alphanumeric"
passcodePreviousPasscodeBlockCount = 5
passcodeExpirationDays = 90
# Device Security
deviceThreatProtectionEnabled = $true
deviceThreatProtectionRequiredSecurityLevel = "medium"
jailbrokenDevicesBlocked = $true
# Managed Apps
managedEmailProfileRequired = $true
# Device Properties
securityBlockJailbrokenDevices = $true
}
# Create the iOS compliance policy
try {
$iOSPolicy = New-MgDeviceManagementDeviceCompliancePolicy -BodyParameter $iOSCompliancePolicy
Write-Host "✓ Successfully created iOS compliance policy: $($iOSPolicy.DisplayName)" -ForegroundColor Green
Write-Host "Policy ID: $($iOSPolicy.Id)" -ForegroundColor Cyan
} catch {
Write-Error "❌ Failed to create iOS compliance policy: $($_.Exception.Message)"
}
Bulk Policy Management from CSV
Manage multiple compliance policies using a CSV file for bulk operations:
Platform,PolicyName,Description,MinOSVersion,MaxOSVersion,PasswordRequired,PasswordLength,InactivityTimeout
Windows,HR Department Windows Policy,Compliance for HR Windows devices,10.0.19041,10.0.99999,True,8,15
iOS,Sales Team iOS Policy,Compliance for Sales iOS devices,15.0,99.0,True,6,10
Android,Marketing Android Policy,Compliance for Marketing Android devices,10.0,99.0,True,6,15
# Function to create compliance policy from CSV row
function New-CompliancePolicyFromCSV {
param(
[Parameter(Mandatory)]
[PSCustomObject]$PolicyData
)
$BasePolicy = @{
displayName = $PolicyData.PolicyName
description = $PolicyData.Description
passwordRequired = [bool]::Parse($PolicyData.PasswordRequired)
passwordMinimumLength = [int]$PolicyData.PasswordLength
passwordMinutesOfInactivityBeforeLock = [int]$PolicyData.InactivityTimeout
}
switch ($PolicyData.Platform) {
"Windows" {
$Policy = $BasePolicy + @{
"@odata.type" = "#microsoft.graph.windows10CompliancePolicy"
osMinimumVersion = $PolicyData.MinOSVersion
osMaximumVersion = $PolicyData.MaxOSVersion
bitLockerEnabled = $true
secureBootEnabled = $true
antivirusRequired = $true
}
}
"iOS" {
$Policy = $BasePolicy + @{
"@odata.type" = "#microsoft.graph.iosCompliancePolicy"
osMinimumVersion = $PolicyData.MinOSVersion
osMaximumVersion = $PolicyData.MaxOSVersion
jailbrokenDevicesBlocked = $true
managedEmailProfileRequired = $true
}
}
"Android" {
$Policy = $BasePolicy + @{
"@odata.type" = "#microsoft.graph.androidCompliancePolicy"
osMinimumVersion = $PolicyData.MinOSVersion
osMaximumVersion = $PolicyData.MaxOSVersion
securityRequiredAndroidSafetyNetEvaluationType = "basicIntegrity"
securityBlockJailbrokenDevices = $true
}
}
}
return $Policy
}
# Process CSV file
$CSV = Import-Csv -Path ".\compliance-policies.csv"
$Results = @()
foreach ($Row in $CSV) {
try {
Write-Host "Creating policy: $($Row.PolicyName)" -ForegroundColor Yellow
$PolicyConfig = New-CompliancePolicyFromCSV -PolicyData $Row
$NewPolicy = New-MgDeviceManagementDeviceCompliancePolicy -BodyParameter $PolicyConfig
$Results += [PSCustomObject]@{
PolicyName = $Row.PolicyName
Platform = $Row.Platform
Status = "Success"
PolicyId = $NewPolicy.Id
Error = $null
}
Write-Host "✓ Successfully created: $($Row.PolicyName)" -ForegroundColor Green
} catch {
$Results += [PSCustomObject]@{
PolicyName = $Row.PolicyName
Platform = $Row.Platform
Status = "Failed"
PolicyId = $null
Error = $_.Exception.Message
}
Write-Warning "❌ Failed to create: $($Row.PolicyName) - $($_.Exception.Message)"
}
}
# Display results summary
$Results | Format-Table -AutoSize
Monitoring Compliance Status
Check device compliance status and generate reports:
# Get all compliance policies
$CompliancePolicies = Get-MgDeviceManagementDeviceCompliancePolicy
Write-Host "Found $($CompliancePolicies.Count) compliance policies" -ForegroundColor Green
# Get compliance summary for all devices
$ComplianceOverview = Get-MgDeviceManagementDeviceCompliancePolicyDeviceStateSummary
Write-Host "`nCompliance Overview:" -ForegroundColor Cyan
Write-Host "Compliant Devices: $($ComplianceOverview.CompliantDeviceCount)" -ForegroundColor Green
Write-Host "Non-Compliant Devices: $($ComplianceOverview.NonCompliantDeviceCount)" -ForegroundColor Red
Write-Host "Error Devices: $($ComplianceOverview.ErrorDeviceCount)" -ForegroundColor Yellow
Write-Host "Conflict Devices: $($ComplianceOverview.ConflictDeviceCount)" -ForegroundColor Magenta
# Get detailed compliance status per policy
foreach ($Policy in $CompliancePolicies) {
Write-Host "`nPolicy: $($Policy.DisplayName)" -ForegroundColor Yellow
# Get device compliance states for this policy
$DeviceStates = Get-MgDeviceManagementDeviceCompliancePolicyDeviceStatus -DeviceCompliancePolicyId $Policy.Id
$StatusSummary = $DeviceStates | Group-Object Status | ForEach-Object {
[PSCustomObject]@{
Status = $_.Name
Count = $_.Count
Percentage = "{0:P2}" -f ($_.Count / $DeviceStates.Count)
}
}
$StatusSummary | Format-Table -AutoSize
}
# Export non-compliant devices to CSV
$NonCompliantDevices = @()
foreach ($Policy in $CompliancePolicies) {
$PolicyDevices = Get-MgDeviceManagementDeviceCompliancePolicyDeviceStatus -DeviceCompliancePolicyId $Policy.Id
$PolicyNonCompliant = $PolicyDevices | Where-Object { $_.Status -eq "nonCompliant" } | ForEach-Object {
[PSCustomObject]@{
PolicyName = $Policy.DisplayName
DeviceName = $_.DeviceDisplayName
UserName = $_.UserName
Platform = $_.Platform
LastReportedDateTime = $_.LastReportedDateTime
ComplianceGracePeriodExpirationDateTime = $_.ComplianceGracePeriodExpirationDateTime
}
}
$NonCompliantDevices += $PolicyNonCompliant
}
# Export results
$NonCompliantDevices | Export-Csv -Path ".\NonCompliantDevices_$(Get-Date -Format 'yyyyMMdd_HHmmss').csv" -NoTypeInformation
Write-Host "✓ Non-compliant devices exported to CSV" -ForegroundColor Green
Updating Existing Policies
Modify existing compliance policies to update security requirements:
# Function to update compliance policy settings
function Update-CompliancePolicy {
param(
[Parameter(Mandatory)]
[string]$PolicyId,
[Parameter(Mandatory)]
[hashtable]$UpdatedSettings
)
try {
# Get current policy
$CurrentPolicy = Get-MgDeviceManagementDeviceCompliancePolicy -DeviceCompliancePolicyId $PolicyId
Write-Host "Updating policy: $($CurrentPolicy.DisplayName)" -ForegroundColor Yellow
# Update the policy
Update-MgDeviceManagementDeviceCompliancePolicy -DeviceCompliancePolicyId $PolicyId -BodyParameter $UpdatedSettings
Write-Host "✓ Successfully updated policy" -ForegroundColor Green
} catch {
Write-Error "❌ Failed to update policy: $($_.Exception.Message)"
}
}
# Example: Update password requirements for all Windows policies
$WindowsPolicies = Get-MgDeviceManagementDeviceCompliancePolicy | Where-Object { $_."@odata.type" -eq "#microsoft.graph.windows10CompliancePolicy" }
$NewPasswordSettings = @{
passwordMinimumLength = 10
passwordExpirationDays = 60
passwordPreviousPasswordBlockCount = 10
passwordRequiredType = "alphanumeric"
}
foreach ($Policy in $WindowsPolicies) {
Update-CompliancePolicy -PolicyId $Policy.Id -UpdatedSettings $NewPasswordSettings
Start-Sleep -Seconds 2 # Rate limiting
}
Best Practices & Security Considerations
- Always test compliance policies on a small group before broad deployment
- Use grace periods to allow users time to remediate compliance issues
- Regularly review and update minimum OS version requirements
- Monitor compliance reports and address non-compliant devices promptly
- Document policy changes and maintain an audit trail
- Consider using Conditional Access policies alongside compliance policies
- Implement device trust policies for enhanced security
- Regular backup of compliance policy configurations
Pro Tip
Use Intune's built-in compliance reports and Microsoft Graph APIs to create automated compliance monitoring dashboards and alerting systems for proactive device management.