Microsoft Intune provides a robust set of built-in compliance settings, allowing administrators to verify operating system versions, encryption status, and firewall configurations. However, many enterprise environments require highly specific compliance checks that are not natively supported by the Intune UIāsuch as verifying the presence of a proprietary internal application, checking specific registry keys, or ensuring a custom security agent is running.
To bridge this gap, Microsoft Intune supports Custom Compliance Scripts. This feature allows administrators to execute a PowerShell script on Windows 10/11 endpoints to evaluate complex local conditions and report the findings back to the Intune compliance engine in a structured JSON format.
This guide demonstrates how to architect, write, and deploy a custom PowerShell compliance script to enforce advanced device posture requirements in Microsoft Intune.
The Architecture of Custom Compliance
A custom compliance policy consists of two distinct components:
- The PowerShell Script (.ps1): Executed locally on the Windows endpoint by the Microsoft Intune Management Extension (IME). The script evaluates the device state and must return its findings as a compressed JSON string.
- The JSON Discovery File: Uploaded to the Intune portal, this file defines the expected rules and values that the PowerShell script’s output will be evaluated against.
If the JSON output from the PowerShell script matches the requirements defined in the JSON Discovery File, the device is marked as Compliant. If it fails, or the script encounters an error, the device is marked as Noncompliant, which can trigger Conditional Access blocks.
Step 1: Writing the PowerShell Compliance Script
The PowerShell script must perform the check and output a specific JSON structure. For this tutorial, we will write a script that verifies whether a critical registry key (indicating that a bespoke security agent is installed and active) exists and is set to 1.
Create a file named Check-SecurityAgent.ps1:
# Define the registry path and value we are checking
$RegPath = "HKLM:\Software\InternalCorp\SecurityAgent"
$RegValueName = "IsActive"
# Initialise the default hash table for the result
$hash = @{
"SecurityAgentActive" = "False"
}
try {
# Check if the registry key exists
if (Test-Path $RegPath) {
$RegValue = Get-ItemProperty -Path $RegPath -Name $RegValueName -ErrorAction SilentlyContinue
# If the value is 1, the agent is active
if ($RegValue.$RegValueName -eq 1) {
$hash."SecurityAgentActive" = "True"
}
}
}
catch {
# If an error occurs, default to False
$hash."SecurityAgentActive" = "False"
}
# The script MUST output the result as a compressed, single-line JSON object
return $hash | ConvertTo-Json -Compress
It is critical that the script uses ConvertTo-Json -Compress and returns the object via the standard output pipeline. The Intune Management Extension will capture this string.
Step 2: Creating the JSON Discovery File
Next, we must create the JSON ruleset that tells Intune how to interpret the script’s output. The SettingName in this JSON file must exactly match the key defined in your PowerShell hash table (SecurityAgentActive).
Create a file named SecurityAgentRules.json:
{
"Rules": [
{
"SettingName": "SecurityAgentActive",
"Operator": "IsEquals",
"DataType": "String",
"Operand": "True",
"MoreInfoUrl": "https://intranet.internalcorp.com/it/security-agent-help",
"RemediationStrings": [
{
"Language": "en_US",
"Title": "Security Agent is missing or inactive.",
"Description": "Please ensure the Corporate Security Agent is installed and running. Contact the IT Helpdesk for assistance."
}
]
}
]
}
This file dictates that if the script returns anything other than "SecurityAgentActive": "True", the device will fail compliance.
Step 3: Uploading the PowerShell Script to Intune
Before creating the compliance policy, the PowerShell script must be uploaded to the Intune portal.
- Navigate to the Microsoft Intune admin center.
- Go to Devices > Compliance policies > Scripts.
- Click Add and select Windows 10 and later.
- Name the script Check-SecurityAgent.
- Upload the
Check-SecurityAgent.ps1file. - Leave Run this script using the logged on credentials set to No. (The script requires SYSTEM context to read HKLM registry keys).
- Set Enforce script signature check to No (unless you have digitally signed the script).
- Click Create.
Step 4: Creating the Custom Compliance Policy
Now you can bind the script and the JSON ruleset together in a compliance policy.
- Navigate to Devices > Compliance policies > Policies.
- Click Create policy.
- Select Windows 10 and later as the platform.
- Name the policy Require Internal Security Agent.
- In the Compliance settings tab, expand the Custom Compliance section.
- Toggle Require custom compliance to Require.
- Select your discovery script: Choose the Check-SecurityAgent script you uploaded in Step 3.
- Upload and validate the JSON file with your custom compliance settings: Upload the
SecurityAgentRules.jsonfile. - Proceed through the remaining tabs, assign the policy to your pilot user group, and click Create.
Conclusion
By leveraging Custom Compliance Scripts in Microsoft Intune, administrators are no longer constrained by out-of-the-box configuration options. Whether you need to enforce complex registry configurations, verify running services, or integrate bespoke application checks, PowerShell and JSON discovery files provide the flexibility required to enforce true Zero Trust conditional access based on highly customized endpoint telemetry.