Public/Invoke-IntuneBackupDeviceConfigurationSP.ps1
function Invoke-IntuneBackupDeviceConfigurationSP { <# .SYNOPSIS Backup Intune Device Configurations .DESCRIPTION Backup Intune Device Configurations as JSON files per Device Configuration Policy to the specified Path. .PARAMETER Path Path to store backup files .EXAMPLE Invoke-IntuneBackupDeviceConfiguration -Path "C:\temp" #> [CmdletBinding()] param( [Parameter(Mandatory = $true)] [string]$Path, [Parameter(Mandatory = $false)] [ValidateSet("v1.0", "Beta")] [string]$ApiVersion = "Beta" ) # Ensure the Microsoft Graph module is installed and imported if (-not (Get-Module -Name Microsoft.Graph -ListAvailable)) { Install-Module -Name Microsoft.Graph -Scope CurrentUser -Force } Import-Module Microsoft.Graph.DeviceManagement # Connect to Microsoft Graph if not already connected if (-not (Get-MgUser -UserId me -ErrorAction SilentlyContinue)) { Connect-MgGraph -Scopes "DeviceManagementApps.Read.All","DeviceManagementApps.ReadWrite.All","DeviceManagementConfiguration.Read.All","DeviceManagementConfiguration.ReadWrite.All","DeviceManagementServiceConfig.Read.All","DeviceManagementServiceConfig.ReadWrite.All" } # Function to get all pages of results function Get-AllPages { param ( [Parameter(Mandatory = $true)] [string]$Uri ) $results = @() $response = Invoke-MgGraphRequest -Method GET -Uri $Uri $results += $response.value while ($null -ne $response.'@odata.nextLink') { $response = Invoke-MgGraphRequest -Method GET -Uri $response.'@odata.nextLink' $results += $response.value } return $results } # Create folder if not exists if (-not (Test-Path "$Path\Device Configurations")) { $null = New-Item -Path "$Path\Device Configurations" -ItemType Directory } # Get all device configurations $deviceConfigurations = @() $deviceConfigurations = Get-allpages -Uri "https://graph.microsoft.com/$ApiVersion/deviceManagement/deviceConfigurations" foreach ($deviceConfiguration in $deviceConfigurations) { $fileName = ($deviceConfiguration.displayName).Split([IO.Path]::GetInvalidFileNameChars()) -join '_' # If it's a custom configuration, check if the device configuration contains encrypted OMA settings, then decrypt the OmaSettings to a Plain Text Value (required for import) if (($deviceConfiguration.'@odata.type' -eq '#microsoft.graph.windows10CustomConfiguration') -and ($deviceConfiguration.omaSettings | Where-Object { $_.isEncrypted -contains $true } )) { # Create an empty array for the unencrypted OMA settings. $newOmaSettings = @() foreach ($omaSetting in $deviceConfiguration.omaSettings) { # Check if this particular setting is encrypted, and get the plaintext only if necessary if ($omaSetting.isEncrypted) { $omaSettingValue = Get-allpages -Uri "$apiVersion/deviceManagement/deviceConfigurations/$($deviceConfiguration.id)/getOmaSettingPlainTextValue(secretReferenceValueId='$($omaSetting.secretReferenceValueId)')" } # Define a new 'unencrypted' OMA Setting $newOmaSetting = @{} $newOmaSetting.'@odata.type' = $omaSetting.'@odata.type' $newOmaSetting.displayName = $omaSetting.displayName $newOmaSetting.description = $omaSetting.description $newOmaSetting.omaUri = $omaSetting.omaUri $newOmaSetting.value = $omaSettingValue $newOmaSetting.isEncrypted = $false $newOmaSetting.secretReferenceValueId = $null # Add the unencrypted OMA Setting to the Array $newOmaSettings += $newOmaSetting } # Remove all encrypted OMA Settings from the Device Configuration $deviceConfiguration.omaSettings = @() # Add the unencrypted OMA Settings from the Device Configuration $deviceConfiguration.omaSettings += $newOmaSettings } # Export the Device Configuration Profile $deviceConfiguration | ConvertTo-Json -Depth 100 | Out-File -LiteralPath "$path\Device Configurations\$fileName.json" [PSCustomObject]@{ "Action" = "Backup" "Type" = "Device Configuration" "Name" = $deviceConfiguration.displayName "Path" = "Device Configurations\$fileName.json" } } } |