Palo Alto Automation: Azure HA Configuration

Another day, another post about Palo Alto. We have been covering ways to convert your Palo Alto setup to use more automation, specifically through PowerShell. We continue down that path, as we look at deploying Palo Alto appliances into Azure specifically.

Active / Passive HA

In June, Palo Alto Networks announced they were bringing traditional Active/Passive HA configuration to Azure. Good news for fans of this configuration, providing a single floating IP to the external and internal, and not requiring the configuration of two separate devices.

This setup is helpful if you have devices that need to receive traffic without source translation. Redirecting an Active/Active setup typically requires the use of SNAT to successfully redirect traffic back to the original destination.

The new configuration is not without drawbacks however. An Active/Passive setup relies on using an Azure Service Principal Account to communicate with the Azure Fabric, requiring this account to be configured before the HA setup works.

As part of this communication process, the floating IP can take around three minutes to migrate to the other node if using a Public IP, and around one to two without. If these are risks worth taking for your setup, the process is not too involved in getting it configured.

Azure Configuration

Service Principal Configuration

As discussed, configuring Active/Passive HA requires the creation of a new Service Principal Account. From the documentation provided by Palo Alto, the requested permissions for this account is Contributor to the entire subscription.

If you are comfortable handing out these permissions, follow the rest of the document, and you should be able to configure it without issue. If you are worried about handing off Contributor access to accounts, there are limited permissions you can set to achieve the same goal.

For those wanting to use built-in permissions, you will still require Contributor to the Resource Group containing the Palo Alto’s Network Interfaces, and the Resource Group containing the Virtual Network they are attached to, with Read permissions to the subscription.

If you want to develop a custom role, we will target the same resource levels. We will want to keep Read permissions on the subscription, as we have seen issues when that is removed. For both the Resource Group containing the Network Interfaces, and the Resource Group containing the Virtual Network, we will be able to create a new role with the permissions below.

