Skip to content

Commit 8c5c734

Browse files
Potential speedfix for large tenants and
1 parent a60bd84 commit 8c5c734

File tree

1 file changed

+87
-37
lines changed

1 file changed

+87
-37
lines changed

Modules/CIPPCore/Public/Get-CIPPDrift.ps1

Lines changed: 87 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,14 @@ function Get-CIPPDrift {
4949
# Skip invalid templates
5050
}
5151
} | Sort-Object -Property displayName
52+
53+
# Build GUID-indexed hashtable for faster lookups
54+
$IntuneTemplateLookup = @{}
55+
foreach ($Template in $AllIntuneTemplates) {
56+
if ($Template.GUID) {
57+
$IntuneTemplateLookup[$Template.GUID] = $Template
58+
}
59+
}
5260
}
5361
# Load all CA templates
5462
if ($ConditionalAccessCapable) {
@@ -63,6 +71,14 @@ function Get-CIPPDrift {
6371
# Skip invalid templates
6472
}
6573
} | Sort-Object -Property displayName
74+
75+
# Build GUID-indexed hashtable for faster lookups
76+
$CATemplateLookup = @{}
77+
foreach ($Template in $AllCATemplates) {
78+
if ($Template.GUID) {
79+
$CATemplateLookup[$Template.GUID] = $Template
80+
}
81+
}
6682
}
6783

