A toolkit for backing up, restoring, and managing Microsoft Intune tenant configurations using Github Actions and PowerShell scripts.
This repository provides automated solutions for:
- Tenant Snapshots: Create point-in-time backups of your entire Intune tenant
- Configuration Recovery: Restore specific policies or entire tenant configurations
- Environment Migration: Copy configurations between tenants (DEV β PROD)
- Disaster Recovery: Quickly restore tenant state from snapshots
- Policy Management: Bulk import/export of Intune policies and configurations
- Scheduled Automation: Daily automated backups via GitHub Actions
- JSON Encoding: Built-in UTF-8 conversion for compatibility
- Dry Run Testing: Preview import operations without making changes
- Comprehensive Logging: Detailed execution logs with automatic rotation
π§ Powered by IntuneManagement
This toolkit leverages the powerful IntuneManagement project as its core engine. The IntuneManagement tool provides the robust Microsoft Graph API integration and comprehensive Intune object type support that makes this automation possible.
π Best Practice Policies Included
This repository includes curated best practice policies from OpenIntuneBaseline, providing a comprehensive set of security-focused configurations for Windows, macOS, and mobile platforms. These policies offer a solid foundation for implementing secure endpoint management across your organization.
βββ .github/workflows/ # GitHub Actions workflows
β βββ IntuneExportParameterized.yml # Parameterized export workflow (with scheduling)
β βββ IntuneImportParameterized.yml # Parameterized import workflow (with dry run)
βββ intune-backup/ # Backup storage directory
β βββ OpenIntuneBaseline/ # Best practice policies from OpenIntuneBaseline
β βββ sample-tenant/ # Sample tenant configurations
β βββ [tenant-name]/ # Tenant-specific backups
β βββ Applications/
β βββ CompliancePolicies/
β βββ DeviceConfiguration/
β βββ [other-policy-types]/
βββ Invoke-IntuneBackupRestore.ps1 # Unified backup/restore script with dynamic configuration
βββ logs/ # Execution logs directory (auto-created)
β βββ IntuneBackupRestore_*.log # Timestamped log files
βββ README.md
You'll need an Azure AD app registration with the following permissions:
Microsoft Graph API Permissions:
DeviceManagementApps.ReadWrite.AllDeviceManagementConfiguration.ReadWrite.AllDeviceManagementManagedDevices.ReadWrite.AllDeviceManagementServiceConfig.ReadWrite.AllGroup.Read.AllGroupMember.Read.AllUser.Read.AllAgreement.Read.All(Optional for exporting Terms of use objects)Agreement.ReadWrite.All(Optional for exporting Terms of use objects)
Directory (Azure AD) Graph Permissions:
Policy.ReadWrite.ConditionalAccessPolicy.Read.All
Configure these secrets in your GitHub repository:
AZURE_TENANT_ID: Your Azure AD tenant IDAZURE_CLIENT_ID: Azure AD app registration client IDAZURE_CLIENT_SECRET: Azure AD app registration client secret
- PowerShell 5.1 (PowerShell Core v6+ not currently supported)
- Git (for cloning IntuneManagement tool)
- Internet connection (to download dependencies)
git clone https://github.com/jorgeasaurus/Intune-Snapshot-Recovery
cd Intune-Snapshot-Recovery# Basic backup
.\Invoke-IntuneBackupRestore.ps1 `
-Action Backup `
-TenantId $env:AZURE_TENANT_ID `
-AppId $env:AZURE_CLIENT_ID `
-Secret $env:AZURE_CLIENT_SECRET `
-BackupPath ".\intune-backup\production"
# Customized backup with specific options
.\Invoke-IntuneBackupRestore.ps1 `
-Action Backup `
-TenantId $env:AZURE_TENANT_ID `
-AppId $env:AZURE_CLIENT_ID `
-Secret $env:AZURE_CLIENT_SECRET `
-BackupPath ".\intune-backup\custom" `
-AddCompanyName $true `
-ExportAssignments $true# Basic restore from backup
.\Invoke-IntuneBackupRestore.ps1 `
-Action Restore `
-TenantId $env:AZURE_TENANT_ID `
-AppId $env:AZURE_CLIENT_ID `
-Secret $env:AZURE_CLIENT_SECRET `
-BackupPath ".\intune-backup\production"
# Deploy OpenIntuneBaseline best practice policies
.\Invoke-IntuneBackupRestore.ps1 `
-Action Restore `
-TenantId $env:AZURE_TENANT_ID `
-AppId $env:AZURE_CLIENT_ID `
-Secret $env:AZURE_CLIENT_SECRET `
-BackupPath ".\intune-backup\OpenIntuneBaseline" `
-DryRun
# Dry run restore (preview only)
.\Invoke-IntuneBackupRestore.ps1 `
-Action Restore `
-TenantId $env:AZURE_TENANT_ID `
-AppId $env:AZURE_CLIENT_ID `
-Secret $env:AZURE_CLIENT_SECRET `
-BackupPath ".\intune-backup\production" `
-DryRunThe IntuneExportParameterized.yml workflow runs daily at 14:00 UTC and can be triggered manually.
Use IntuneExportParameterized.yml for custom export operations:
- Go to Actions β Intune Export - Parameterized
- Click Run workflow
- Configure parameters:
- Export path
- Object types to include
- Export options (assignments, scripts, etc.)
- Company name inclusion
- Application file export
- Scheduled execution: Automatically runs daily at 14:00 UTC
Use IntuneImportParameterized.yml for custom import operations:
- Go to Actions β Intune Import - Parameterized
- Click Run workflow
- Configure parameters:
- Import path
- Import behavior (skip/overwrite/append)
- Conditional Access state
- Dry run option for safe testing
- Assignment import control
- Dependency ID replacement
The Invoke-IntuneBackupRestore.ps1 script automatically generates configuration files based on parameters, eliminating the need for manual JSON file management. All configuration is done through script parameters for maximum flexibility and ease of use.
The script automatically generates detailed execution logs for troubleshooting and audit purposes:
Features:
- Automatic Log Creation: Logs are saved to
.\logs\directory (auto-created) - Timestamped Files: Format:
IntuneBackupRestore_[Action]_[Timestamp].log - Detailed Information: Includes script parameters, execution steps, and outcomes
- Automatic Cleanup: Old log files (30+ days) are automatically removed
- Security: Sensitive information (secrets) are redacted from logs
Log Control:
# Enable logging (default)
.\Invoke-IntuneBackupRestore.ps1 `
-Action Backup `
-TenantId "..." `
-AppId "..." `
-Secret "..." `
-BackupPath "..." `
-EnableLogging $true
# Disable logging
.\Invoke-IntuneBackupRestore.ps1 `
-Action Backup `
-TenantId "..." `
-AppId "..." `
-Secret "..." `
-BackupPath "..." `
-EnableLogging $false
# Custom log directory
.\Invoke-IntuneBackupRestore.ps1 `
-Action Backup `
-TenantId "..." `
-AppId "..." `
-Secret "..." `
-BackupPath "..." `
-LogPath "C:\MyLogs"The unified script allows you to specify all configuration options directly as parameters, providing maximum flexibility without requiring configuration files:
# Advanced backup with selective object types
.\Invoke-IntuneBackupRestore.ps1 `
-Action Backup `
-TenantId "$env:AZURE_TENANT_ID" `
-AppId "$env:AZURE_CLIENT_ID" `
-Secret "$env:AZURE_CLIENT_SECRET" `
-BackupPath ".\selective-backup" `
-ObjectTypes @("CompliancePolicies", "DeviceConfiguration") `
-ExportAssignments $true
# Restore with specific import behavior
.\Invoke-IntuneBackupRestore.ps1 `
-Action Restore `
-TenantId "$env:AZURE_TENANT_ID" `
-AppId "$env:AZURE_CLIENT_ID" `
-Secret "$env:AZURE_CLIENT_SECRET" `
-BackupPath ".\intune-backup\production" `
-ImportType "overwrite" `
-ImportAssignments $true `
-CAState "disabled"- Automated daily backups via GitHub Actions
- Version-controlled configuration history
- Quick rollback capabilities
- Deploy OpenIntuneBaseline security policies to new tenants
- Implement industry-standard security configurations
- Use as a foundation for custom policy development
# Export from DEV tenant
.\Invoke-IntuneBackupRestore.ps1 `
-Action Backup `
-TenantId $env:DEV_AZURE_TENANT_ID `
-AppId $env:DEV_AZURE_CLIENT_ID `
-Secret $env:DEV_AZURE_CLIENT_SECRET `
-BackupPath ".\dev-export"
# Import to PROD tenant
.\Invoke-IntuneBackupRestore.ps1 `
-Action Restore `
-TenantId $env:PROD_AZURE_TENANT_ID `
-AppId $env:PROD_AZURE_CLIENT_ID `
-Secret $env:PROD_AZURE_CLIENT_SECRET `
-BackupPath ".\dev-export"- Restore from latest backup in
intune-backup/directory - Use dry run to validate before applying changes
- Selective restore of specific policy types
- Use dry run mode in GitHub Actions
- Validate configurations without applying changes
- Test import behavior safely
# Only export specific object types using parameters
.\Invoke-IntuneBackupRestore.ps1 `
-Action Backup `
-TenantId "$env:AZURE_TENANT_ID" `
-AppId "$env:AZURE_CLIENT_ID" `
-Secret "$env:AZURE_CLIENT_SECRET" `
-BackupPath ".\selective-backup" `
-ObjectTypes @("CompliancePolicies", "DeviceConfiguration", "AppProtection")skipIfExist: Skip if policy already existsoverwrite: Replace existing policiesappend: Add new policies only
disabled: Import CA policies in disabled stateenabled: Import CA policies as enabledenabledForReportingButNotEnforced: Report-only mode
- Store Azure credentials securely in GitHub Secrets
- Use service principal with minimal required permissions
- Regularly rotate client secrets
- Review export contents before committing to version control
- Always test imports in non-production environments first
- Use dry run mode to validate configurations
- Maintain separate configurations for different tenants
- Regular backup schedule (daily recommended)
- Document any custom configurations or filters
- Some settings may not be exportable/importable
- Tenant-specific GUIDs will be different between environments
- Some dependencies may need manual configuration
- Rate limiting may affect large tenant operations
PowerShell Execution Policy
Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUserAuthentication Failures
- Verify Azure AD app permissions
- Check client secret expiration
- Confirm tenant ID is correct
Add -Verbose parameter to scripts for detailed logging:
.\Invoke-IntuneBackupRestore.ps1 `
-Action Backup `
-TenantId $env:AZURE_TENANT_ID `
-AppId $env:AZURE_CLIENT_ID `
-Secret $env:AZURE_CLIENT_SECRET `
-BackupPath ".\debug-backup" `
-VerboseReview execution logs for detailed troubleshooting information:
# View latest log file
Get-ChildItem -Path ".\logs" -Filter "IntuneBackupRestore_*.log" |
Sort-Object LastWriteTime -Descending | Select-Object -First 1 | Get-Content
# Search for errors in recent logs
Get-ChildItem -Path ".\logs" -Filter "IntuneBackupRestore_*.log" |
Sort-Object LastWriteTime -Descending | Select-Object -First 5 |
ForEach-Object { Select-String -Path $_.FullName -Pattern "ERROR" }- IntuneManagement Tool - Underlying backup/restore engine
- Microsoft Graph API Documentation
- Azure AD App Registration Guide
- Fork the repository
- Create a feature branch
- Make your changes
- Test thoroughly
- Submit a pull request
This project is licensed under the MIT License - see the LICENSE file for details.
This tool is provided as-is. Always test in non-production environments first. The authors are not responsible for any data loss or configuration issues that may arise from using this tool.
