Skip to content

Commit 52822bb

Browse files
authored
Merge pull request #586 from KelvinTegelaar/dev
[pull] dev from KelvinTegelaar:dev
2 parents 475541e + 271c3b8 commit 52822bb

File tree

2 files changed

+114
-41
lines changed

2 files changed

+114
-41
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

Modules/CIPPCore/Public/New-CIPPCAPolicy.ps1

Lines changed: 27 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,6 @@ function New-CIPPCAPolicy {
1313
$Headers
1414
)
1515

16-
$User = $Request.Headers
17-
1816
function Remove-EmptyArrays ($Object) {
1917
if ($Object -is [Array]) {
2018
foreach ($Item in $Object) { Remove-EmptyArrays $Item }
@@ -45,14 +43,14 @@ function New-CIPPCAPolicy {
4543
$GroupIds = [System.Collections.Generic.List[string]]::new()
4644
$groupNames | ForEach-Object {
4745
if (Test-IsGuid $_) {
48-
Write-LogMessage -Headers $User -API 'Create CA Policy' -message "Already GUID, no need to replace: $_" -Sev 'Debug'
46+
Write-LogMessage -Headers $Headers -API 'Create CA Policy' -message "Already GUID, no need to replace: $_" -Sev 'Debug'
4947
$GroupIds.Add($_) # it's a GUID, so we keep it
5048
} else {
5149
$groupId = ($groups | Where-Object -Property displayName -EQ $_).id # it's a display name, so we get the group ID
5250
if ($groupId) {
5351
foreach ($gid in $groupId) {
5452
Write-Warning "Replaced group name $_ with ID $gid"
55-
$null = Write-LogMessage -Headers $User -API 'Create CA Policy' -message "Replaced group name $_ with ID $gid" -Sev 'Debug'
53+
$null = Write-LogMessage -Headers $Headers -API 'Create CA Policy' -message "Replaced group name $_ with ID $gid" -Sev 'Debug'
5654
$GroupIds.Add($gid) # add the ID to the list
5755
}
5856
} elseif ($CreateGroups) {
@@ -141,6 +139,31 @@ function New-CIPPCAPolicy {
141139
}
142140
}
143141

142+
#if we have excluded or included applications, we need to remove any appIds that do not have a service principal in the tenant
143+
144+
if (($JSONobj.conditions.applications.includeApplications -and $JSONobj.conditions.applications.includeApplications -notcontains 'All') -or ($JSONobj.conditions.applications.excludeApplications -and $JSONobj.conditions.applications.excludeApplications -notcontains 'All')) {
145+
$AllServicePrincipals = New-GraphGETRequest -uri 'https://graph.microsoft.com/v1.0/servicePrincipals?$select=appId' -tenantid $TenantFilter -asApp $true
146+
147+
if ($JSONobj.conditions.applications.excludeApplications -and $JSONobj.conditions.applications.excludeApplications -notcontains 'All') {
148+
$ValidExclusions = [system.collections.generic.list[string]]::new()
149+
foreach ($appId in $JSONobj.conditions.applications.excludeApplications) {
150+
if ($AllServicePrincipals.appId -contains $appId) {
151+
$ValidExclusions.Add($appId)
152+
}
153+
}
154+
$JSONobj.conditions.applications.excludeApplications = $ValidExclusions
155+
}
156+
if ($JSONobj.conditions.applications.includeApplications -and $JSONobj.conditions.applications.includeApplications -notcontains 'All') {
157+
$ValidInclusions = [system.collections.generic.list[string]]::new()
158+
foreach ($appId in $JSONobj.conditions.applications.includeApplications) {
159+
if ($AllServicePrincipals.appId -contains $appId) {
160+
$ValidInclusions.Add($appId)
161+
}
162+
}
163+
$JSONobj.conditions.applications.includeApplications = $ValidInclusions
164+
}
165+
}
166+
144167
#for each of the locations, check if they exist, if not create them. These are in $JSONobj.LocationInfo
145168
$LocationLookupTable = foreach ($locations in $JSONobj.LocationInfo) {
146169
if (!$locations) { continue }

0 commit comments

Comments
 (0)