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"
        }
    }
}