Src/Private/Get-AbrIntuneFailedAssignments.ps1
|
function Get-AbrIntuneFailedAssignments { <# .SYNOPSIS Documents Intune policies with failed device-level deployment status. .DESCRIPTION Collects and reports on: - Compliance policies with devices in Error or Failed state - Configuration profiles with Error deployment state - Summary table of policy name, platform, failed count, error count .NOTES Version: 0.1.0 Author: Pai Wei Sing #> [CmdletBinding()] param ( [Parameter(Position = 0, Mandatory)] [string]$TenantId ) begin { Write-PScriboMessage -Message "Collecting Intune Failed Assignments for $TenantId." Show-AbrDebugExecutionTime -Start -TitleMessage 'Failed Assignments' } process { Section -Style Heading2 'Failed Assignments' { Paragraph "The following section documents Intune policies with deployment failures at the device level for tenant $TenantId." BlankLine $failedObj = [System.Collections.ArrayList]::new() $foundAny = $false #region Compliance Policy Device Statuses try { Write-Host " - Retrieving compliance policy device statuses..." $CompPoliciesResp = Invoke-MgGraphRequest -Method GET ` -Uri "$($script:GraphEndpoint)/v1.0/deviceManagement/deviceCompliancePolicies?`$select=id,displayName" ` -ErrorAction SilentlyContinue $CompPolicies = $CompPoliciesResp.value if ($CompPolicies) { foreach ($Policy in $CompPolicies) { try { $StatusResp = Invoke-MgGraphRequest -Method GET ` -Uri "$($script:GraphEndpoint)/v1.0/deviceManagement/deviceCompliancePolicies/$($Policy.id)/deviceStatusOverview" ` -ErrorAction SilentlyContinue if ($StatusResp -and ($StatusResp.errorCount -gt 0 -or $StatusResp.failedCount -gt 0)) { $foundAny = $true $failInObj = [ordered] @{ 'Policy Name' = $Policy.displayName 'Policy Type' = 'Compliance Policy' 'Failed Devices' = $StatusResp.failedCount 'Error Devices' = $StatusResp.errorCount 'Success Devices'= $StatusResp.succeededCount 'Pending Devices'= $StatusResp.pendingCount 'Not Applicable' = $StatusResp.notApplicableCount } $null = $failedObj.Add([pscustomobject]$failInObj) } } catch { } } } } catch { if (Test-AbrGraphForbidden -ErrorRecord $_) { Write-AbrPermissionError -Section 'Compliance Policy Statuses' -RequiredRole 'Intune Service Administrator or Global Administrator' } else { Write-AbrSectionError -Section 'Compliance Policy Statuses' -Message "$($_.Exception.Message)" } } #endregion #region Configuration Profile Device Statuses try { Write-Host " - Retrieving configuration profile device statuses..." $ConfigPoliciesResp = Invoke-MgGraphRequest -Method GET ` -Uri "$($script:GraphEndpoint)/v1.0/deviceManagement/deviceConfigurations?`$select=id,displayName" ` -ErrorAction SilentlyContinue $ConfigPolicies = $ConfigPoliciesResp.value if ($ConfigPolicies) { foreach ($Policy in $ConfigPolicies) { try { $StatusResp = Invoke-MgGraphRequest -Method GET ` -Uri "$($script:GraphEndpoint)/v1.0/deviceManagement/deviceConfigurations/$($Policy.id)/deviceStatusOverview" ` -ErrorAction SilentlyContinue if ($StatusResp -and ($StatusResp.errorCount -gt 0 -or $StatusResp.failedCount -gt 0)) { $foundAny = $true $failInObj = [ordered] @{ 'Policy Name' = $Policy.displayName 'Policy Type' = 'Configuration Profile' 'Failed Devices' = $StatusResp.failedCount 'Error Devices' = $StatusResp.errorCount 'Success Devices'= $StatusResp.succeededCount 'Pending Devices'= $StatusResp.pendingCount 'Not Applicable' = $StatusResp.notApplicableCount } $null = $failedObj.Add([pscustomobject]$failInObj) } } catch { } } } } catch { if (Test-AbrGraphForbidden -ErrorRecord $_) { Write-AbrPermissionError -Section 'Configuration Profile Statuses' -RequiredRole 'Intune Service Administrator or Global Administrator' } else { Write-AbrSectionError -Section 'Configuration Profile Statuses' -Message "$($_.Exception.Message)" } } #endregion if ($foundAny -and $failedObj.Count -gt 0) { # Sort by most failed first $failedObj = [System.Collections.ArrayList]($failedObj | Sort-Object { [int]$_.'Failed Devices' + [int]$_.'Error Devices' } -Descending) $null = (& { if ($HealthCheck.Intune.FailedAssignments) { $null = ($failedObj | Where-Object { [int]$_.'Failed Devices' -gt 0 } | Set-Style -Style Critical | Out-Null) $null = ($failedObj | Where-Object { [int]$_.'Error Devices' -gt 0 -and [int]$_.'Failed Devices' -eq 0 } | Set-Style -Style Warning | Out-Null) } }) $FailTableParams = @{ Name = "Failed Policy Deployments - $TenantId"; ColumnWidths = 28, 20, 11, 11, 11, 11, 8 } if ($Report.ShowTableCaptions) { $FailTableParams['Caption'] = "- $($FailTableParams.Name)" } $failedObj | Table @FailTableParams if (Get-IntuneExcelSheetEnabled -SheetKey 'FailedAssignments') { $script:ExcelSheets['Failed Assignments'] = $failedObj } BlankLine Paragraph "Total policies with deployment failures: $($failedObj.Count). Review affected devices in the Intune portal under Devices > Monitor." } else { Paragraph "No policy deployment failures detected in tenant $TenantId." } } } end { Show-AbrDebugExecutionTime -End -TitleMessage 'Failed Assignments' } } |