Blog Post

Azure Network Security Blog
4 MIN READ

Runbook to manage Azure Firewall Back ups

tobiotolorin's avatar
tobiotolorin
Icon for Microsoft rankMicrosoft
Jan 19, 2022

Azure Firewall is a managed stateful network security service that recently became generally available for premium features across most Azure regions, providing capabilities such as TLS inspection, URL filtering and more

Across the different virtual networks and subscriptions, rules are created for network segmentation and access control. Managing the network traffic may require you to audit rules for utilization, flow hit count or require a previous working configuration.

This runbook will help create instantaneous back-up copies of Azure Firewall with the Firewall Policy and when scheduled with an automation account, you can take daily/weekly snapshots and store them in a specified path.

For this runbook, Azure blob storage will be used to store Azure Firewall configuration for both network infrastructure and firewall policy at the time of the dump. You can edit the template to specify another storage method. We also discuss how to redeploy a firewall to a known configuration using one of the backed-up templates. For more information on other network resources that you may like to adapt to this runbook, please see the Export-AzResourceGroup module.


Requirements

  • Automation account
  • Storage Account
  • Runbook

 

Set up Automation account

Go to the Search bar and type Automation account. Create a New Automation account. When done, go to the Automation account and in the Settings blade, under Account settings, create a “Run As” account. This provide the service principal access that will be used to auto-login into our script later.

 

 

 

This runbook is a PowerShell module and we need to confirm that we have access to network and resources modules. On the Automation account blade which you have just created, go to Modules and then search the Gallery to import the following three requisites:

- Az.Account

- Az.Network

- Az.Resources

 

Create Storage account

Next, we create a storage account to store each back-up created in Azure Blob storage. Go to the search bar for resources and search for Storage Account. Create a Storage account. Select Cool storage mode

Next, we create the Runbook.

On the Automation account blade, click on Runbooks and create one. Here below, I have created AzFwBackUp.

 

 

After creating the runbook, copy the code from our Azure Network Security Github repository and paste it in line one. This code has three functions: 1. Create storage, 2. Export the firewall configuration, and save in the storage, and 3. Purge the older backups. It uses the Get-AzFirewall and Get-AzFirewallPolicy cmdlet to create snapshot instances.

 

Click Save and then click on Test Plane

 

 

 

 

On the next page, you will be prompted for a few parameters which you have set up earlier:

  • Provide the resource group name, Azure Firewall name and Firewall Policy name, obtainable in your Resource group
  • Provide storage account name that was created in the step earlier above and the storage key.  The storage key can be obtained under “Access Keys” in the Storage Account blade (see image below).
  • Give it a Blob container name and specify a retention date. Back-ups older than this date will be deleted at next run.

 

 

Test the script

Click Start to begin the dry run to confirm you can store a copy of the current configuration. Once done, you can then proceed to create a schedule to make this run periodically.

 

 

 

 The back-up should be available in your Storage -> Container in .json format.

 

Create a schedule

To create a schedule, go to the Runbook that was created, at the Runbook blade, select Schedules -> Add a Schedule. Give it a name and select “RecurringConfigure for every week or month.

 

 

Click to “Link the schedule to the runbook.” Select the runbook you have created and then click “Configure parameters and run settings,” Fill this form as done earlier.

The Runbook should now be all set to create back-ups in. json template that may be used to restore the firewall to an earlier configuration. The storage account should now store your back-ups as specified.

 

 

Restore Azure Firewall

To restore an Azure firewall (firewall infrastructure and firewall policy) to an earlier configuration, run the following syntax in your Cloud shell:

 

New-AzResourceGroupDeployment -name $azurefirewallname -ResourceGroupName $resourcegroupname -TemplateFile $filepath

 

Note that Rule Collection Groups or RCGs are treated as dependency objects and these objects cannot be deployed in parallel. Collection groups all reference the policy as dependant (dependsOn in the arm template).

