Skip to content

Category: Device Managment

Auto Update Minimum OS Version in Compliance Policy

So, one of my customers requested that the compliance policy must be always up to date.
The minimum accepted OS version shouldn’t be older than the last ~4 patches, as compliance will be used for various Conditional Access policies.

Sounds simple enough? Well, not really as Intune doesn’t offer this option out of the box.
All you get is the possibility to define a static minimum version.

Azure Automation and Graph PowerShell to the rescue!

How will this work? Well, Azure Automation has the possibility to use a system assigned identity, this identity can be granted

So first things first, we deploy an Azure Automation Account in our subscription:

Automation Account in Marketplace

After filling in the basics, we can swap to the advanced tab, to enable the System assigned identity:

Create Automation Account
Click System assigned Identity

After we hit create, our Automation Account is deployed and we can open it, personally I prefer the new “Runtime Environment Experience”, therefore I will switch to it.

Try Runtime Environment Experience

Next step is to create our empty Workbook:

During the creation of the Runbook we will have, if you did option to the new experience, the option the create a Runtime Enviroment.

After giving the Runtime Enviroment a fitting name, we can now add PowerShell Modules to it.

I’ve added 3 Modules that we will need for our Compliance Policy Update script:
Microsoft.Graph.Authentication, Microsoft.Graph.DeviceManagement and PSParseHTML.

Now it’s time to create the Runbook and edit it.

The script will download the latest Version Information from the Microsoft Learn site and update the compliance policy with the specified version.

You’ll need the id of your compliance policy and you need to specify how many versions back will be compliant.

$compliancePolicyId = "60bf37e1-fcc4-418a-b8d2-afee15592426"
$oldVersions = 4

Function Get-LatestWinBuild {
    param (
        [string]$latestUri = "https://learn.microsoft.com/en-us/windows/release-health/windows11-release-information",
        [string]$tableId = "historyTable_0",
        [int]$buildIndex,
        [int]$winVersion
    )
    if ($winVersion -eq 10) {
        $latestUri = "https://learn.microsoft.com/en-us/windows/release-health/release-information"
    }
    $output = ConvertFrom-HTMLTag -Id $tableId -Url $latestUri -ReturnObject
    $output = ConvertFrom-HtmlTable -Content $output.OuterHtml

    return [string] "10.0.$($output.Build[$buildIndex])"

}

$winBuild = Get-LatestWinBuild -buildIndex $oldVersions

if ($winBuild){
    Write-Output "Latest found build: $winBuild"
} else {
    Write-Output "Error fetching build number."
}

Connect-MgGraph -Identity -NoWelcome

if ($winBuild -match "\d\d.\d.\d\d\d\d\d.\d\d\d\d") {
    $params = @{
        "@odata.type"    = "#microsoft.graph.windows10CompliancePolicy"
        osMinimumVersion = $winBuild
    }
    Write-Output "Updating compliance policy: $compliancePolicyId setting osMinimumVersion to $winBuild"
    Update-MgDeviceManagementDeviceCompliancePolicy -DeviceCompliancePolicyId $compliancePolicyId -BodyParameter $params
}
else {
    #trigger some alert, because version number seems invalid.
    Write-Output "Error."
}
PowerShell

After saving the Runbook, we can specify a Job trigger.

I opted for a Weekly update.

We’re not done yet tho!
As last step, we need to grant the System Assigned Identity the permission to use Microsoft Graph.

We’re doing this via Powershell, for this we’ll need our Tenant id, the id of the System Assigned identity, the GraphAddId and the name of the Automation Account.

$TenantID="YOUR TENANT"
$GraphAppId = "00000003-0000-0000-c000-000000000000"
$DisplayNameOfMSI="YOUR AUTOMATION ACCOUNT"

$PermissionName = @("DeviceManagementConfiguration.ReadWrite.All",
"DeviceManagementConfiguration.Read.All") 

Connect-AzureAD -TenantId $TenantID

$MSI = (Get-AzureADServicePrincipal -Filter "displayName eq '$DisplayNameOfMSI'")
Start-Sleep -Seconds 10
$GraphServicePrincipal = Get-AzureADServicePrincipal -Filter "appId eq '$GraphAppId'"

foreach ($permission in $PermissionName){

    $AppRole = $GraphServicePrincipal.AppRoles | Where-Object {$_.Value -eq $permission -and $_.AllowedMemberTypes -contains "Application"}
    New-AzureAdServiceAppRoleAssignment -ObjectId $MSI.ObjectId -PrincipalId $MSI.ObjectId -ResourceId $GraphServicePrincipal.ObjectId -Id $AppRole.Id
}
PowerShell

Now you can start your first Test Run!

Leave a Comment