Azure Automation Runbook – Stop/Start Azure Firewall

Azure Automation runbooks can be used for numerous scheduled tasks throughout your Azure subscription, in this blog I will show how it can be used to stop & start Azure Firewall in both a schedule and invoking using a webhook.

What types of runbooks are available?

TypeDescription
GraphicalBased on Windows PowerShell that uses a graphical editor
Graphical PowerShell Workflow Based on Windows PowerShell workflow that uses a graphical editor
PowerShell Based on Windows PowerShell
PowerShell Workflow Based on Windows PowerShell workflow
PythonBased on Python

For the scripting below, it will be based on type: PowerShell

What is needed to create an Azure Automation Runbook?

To create a runbook, you need to create an Azure Automation account, I will create an AutomationAccount: tamopsaa in Resource Group: tamops-aa-rg in Region: eastus

$ResourceGroup = "tamops-aa-rg"
$Location = "eastus"
$AutomationAccountName = "tamopsaa"

$RG = New-AzResourceGroup -Name $ResourceGroup -Location $Location
New-AzAutomationAccount -Name $AutomationAccountName -Location $RG.Location -ResourceGroupName $RG.ResourceGroupName

Now that we have created an Azure Automation Account, we now need to create an “Run As Account” within this. The “Run As Account” is used to provide authentication for managing resources within your Azure Portal using Azure cmdlets.

When the account is created, you are creating a service principle user within the Azure Active Directory that has been assigned contributor role to your subscription.

Select Automation Account: tamopsaa

Under Account Settings -> Run as Accounts

Select Azure Run As Account & Create

As AzFirewall cmdlets will be used, Az.Accounts & Az.Network module needs to be added from the gallery.

Within Automation Account: tamopsaa

Select Modules

Select Browse Gallery

Search for Az.Accounts

Select import & wait for module to be imported into Modules location as above. Now do the same process for Az.Network

The PowerShell runbook

Now the start/stop Azure Firewall script can be added to a runbook, script is below:

Param(
        [Parameter(Mandatory=$false)][ValidateNotNullOrEmpty()] 
        [String]
        $RunAsConnectionName = "AzureRunAsConnection",
        
        [Parameter(Mandatory=$true)][ValidateNotNullOrEmpty()] 
        [String] 
        $AzureFirewallName, 
        
        [Parameter(Mandatory=$true)][ValidateNotNullOrEmpty()] 
        [String] 
        $AzureFirewallResourceGroup, 
        
        [Parameter(Mandatory=$true)][ValidateNotNullOrEmpty()] 
        [String] 
        $AzureFirewallVnetName, 

        [Parameter(Mandatory=$true)][ValidateNotNullOrEmpty()] 
        [String] 
        $AzureFirewallPipName, 

        [Parameter(Mandatory=$true)][ValidateNotNullOrEmpty()] 
        [String] 
        $AzureFirewallPipResourceGroup, 

        [Parameter(Mandatory=$true)][ValidateSet("Start","Stop")] 
        [String] 
        $Action
)


try {
    # Get the connection "AzureRunAsConnection "
    $servicePrincipalConnection = Get-AutomationConnection -Name $RunAsConnectionName
    "Logging in to Azure..."
    $connectionResult =  Connect-AzAccount -Tenant $servicePrincipalConnection.TenantID `
                             -ApplicationId $servicePrincipalConnection.ApplicationID   `
                             -CertificateThumbprint $servicePrincipalConnection.CertificateThumbprint `
                             -ServicePrincipal
    "Logged in."
}
catch {
    if (!$servicePrincipalConnection) {
        $ErrorMessage = "Connection $RunAsConnectionName not found."
        throw $ErrorMessage
    } else{
        Write-Error -Message $_.Exception
        throw $_.Exception
    }
}

    $azfw = Get-AzFirewall -Name $AzureFirewallName -ResourceGroupName $AzureFirewallResourceGroup

if($Action -eq "Stop") { 
    "Stopping Azure Firewall $AzureFirewallName"
    $azfw.Deallocate() 
    
        Set-AzFirewall -AzureFirewall $azfw

} elseif ($Action -eq "Start") {
    $vnet = Get-AzVirtualNetwork -ResourceGroupName $AzureFirewallResourceGroup -Name $AzureFirewallVnetName
    $publicip = Get-AzPublicIpAddress -Name $AzureFirewallPipName -ResourceGroupName $AzureFirewallPipResourceGroup
    $azfw.Allocate($vnet,$publicip) 
    
        Set-AzFirewall -AzureFirewall $azfw
}

To create Azure Automation RunBook

Select Runbooks within Automation Account

Select Create a Runbook

Enter details and create

Click Edit and paste in script & save Runbook

Now the Runbook is ready to be scheduled, from the script – there is several parameters required:-

$RunAsConnectionName – Leave default and “AzureRunAsConnection” will be used
$AzureFirewallName – Name of Azure Firewall
$AzureFirewallResourceGroup – Azure Firewall Resource Group
$AzureFirewallVnetName – Azure Firewall vNET
$AzureFirewallPipName – Azure Firewall Public IP
$AzureFirewallPipResourceGroup – Azure Firewall Public IP Resource Group
$Action – Validation, only Start / Stop allowed

Before creating a schedule, the runbook needs to be Published

Select Schedules

Create a New Schedule as below, showing a daily PowerOff for 19:00

Now configure parameters as mentioned above and select save

Schedule now created and ready to go.

Lets now look at WebHooks

The runbook can be invoked with a Post method as well within a Webhook, handy to use if multiple users may want to stop/start Azure Firewall – they only need to use the URL.

Within the runbook – select Webhooks

Add Webhook as below – Note down URL , in parameters and run settings have either stop or start Azure Firewall. If required for both, two webhooks will be required. (You can script the PowerShell to invoke paramters from Webhooks but in this example I haven’t included this)

To run the newly created webhook in PowerShell

Invoke-WebRequest https://s16events.azure-automation.net/webhooks?token=iCTXDD%2bp7%2fHBGLm4MV%2f57rB%2bryacwKRDE7pTB0yPSyI%3d -Method Post

Will return

StatusCode        : 202
StatusDescription : Accepted
Content           : {"JobIds":["58c23c5e-d268-403b-9624-1a068c939568"]}
RawContent        : HTTP/1.1 202 Accepted
                    Pragma: no-cache
                    Strict-Transport-Security: max-age=31536000; includeSubDomains
                    Content-Length: 51
                    Cache-Control: no-cache
                    Content-Type: application/json; charset=utf-8
                    Dat...
Forms             : {}
Headers           : {[Pragma, no-cache], [Strict-Transport-Security, max-age=31536000; includeSubDomains], [Content-Length, 51], [Cache-Control, no-cache]...}
Images            : {}
InputFields       : {}
Links             : {}
ParsedHtml        : mshtml.HTMLDocumentClass
RawContentLength  : 51

To review output further, you can select the job within runbook Overview

Within this blog, I have referenced how to deploy Azure Runbooks and also invoke them using a schedule along with webhooks – any further queries, do give me a shout !

3 comments

    1. Hi Grant,

      Yes that is correct – multiple subscriptions context was not considered as part of this script

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s