-
Notifications
You must be signed in to change notification settings - Fork 21
Expand file tree
/
Copy pathGet-IntunePolicyWithSettingDefinitions.ps1
More file actions
220 lines (182 loc) · 8.54 KB
/
Get-IntunePolicyWithSettingDefinitions.ps1
File metadata and controls
220 lines (182 loc) · 8.54 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
<#
.SYNOPSIS
This script retrieves all Settings Catalog policies from Intune, for each policy getting settings with expanded setting definitions.
.DESCRIPTION
This script retrieves all Settings Catalog policies from Intune with their expanded setting definitions and exports them.
.NOTES
Requires Microsoft.Graph.DeviceManagement module
Requires Microsoft.Graph.Authentication module
Author: Sandy Zeng
Version: 1.0
Version histroy:
1.0.0 - 27.08.2025 Initial release
1.0.1 - 28.08.2025 Move summary file to root folder
1.0.2 - 28.08.2025 Added NextLink for getting all the settings
1.0.3 - 30.03.2026 Fixed export summary table.
#>
param(
[Parameter(Mandatory = $false)]
[string]$OutputPath = ".\SettingsCatalogPolicies",
[Parameter(Mandatory = $false)]
[switch]$IncludeTimestamp,
[Parameter(Mandatory = $false)]
[int]$JsonDepth = 50
)
# Import required modules
try {
Import-Module Microsoft.Graph.DeviceManagement -ErrorAction Stop
Import-Module Microsoft.Graph.Authentication -ErrorAction Stop
Write-Host "Required modules imported successfully" -ForegroundColor Green
}
catch {
Write-Host "Failed to import required modules. Please install Microsoft.Graph.DeviceManagement module." -ForegroundColor Red
Write-Host "Run: Install-Module Microsoft.Graph.DeviceManagement -Force" -ForegroundColor Yellow
exit 1
}
# Function to sanitize filename
function Get-SafeFileName {
param([string]$FileName)
$invalidChars = [System.IO.Path]::GetInvalidFileNameChars()
foreach ($char in $invalidChars) {
$FileName = $FileName.Replace($char, '_')
}
return $FileName
}
# Function to create output directory
function New-OutputDirectory {
param([string]$Path)
if ($IncludeTimestamp) {
$timestamp = Get-Date -Format "yyyy-MM-dd_HH-mm-ss"
$Path = Join-Path $Path "Export_$timestamp"
}
if (-not (Test-Path $Path)) {
New-Item -ItemType Directory -Path $Path -Force | Out-Null
Write-Host "Created output directory: $Path" -ForegroundColor Green
}
return $Path
}
# Main execution
try {
Write-Host "Starting Settings Catalog Policy Export..." -ForegroundColor Cyan
# Check if already connected to Microsoft Graph
$context = Get-MgContext
if (-not $context) {
Write-Host "Connecting to Microsoft Graph..." -ForegroundColor Yellow
Connect-MgGraph -Scopes "DeviceManagementConfiguration.Read.All" -NoWelcome
Write-Host "Connected to Microsoft Graph" -ForegroundColor Green
} else {
Write-Host "Already connected to Microsoft Graph as: $($context.Account)" -ForegroundColor Green
}
# Create output directory
$outputDir = New-OutputDirectory -Path $OutputPath
# First, get all Settings Catalog policies (basic info only)
Write-Host "Retrieving Settings Catalog policies list..." -ForegroundColor Yellow
$listUri = "https://graph.microsoft.com/beta/deviceManagement/configurationPolicies"
$policies = @()
$nextLink = $listUri
do {
try {
$response = Invoke-MgGraphRequest -Uri $nextLink -Method GET
$policies += $response.value
$nextLink = $response.'@odata.nextLink'
Write-Host "Retrieved $($policies.Count) policies so far..." -ForegroundColor Gray
}
catch {
Write-Host "Error retrieving policies list: $($_.Exception.Message)" -ForegroundColor Red
throw
}
} while ($nextLink)
Write-Host "Retrieved $($policies.Count) Settings Catalog policies" -ForegroundColor Green
# Process each policy with individual API calls
$exportedCount = 0
$errorCount = 0
Write-Host "Making individual API calls for each policy..." -ForegroundColor Yellow
foreach ($policy in $policies) {
try {
Write-Host "Processing policy: $($policy.name)" -ForegroundColor Cyan
# Make individual API call for this policy's settings with expanded definitions
$policyDetailUri = "https://graph.microsoft.com/beta/deviceManagement/configurationPolicies/$($policy.id)/settings?`$expand=settingDefinitions"
# Handle pagination for policy settings
$allSettings = @()
$nextSettingsLink = $policyDetailUri
$pageCount = 0
do {
$pageCount++
Write-Host " Retrieving settings page $pageCount..." -ForegroundColor Gray
$settingsResponse = Invoke-MgGraphRequest -Uri $nextSettingsLink -Method GET
$allSettings += $settingsResponse.value
$nextSettingsLink = $settingsResponse.'@odata.nextLink'
} while ($nextSettingsLink)
# Create the complete response object with all settings
$rawPolicyResponse = @{
value = $allSettings
'@odata.context' = $settingsResponse.'@odata.context'
}
Write-Host " Retrieved $($allSettings.Count) settings across $pageCount page(s)" -ForegroundColor Gray
# Create safe filename
$policyName = if ($policy.name) { $policy.name } else { "Policy_$($policy.id)" }
$safeFileName = Get-SafeFileName -FileName $policyName
$fileName = "$safeFileName.json"
$filePath = Join-Path $outputDir $fileName
# Handle duplicate filenames
$counter = 1
while (Test-Path $filePath) {
$fileName = "$safeFileName`_$counter.json"
$filePath = Join-Path $outputDir $fileName
$counter++
}
# Export raw response to JSON
try {
$jsonContent = $rawPolicyResponse | ConvertTo-Json -Depth $JsonDepth -WarningAction SilentlyContinue
$jsonContent | Out-File -FilePath $filePath -Encoding UTF8
# Check if the JSON content contains truncation warning
if ($jsonContent -match "serialization has exceeded the set depth") {
Write-Host "Warning: Policy '$($policy.name)' may have truncated data due to complex nesting" -ForegroundColor Yellow
}
}
catch {
# Fallback: try with maximum PowerShell depth (100)
Write-Host "Retrying export with maximum depth for policy: $($policy.name)" -ForegroundColor Yellow
$rawPolicyResponse | ConvertTo-Json -Depth 100 -WarningAction SilentlyContinue | Out-File -FilePath $filePath -Encoding UTF8
}
Write-Host "Exported: $($policy.name) -> $fileName" -ForegroundColor Green
$exportedCount++
}
catch {
Write-Host "Failed to export policy '$($policy.name)': $($_.Exception.Message)" -ForegroundColor Red
$errorCount++
}
}
# Summary
Write-Host "" -ForegroundColor White
Write-Host "=========================================" -ForegroundColor Cyan
Write-Host "Export Summary:" -ForegroundColor Cyan
Write-Host " Total policies found: $($policies.Count)" -ForegroundColor White
Write-Host " Successfully exported: $exportedCount" -ForegroundColor Green
Write-Host " Errors: $errorCount" -ForegroundColor $(if ($errorCount -gt 0) { "Red" } else { "Green" })
Write-Host " Output directory: $outputDir" -ForegroundColor White
Write-Host "" -ForegroundColor White
if ($exportedCount -gt 0) {
Write-Host "Settings Catalog policies exported successfully!" -ForegroundColor Green
# Create summary file
$summary = @{
ExportDate = Get-Date
TotalPolicies = $policies.Count
ExportedPolicies = $exportedCount
Errors = $errorCount
OutputDirectory = $outputDir
Policies = $policies | ForEach-Object { [PSCustomObject]$_ } | Select-Object id, name, description
}
$summaryPath = Join-Path (Get-Location) "SettingsCatalogPolicies_ExportSummary.json"
$summary | ConvertTo-Json -Depth 5 | Out-File -FilePath $summaryPath -Encoding UTF8
Write-Host "Export summary saved to: $($summaryPath)" -ForegroundColor Green
}
}
catch {
Write-Host "Script execution failed: $($_.Exception.Message)" -ForegroundColor Red
exit 1
}
finally {
Write-Host "" -ForegroundColor White
Write-Host "Script execution completed." -ForegroundColor Cyan
}