Skip to main content

Palo Alto Networks VM-Series Module for Azure

A Terraform module for deploying a VM-Series firewall in Azure cloud. The module is not intended for use with Scale Sets.

GitHub Logo Terraform Logo

Usage

For usage please refer to any reference architecture example.

Accept Azure Marketplace Terms

Accept the Azure Marketplace terms for the VM-Series images. In a typical situation use these commands:

az vm image terms accept --publisher paloaltonetworks --offer vmseries-flex --plan byol --subscription MySubscription
az vm image terms accept --publisher paloaltonetworks --offer vmseries-flex --plan bundle1 --subscription MySubscription
az vm image terms accept --publisher paloaltonetworks --offer vmseries-flex --plan bundle2 --subscription MySubscription

You can revoke the acceptance later with the az vm image terms cancel command. The acceptance applies to the entirety of your Azure Subscription.

Caveat Regarding Region

By default, the VM-Series is placed into an Availability Zone "1". Hence, it can only deploy successfully in the Regions that support Zones. If your Region doesn't, use an alternative mechanism of Availability Set, which is inferior but universally supported:

   avset_id = azurerm_availability_set.this.id
avzone = null

Reference

Requirements

NameVersion
terraform>= 1.2, < 2.0
azurerm~> 3.25

Providers

NameVersion
azurerm~> 3.25

Modules

No modules.

Resources

NameType
azurerm_network_interface.thisresource
azurerm_network_interface_backend_address_pool_association.thisresource
azurerm_public_ip.thisresource
azurerm_virtual_machine.thisresource
azurerm_public_ip.thisdata source

Inputs

NameDescriptionTypeDefaultRequired
locationRegion where to deploy VM-Series and dependencies.stringn/ayes
resource_group_nameName of the existing resource group where to place the resources created.stringn/ayes
nameVM-Series instance name.stringn/ayes
enable_zonesIf false, the input avzone is ignored and also all created Public IP addresses default to not to use Availability Zones (the No-Zone setting). It is intended for the regions that do not yet support Availability Zones.booltrueno
avzoneThe availability zone to use, for example "1", "2", "3". Ignored if enable_zones is false. Conflicts with avset_id, in which case use avzone = null.string"1"no
avzonesAfter provider version 3.x you need to specify in which availability zone(s) you want to place IP.
ie: for zone-redundant with 3 availability zone in current region value will be:
["1","2","3"]
list(string)[]no
avset_idThe identifier of the Availability Set to use. When using this variable, set avzone = null.stringnullno
interfacesList of the network interface specifications.

NOTICE. The ORDER in which you specify the interfaces DOES MATTER.
Interfaces will be attached to VM in the order you define here, therefore:
The first should be the management interface, which does not participate in data filtering.
The remaining ones are the dataplane interfaces.

Options for an interface object:
- name - (required|string) Interface name.
- subnet_id - (required|string) Identifier of an existing subnet to create interface in.
- create_public_ip - (optional|bool) If true, create a public IP for the interface and ignore the public_ip_address_id. Default is false.
- private_ip_address - (optional|string) Static private IP to asssign to the interface. If null, dynamic one is allocated.
- public_ip_name - (optional|string) Name of an existing public IP to associate to the interface, used only when create_public_ip is false.
- public_ip_resource_group - (optional|string) Name of a Resource Group that contains public IP resource to associate to the interface. When not specified defaults to var.resource_group_name. Used only when create_public_ip is false.
- availability_zone - (optional|string) Availability zone to create public IP in. If not specified, set based on avzone and enable_zones.
- enable_ip_forwarding - (optional|bool) If true, the network interface will not discard packets sent to an IP address other than the one assigned. If false, the network interface only accepts traffic destined to its IP address.
- enable_backend_pool - (optional|bool) If true, associate interface with backend pool specified with lb_backend_pool_id. Default is false.
- lb_backend_pool_id - (optional|string) Identifier of an existing backend pool to associate interface with. Required if enable_backend_pool is true.
- tags - (optional|map) Tags to assign to the interface and public IP (if created). Overrides contents of tags variable.

Example:
[
{
name = "fw-mgmt"
subnet_id = azurerm_subnet.my_mgmt_subnet.id
public_ip_address_id = azurerm_public_ip.my_mgmt_ip.id
create_public_ip = true
},
{
name = "fw-public"
subnet_id = azurerm_subnet.my_pub_subnet.id
lb_backend_pool_id = module.inbound_lb.backend_pool_id
enable_backend_pool = true
create_public_ip = false
public_ip_name = "fw-public-ip"
},
]
list(any)n/ayes
usernameInitial administrative username to use for VM-Series. Mind the Azure-imposed restrictions.stringn/ayes
passwordInitial administrative password to use for VM-Series. If not defined the ssh_key variable must be specified. Mind the Azure-imposed restrictions.stringnullno
ssh_keysA list of initial administrative SSH public keys that allow key-pair authentication.

