All scripts
Automation 190

Backup-AzurePolicyDefinitions

Exports every custom Azure Policy definition and initiative in the subscription to JSON, so custom governance work can be version controlled or restored after an accidental change.

Backup-AzurePolicyDefinitions.ps1
<#
.SYNOPSIS
    Backs up custom Azure Policy definitions and initiatives to JSON.

.DESCRIPTION
    Exports every custom (non built in) policy definition and initiative
    to individual JSON files, so custom governance work can be version
    controlled outside the portal or restored after an accidental
    change.

.PARAMETER BackupPath
    Folder to write the backup files to. Defaults to the current directory.

.EXAMPLE
    .\Backup-AzurePolicyDefinitions.ps1 -BackupPath C:\Backups\Policy

.NOTES
    Requires the Az.PolicyInsights module and an active Connect-AzAccount session.

.AUTHOR
    Shehryar Hassan
#>

param(
    [string]$BackupPath = (Get-Location).Path
)

$stamp = Get-Date -Format "yyyy-MM-dd_HHmmss"
$folder = Join-Path $BackupPath "AzurePolicyBackup_$stamp"
New-Item -ItemType Directory -Path $folder -Force | Out-Null

$definitions = Get-AzPolicyDefinition -Custom
foreach ($def in $definitions) {
    $safeName = $def.Name -replace "[:\\/*?<>|]", "_"
    $def | ConvertTo-Json -Depth 8 | Out-File -FilePath (Join-Path $folder "$safeName.json") -Encoding utf8
}

$initiatives = Get-AzPolicySetDefinition -Custom
foreach ($init in $initiatives) {
    $safeName = $init.Name -replace "[:\\/*?<>|]", "_"
    $init | ConvertTo-Json -Depth 8 | Out-File -FilePath (Join-Path $folder "initiative-$safeName.json") -Encoding utf8
}

Write-Host "Backed up $($definitions.Count) definition(s) and $($initiatives.Count) initiative(s) to $folder" -ForegroundColor Cyan

Read it before you run it, and test in a safe tenant first.