Skip to content

Commit 21f8cee

Browse files
committed
Enhance template library logic
Improved the template creation process for Conditional Access, Intune Configuration, Compliance, and Protection policies by adding bulk Graph API requests, preloading users/groups, and ensuring more robust handling of existing templates. Added 'Source' and 'GUID' properties to template entities, improved logging, and updated return values for better feedback and consistency.
1 parent 7f3d7e0 commit 21f8cee

File tree

2 files changed

+92
-37
lines changed

2 files changed

+92
-37
lines changed

Modules/CIPPCore/Public/Entrypoints/Activity Triggers/Push-ExecScheduledCommand.ps1

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -341,4 +341,5 @@ function Push-ExecScheduledCommand {
341341
Write-LogMessage -API 'Scheduler_UserTasks' -tenant $Tenant -tenantid $TenantInfo.customerId -message "Successfully executed task: $($task.Name)" -sev Info
342342
}
343343
Remove-Variable -Name ScheduledTaskId -Scope Script -ErrorAction SilentlyContinue
344+
return 'Task Completed Successfully.'
344345
}

Modules/CIPPCore/Public/New-CIPPTemplateRun.ps1

Lines changed: 91 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,9 @@ function New-CIPPTemplateRun {
1010
$data = $_.JSON | ConvertFrom-Json -ErrorAction SilentlyContinue -Depth 100
1111
$data | Add-Member -NotePropertyName 'GUID' -NotePropertyValue $_.RowKey -Force -ErrorAction Stop
1212
$data | Add-Member -NotePropertyName 'PartitionKey' -NotePropertyValue $_.PartitionKey -Force -ErrorAction Stop
13-
$data | Add-Member -NotePropertyName 'SHA' -NotePropertyValue $_.SHA -Force -ErrorAction Stop
13+
$data | Add-Member -NotePropertyName 'SHA' -NotePropertyValue $_.SHA -Force -ErrorAction SilentlyContinue
14+
$data | Add-Member -NotePropertyName 'Package' -NotePropertyValue $_.Package -Force -ErrorAction SilentlyContinue
15+
$data | Add-Member -NotePropertyName 'Source' -NotePropertyValue $_.Source -Force -ErrorAction SilentlyContinue
1416
$data
1517
} catch {
1618
return
@@ -79,42 +81,67 @@ function New-CIPPTemplateRun {
7981
return "Failed to get data from community repo $($TemplateSettings.templateRepo.value). Error: $($_.Exception.Message)"
8082
}
8183
} else {
82-
foreach ($Task in $Tasks) {
83-
Write-Information "Working on task $Task"
84+
# Tenant template library
85+
$Results = foreach ($Task in $Tasks) {
8486
switch ($Task) {
8587
'ca' {
8688
Write-Information "Template Conditional Access Policies for $TenantFilter"
87-
$Policies = New-GraphGetRequest -uri 'https://graph.microsoft.com/beta/conditionalAccess/policies?$top=999' -tenantid $TenantFilter
89+
# Preload users/groups for CA templates
90+
Write-Information "Preloading information for Conditional Access templates for $TenantFilter"
91+
$Requests = @(
92+
@{
93+
id = 'preloadedUsers'
94+
url = 'users?$top=999&$select=displayName,id'
95+
method = 'GET'
96+
}
97+
@{
98+
id = 'preloadedGroups'
99+
url = 'groups?$top=999&$select=displayName,id'
100+
method = 'GET'
101+
}
102+
@{
103+
id = 'conditionalAccessPolicies'
104+
url = 'conditionalAccess/policies?$top=999'
105+
method = 'GET'
106+
}
107+
)
108+
$BulkResults = New-GraphBulkRequest -Requests @($Requests) -tenantid $TenantFilter -asapp $true
109+
$preloadedUsers = ($BulkResults | Where-Object { $_.id -eq 'preloadedUsers' }).body.value
110+
$preloadedGroups = ($BulkResults | Where-Object { $_.id -eq 'preloadedGroups' }).body.value
111+
$policies = ($BulkResults | Where-Object { $_.id -eq 'conditionalAccessPolicies' }).body.value
112+
88113
Write-Information 'Creating templates for found Conditional Access Policies'
89114
foreach ($policy in $policies) {
90115
try {
91116
$Hash = Get-StringHash -String ($policy | ConvertTo-Json -Depth 100 -Compress)
92-
$ExistingPolicy = $ExistingTemplates | Where-Object { $_.displayName -eq $policy.displayName } | Select-Object -First 1
117+
$ExistingPolicy = $ExistingTemplates | Where-Object { $_.PartitionKey -eq 'CATemplate' -and $_.displayName -eq $policy.displayName } | Select-Object -First 1
93118
if ($ExistingPolicy -and $ExistingPolicy.SHA -eq $Hash) {
94-
"Policy $($policy.displayName) found, SHA matches, skipping template creation"
119+
"CA Policy $($policy.displayName) found, SHA matches, skipping template creation"
95120
continue
96121
}
97-
$Template = New-CIPPCATemplate -TenantFilter $TenantFilter -JSON $policy
122+
$Template = New-CIPPCATemplate -TenantFilter $TenantFilter -JSON $policy -preloadedUsers $preloadedUsers -preloadedGroups $preloadedGroups
98123
#check existing templates, if the displayName is the same, overwrite it.
99124

100125
if ($ExistingPolicy -and $ExistingPolicy.PartitionKey -eq 'CATemplate') {
101-
"Policy $($policy.displayName) found, updating template"
126+
"CA Policy $($policy.displayName) found, updating template"
102127
Add-CIPPAzDataTableEntity @Table -Entity @{
103128
JSON = "$Template"
104129
RowKey = $ExistingPolicy.GUID
105130
PartitionKey = 'CATemplate'
106131
GUID = $ExistingPolicy.GUID
107132
SHA = $Hash
133+
Source = $ExistingPolicy.Source
108134
} -Force
109135
} else {
110-
"Policy $($policy.displayName) not found in existing templates, creating new template"
136+
"CA Policy $($policy.displayName) not found in existing templates, creating new template"
111137
$GUID = (New-Guid).GUID
112138
Add-CIPPAzDataTableEntity @Table -Entity @{
113139
JSON = "$Template"
114140
RowKey = "$GUID"
115141
PartitionKey = 'CATemplate'
116142
GUID = "$GUID"
117143
SHA = $Hash
144+
Source = $TenantFilter
118145
}
119146
}
120147

@@ -125,27 +152,44 @@ function New-CIPPTemplateRun {
125152
}
126153
'intuneconfig' {
127154
Write-Information "Backup Intune Configuration Policies for $TenantFilter"
128-
$GraphURLS = @("https://graph.microsoft.com/beta/deviceManagement/deviceConfigurations?`$select=id,displayName,lastModifiedDateTime,roleScopeTagIds,microsoft.graph.unsupportedDeviceConfiguration/originalEntityTypeName&`$expand=assignments&top=1000"
129-
'https://graph.microsoft.com/beta/deviceManagement/windowsDriverUpdateProfiles'
130-
"https://graph.microsoft.com/beta/deviceManagement/groupPolicyConfigurations?`$expand=assignments&top=999"
131-
"https://graph.microsoft.com/beta/deviceAppManagement/mobileAppConfigurations?`$expand=assignments&`$filter=microsoft.graph.androidManagedStoreAppConfiguration/appSupportsOemConfig%20eq%20true"
132-
'https://graph.microsoft.com/beta/deviceManagement/configurationPolicies'
133-
'https://graph.microsoft.com/beta/deviceManagement/windowsFeatureUpdateProfiles'
134-
'https://graph.microsoft.com/beta/deviceManagement/windowsQualityUpdatePolicies'
135-
'https://graph.microsoft.com/beta/deviceManagement/windowsQualityUpdateProfiles'
155+
$GraphURLS = @(
156+
"deviceManagement/deviceConfigurations?`$select=id,displayName,lastModifiedDateTime,roleScopeTagIds,microsoft.graph.unsupportedDeviceConfiguration/originalEntityTypeName&`$expand=assignments&top=1000"
157+
'deviceManagement/windowsDriverUpdateProfiles'
158+
"deviceManagement/groupPolicyConfigurations?`$expand=assignments&top=999"
159+
"deviceAppManagement/mobileAppConfigurations?`$expand=assignments&`$filter=microsoft.graph.androidManagedStoreAppConfiguration/appSupportsOemConfig%20eq%20true"
160+
'deviceManagement/configurationPolicies'
161+
'deviceManagement/windowsFeatureUpdateProfiles'
162+
'deviceManagement/windowsQualityUpdatePolicies'
163+
'deviceManagement/windowsQualityUpdateProfiles'
136164
)
137165

138-
$Policies = foreach ($url in $GraphURLS) {
139-
try {
140-
$Policies = New-GraphGetRequest -uri "$($url)" -tenantid $TenantFilter
141-
$URLName = (($url).split('?') | Select-Object -First 1) -replace 'https://graph.microsoft.com/beta/deviceManagement/', ''
166+
$Requests = [System.Collections.Generic.List[PSCustomObject]]::new()
167+
foreach ($url in $GraphURLS) {
168+
$URLName = (($url).split('?') | Select-Object -First 1) -replace 'deviceManagement/', '' -replace 'deviceAppManagement/', ''
169+
$Requests.Add([PSCustomObject]@{
170+
id = $URLName
171+
url = $url
172+
method = 'GET'
173+
})
174+
}
175+
$BulkResults = New-GraphBulkRequest -Requests @($Requests) -tenantid $TenantFilter
176+
foreach ($Result in $BulkResults) {
177+
Write-Information "Processing Intune Configuration Policies for $($Result.id) - Status Code: $($Result.status)"
178+
if ($Result.status -eq 200) {
179+
$URLName = $Result.id
180+
$Policies = $Result.body.value
181+
Write-Information "Found $($Policies.Count) policies for $($Result.id)"
142182
foreach ($Policy in $Policies) {
143183
try {
144184
$Hash = Get-StringHash -String ($Policy | ConvertTo-Json -Depth 100 -Compress)
145-
$ExistingPolicy = $ExistingTemplates | Where-Object { $_.displayName -eq $Template.DisplayName } | Select-Object -First 1
185+
$DisplayName = $Policy.displayName ?? $Policy.name
186+
187+
$ExistingPolicy = $ExistingTemplates | Where-Object { $_.PartitionKey -eq 'IntuneTemplate' -and $_.displayName -eq $DisplayName } | Select-Object -First 1
188+
189+
Write-Information "Processing Intune Configuration Policy $($DisplayName) - $($ExistingPolicy ? 'Existing template found' : 'No existing template found')"
146190

147191
if ($ExistingPolicy -and $ExistingPolicy.SHA -eq $Hash) {
148-
"Policy $($Policy.displayName) found, SHA matches, skipping template creation"
192+
"Intune Configuration Policy $($Policy.displayName) found, SHA matches, skipping template creation"
149193
continue
150194
}
151195

@@ -165,10 +209,12 @@ function New-CIPPTemplateRun {
165209
RowKey = $ExistingPolicy.GUID
166210
PartitionKey = 'IntuneTemplate'
167211
Package = $ExistingPolicy.Package
212+
GUID = $ExistingPolicy.GUID
168213
SHA = $Hash
214+
Source = $ExistingPolicy.Source
169215
} -Force
170216
} else {
171-
"Policy $($Template.DisplayName) not found in existing templates, creating new template"
217+
"Intune Configuration Policy $($Template.DisplayName) not found in existing templates, creating new template"
172218
$GUID = (New-Guid).GUID
173219
$object = [PSCustomObject]@{
174220
Displayname = $Template.DisplayName
@@ -182,32 +228,34 @@ function New-CIPPTemplateRun {
182228
JSON = "$object"
183229
RowKey = "$GUID"
184230
PartitionKey = 'IntuneTemplate'
231+
GUID = "$GUID"
185232
SHA = $Hash
233+
Source = $TenantFilter
186234
} -Force
187235
}
188236
} catch {
189237
$ErrorMessage = Get-NormalizedError -Message $_.Exception.Message
190238
"Failed to create a template of the Intune Configuration Policy with ID: $($Policy.id). Error: $ErrorMessage"
191239
}
192240
}
193-
} catch {
194-
Write-Information "Failed to backup $url"
241+
} else {
242+
Write-Information "Failed to get $($Result.id) policies - Status Code: $($Result.status) - Message: $($Result.body.error.message)"
195243
}
196244
}
197245
}
198246
'intunecompliance' {
199-
Write-Information "Backup Intune Compliance Policies for $TenantFilter"
247+
Write-Information "Create Intune Compliance Policy Templates for $TenantFilter"
200248
New-GraphGetRequest -uri 'https://graph.microsoft.com/beta/deviceManagement/deviceCompliancePolicies?$top=999' -tenantid $TenantFilter | ForEach-Object {
201249
$Hash = Get-StringHash -String (ConvertTo-Json -Depth 100 -Compress -InputObject $_)
202250
$ExistingPolicy = $ExistingTemplates | Where-Object { $_.displayName -eq $_.DisplayName } | Select-Object -First 1
203251
if ($ExistingPolicy -and $ExistingPolicy.SHA -eq $Hash) {
204-
"Policy $($_.DisplayName) found, SHA matches, skipping template creation"
252+
"Intune Compliance Policy $($_.DisplayName) found, SHA matches, skipping template creation"
205253
continue
206254
}
207255

208256
$Template = New-CIPPIntuneTemplate -TenantFilter $TenantFilter -URLName 'deviceCompliancePolicies' -ID $_.ID
209257
if ($ExistingPolicy -and $ExistingPolicy.PartitionKey -eq 'IntuneTemplate') {
210-
"Policy $($Template.DisplayName) found, updating template"
258+
"Intune Compliance Policy $($Template.DisplayName) found, updating template"
211259
$object = [PSCustomObject]@{
212260
Displayname = $Template.DisplayName
213261
Description = $Template.Description
@@ -221,10 +269,12 @@ function New-CIPPTemplateRun {
221269
RowKey = $ExistingPolicy.GUID
222270
PartitionKey = 'IntuneTemplate'
223271
Package = $ExistingPolicy.Package
272+
GUID = $ExistingPolicy.GUID
224273
SHA = $Hash
274+
Source = $ExistingPolicy.Source
225275
} -Force
226276
} else {
227-
"Policy $($Template.DisplayName) not found in existing templates, creating new template"
277+
"Intune Compliance Policy $($Template.DisplayName) not found in existing templates, creating new template"
228278
$GUID = (New-Guid).GUID
229279
$object = [PSCustomObject]@{
230280
Displayname = $Template.DisplayName
@@ -239,24 +289,26 @@ function New-CIPPTemplateRun {
239289
RowKey = "$GUID"
240290
PartitionKey = 'IntuneTemplate'
241291
SHA = $Hash
292+
GUID = "$GUID"
293+
Source = $TenantFilter
242294
} -Force
243295
}
244296
}
245297
}
246298

247299
'intuneprotection' {
248-
Write-Information "Backup Intune Protection Policies for $TenantFilter"
300+
Write-Information "Create Intune Protection Policy Templates for $TenantFilter"
249301
New-GraphGetRequest -uri 'https://graph.microsoft.com/beta/deviceAppManagement/managedAppPolicies?$top=999' -tenantid $TenantFilter | ForEach-Object {
250302
$Hash = Get-StringHash -String (ConvertTo-Json -Depth 100 -Compress -InputObject $_)
251303
$ExistingPolicy = $ExistingTemplates | Where-Object { $_.displayName -eq $_.DisplayName } | Select-Object -First 1
252304
if ($ExistingPolicy -and $ExistingPolicy.SHA -eq $Hash) {
253-
"Policy $($_.DisplayName) found, SHA matches, skipping template creation"
305+
"Intune Protection Policy $($_.DisplayName) found, SHA matches, skipping template creation"
254306
continue
255307
}
256308

257309
$Template = New-CIPPIntuneTemplate -TenantFilter $TenantFilter -URLName 'managedAppPolicies' -ID $_.ID
258310
if ($ExistingPolicy -and $ExistingPolicy.PartitionKey -eq 'IntuneTemplate') {
259-
"Policy $($Template.DisplayName) found, updating template"
311+
"Intune Protection Policy $($Template.DisplayName) found, updating template"
260312
$object = [PSCustomObject]@{
261313
Displayname = $Template.DisplayName
262314
Description = $Template.Description
@@ -271,9 +323,11 @@ function New-CIPPTemplateRun {
271323
PartitionKey = 'IntuneTemplate'
272324
Package = $ExistingPolicy.Package
273325
SHA = $Hash
326+
GUID = $ExistingPolicy.GUID
327+
Source = $ExistingPolicy.Source
274328
} -Force
275329
} else {
276-
"Policy $($Template.DisplayName) not found in existing templates, creating new template"
330+
"Intune Protection Policy $($Template.DisplayName) not found in existing templates, creating new template"
277331
$GUID = (New-Guid).GUID
278332
$object = [PSCustomObject]@{
279333
Displayname = $Template.DisplayName
@@ -288,14 +342,14 @@ function New-CIPPTemplateRun {
288342
RowKey = "$GUID"
289343
PartitionKey = 'IntuneTemplate'
290344
SHA = $Hash
345+
GUID = "$GUID"
346+
Source = $TenantFilter
291347
} -Force
292348
}
293349
}
294350
}
295-
296351
}
297352
}
298353
}
299-
return $BackupData
354+
return $Results
300355
}
301-

0 commit comments

Comments
 (0)