Remediation/Intune/INT-NONCOMPLIANT.ps1
|
# UNTESTED: this script has never been run on a real tenant. Read it, try it on a test tenant first, and use it at your own risk. <# .SYNOPSIS Groups the noncompliant devices of the target and their causes (procedure INT-NONCOMPLIANT). .DESCRIPTION Preview: report of the noncompliant devices from the snapshot, setting apart those that are inactive (procedure INT-STALE). -Apply run, read only: the script reads through Graph the settings at fault in the whole tenant, then, for each setting, the devices affected. It fixes nothing: the fix depends on each cause and on the device owner. The moment to enforce compliance stays to set with the customer. #> $c = Open-TcRemediation $Threshold = [int](Get-TcRemediationOption 'StaleDeviceDays') foreach ($t in $c.Tenants) { Write-TcRemediationTenant $t $devices = @(Get-TcRemediationTable $t 'managedDevices') if (-not $devices.Count -and -not (Test-TcCollectionComplete $t 'managedDevices')) { Write-TcRemediationAlert 'Device collection incomplete: run Invoke-TcAssessment again.'; continue } $noncompliant = @($devices | Where-Object { $_['Compliance'] -eq 'noncompliant' }) $inactive = @($noncompliant | Where-Object { [int]$_['Days inactive'] -ge $Threshold }) $bySystem = @($noncompliant | Group-Object { $_['OS'] } | ForEach-Object { '{0}: {1}' -f (Get-TcMember $_ 'Name'), (Get-TcCount $_) }) Write-TcRemediationNote ("{0} noncompliant device(s) out of {1} ({2}), {3} inactive to handle with INT-STALE" -f $noncompliant.Count, $devices.Count, ($bySystem -join ', '), $inactive.Count) Export-TcRemediationReport -Name "noncompliant-$t" -Rows @($noncompliant | ForEach-Object { [ordered]@{ Device = $_['Name']; OS = $_['OS']; Version = $_['Version']; User = $_['User']; 'Last sync' = $_['Last sync']; 'Days inactive' = $_['Days inactive']; 'Encrypted' = $_['Encrypted']; Inactive = $(if ([int]$_['Days inactive'] -ge $Threshold) { 'Yes' } else { 'No' }) } }) | Out-Null Add-TcBlockAction -Tenant $t -Service Graph -Object 'Noncompliance causes' -Description 'Read the settings at fault and the devices affected' -Reason 'Read only.' -Data @{ Tenant = $t } ` -Block { param($a) $rootPath = 'v1.0/deviceManagement/deviceCompliancePolicySettingStateSummaries' $summaries = @(Invoke-TcGraph -Tenant $a.tenant -Uri $rootPath -All | Where-Object { [int](Get-TcMember $_ 'nonCompliantDeviceCount') + [int](Get-TcMember $_ 'errorDeviceCount') -gt 0 }) Export-TcRemediationReport -Name "causes-by-setting-$($a.tenant)" -Rows @($summaries | Sort-Object { [int](Get-TcMember $_ 'nonCompliantDeviceCount') } -Descending | ForEach-Object { [ordered]@{ 'Setting' = (Get-TcMember $_ 'settingName'); Platform = (Get-TcMember $_ 'platformType'); 'Noncompliant' = (Get-TcMember $_ 'nonCompliantDeviceCount'); 'In error' = (Get-TcMember $_ 'errorDeviceCount'); Compliant = (Get-TcMember $_ 'compliantDeviceCount') } }) | Out-Null $rows = [System.Collections.Generic.List[object]]::new() foreach ($r in $summaries) { foreach ($s in @(Invoke-TcGraph -Tenant $a.tenant -Uri "$rootPath/$((Get-TcMember $r 'id'))/deviceComplianceSettingStates" -All | Where-Object { (Get-TcMember $_ 'state') -in 'nonCompliant', 'error' })) { $rows.Add([ordered]@{ Device = (Get-TcMember $s 'deviceName'); User = (Get-TcMember $s 'userPrincipalName'); 'Setting' = (Get-TcMember $r 'settingName'); 'State' = (Get-TcMember $s 'state') }) } } Export-TcRemediationReport -Name "causes-by-device-$($a.tenant)" -Rows @($rows) | Out-Null } } Invoke-TcRemediationPlan Close-TcRemediation |