Microsoft.Network/dnszones/*/write
Microsoft.Network/dnszones/*/read
Microsoft.Network/dnszones/*/delete
Microsoft.Network/locations/*/read
Microsoft.Network/networkIntentPolicies/read
Microsoft.Network/networkInterfaces/delete
Microsoft.Network/networkInterfaces/read
Microsoft.Network/networkInterfaces/write
Microsoft.Network/operations/read
Microsoft.Network/privateDnsZones/*/delete
Microsoft.Network/privateDnsZones/*/read
Microsoft.Network/privateDnsZones/*/write
Microsoft.Network/publicIPAddresses/delete
Microsoft.Network/publicIPAddresses/join/action
Microsoft.Network/publicIPAddresses/read
Microsoft.Network/publicIPAddresses/write
Microsoft.Network/publicIPPrefixes/delete
Microsoft.Network/publicIPPrefixes/join/action
Microsoft.Network/publicIPPrefixes/read
Microsoft.Network/publicIPPrefixes/write
Microsoft.Network/virtualNetworks/join/action
Microsoft.Network/virtualNetworks/read
Microsoft.Network/virtualNetworks/subnets/join/action
Microsoft.Network/virtualNetworks/subnets/read
Microsoft.Network/virtualNetworks/subnets/virtualMachines/read
Microsoft.Network/virtualNetworks/subnets/write
Microsoft.Network/virtualNetworks/usages/read
Microsoft.Network/virtualNetworks/virtualMachines/read
Microsoft.Network/virtualNetworks/write

With these permissions in place, we were able to successfully perform a failover, without having to hand out Contributor access.

Device Configuration

After licensing the device, head to the Device tab, and locate the VM-Series option in the left pane. Upon selecting it, you will see two boxes, Azure Application Insights, and Azure HA Configuration. We’re going to cover the latter today.

Selecting the gear icon on Azure HA Configuration opens a small pop-up. Within this pop-up enter the details from the Azure Service Principal Account. Adding the Application ID as Client Id, the Key as Secret, and the Tenant, Subscription, and Resource Group from the subscription you configured the account within.

This works great, but what if we want to look at automating this solution? We covered how to get these requests from the debug log, so we should head over and see what information we can pull.

<request cmd="edit" obj="/config/devices/entry[@name='localhost.localdomain']/deviceconfig/plugins/vm_series/azure-ha-config">
<azure-ha-config>
<client-id>ClientId</client-id>
<client-####censored 'secret''####

That is less helpful than we anticipated. The good news is there are other ways to get this information.

Automation Solution

Again referencing our earlier posts, we covered how to generate Palo Alto requests via PowerShell. This is helpful here, as the config command from the REST API modifies the underlying XML configuration. This helps lead us to the correct solution, too. By exporting the configuration from the Palo Alto, we can find the following within it.

  <plugins version="1.0.2">
    <vm_series>
      <azure-ha-config>
        <client-id>ClientId</client-id>
        <client-secret>WWVhaE5vdEFSZWFsUGFzc3dvcmQ=</client-secret>
        <resource-group>PaloResourceGroup</resource-group>
        <subscription-id>SubscriptionId</subscription-id>
        <tenant-id>SubscriptionTenant</tenant-id>
      </azure-ha-config>
    </vm_series>
  </plugins>
</deviceconfig>

With this information we can craft our command. First the path we need to modify can be found by converting the brackets up to azure-ha-config. Next the element will be everything within those brackets, including the ID, Secret, Resource Group, Subscription ID, and Tenant ID. Pasting those values within XPath and Element into the Request-PaloApi command, we are able to successfully update the value.

$xpath = "/config/devices/entry[@name='localhost.localdomain']/deviceconfig/plugins/vm_series/azure-ha-config"

$element = ('<client-id>{0}</client-id><client-secret>{1}</client-secret><tenant-id>{2}</tenant-id><subscription-id>{3}</subscription-id><resource-group>{4}</resource-group>' -f $clientId, $clientSecret, $tenantId, $subscriptionId, $resourceGroup)

Request-PaloApi -Verbose -ipAddress $mgmtAddress `
  -paloKey $paloKey `
  -apiType 'config' `
  -apiAction 'set' `
  -apiXpath $xpath `
  -apiElement $element

This gets us past the hurdle of configuring the obfuscated values for the Azure HA Config. You can then configure the rest of the HA Process, which is thankfully not hidden within the debug logs, and can be grabbed from within (or below, because why do work?).

$configPathHA = "/config/devices/entry[@name='localhost.localdomain']/deviceconfig/high-availability"
    
#Configure Peer
Write-Verbose -Message 'Configure HA Peer'
$xpath= ('{0}/group' -f $configPathHA)
$element= ('<group-id>1</group-id><peer-ip>{0}</peer-ip>' -f $paloMgmt2)
Request-PaloApi -Verbose -ipAddress $paloMgmt1 `
  -paloKey $paloKey `
  -apiType 'config' `
  -apiAction 'set' `
  -apiXpath $xpath `
  -apiElement $element

#Enable Configuration Sync
Write-Verbose -Message 'Configure HA Config Sync'
$xpath= ('{0}/group' -f $configPathHA)
$element= '<configuration-synchronization><enabled>yes</enabled></configuration-synchronization>'
Request-PaloApi -Verbose -ipAddress $paloMgmt1 `
  -paloKey $paloKey `
  -apiType 'config' `
  -apiAction 'set' `
  -apiXpath $xpath `
  -apiElement $element

#Enable HA Configuration
Write-Verbose -Message 'Enable HA'
$element= '<enabled>yes</enabled>'
Request-PaloApi -Verbose -ipAddress $paloMgmt1 `
  -paloKey $paloKey `
  -apiType 'config' `
  -apiAction 'set' `
  -apiXpath $configPathHA `
  -apiElement $element

As an addendum, if you are using the code from the previous blog entry, you may occasionally receive an error. This can happen due to the client secret containing special characters that are not being successfully parsed via the web request. To counter this, we can run the secret through the URL encode function of the Web.HTTPUtility within PowerShell. This will format special characters so that they do not get parsed incorrectly as part of the web request.

Add-Type -AssemblyName System.Web
$clientSecret = [system.web.httputility]::urlencode($clientSecret)

VM-Series Plugin

A final interjection before wrapping, the latest version of the VM-Series Plugin (1.0.4) has an update that encrypts the secret value for the Service Principal account. However, the update does not automatically encrypt the value, and you must instead re-enter the value, to allow it to be encrypted, and then perform a commit.

Attempts to perform a commit without updating that value after updating the plugin will cause errors, and force the commit to not complete. Thankfully, if you are using the command above, entering the details via this command will still work, as we are modifying the underlying XML (the same trick can be used for LDAP configuration).

Reach out if you have any more questions about automation, Palo, or Azure. Looking forward to getting you more info in the future.

Palo Alto Automation: Azure HA Configuration

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.