Creating Intune Proactive Remediation via Powershell

Proactive Remediations are one of my favourite features within Intune, but I’m a fan of automation so I thought I’d do some digging in MS Graph to see how much I can automate.

Before I start, if you haven’t installed it yet, go and get the Graph X-Ray extension for Edge/Chrome from here. It will show you exactly what’s happening behind the scenes when working in Intune.

Now, onto the script. For this example I’m doing a simple reg key, but you’ll be able to see the powershell code itself is inline so it can accept anything.

As usual, you can download a copy from github here

First, let’s set some variables

$DisplayName = "Remediate Fastboot Automated"
$Description = "This was created via PowerShell!"
$Publisher = "Andrew Taylor"
##RunAs can be "system" or "user"
$RunAs = "system"
##True for 32-bit, false for 64-bit
$RunAs32 = $true
##Daily or Hourly
$ScheduleType = "Daily"
##How Often
$ScheduleFrequency = "1"
##Start Time (if daily)
$StartTime = "01:00"
$AADGroupName = "Intune-Users"

The Start Time is only required if the schedule is set to Daily

Now we need to set the detection script

$detect = @'
$Path = "HKLM:\SYSTEM\CurrentControlSet\Control\Session Manager\Power"
$Name = "HiberbootEnabled"
$Type = "DWORD"
$Value = 0

Try {
    $Registry = Get-ItemProperty -Path $Path -Name $Name -ErrorAction Stop | Select-Object -ExpandProperty $Name
    If ($Registry -eq $Value){
        Write-Output "Compliant"
        Exit 0
    } 
    Write-Warning "Not Compliant"
    Exit 1
} 
Catch {
    Write-Warning "Not Compliant"
    Exit 1
}
'@

It can be anything you would normally write in PowerShell

Then we need the remediation script

$remediate = @"
New-ItemProperty -LiteralPath 'HKLM:\SYSTEM\CurrentControlSet\Control\Session Manager\Power' -Name 'HiberbootEnabled' -Value 0 -PropertyType DWord -Force -ea SilentlyContinue;
"@

The script needs the Microsoft.Graph.Intune and AzureAD modules, I won’t list the code here, but feel free to grab it from the script, it’s a simple install if not detected and then import.

Once we have connected to both, we can start the building

The all important JSON to build the thing

$params = @{
         DisplayName = $DisplayName
         Description = $Description
         Publisher = $Publisher
         RunAs32Bit = $RunAs32
         RunAsAccount = $RunAs
         EnforceSignatureCheck = $false
         DetectionScriptContent = [System.Text.Encoding]::ASCII.GetBytes($detect)
         RemediationScriptContent = [System.Text.Encoding]::ASCII.GetBytes($remediate)
         RoleScopeTagIds = @(
                 "0"
         )
}

As you can see, we are converting the PS Code to ASCII to get it uploaded. If you use Scope tags, you can edit them here

To deploy it:

$graphApiVersion = "beta"
$Resource = "deviceManagement/deviceHealthScripts"
$uri = "https://graph.microsoft.com/$graphApiVersion/$Resource"

try {
    $proactive = Invoke-MSGraphRequest -Url $uri -HttpMethod Post -Content $params
}
catch {
    Write-Error $_.Exception 
    
}

Proactive Remediations all use the “DeviceHealthScripts” within Graph

Now, we need to assign it, it’s similar to any other policy, but this one has a schedule attached.

Quickly grab the group ObjectID:

$AADGroupID = (get-azureadgroup | where-object DisplayName -eq $AADGroupName).ObjectID

For Daily:

    $params = @{
        DeviceHealthScriptAssignments = @(
            @{
                Target = @{
                    "@odata.type" = "#microsoft.graph.groupAssignmentTarget"
                    GroupId = $AADGroupID
                }
                RunRemediationScript = $true
                RunSchedule = @{
                    "@odata.type" = "#microsoft.graph.deviceHealthScriptDailySchedule"
                    Interval = $scheduleFrequency
                    Time = $StartTime
                    UseUtc = $false
                }
            }
        )
    }

Or hourly:

$params = @{
	DeviceHealthScriptAssignments = @(
		@{
			Target = @{
				"@odata.type" = "#microsoft.graph.groupAssignmentTarget"
				GroupId = $AADGroupID
			}
			RunRemediationScript = $true
			RunSchedule = @{
				"@odata.type" = "#microsoft.graph.deviceHealthScriptHourlySchedule"
				Interval = $scheduleFrequency
			}
		}
	)
}

Finally grab the ID of the remediation and assign it to the AAD Group

$remediationID = $proactive.ID


$graphApiVersion = "beta"
$Resource = "deviceManagement/deviceHealthScripts"
$uri = "https://graph.microsoft.com/$graphApiVersion/$Resource/$remediationID/assign"

try {
    $proactive = Invoke-MSGraphRequest -Url $uri -HttpMethod Post -Content $params
}
catch {
    Write-Error $_.Exception 
    
}

Using this you could easily deploy multiple remediations across tenants without having to log into the GUI on each

Posted in Intune