This means it will first update policy and then try to update all rule collection groups in parallel. This may fail due to the policy dependency issue. (This is currently by ARM (Azure Resource Manager) design and a roadmap item).

Hence, rule collection groups must be deployed one after the other using the “depends on” tag in your firewall backup file.

As an example, the Rule Collection Group would have to be edited using the rule processing order.

The format is to first specify the Firewall Policy name, then Policy RCG object.

 

 

      "type": "Microsoft.Network/firewallPolicies/ruleCollectionGroups",

      "apiVersion": "2020-11-01",

      "name": "SOC-NS-FWPolicy_premium/DefaultNetworkRuleCollectionGroup",

      "location": "westus2",

      "dependsOn": [

        "[resourceId('Microsoft.Network/firewallPolicies', 'SOC-NS-FWPolicy_premium')]",

   "[resourceId('Microsoft.Network/firewallPolicies/ruleCollectionGroups', 'SOC-NS-FWPolicy_premium','DefaultDnatRuleCollectionGroup')]"

      ]

 

(Also, confirm that the KeyVault information is not missing after the redeployment is complete)

 

In summary, you may need to export firewall settings when creating child policies, restoring from a wrong configuration, auditing rules etc. By setting up frequent back up schedule, you can create a historical record of your configuration.
For more information about Azure firewall use cases and governance information, see the Azure Network Security TechCommunity blog  