6884
try {
@@ -95,36 +111,39 @@ function Get-CIPPDrift {
95111
if ($Alignment.ComparisonDetails) {
96112
foreach ($ComparisonItem in $Alignment.ComparisonDetails) {
97113
if ($ComparisonItem.Compliant -ne $true) {
98-
$Status = if ($ExistingDriftStates.ContainsKey($ComparisonItem.StandardName)) {
99-
$ExistingDriftStates[$ComparisonItem.StandardName].Status
114+
# Cache the existing drift state lookup
115+
$ExistingDriftState = if ($ExistingDriftStates.ContainsKey($ComparisonItem.StandardName)) {
116+
$ExistingDriftStates[$ComparisonItem.StandardName]
100117
} else {
101-
'New'
118+
$null
102119
}
103-
# Reset displayName and description for each deviation to prevent carryover from previous iterations
120+
121+
$Status = if ($ExistingDriftState) { $ExistingDriftState.Status } else { 'New' }
104122
$displayName = $null
105123
$standardDescription = $null
124+
106125
#if the $ComparisonItem.StandardName contains *intuneTemplate*, then it's an Intune policy deviation, and we need to grab the correct displayname from the template table
107126
if ($ComparisonItem.StandardName -like '*intuneTemplate*') {
108-
$CompareGuid = $ComparisonItem.StandardName.Split('.') | Select-Object -Index 2
127+
$CompareGuid = ($ComparisonItem.StandardName -split '\.')[2]
109128
Write-Verbose "Extracted GUID: $CompareGuid"
110-
$Template = $AllIntuneTemplates | Where-Object { $_.GUID -eq "$CompareGuid" }
129+
$Template = $IntuneTemplateLookup[$CompareGuid]
111130
if ($Template) {
112131
$displayName = $Template.displayName
113132
$standardDescription = $Template.description
114133
}
115134
}
116135
# Handle Conditional Access templates
117136
if ($ComparisonItem.StandardName -like '*ConditionalAccessTemplate*') {
118-
$CompareGuid = $ComparisonItem.StandardName.Split('.') | Select-Object -Index 2
137+
$CompareGuid = ($ComparisonItem.StandardName -split '\.')[2]
119138
Write-Verbose "Extracted CA GUID: $CompareGuid"
120-
$Template = $AllCATemplates | Where-Object { $_.GUID -eq "$CompareGuid" }
139+
$Template = $CATemplateLookup[$CompareGuid]
121140
if ($Template) {
122141
$displayName = $Template.displayName
123142
$standardDescription = $Template.description
124143
}
125144
}
126-
$reason = if ($ExistingDriftStates.ContainsKey($ComparisonItem.StandardName)) { $ExistingDriftStates[$ComparisonItem.StandardName].Reason }
127-
$User = if ($ExistingDriftStates.ContainsKey($ComparisonItem.StandardName)) { $ExistingDriftStates[$ComparisonItem.StandardName].User }
145+
$reason = if ($ExistingDriftState) { $ExistingDriftState.Reason } else { $null }
146+
$User = if ($ExistingDriftState) { $ExistingDriftState.User } else { $null }
128147
$StandardsDeviations.Add([PSCustomObject]@{
129148
standardName = $ComparisonItem.StandardName
130149
standardDisplayName = $displayName
@@ -256,22 +275,26 @@ function Get-CIPPDrift {
256275
}
257276
}
258277

278+
# Build hashtable lookup for template policies
279+
$TemplatePolicyLookup = @{}
280+
foreach ($TemplatePolicy in $TemplateIntuneTemplates) {
281+
$names = @(
282+
$TemplatePolicy.displayName,
283+
$TemplatePolicy.name
284+
) | Where-Object { $_ }
285+
foreach ($name in $names) {
286+
$TemplatePolicyLookup[$name] = $true
287+
}
288+
}
289+
259290
# Check for extra Intune policies not in template
260291
foreach ($TenantPolicy in $TenantIntunePolicies) {
261-
$PolicyFound = $false
262292
$tenantPolicy.policy | Add-Member -MemberType NoteProperty -Name 'URLName' -Value $TenantPolicy.Type -Force
263293
$TenantPolicyName = if ($TenantPolicy.Policy.displayName) { $TenantPolicy.Policy.displayName } else { $TenantPolicy.Policy.name }
264-
foreach ($TemplatePolicy in $TemplateIntuneTemplates) {
265-
$TemplatePolicyName = if ($TemplatePolicy.displayName) { $TemplatePolicy.displayName } else { $TemplatePolicy.name }
266-
267-
if ($TemplatePolicy.displayName -eq $TenantPolicy.Policy.displayName -or
268-
$TemplatePolicy.name -eq $TenantPolicy.Policy.name -or
269-
$TemplatePolicy.displayName -eq $TenantPolicy.Policy.name -or
270-
$TemplatePolicy.name -eq $TenantPolicy.Policy.displayName) {
271-
$PolicyFound = $true
272-
break
273-
}
274-
}
294+
295+
# Use hashtable lookup instead of nested loop - check for null to avoid ContainsKey errors
296+
$PolicyFound = ($TenantPolicy.Policy.displayName -and $TemplatePolicyLookup.ContainsKey($TenantPolicy.Policy.displayName)) -or
297+
($TenantPolicy.Policy.name -and $TemplatePolicyLookup.ContainsKey($TenantPolicy.Policy.name))
275298

276299
if (-not $PolicyFound) {
277300
$PolicyKey = "IntuneTemplates.$($TenantPolicy.Policy.id)"
@@ -292,16 +315,18 @@ function Get-CIPPDrift {
292315
}
293316
}
294317

318+
# Build hashtable lookup for template CA policies
319+
$TemplateCALookup = @{}
320+
foreach ($TemplateCAPolicy in $TemplateCATemplates) {
321+
if ($TemplateCAPolicy.displayName) {
322+
$TemplateCALookup[$TemplateCAPolicy.displayName] = $true
323+
}
324+
}
325+
295326
# Check for extra Conditional Access policies not in template
296327
foreach ($TenantCAPolicy in $TenantCAPolicies) {
297-
$PolicyFound = $false
298-
299-
foreach ($TemplateCAPolicy in $TemplateCATemplates) {
300-
if ($TemplateCAPolicy.displayName -eq $TenantCAPolicy.displayName) {
301-
$PolicyFound = $true
302-
break
303-
}
304-
}
328+
# Use hashtable lookup instead of nested loop
329+
$PolicyFound = $TemplateCALookup.ContainsKey($TenantCAPolicy.displayName)
305330

306331
if (-not $PolicyFound) {
307332
$PolicyKey = "ConditionalAccessTemplates.$($TenantCAPolicy.id)"
@@ -328,14 +353,39 @@ function Get-CIPPDrift {
328353
$AllDeviations.AddRange($StandardsDeviations)
329354
$AllDeviations.AddRange($PolicyDeviations)
330355

331-
# Filter deviations by status for counting
332-
$NewDeviations = $AllDeviations | Where-Object { $_.Status -eq 'New' }
333-
$AcceptedDeviations = $AllDeviations | Where-Object { $_.Status -eq 'Accepted' }
334-
$DeniedDeviations = $AllDeviations | Where-Object { $_.Status -like 'Denied*' }
335-
$CustomerSpecificDeviations = $AllDeviations | Where-Object { $_.Status -eq 'CustomerSpecific' }
356+
# Single-pass grouping instead of multiple Where-Object filters
357+
$DeviationGroups = @{
358+
New = [System.Collections.Generic.List[object]]::new()
359+
Accepted = [System.Collections.Generic.List[object]]::new()
360+
Denied = [System.Collections.Generic.List[object]]::new()
361+
CustomerSpecific = [System.Collections.Generic.List[object]]::new()
362+
Current = [System.Collections.Generic.List[object]]::new()
363+
}
364+
365+
foreach ($Deviation in $AllDeviations) {
366+
switch ($Deviation.Status) {
367+
'New' {
368+
$DeviationGroups.New.Add($Deviation)
369+
$DeviationGroups.Current.Add($Deviation)
370+
}
371+
'Accepted' {
372+
$DeviationGroups.Accepted.Add($Deviation)
373+
}
374+
{ $_ -like 'Denied*' } {
375+
$DeviationGroups.Denied.Add($Deviation)
376+
$DeviationGroups.Current.Add($Deviation)
377+
}
378+
'CustomerSpecific' {
379+
$DeviationGroups.CustomerSpecific.Add($Deviation)
380+
}
381+
}
382+
}
336383

337-
# Current deviations are New + Denied (not accepted or customer specific)
338-
$CurrentDeviations = $AllDeviations | Where-Object { $_.Status -in @('New', 'Denied') }
384+
$NewDeviations = $DeviationGroups.New
385+
$AcceptedDeviations = $DeviationGroups.Accepted
386+
$DeniedDeviations = $DeviationGroups.Denied
387+
$CustomerSpecificDeviations = $DeviationGroups.CustomerSpecific
388+
$CurrentDeviations = $DeviationGroups.Current
339389

340390
$Result = [PSCustomObject]@{
341391
tenantFilter = $TenantFilter

0 commit comments

Comments
 (0)