backup/Backup-ManagementIntents.ps1

#Requires -Version 7.0
function Backup-ManagementIntents {
    [CmdletBinding()]
    param(
        [Parameter(Mandatory)] [string]$BackupPath,
        [Parameter(Mandatory)] [SecureString]$Token,
        [hashtable]$ScopeTagMap = @{}
    )

    try {
        # fetch all intents and templates
        $intentsUri = '/beta/deviceManagement/intents'
        $intents = Invoke-GraphRequest2 -Uri $intentsUri -Token $Token

        $templatesUri = '/beta/deviceManagement/templates'
        $templates = Invoke-GraphRequest2 -Uri $templatesUri -Token $Token

        # create a map of templateId to template object
        $templateMap = @{}
        foreach ($template in $templates) {
            $templateMap[$template.id] = $template
        }

        foreach ($intent in $intents) {
            # find the matching template
            $matchingTemplate = $templateMap[$intent.templateId]
            if (!$matchingTemplate) {
                Write-Verbose "skipping intent $($intent.id) - no matching template found"
                continue
            }

            # fetch categories for the template
            $categoriesUri = "/beta/deviceManagement/templates/$($intent.templateId)/categories"
            $categories = Invoke-GraphRequest2 -Uri $categoriesUri -Token $Token

            # fetch settings for each category
            $allSettings = @()
            if ($categories) {
                foreach ($category in $categories) {
                    $settingsUri = "/beta/deviceManagement/intents/$($intent.id)/categories/$($category.id)/settings"
                    $settings = Invoke-GraphRequest2 -Uri $settingsUri -Token $Token
                    if ($settings) {
                        $settings = @($settings | ForEach-Object {
                            $setting = $_
                            # keep only definitionId and value
                            [PSCustomObject]@{
                                definitionId = $setting.definitionId
                                value = $setting.value
                            }
                        })
                        $allSettings += $settings
                    }
                }
            }

            # attach settings to the intent
            if ($allSettings) {
                $intent | Add-Member -MemberType NoteProperty -Name 'settingsDelta' -Value $allSettings -Force
            }

            # fetch and attach assignments
            $assignmentsUri = "/beta/deviceManagement/intents/$($intent.id)/assignments"
            $assignments = Resolve-Assignments -AssignmentsUri $assignmentsUri -Token $Token
            if ($assignments) {
                $intent | Add-Member -MemberType NoteProperty -Name 'assignments' -Value $assignments -Force
            }

            # determine output folder based on template display name
            $folder = Join-Path $BackupPath 'Management Intents' $matchingTemplate.displayName

            $clean = Remove-VolatileKeys -InputObject $intent
            Save-BackupItem -Item $clean -Folder $folder -ScopeTagMap $ScopeTagMap
        }
        Write-Verbose "backed up $($intents.Count) management intents to $BackupPath/Management Intents/"
    }
    catch {
        Write-Error "failed to backup management intents: $_"
        return
    }
}

Export-ModuleMember -Function Backup-ManagementIntents