Deploy a custom compliance policy in MEM
Did you know that Microsoft Endpoint Manager recently released a feature in preview to use custom compliance settings for Windows 10 and later devices? You may have noticed the Scripts pane in your MEM console – it’s for custom compliance!
There are two steps to deploying a custom compliance policy. First, we need a JSON file that defines what we are checking. Then we need a PowerShell script that checks what was defined in the JSON file.
Create a JSON file for Custom Compliance
According to the Microsoft Docs, our JSON for custom compliance needs the following information listed:
- SettingName
- Operator
- DataType
- Operand
- MoreInfoURL
- RemediationStrings
There’s a lot more detail on the Docs, included supported data types and languages, but the easiest way I’ve found to get started is by copying the example JSON file and editing it to fit our needs. I’ll start by doing just that and copying the JSON contents from the Docs page into Visual Studio Code:
For our test I think it’d be fun to check a device’s uptime. If a device hasn’t restarted for 30 days, for example, then we’ll mark it out of compliance and tell the user to reboot. (Note that in the real world, this isn’t super useful, because Windows Fast Startup doesn’t reset this number)
For our rule, we want the uptime to be less than 30 days, or else it will be out of compliance:
{ "Rules":[ { "SettingName":"Uptime", "Operator":"LessThan", "DataType":"Int64", "Operand":"30", "MoreInfoUrl":"https://deviceadvice.io", "RemediationStrings":[ { "Language":"en_US", "Title":"This device hasn't restarted in {ActualValue} days.", "Description": "Please reboot the device." } ] } ] }
Create the PowerShell script that checks for the JSON contents
Now that we know what the JSON is looking for, let’s make a simple script the corresponding contents. After some testing on the device to get PowerShell to return the uptime in days, I have:
$Time = Get-CIMInstance -Class CIM_OperatingSystem | Select-Object LastBootUpTime $Today = get-date $Difference = new-timespan -start $time.LastBootUpTime -end $Today $Days = [int64] $Difference.Days $hash = @{ Uptime = $Days; } return $hash | ConvertTo-Json -Compress
The script checks the last boot time reported in the OS, compares it against the current date, grabs the Days count from that comparison, casts the variable as an int64 (since that’s what the JSON is looking for), and then returns the content as a JSON value.
That last part I took from the sample also on the Microsoft Docs.
Create the custom compliance policy
Now that we have the JSON and PowerShell script, let’s create the custom policy. Start by uploading the script in Microsoft Endpoint Manager > Devices > Compliance policies > Scripts >+ Add
Provide a detailed name and description:
In the settings pane, paste the detection script into the window and edit the remaining settings. For our script we’ll want to run as system and in 64 bit PowerShell, so we will leave the options as default:
Then review and click create!
Now we need to actually create the custom compliance policy in Microsoft Endpoint Manager > Devices > Compliance policies > + Create policy
Provide a simple name and click next:
In compliance settings, change custom compliance to Require, and select the discovery script we just uploaded:
And then upload the matching JSON file:
And finally we’ll target to our test group and create the policy:
Beautiful! And now we need to wait for the device to report back, and we’ll see:
The device is compliant! I did notice that devices will appear as “not applicable” until you reboot them, which does somewhat invalidate the usefulness of this custom compliance script. But hey, that’s just an example use! Be on the lookout though – as this feature comes out of preview, it may require an additional license (as stated in the purple banner when configure it), which would result in devices maybe not being applicable.
Happy monitoring 🎯