Start-IntuneBackup.ps1
|
#Requires -Version 7.0 <# .SYNOPSIS Orchestrates a full Intune backup. .DESCRIPTION Calls all Backup-* functions in parallel (or sequentially with -Sequential) and writes JSON output to BackupPath. .PARAMETER BackupPath The output root directory where backup files will be written. .PARAMETER Token Bearer token for Microsoft Graph as a SecureString. Falls back to $env:GRAPH_TOKEN. .PARAMETER Exclude Array of module names to skip (e.g., @('Filters', 'ScopeTags')). .PARAMETER IncludeActivationLock When set, also runs Backup-ActivationLock. .PARAMETER IncludeAutopilotDevices When set, also runs Backup-AutopilotDevices. .PARAMETER ThrottleLimit Maximum number of parallel threads. Default is 10. .PARAMETER Sequential When set, modules run sequentially instead of in parallel. Useful for testing. .PARAMETER SkipAssignmentReport When set, skips generating the Assignment Report. Useful when only policy backups are needed. .PARAMETER ResolveScopeTagIds When set, translates roleScopeTagIds from numeric IDs to display names in exported JSON. .EXAMPLE Start-IntuneBackup -BackupPath C:\Backup -Token $token #> function Start-IntuneBackup { [CmdletBinding()] param( [Parameter(Mandatory)] [string]$BackupPath, [SecureString]$Token = $null, [string[]]$Exclude = @(), [switch]$IncludeActivationLock, [switch]$IncludeAutopilotDevices, [int]$ThrottleLimit = 10, [switch]$Sequential, [switch]$ResolveScopeTagIds ) # Validate token if ($null -eq $Token -and $env:GRAPH_TOKEN) { $Token = ConvertTo-SecureString -String $env:GRAPH_TOKEN -AsPlainText -Force } if ($null -eq $Token) { throw 'No token provided and $env:GRAPH_TOKEN is not set' } # Create backup path if it doesn't exist if (-not (Test-Path -Path $BackupPath)) { New-Item -ItemType Directory -Path $BackupPath -Force | Out-Null } # Fetch scope tag map once (only when scope tag ID resolution is requested) $scopeTagMap = if ($ResolveScopeTagIds) { Get-ScopeTags -Token $Token } else { @{} } # Build modules list (35 standard non-opt-in modules) $modules = @( @{ Name = 'APNs'; Function = 'Backup-APNs' }, @{ Name = 'AppConfiguration'; Function = 'Backup-AppConfiguration' }, @{ Name = 'AppProtection'; Function = 'Backup-AppProtection' }, @{ Name = 'AppleEnrollmentProfiles'; Function = 'Backup-AppleEnrollmentProfiles' }, @{ Name = 'Applications'; Function = 'Backup-Applications' }, @{ Name = 'Compliance'; Function = 'Backup-Compliance' }, @{ Name = 'CompliancePartner'; Function = 'Backup-CompliancePartner' }, @{ Name = 'ComplianceScripts'; Function = 'Backup-ComplianceScripts' }, @{ Name = 'ConditionalAccess'; Function = 'Backup-ConditionalAccess' }, @{ Name = 'CustomAttributes'; Function = 'Backup-CustomAttributes' }, @{ Name = 'DeviceCategories'; Function = 'Backup-DeviceCategories' }, @{ Name = 'DeviceCompliance'; Function = 'Backup-DeviceCompliance' }, @{ Name = 'DeviceConfigurations'; Function = 'Backup-DeviceConfigurations' }, @{ Name = 'DeviceManagementSettings'; Function = 'Backup-DeviceManagementSettings' }, @{ Name = 'EnrollmentConfigurations'; Function = 'Backup-EnrollmentConfigurations' }, @{ Name = 'EnrollmentStatusPage'; Function = 'Backup-EnrollmentStatusPage' }, @{ Name = 'Filters'; Function = 'Backup-Filters' }, @{ Name = 'GroupPolicyConfigurations'; Function = 'Backup-GroupPolicyConfigurations' }, @{ Name = 'ManagedGooglePlay'; Function = 'Backup-ManagedGooglePlay' }, @{ Name = 'ManagementIntents'; Function = 'Backup-ManagementIntents' }, @{ Name = 'ManagementPartner'; Function = 'Backup-ManagementPartner' }, @{ Name = 'NotificationTemplates'; Function = 'Backup-NotificationTemplates' }, @{ Name = 'PowerShellScripts'; Function = 'Backup-PowerShellScripts' }, @{ Name = 'ProactiveRemediation'; Function = 'Backup-ProactiveRemediation' }, @{ Name = 'RemoteAssistancePartner'; Function = 'Backup-RemoteAssistancePartner' }, @{ Name = 'ReusableSettings'; Function = 'Backup-ReusableSettings' }, @{ Name = 'Roles'; Function = 'Backup-Roles' }, @{ Name = 'ScopeTags'; Function = 'Backup-ScopeTags' }, @{ Name = 'SettingsCatalog'; Function = 'Backup-SettingsCatalog' }, @{ Name = 'ShellScripts'; Function = 'Backup-ShellScripts' }, @{ Name = 'VolumePurchaseProgram'; Function = 'Backup-VolumePurchaseProgram' }, @{ Name = 'WindowsDriverUpdates'; Function = 'Backup-WindowsDriverUpdates' }, @{ Name = 'WindowsEnrollmentProfiles'; Function = 'Backup-WindowsEnrollmentProfiles' }, @{ Name = 'WindowsFeatureUpdates'; Function = 'Backup-WindowsFeatureUpdates' }, @{ Name = 'WindowsQualityUpdates'; Function = 'Backup-WindowsQualityUpdates' }, @{ Name = 'AssignmentReport'; Function = 'Build-AssignmentReport' } ) # Add opt-in modules if ($IncludeActivationLock) { $modules += @{ Name = 'ActivationLock'; Function = 'Backup-ActivationLock' } } if ($IncludeAutopilotDevices) { $modules += @{ Name = 'AutopilotDevices'; Function = 'Backup-AutopilotDevices' } } # Filter out excluded modules $modulesToRun = $modules | Where-Object { $_.Name -notin $Exclude } if ($Sequential) { # Sequential mode — enables mock interception in tests foreach ($mod in $modulesToRun) { & $mod.Function -BackupPath $BackupPath -Token $Token -ScopeTagMap $scopeTagMap } } else { # Parallel mode (production default) # SecureString cannot cross runspace boundaries — decrypt here and re-encrypt per runspace $modulePath = "$PSScriptRoot\IntuneBackup.psm1" $plainToken = ConvertFrom-SecureString -SecureString $Token -AsPlainText $path = $BackupPath $tags = $scopeTagMap $modulesToRun | ForEach-Object -Parallel { Import-Module $using:modulePath -Force $secureToken = ConvertTo-SecureString -String $using:plainToken -AsPlainText -Force $func = $_ & $func.Function -BackupPath $using:path -Token $secureToken -ScopeTagMap $using:tags } -ThrottleLimit $ThrottleLimit } Write-Host "Backup complete. $($modulesToRun.Count) module(s) backed up to $BackupPath" } Export-ModuleMember -Function Start-IntuneBackup |