Managing Intune Device Compliance Policies with PowerShell

Learn how to create, manage, and monitor device compliance policies in Microsoft Intune using PowerShell and Microsoft Graph API.

8 min read
Microsoft Intune
October 2025

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

Installing Required Modules

First, install the Microsoft Graph PowerShell SDK:

PowerShell
# 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:

PowerShell
# 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:

PowerShell
# 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:

PowerShell
# 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:

CSV
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
PowerShell
# 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:

PowerShell
# 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:

PowerShell
# 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

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.

Back to Intune Posts View All Posts