Updated Jan 28, 2022
Version 3.0
  • It doesn't work. I copied the script into the runbook. It doesn't ask me to enter the details like storage ,Firewall, policy etc. Documentation is not adequate.

  • Hi Thangavel Mudaliar, thank you for the feedback.

    After pasting the script, click Save and then "Test Pane", you should see the following image below with all the input fields. Please let me know if you are still having problems.

     

     

  • Hi tobiotolorin,
    What is the cause of this error when I clicked on the start button.

    Failed
    Connection AzureRunAsConnection not established. (Connection AzureRunAsConnection not established.)

    What is the solution. 

     

  • Jmudhar90's avatar
    Jmudhar90
    Copper Contributor

    Hello, 

     

    This script does not function I am receiving same error as 'Run As' has been retired as of September 2023. 

     

    We now have to use Managed Identities , I have tried modifying the PowerShell script with no luck, 

     

    Any help would be appreciated. 

     

    Thanks

  • Jmudhar90's avatar
    Jmudhar90
    Copper Contributor

    Hello, 

     

    I have managed to update the script and got it working. 

     

    Azure Run As account has been retired so Managed Identities System Assigned is being used. I also added a Contributor Role Assignments in Identity within the Automation Account. 

     

    Please use the following: 

     

    <#

    ****************************************************************************************************************************
    This Azure Automation runbook automates Azure Firewall backups. It takes snapshots at different instances or schedules and 
    saves them to a Blob storage container. It also deletes old backups from blob storage.
    ****************************************************************************************************************************

    .DESCRIPTION
        You should use this Runbook if you want to manage Azure Firewall backups in Blob storage or just want to export the current configuration. It
        works as a power runbook.
        
    #>

    param(
        [parameter(Mandatory=$true)]
        [String] $ResourceGroupName,
        [parameter(Mandatory=$true)]
        [String] $AzureFirewallName,
        [parameter(Mandatory=$true)]
        [String] $AzureFirewallPolicy,
        [parameter(Mandatory=$true)]
        [String]$StorageAccountName,
        [parameter(Mandatory=$true)]
        [String]$StorageKey,
        [parameter(Mandatory=$true)]
        [string]$BlobContainerName,
        [parameter(Mandatory=$true)]
        [Int32]$RetentionDays
    )

    $ErrorActionPreference = 'stop'

    function Login() {
        $connectionName = "AzureRunAsConnection"
        try {
            # Connect using Managed Identity
            Write-Verbose "Connecting to Azure with Managed Identity..." -Verbose
            Connect-AzAccount -Identity

            # Example of using Service Principal
            # $servicePrincipalCredentials = Get-Credential
            # $null = Connect-AzAccount -ServicePrincipal -Credential $servicePrincipalCredentials
        }
        catch {
            Write-Error -Message $_.Exception
            throw $_.Exception
        }
    }

    function Create-newContainer([string]$blobContainerName$storageContext) {
        Write-Verbose "Creating '$blobContainerName' blob container space for storage..." -Verbose
        if (Get-AzureStorageContainer -ErrorAction "Stop" -Context $storageContext | Where-Object { $_.Name -eq $blobContainerName }) {
            Write-Verbose "Container '$blobContainerName' already exists" -Verbose
        } else {
            New-AzureStorageContainer -ErrorAction "Stop" -Name $blobContainerName -Permission Off -Context $storageContext
            Write-Verbose "Container '$blobContainerName' created" -Verbose
        }
    }

    function Export-To-Storageaccount([string]$resourceGroupName, [string]$AzureFirewallName, [string]$storageKey, [string]$blobContainerName,$storageContext) {
        Write-Verbose "Starting Azure Firewall current configuration export in json..." -Verbose
        try {
            $BackupFilename = $AzureFirewallName + (Get-Date).ToString("yyyyMMddHHmm") + ".json"
            $BackupFilePath = ($env:TEMP + "\" + $BackupFilename)
            $AzureFirewallId = (Get-AzFirewall -Name $AzureFirewallName -ResourceGroupName $resourceGroupName).id
            $FirewallPolicyID = (Get-AzFirewallPolicy -Name $AzureFirewallPolicy -ResourceGroupName $resourceGroupName).id
            Export-AzResourceGroup -ResourceGroupName $resourceGroupName -SkipAllParameterization -Resource @($AzureFirewallId$FirewallPolicyID) -Path $BackupFilePath
            #Export value and store with name created
            Write-Output "Submitting request to dump Azure Firewall configuration"
            $blobname = $BackupFilename
            $output = Set-AzureStorageBlobContent -File $BackupFilePath -Blob $blobname -Container $blobContainerName -Context $storageContext -Force -ErrorAction stop
        }
        #send out message if backup fails
        catch {
            $ErrorMessage = "BackUp not created. Please check the input values."
            throw $ErrorMessage
        }
    }

    function Remove-Older-Backups([int]$retentionDays, [string]$blobContainerName$storageContext) {
        Write-Output "Removing backups older than '$retentionDays' days from blob: '$blobContainerName'"
        $isOldDate = [DateTime]::UtcNow.AddDays(-$retentionDays)
        $blobs = Get-AzureStorageBlob -Container $blobContainerName -Context $storageContext
        foreach ($blob in ($blobs | Where-Object { $_.LastModified.UtcDateTime -lt $isOldDate -and $_.BlobType -eq "BlockBlob" })) {
            Write-Verbose ("Removing blob: " + $blob.Name) -Verbose
            Remove-AzureStorageBlob -Blob $blob.Name -Container $blobContainerName -Context $storageContext
        }
    }

    Write-Verbose "Starting database backup..." -Verbose

    $StorageContext = New-AzureStorageContext -StorageAccountName $storageAccountName -StorageAccountKey $storageKey

    #login to Azure
    Login
    Import-Module Az.Network
    Import-Module Az.Resources

    Create-newContainer `
        -blobContainerName $blobContainerName `
        -storageContext $storageContext
        
    Export-To-Storageaccount `
        -resourceGroupName $ResourceGroupName `
        -AzureFirewallName $AzureFirewallName `
        -storageKey $StorageKey `
        -blobContainerName $BlobContainerName `
        -storageContext $storageContext
        
    Remove-Older-Backups `
        -retentionDays $RetentionDays `
        -storageContext $StorageContext `
        -blobContainerName $BlobContainerName
        
    Write-Verbose "Azure Firewall current configuration back up completed." -Verbose