Skip to content

Commit baf1e3f

Browse files
committed
feat: improve intune policy support for alltenants using the ReportDB
1 parent bfd739f commit baf1e3f

3 files changed

Lines changed: 186 additions & 0 deletions

File tree

Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Endpoint/MEM/Invoke-ListIntunePolicy.ps1

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,24 @@ function Invoke-ListIntunePolicy {
1212
$TenantFilter = $Request.Query.TenantFilter
1313
$id = $Request.Query.ID
1414
$URLName = $Request.Query.URLName
15+
$UseReportDB = $Request.Query.UseReportDB
16+
1517
try {
18+
# Return cached report data when AllTenants is requested or UseReportDB is set
19+
if ($TenantFilter -eq 'AllTenants' -or $UseReportDB -eq 'true') {
20+
try {
21+
$GraphRequest = Get-CIPPIntunePolicyReport -TenantFilter $TenantFilter -ErrorAction Stop
22+
$StatusCode = [HttpStatusCode]::OK
23+
} catch {
24+
$StatusCode = [HttpStatusCode]::InternalServerError
25+
$GraphRequest = $_.Exception.Message
26+
}
27+
return ([HttpResponseContext]@{
28+
StatusCode = $StatusCode
29+
Body = @($GraphRequest)
30+
})
31+
}
32+
1633
if ($ID) {
1734
$GraphRequest = New-GraphGetRequest -uri "https://graph.microsoft.com/beta/deviceManagement/$($URLName)('$ID')" -tenantid $TenantFilter
1835
} else {
Lines changed: 165 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,165 @@
1+
function Get-CIPPIntunePolicyReport {
2+
<#
3+
.SYNOPSIS
4+
Returns the Intune configuration policy list from the CIPP reporting database
5+
6+
.DESCRIPTION
7+
Retrieves cached Intune policy data for a tenant, applies the same assignment name
8+
resolution and PolicyTypeName enrichment as the live Invoke-ListIntunePolicy endpoint,
9+
and returns a payload in the same shape.
10+
11+
Note: The Windows update profile types (WindowsDriverUpdateProfiles,
12+
WindowsFeatureUpdateProfiles, windowsQualityUpdatePolicies, windowsQualityUpdateProfiles)
13+
are not currently cached; only the four types below are retrieved from cache:
14+
- DeviceConfigurations
15+
- ConfigurationPolicies
16+
- GroupPolicyConfigurations
17+
- MobileAppConfigurations
18+
19+
.PARAMETER TenantFilter
20+
Tenant domain name or 'AllTenants'
21+
22+
.EXAMPLE
23+
Get-CIPPIntunePolicyReport -TenantFilter 'contoso.onmicrosoft.com'
24+
25+
.EXAMPLE
26+
Get-CIPPIntunePolicyReport -TenantFilter 'AllTenants'
27+
#>
28+
[CmdletBinding()]
29+
param(
30+
[Parameter(Mandatory = $true)]
31+
[string]$TenantFilter
32+
)
33+
34+
# Maps DB cache type key -> Graph URL segment (URLName used by actions/deploy)
35+
$PolicyTypeMap = [ordered]@{
36+
IntuneDeviceConfigurations = 'DeviceConfigurations'
37+
IntuneConfigurationPolicies = 'ConfigurationPolicies'
38+
IntuneGroupPolicyConfigurations = 'GroupPolicyConfigurations'
39+
IntuneMobileAppConfigurations = 'MobileAppConfigurations'
40+
IntuneWindowsDriverUpdateProfiles = 'WindowsDriverUpdateProfiles'
41+
IntuneWindowsFeatureUpdateProfiles = 'WindowsFeatureUpdateProfiles'
42+
IntuneWindowsQualityUpdatePolicies = 'WindowsQualityUpdatePolicies'
43+
IntuneWindowsQualityUpdateProfiles = 'WindowsQualityUpdateProfiles'
44+
}
45+
46+
if ($TenantFilter -eq 'AllTenants') {
47+
# Collect all tenants that have any cached Intune policy data
48+
$AnyItems = Get-CIPPDbItem -TenantFilter 'allTenants' -Type 'IntuneDeviceConfigurations'
49+
$Tenants = @($AnyItems | Where-Object { $_.RowKey -notlike '*-Count' } | Select-Object -ExpandProperty PartitionKey -Unique)
50+
51+
$TenantList = Get-Tenants -IncludeErrors
52+
$Tenants = $Tenants | Where-Object { $TenantList.defaultDomainName -contains $_ }
53+
54+
$AllResults = [System.Collections.Generic.List[PSCustomObject]]::new()
55+
foreach ($Tenant in $Tenants) {
56+
try {
57+
$TenantResults = Get-CIPPIntunePolicyReport -TenantFilter $Tenant
58+
foreach ($Result in $TenantResults) {
59+
$Result | Add-Member -NotePropertyName 'Tenant' -NotePropertyValue $Tenant -Force
60+
$AllResults.Add($Result)
61+
}
62+
} catch {
63+
Write-LogMessage -API 'IntunePolicyReport' -tenant $Tenant -message "Failed to get report for tenant: $($_.Exception.Message)" -sev Warning
64+
}
65+
}
66+
return $AllResults
67+
}
68+
69+
try {
70+
# Load cached group display names for assignment resolution
71+
$GroupItems = Get-CIPPDbItem -TenantFilter $TenantFilter -Type 'Groups' |
72+
Where-Object { $_.RowKey -notlike '*-Count' }
73+
74+
$Groups = foreach ($GroupItem in $GroupItems) {
75+
try { $GroupItem.Data | ConvertFrom-Json -ErrorAction Stop } catch { $null }
76+
}
77+
78+
# Get cache timestamp from any available type
79+
$CacheTimestamp = $null
80+
81+
$AllPolicies = [System.Collections.Generic.List[PSCustomObject]]::new()
82+
83+
foreach ($TypeKey in $PolicyTypeMap.Keys) {
84+
$URLNameValue = $PolicyTypeMap[$TypeKey]
85+
86+
$Items = Get-CIPPDbItem -TenantFilter $TenantFilter -Type $TypeKey |
87+
Where-Object { $_.RowKey -notlike '*-Count' }
88+
89+
if (-not $Items) { continue }
90+
91+
# Use the most recent Timestamp seen across all types
92+
$TypeTimestamp = ($Items | Where-Object { $_.Timestamp } | Sort-Object Timestamp -Descending | Select-Object -First 1).Timestamp
93+
if ($null -eq $CacheTimestamp -or ($TypeTimestamp -and $TypeTimestamp -gt $CacheTimestamp)) {
94+
$CacheTimestamp = $TypeTimestamp
95+
}
96+
97+
foreach ($Item in $Items) {
98+
$Policy = try { $Item.Data | ConvertFrom-Json -Depth 10 -ErrorAction Stop } catch { continue }
99+
100+
if ($null -eq $Policy) { continue }
101+
102+
# Determine PolicyTypeName using the same switch as the live endpoint
103+
$policyTypeName = switch -Wildcard ($Policy.'assignments@odata.context') {
104+
'*microsoft.graph.windowsIdentityProtectionConfiguration*' { 'Identity Protection' }
105+
'*microsoft.graph.windows10EndpointProtectionConfiguration*' { 'Endpoint Protection' }
106+
'*microsoft.graph.windows10CustomConfiguration*' { 'Custom' }
107+
'*microsoft.graph.windows10DeviceFirmwareConfigurationInterface*' { 'Firmware Configuration' }
108+
'*groupPolicyConfigurations*' { 'Administrative Templates' }
109+
'*windowsDomainJoinConfiguration*' { 'Domain Join configuration' }
110+
'*windowsUpdateForBusinessConfiguration*' { 'Update Configuration' }
111+
'*windowsHealthMonitoringConfiguration*' { 'Health Monitoring' }
112+
'*microsoft.graph.macOSGeneralDeviceConfiguration*' { 'MacOS Configuration' }
113+
'*microsoft.graph.macOSEndpointProtectionConfiguration*' { 'MacOS Endpoint Protection' }
114+
'*microsoft.graph.androidWorkProfileGeneralDeviceConfiguration*' { 'Android Configuration' }
115+
'*windowsFeatureUpdateProfiles*' { 'Feature Update' }
116+
'*windowsQualityUpdatePolicies*' { 'Quality Update' }
117+
'*windowsQualityUpdateProfiles*' { 'Quality Update' }
118+
'*iosUpdateConfiguration*' { 'iOS Update Configuration' }
119+
'*windowsDriverUpdateProfiles*' { 'Driver Update' }
120+
'*configurationPolicies*' { 'Device Configuration' }
121+
default { $Policy.'assignments@odata.context' }
122+
}
123+
124+
# Resolve assignment names from cached group data
125+
$Assignments = $Policy.assignments.target | Select-Object -Property '@odata.type', groupId
126+
$PolicyAssignment = [System.Collections.Generic.List[string]]::new()
127+
$PolicyExclude = [System.Collections.Generic.List[string]]::new()
128+
129+
foreach ($target in $Assignments) {
130+
switch ($target.'@odata.type') {
131+
'#microsoft.graph.allDevicesAssignmentTarget' { $PolicyAssignment.Add('All Devices') }
132+
'#microsoft.graph.exclusionallDevicesAssignmentTarget' { $PolicyExclude.Add('All Devices') }
133+
'#microsoft.graph.allUsersAssignmentTarget' { $PolicyAssignment.Add('All Users') }
134+
'#microsoft.graph.allLicensedUsersAssignmentTarget' { $PolicyAssignment.Add('All Licenced Users') }
135+
'#microsoft.graph.exclusionallUsersAssignmentTarget' { $PolicyExclude.Add('All Users') }
136+
'#microsoft.graph.groupAssignmentTarget' { $PolicyAssignment.Add(($Groups | Where-Object { $_.id -eq $target.groupId }).displayName) }
137+
'#microsoft.graph.exclusionGroupAssignmentTarget' { $PolicyExclude.Add(($Groups | Where-Object { $_.id -eq $target.groupId }).displayName) }
138+
default {
139+
$PolicyAssignment.Add($null)
140+
$PolicyExclude.Add($null)
141+
}
142+
}
143+
}
144+
145+
if ($null -eq $Policy.displayName) {
146+
$Policy | Add-Member -NotePropertyName displayName -NotePropertyValue $Policy.name -Force
147+
}
148+
$Policy | Add-Member -NotePropertyName PolicyTypeName -NotePropertyValue $policyTypeName -Force
149+
$Policy | Add-Member -NotePropertyName URLName -NotePropertyValue $URLNameValue -Force
150+
$Policy | Add-Member -NotePropertyName PolicyAssignment -NotePropertyValue ($PolicyAssignment -join ', ') -Force
151+
$Policy | Add-Member -NotePropertyName PolicyExclude -NotePropertyValue ($PolicyExclude -join ', ') -Force
152+
$Policy | Add-Member -NotePropertyName CacheTimestamp -NotePropertyValue $CacheTimestamp -Force
153+
154+
$AllPolicies.Add($Policy)
155+
}
156+
}
157+
158+
# Apply the same filters as the live endpoint
159+
return ($AllPolicies | Where-Object { $_.platforms -ne 'linux' -and $_.templateReference.templateFamily -ne 'deviceConfigurationScripts' -and $null -ne $_.displayName } | Sort-Object -Property displayName)
160+
161+
} catch {
162+
Write-LogMessage -API 'IntunePolicyReport' -tenant $TenantFilter -message "Failed to generate Intune policy report: $($_.Exception.Message)" -sev Error -LogData (Get-CippException -Exception $_)
163+
throw
164+
}
165+
}

Modules/CIPPCore/Public/Set-CIPPDBCacheIntunePolicies.ps1

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,10 @@ function Set-CIPPDBCacheIntunePolicies {
3737
@{ Type = 'DeviceEnrollmentConfigurations'; Uri = '/deviceManagement/deviceEnrollmentConfigurations?$top=999'; FetchAssignments = $true }
3838
@{ Type = 'DeviceManagementScripts'; Uri = '/deviceManagement/deviceManagementScripts?$top=999&$expand=assignments' }
3939
@{ Type = 'MobileApps'; Uri = '/deviceAppManagement/mobileApps?$top=999&$select=id,displayName,description,publisher,isAssigned,createdDateTime,lastModifiedDateTime'; FetchAssignments = $true }
40+
@{ Type = 'WindowsDriverUpdateProfiles'; Uri = '/deviceManagement/windowsDriverUpdateProfiles?$top=200&$expand=assignments' }
41+
@{ Type = 'WindowsFeatureUpdateProfiles'; Uri = '/deviceManagement/windowsFeatureUpdateProfiles?$top=200&$expand=assignments' }
42+
@{ Type = 'WindowsQualityUpdatePolicies'; Uri = '/deviceManagement/windowsQualityUpdatePolicies?$top=200&$expand=assignments' }
43+
@{ Type = 'WindowsQualityUpdateProfiles'; Uri = '/deviceManagement/windowsQualityUpdateProfiles?$top=200&$expand=assignments' }
4044
)
4145

4246
# Build bulk requests for all policy types

0 commit comments

Comments
 (0)