This is a list of strings, so each item should be the actual public key value. If you would like to load them from files instead, following method is available:
[
file("/path/to/public/keys/key_1.pub"),
file("/path/to/public/keys/key_2.pub")
]
If the password variable is also set, VM-Series will accept both authentication methods.
list(string)[]no
managed_disk_typeType of OS Managed Disk to create for the virtual machine. Possible values are Standard_LRS, StandardSSD_LRS or Premium_LRS. The Premium_LRS works only for selected vm_size values, details in Azure docs.string"StandardSSD_LRS"no
os_disk_nameOptional name of the OS disk to create for the virtual machine. If empty, the name is auto-generated.stringnullno
vm_sizeAzure VM size (type) to be created. Consult the VM-Series Deployment Guide as only a few selected sizes are supported.string"Standard_D3_v2"no
custom_image_idAbsolute ID of your own Custom Image to be used for creating new VM-Series. If set, the username, password, img_version, img_publisher, img_offer, img_sku inputs are all ignored (these are used only for published images, not custom ones). The Custom Image is expected to contain PAN-OS software.stringnullno
enable_planEnable usage of the Offer/Plan on Azure Marketplace. Even plan sku "byol", which means "bring your own license", still requires accepting on the Marketplace (as of 2021). Can be set to false when using a custom image.booltrueno
img_publisherThe Azure Publisher identifier for a image which should be deployed.string"paloaltonetworks"no
img_offerThe Azure Offer identifier corresponding to a published image. For img_version 9.1.1 or above, use "vmseries-flex"; for 9.1.0 or below use "vmseries1".string"vmseries-flex"no
img_skuVM-series SKU - list available with az vm image list -o table --all --publisher paloaltonetworksstring"byol"no
img_versionVM-series PAN-OS version - list available for a default img_offer with az vm image list -o table --publisher paloaltonetworks --offer vmseries-flex --allstring"10.1.0"no
tagsA map of tags to be associated with the resources created.map(any){}no
identity_typeSee the provider documentation.string"SystemAssigned"no
identity_idsSee the provider documentation.list(string)nullno
accelerated_networkingEnable Azure accelerated networking (SR-IOV) for all network interfaces except the primary one (it is the PAN-OS management interface, which does not support acceleration).booltrueno
bootstrap_optionsBootstrap options to pass to VM-Series instance.

Proper syntax is a string of semicolon separated properties.
Example:
bootstrap_options = "type=dhcp-client;panorama-server=1.2.3.4"

A list of available properties: storage-account, access-key, file-share, share-directory, type, ip-address, default-gateway, netmask, ipv6-address, ipv6-default-gateway, hostname, panorama-server, panorama-server-2, tplname, dgname, dns-primary, dns-secondary, vm-auth-key, op-command-modes, op-cmd-dpdk-pkt-io, plugin-op-commands, dhcp-send-hostname, dhcp-send-client-id, dhcp-accept-server-hostname, dhcp-accept-server-domain, auth-key, vm-series-auto-registration-pin-value, vm-series-auto-registration-pin-id.

For more details on bootstrapping see documentation: https://docs.paloaltonetworks.com/vm-series/10-2/vm-series-deployment/bootstrap-the-vm-series-firewall/create-the-init-cfgtxt-file/init-cfgtxt-file-components
string""no
diagnostics_storage_uriThe storage account's blob endpoint to hold diagnostic files.stringnullno

Outputs

NameDescription
mgmt_ip_addressVM-Series management IP address. If create_public_ip was true, it is a public IP address, otherwise a private IP address.
interfacesMap of VM-Series network interfaces. Keys are equal to var.interfaces name properties.
principal_idThe oid of Azure Service Principal of the created VM-Series. Usable only if identity_type contains SystemAssigned.

Custom Metrics

(Optional) Firewalls can publish custom metrics (for example panSessionUtilization) to Azure Application Insights. This however requires a manual initialization: copy the output metrics_instrumentation_key and paste it into your PAN-OS webUI -> Device -> VM-Series -> Azure. The module automatically completes the Step 1 of the official procedure.

The metrics gathered within a single Azure Application Insights instance provided by the module, cannot be split to obtain back a result for solely a single firewall. Thus for example if three firewalls use the same Instrumentation Key and report their respective session utilizations as 90%, 20%, 10%, it is possible to see in Azure the average of 40%, the sum of 120%, the max of 90%, but it is not possible to know which of the firewalls reported the 90% utilization.