One of our customers wanted to be sure that there were no additional accounts in the local Administrators group on their Intune devices, and… That’s where Custom Compliance policies come in 🙂 In this blog post, I will show you how to automatically check the Administrators group and mark the device as non-compliant if needed.
How the script works
On an Intune device, you will always find three standard members of the Administrators group, the default local Administrator account, the Global Admin, and the Azure AD Joined Device Local Administrator role. If there are more members present, then there might be a security issue on that device.
The script reads all the members, excludes the three standard ones, and if there are more… Then it will return that to the Custom Compliance policy, and the device will be marked as Non-Compliant. When the device is Non-Compliant, the Conditional Access Rules will stop it from using all services in your tenant until remediated.
Note: For this to work, you need a Microsoft 365 E3/E5 license
How to add this to Intune?
To add this solution to Intune, you can follow the steps in the chapters below.
Customizing the script for your tenant
You will first need to find the IDs for the Global Admin and Azure AD Joined Device Local Administrator roles, and I used this blog post for that: https://oliverkieselbach.com/2020/05/13/powershell-helpers-to-convert-azure-ad-object-ids-and-sids/. You first retrieve all the roles, get the ObjectID and convert that to a sid. Below is my example (In which I changed the SIDs 😉 )
#Retrieve all members of local Administrator group using ADSI $admins = { ([ADSI]"WinNT://./Administrators").psbase.Invoke('Members') | ForEach-Object { ([ADSI]$_).InvokeGet('AdsPath') } }.Invoke() #Remove all defaults accounts and groups from the $admins variable #Use https://oliverkieselbach.com/2020/05/13/powershell-helpers-to-convert-azure-ad-object-ids-and-sids/ to get the corresponding Role/Group $defaultAdmins = ` "WinNT://$($env:COMPUTERNAME)/Administrator", # Default local administrator ` "WinNT://S-1-12-1-1234567890-1234567890-1234567890-1234567890", # Global Administrator Role ` "WinNT://S-1-12-1-0987654321-0987654321-0987654321-0987654321" # Azure AD Joined Device Local Administrator Role foreach ($defaultAdmin in $defaultAdmins) { $admins.Remove($defaultAdmin) } $hash = @{ numberOfExtraAdmins = $admins.count } return $hash | ConvertTo-Json -Compress
Create a JSON file for the Custom Compliance Policy
The script will gather the results and return a JSON-formatted output. The Custom Compliance Script needs a JSON to compare those results and take action if the check fails. Create an admins.json text file, insert the lines below, and save it afterward. (You can customize the Title and Description to your liking)
More information about formatting the JSON file is here.
{ "Rules": [ { "SettingName": "numberOfExtraAdmins", "Operator": "IsEquals", "DataType": "Int64", "Operand": "0", "MoreInfoUrl": "https://powershellisfun.com", "RemediationStrings": [ { "Language": "en_US", "Title": "Additional admins found!", "Description": "There are too many members of the Administrators on this system. Please get in touch with IT Support. The device is now marked as non-compliant." } ] } ] }
Adding the script to Intune
Once the script is adjusted to your tenant, then you can follow these steps to upload it into Intune:
- Go to Compliance policies – Microsoft Intune admin center
- Select Add, and select Windows 10 and later
- Enter a Name (Local Administrators check, for example) and choose Next
- Insert the script’s contents in the Detection Script pane and choose Next.
- Review the values and choose Create.
You should now return to the Compliance Policies/Scripts pane and see the script is listed.

Creating a Custom Compliance Script
Now that the script is available in Intune, the Custom Compliance Script can be created. Follow these steps to create one:
- Go to Compliance policies – Microsoft Intune admin center
- Select Create Policy
- Select Windows 10 and later as Platform and select Create
- Enter a Name (Local Administrator Compliance, for example) and choose Next
- Expand Custom Compliance and select Require
- Select Click to select, select the Local Administrators check from the list, and click Select.
- Click on Select a file, browse, and open the admins.json file you saved earlier. When uploaded, it will check the format and display an error if it’s not correctly formatted.
- Click Next
- Select the noncompliance actions you want, Mark device noncompliant is mandatory in this case, but you can email the end user if you have created a template for that here.
- Click Next and assign the correct device group for this Custom Compliance Script.
- Click Next
- Review the settings and select Create.
Note: The script will run every 8 hours after it runs the first time and will also check for updated versions every 8 hours.
Results on a non-compliant Intune Device
After assigning the script (And waiting for about 15 minutes), this is how it will look when a device is not compliant:
Logs
In c:\ProgramData\Microsoft\IntuneManagementExtension\Logs you can view the AgentExecutor.log or IntuneManagementExtension.log file and search for the “HealthSchript” keyword. Somewhere near those lines, you should see:
]LOG]!><time="19:44:39.6940524" date="4-18-2023" component="AgentExecutor" context="" type="1" thread="1" file=""> <![LOG[Powershell script is successfully executed.]LOG]!><time="19:44:39.6940524" date="4-18-2023" component="AgentExecutor" context="" type="1" thread="1" file=""> <![LOG[write output done. output = True False False {"numberOfExtraAdmins":2}
or
<![LOG[[HS] err output = ]LOG]!><time="19:44:44.7258239" date="4-18-2023" component="IntuneManagementExtension" context="" type="1" thread="38" file=""> <![LOG[[HS] std output = {"numberOfExtraAdmins":2}]LOG]!><time="19:44:44.7258239" date="4-18-2023" component="IntuneManagementExtension" context="" type="1" thread="38" file=""> <![LOG[[HS] PreDetectScript parsing result is done ]LOG]!><time="19:44:44.7258239" date="4-18-2023" component="IntuneManagementExtension" context="" type="1" thread="38" file="">
Company Portal
The Company Portal will show an event like this:

(Clicking on the “How to resolve this” link will redirect your browser to the address specified in the JSON file, in my case https://powershellisfun.com 😉 )
Results on a compliant Intune Device
Logs
In c:\ProgramData\Microsoft\IntuneManagementExtension\Logs you can view the AgentExecutor.log or IntuneManagementExtension.log file and search for the “HealthSchript” keyword. Somewhere near those lines, you should see:
<![LOG[Powershell script is successfully executed.]LOG]!><time="20:37:52.2049168" date="4-18-2023" component="AgentExecutor" context="" type="1" thread="1" file=""> <![LOG[write output done. output = True True True {"numberOfExtraAdmins":0}
or
<![LOG[[HS] std output = {"numberOfExtraAdmins":0}]LOG]!><time="20:37:57.2299454" date="4-18-2023" component="IntuneManagementExtension" context="" type="1" thread="43" file=""> <![LOG[[HS] PreDetectScript parsing result is done ]LOG]!><time="20:37:57.2299454" date="4-18-2023" component="IntuneManagementExtension" context="" type="1" thread="43" file=""> <![LOG[[HS] Returned exitcode from child process is 0]LOG]!><time="20:37:57.2299454" date="4-18-2023" component="IntuneManagementExtension" context="" type="1" thread="43" file="">
Company Portal
When opening the Company Portal, the device status will look like this:

Pingback: Intune Newsletter - 23rd April 2023 - Andrew Taylor