Private/Graph/Get-IntunePolicyList.ps1
|
# Copyright (c) 2026 Sandy Zeng. All rights reserved. # Source-available. All rights reserved. See LICENSE file. <# Get-IntunePolicyList.ps1 — Fetches all Intune Settings Catalog and Security Baseline policies for the tenant. Author: Sandy Zeng Project: IntuneDiff Version History: 1.0.0 Initial release. #> function Get-IntunePolicyList { <# .SYNOPSIS Returns all Intune Settings Catalog and Security Baseline policies for the signed-in tenant. .DESCRIPTION Uses Graph JSON Batching to fetch Settings Catalog policies, Security Baseline templates, and Windows Hello intents in a single batch request for faster loading. #> [CmdletBinding()] param() $results = New-Object System.Collections.Generic.List[object] # Policy IDs known to cause persistent 504 errors - skip them $skipPolicyIdPrefixes = @( 'c64bf257-bce5-4c4d-8ad8-03222f13d84c' ) # Baseline template names that always fail to load settings $skipBaselineNames = @( 'Microsoft Windows 11 Security Technical Implementation Guide' ) # Build batch requests for all 3 policy sources $catalogFilter = "(platforms eq 'windows10') and (technologies has 'mdm' or technologies has 'windows10XManagement') and (templateReference/templateFamily le 'baseline' or templateReference/templateFamily eq 'deviceConfigurationPolicies')" $catalogSelect = 'id,name,description,platforms,technologies,templateReference,settingCount,createdDateTime,lastModifiedDateTime,isAssigned' $whfbTemplateId = '0f2b5d70-d4e9-4156-8c16-1397eb6c54a5' $baselineFilter = "(lifecycleState eq 'draft' or lifecycleState eq 'active') and (templateFamily eq 'Baseline')" $batchRequests = @( @{ id = 'catalog' method = 'GET' url = "/deviceManagement/configurationPolicies?`$top=100&`$filter=$catalogFilter&`$select=$catalogSelect" }, @{ id = 'baselines' method = 'GET' url = "/deviceManagement/configurationPolicyTemplates?`$top=500&`$filter=$baselineFilter" }, @{ id = 'intents' method = 'GET' url = "/deviceManagement/intents?`$filter=templateId eq '$whfbTemplateId'" } ) $batchResponses = Invoke-GraphBatchRequest -Requests $batchRequests # Process Settings Catalog response $catalogResp = $batchResponses['catalog'] if ($catalogResp -and $catalogResp.value) { # Handle pagination for catalog (if > 100 policies) $catalogValues = @($catalogResp.value) $nextLink = $catalogResp.'@odata.nextLink' while ($nextLink) { if ($nextLink -notmatch '^https://graph\.microsoft\.com/') { break } $pageResp = Invoke-IntuneDiffRequest -Method GET -Uri $nextLink if ($pageResp.value) { $catalogValues += $pageResp.value } $nextLink = $pageResp.'@odata.nextLink' } foreach ($p in $catalogValues) { $type = 'Settings Catalog' $typeKey = 'settingsCatalog' $templateFamily = $null if ($p.templateReference -and $p.templateReference.templateFamily) { $templateFamily = [string]$p.templateReference.templateFamily $lf = $templateFamily.ToLowerInvariant() if ($lf -eq 'baseline') { $type = 'Security Baseline Policy' $typeKey = 'customSecurityBaseline' } elseif ($lf -like '*endpointsecurity*') { $type = 'Endpoint Security' $typeKey = 'endpointSecurity' } } $results.Add([pscustomobject]@{ Id = $p.id Name = $p.name Description = $p.description Type = $type TypeKey = $typeKey SettingCount = $p.settingCount IsAssigned = [bool]$p.isAssigned Platforms = $p.platforms }) } } else { # Fallback: fetch catalog sequentially if batch failed try { $catalogUri = "/beta/deviceManagement/configurationPolicies?`$top=100&`$filter=$catalogFilter&`$select=$catalogSelect" $catalogResponse = Invoke-IntuneDiffRequest -Method GET -Uri $catalogUri -All foreach ($p in $catalogResponse.value) { $type = 'Settings Catalog' $typeKey = 'settingsCatalog' if ($p.templateReference -and $p.templateReference.templateFamily) { $lf = ([string]$p.templateReference.templateFamily).ToLowerInvariant() if ($lf -eq 'baseline') { $type = 'Security Baseline Policy'; $typeKey = 'customSecurityBaseline' } elseif ($lf -like '*endpointsecurity*') { $type = 'Endpoint Security'; $typeKey = 'endpointSecurity' } } $results.Add([pscustomobject]@{ Id = $p.id; Name = $p.name; Description = $p.description; Type = $type; TypeKey = $typeKey SettingCount = $p.settingCount; IsAssigned = [bool]$p.isAssigned; Platforms = $p.platforms }) } } catch { Write-Verbose "Failed catalog fetch: $($_.Exception.Message)" } } # Process Security Baseline templates response $baselineResp = $batchResponses['baselines'] if ($baselineResp -and $baselineResp.value) { foreach ($b in $baselineResp.value) { if ($skipPolicyIdPrefixes | Where-Object { $b.id -like "$_*" }) { continue } $displayName = $b.displayName if (-not $displayName) { $displayName = $b.name } if (-not $displayName) { $displayName = 'Unknown Baseline' } if ($skipBaselineNames | Where-Object { $displayName -like "$_*" }) { continue } if ($b.displayVersion -and ($displayName -notlike "*$($b.displayVersion)*")) { $displayName = "$displayName (Version $($b.displayVersion))" } $results.Add([pscustomobject]@{ Id = $b.id Name = $displayName Description = $b.description Type = 'Security Baseline Template' TypeKey = 'securityBaseline' SettingCount = $null IsAssigned = $false Platforms = $b.platforms }) } } else { # Fallback try { $baselineUri = "/beta/deviceManagement/configurationPolicyTemplates?`$top=500&`$filter=$baselineFilter" $baselineResponse = Invoke-IntuneDiffRequest -Method GET -Uri $baselineUri -All foreach ($b in $baselineResponse.value) { if ($skipPolicyIdPrefixes | Where-Object { $b.id -like "$_*" }) { continue } $displayName = if ($b.displayName) { $b.displayName } elseif ($b.name) { $b.name } else { 'Unknown Baseline' } if ($skipBaselineNames | Where-Object { $displayName -like "$_*" }) { continue } if ($b.displayVersion -and ($displayName -notlike "*$($b.displayVersion)*")) { $displayName = "$displayName (Version $($b.displayVersion))" } $results.Add([pscustomobject]@{ Id = $b.id; Name = $displayName; Description = $b.description; Type = 'Security Baseline Template' TypeKey = 'securityBaseline'; SettingCount = $null; IsAssigned = $false; Platforms = $b.platforms }) } } catch { Write-Verbose "Skipping Security Baseline templates: $($_.Exception.Message)" } } # Process Windows Hello intents response $intentsResp = $batchResponses['intents'] if ($intentsResp -and $intentsResp.value) { foreach ($intent in $intentsResp.value) { $results.Add([pscustomobject]@{ Id = $intent.id Name = $intent.displayName Description = $intent.description Type = 'Endpoint Security' TypeKey = 'intent' SettingCount = $null IsAssigned = [bool]$intent.isAssigned Platforms = 'windows10' }) } } else { # Fallback try { $intentsUri = "/beta/deviceManagement/intents?`$filter=templateId eq '$whfbTemplateId'" $intentsResponse = Invoke-IntuneDiffRequest -Method GET -Uri $intentsUri -All foreach ($intent in $intentsResponse.value) { $results.Add([pscustomobject]@{ Id = $intent.id; Name = $intent.displayName; Description = $intent.description Type = 'Endpoint Security'; TypeKey = 'intent'; SettingCount = $null IsAssigned = [bool]$intent.isAssigned; Platforms = 'windows10' }) } } catch { Write-Verbose "Skipping Windows Hello intents: $($_.Exception.Message)" } } return $results } |