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:
- A restore point for an adhoc change.
- 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!