backup/Backup-Compliance.ps1

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

    try {
        $folder = Join-Path $BackupPath 'Compliance Policies' 'Policies'
        $uri = '/beta/deviceManagement/deviceCompliancePolicies/?$expand=scheduledActionsForRule($expand=scheduledActionConfigurations)'
        $items = Invoke-GraphRequest2 -Uri $uri -Token $Token

        foreach ($item in $items) {
            # process scheduled actions
            if ($item.scheduledActionsForRule) {
                foreach ($action in $item.scheduledActionsForRule) {
                    if ($action.scheduledActionConfigurations) {
                        $action.scheduledActionConfigurations = @($action.scheduledActionConfigurations | ForEach-Object {
                            $config = $_

                            # resolve notification template
                            if ($config.notificationTemplateId -and $config.notificationTemplateId -ne '00000000-0000-0000-0000-000000000000') {
                                $templateUri = "/beta/deviceManagement/notificationMessageTemplates/$($config.notificationTemplateId)"
                                $template = Invoke-GraphRequest2 -Uri $templateUri -Token $Token
                                if ($template.displayName) {
                                    $config | Add-Member -MemberType NoteProperty -Name 'notificationTemplateName' -Value $template.displayName -Force
                                }
                            }

                            # resolve compliance script
                            if ($config.complianceScriptId) {
                                $scriptUri = "/beta/deviceManagement/deviceComplianceScripts/$($config.complianceScriptId)"
                                $script = Invoke-GraphRequest2 -Uri $scriptUri -Token $Token
                                if ($script.displayName) {
                                    $config | Add-Member -MemberType NoteProperty -Name 'complianceScriptName' -Value $script.displayName -Force
                                }
                            }

                            Remove-VolatileKeys -InputObject $config
                        })
                    }
                }
            }

            $assignments = Resolve-Assignments -AssignmentsUri "/beta/deviceManagement/deviceCompliancePolicies/$($item.id)/assignments" -Token $Token
            if ($assignments) {
                $item | Add-Member -MemberType NoteProperty -Name 'assignments' -Value $assignments -Force
            }

            # construct filename
            $odataType = $item.'@odata.type'
            $appType = $odataType -replace '#microsoft\.graph\.', ''
            $fileName = "$($item.displayName)_$appType"

            $clean = Remove-VolatileKeys -InputObject $item
            Save-BackupItem -Item $clean -Folder $folder -FileName $fileName -ScopeTagMap $ScopeTagMap
        }
        Write-Verbose "backed up $($items.Count) compliance policies to $folder"
    }
    catch {
        Write-Error "failed to backup compliance policies: $_"
        return
    }
}

Export-ModuleMember -Function Backup-Compliance