Contents

Backup and Restore Azure Firewall

Contents

Issue

Azure Firewall has no backup feature. Yes, really.
Surprisingly, there is no config back facility within Azure Firewall. It is typical to regularly create a backup of the config and also to perform backup prior to a change.

Let’s address that with some PowerShell.


Solution

We can leverage the Export-AzResourceGroup cmdlet to create an effective backup by exporting a deployment JSON template.

This post will create a local backup useful for:

  1. A restore point for an adhoc change.
  2. Documenting a recent deployment.

A future post will address automating a backup.

Note
Note, I am using PoshLog for logging.
Check out my previous post on PowerShell logging.

Backup

Create a backup of the firewall and store to the local machine.


 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
# BACKUP AZURE FIREWALL RESOURCE: #############################################
# DEFINITIONS: ################################################################
# Tenancy: --------------------------------------------------------------------
$SubscriptionId         = "[REDACTED]"
$TenantId               = "[REDACTED]"

# Firewall: -------------------------------------------------------------------
$AzFwName               = "fw-hub-ase-01"
$AzFwBackupFileName     = "Backup-$AzFwName-$(Get-Date -Format 'yyyy-MM-dTHH-mm-ss').json"
$FirewallBackup         = [System.IO.Path]::Combine($BackupFilePath, $AzFwBackupFileName)

# Backup Location: ------------------------------------------------------------
$BackupFilePath         = "C:\Temp\" 

# Logging: --------------------------------------------------------------------
$LogPath                = "C:\Temp\"
$LogFilename            = "Log-$(Get-Date -Format 'yyyy-MM-dTHH-mm-ss').log"
$Log                    = [System.IO.Path]::Combine($LogPath, $LogFilename  )

$Logger = New-Logger |
     Set-MinimumLevel -Value Verbose |
     Add-EnrichWithProperty -Name UserName -Value $($env:USERNAME).ToLower() |
     Add-EnrichWithEnvironment -UserName -MachineName |
     Add-EnrichWithProcessId | Add-EnrichWithProcessName |
     Add-EnrichWithExceptionDetails |
     Add-SinkFile -Path $Log -OutputTemplate '[ {Level:u3} ] [ {UserName}@{MachineName} ] [ PID: {ProcessName}:{ProcessId} ] [ {Timestamp:yyyy-MM-dd HH:mm:ss.fff zzz} ] {Message:lj}{NewLine}{Exception}' |
     Add-SinkConsole -OutputTemplate "[{Timestamp:HH:mm:ss} {Level:u3}] {Message:lj}{NewLine}{Exception}" | 
     Start-Logger -PassThru

Write-InfoLog "Log File Location: {log}" -PropertyValues $Log

# CONNECTION: #################################################################
# Connect to Tenancy: ---------------------------------------------------------
try {
    Write-InfoLog "Connecting to Azure Subscription [ {SubscriptionID} ] on tenancy [ {TenantId} ]..." -PropertyValues $SubscriptionID, $TenantId
    Connect-AzAccount -Subscription $SubscriptionId -Tenant $TenantId -ErrorAction Stop
}
catch {
    Write-WarningLog "Connecting to Azure Subscription [ {SubscriptionID} ] on tenancy [ {TenantId} ] failed!" -PropertyValues $SubscriptionID, $TenantId
    Write-ErrorLog -Exception $_
    exit

} # END try/catch

# BACKUP: #####################################################################
try {
    # Capture the firewall object.
    Write-InfoLog "Capturing Azure Firewall Object [ {AzFwName} ]..." -PropertyValues $AzFwName
    $AzFw = Get-AzFirewall -Name $AzFwName -ErrorAction Stop

    # Export the JSON template.
    Write-InfoLog "Backing up [ $($AzFw.Name) ] firewall config to {FirewallBackup}" -PropertyValues $FirewallBackup
    Export-AzResourceGroup -ResourceGroupName $AzFw.ResourceGroupName -Resource $AzFw.Id -SkipAllParameterization -Path $FirewallBackup -ErrorAction Stop

}
catch {
    Write-WarningLog "Backing up [ $($AzFw.Name) ] firewall config to ${FirewallBackup} failed." -PropertyValues $FirewallBackup
    Write-ErrorLog -Exception $_
    exit
    
} # END try/catch

Close-Logger

With a successful backup changes can be made to the firewall with the option of a rollback.


Rollback

The rollback assumes maintaining the current PowerShell session with the loaded variables.


 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
# Restore Firewall Object: ####################################################
# Restart the Logger: ---------------------------------------------------------
$Logger = New-Logger |
     Set-MinimumLevel -Value Verbose |
     Add-EnrichWithProperty -Name UserName -Value $($env:USERNAME).ToLower() |
     Add-EnrichWithEnvironment -UserName -MachineName |
     Add-EnrichWithProcessId | Add-EnrichWithProcessName |
     Add-EnrichWithExceptionDetails |
     Add-SinkFile -Path $Log -OutputTemplate '[ {Level:u3} ] [ {UserName}@{MachineName} ] [ PID: {ProcessName}:{ProcessId} ] [ {Timestamp:yyyy-MM-dd HH:mm:ss.fff zzz} ] {Message:lj}{NewLine}{Exception}' |
     Add-SinkConsole -OutputTemplate "[{Timestamp:HH:mm:ss} {Level:u3}] {Message:lj}{NewLine}{Exception}" | 
     Start-Logger -PassThru

try {
   # Deploy the rollback JSON template: ---------------------------------------
   Write-InfoLog "Restoring [ $($AzFw.Name) ] from [ {FirewallBackup} ]..." -PropertyValues $FirewallBackup
   New-AzResourceGroupDeployment -Name "FirewallRestoreJob" -ResourceGroupName $AzFw.ResourceGroupName -TemplateFile "$FirewallBackup" -ErrorAction Stop
   Write-InfoLog "Restore [ $($AzFw.Name) ] from [ {FirewallBackup} ] complete." -PropertyValues $FirewallBackup   
}
catch {
   Write-InfoLog "Restoring [ $($AzFw.Name) ] from [ {FirewallBackup} ] failed!" -PropertyValues $FirewallBackup
   Write-ErrorLog -Exception $_
   
} # END try/catch

Close-Logger $Logger

Note
A backup and restore has been tested and functions as at the time of writing. Azure Firewall is a developing product so always test in development to ensure the expected behaviour.

Summary

Done!
Hopefully this post shows you how simply you can create a backup and restore your way out of trouble.

Hope that helps!