Code Share: Automate Palo Alto Next-Generation Firewall (NGFW) using Terraform

Sebastian Maniak
5 min readMay 29, 2022

--

In this article I will provide code to get you started on automating Palo Alto Next-Generation Firewall (NGFW) using Terraform. Let’s go over the benefits of Infrastructure as Code so you can get a high-level understanding why I build network infrastructure with code.

Values of Software Defined Network Infrastructure:

Software workflows for infrastructure changes to match product:

  • Versioning
  • Issue management
  • Change-logs
  • Audibility

Benefits of IaC and Software

Testing that building and running the infrastructure works as planned:

  • Repeatable
  • Stable
  • Secure
  • Visible

Lab Overview

I used the PAN-OS VM .OVA file to deploy the default configuration in my VMware lab. Terraform code will build the following:

  • PAN-OS Management Profile
  • Network Interfaces/Adapters
  • Virtual Router
  • 3 Zones [ Untrusted, Secure and WebFront]
  • Configure NAT rule for Secure and Web Front Zones to be able to go out to the internet
  • Configure address groups with my specific servers
  • Configure specific security policies to allow communication of applications between services/zones.

Terraform Code

The following code will be located here https://github.com/maniak-academy/medium-panos-vm-terraform feel free to fork it, clone it and get play around with it.

Initialize the Provider

First thing we are going to do is initialize the provider. The following code below outlines the terraform provider panos we are going to use. Next we are going to configure the panos provider. https://registry.terraform.io/providers/PaloAltoNetworks/panos/latest/docs

terraform {
required_providers {
panos = {
source = "PaloAltoNetworks/panos"
version = "1.10.1"
}
}
}
provider "panos" {
hostname = var.hostname
username = var.username
password = var.password
}

Configure Network Interfaces

We’re going to be performing the initial networking configuration with Terraform. If you take a look at the code, you will see a network.tf file where the network interface configuration will be located.

resource "panos_management_profile" "mymgmtprofile" {
name = "allow stuff"
ssh = true
ping = true
permitted_ips = ["10.1.1.0/24", "10.1.2.0/24", "192.168.86.0/24"]
}
resource "panos_ethernet_interface" "untrust" {
name = "ethernet1/1"
vsys = "vsys1"
mode = "layer3"
enable_dhcp = true
create_dhcp_default_route = true
management_profile = panos_management_profile.mymgmtprofile.id
}resource "panos_ethernet_interface" "web" {
name = "ethernet1/2"
vsys = "vsys1"
mode = "layer3"
static_ips = ["10.1.1.1/24"]
enable_dhcp = false
management_profile = panos_management_profile.mymgmtprofile.id
}
resource "panos_ethernet_interface" "secure" {
name = "ethernet1/3"
vsys = "vsys1"
mode = "layer3"
static_ips = ["10.1.2.1/24"]
enable_dhcp = false
management_profile = panos_management_profile.mymgmtprofile.id
}resource "panos_virtual_router" "vtr" {
name = "my virtual router"
static_dist = 15
interfaces = ["ethernet1/1", "ethernet1/2", "ethernet1/3"]
}
resource "panos_zone" "untrust" {
name = "untrust"
mode = "layer3"
interfaces = ["${panos_ethernet_interface.e1.name}"]
enable_user_id = true
}
resource "panos_ethernet_interface" "e1" {
name = "ethernet1/1"
mode = "layer3"
}
resource "panos_zone" "web" {
name = "web"
mode = "layer3"
interfaces = ["${panos_ethernet_interface.e2.name}"]
enable_user_id = true
}
resource "panos_ethernet_interface" "e2" {
name = "ethernet1/2"
mode = "layer3"
}
resource "panos_zone" "secure" {
name = "secure"
mode = "layer3"
interfaces = ["${panos_ethernet_interface.e3.name}"]
enable_user_id = true
}
resource "panos_ethernet_interface" "e3" {
name = "ethernet1/3"
mode = "layer3"
}

Address Groups

Next we will define some address groups so we can be more specific in what servers have access to. address-group.tf

resource "panos_address_group" "consul-servers" {
name = "consul-servers"
description = "Consul-servers"
static_addresses = [
panos_address_object.consul1.name,
panos_address_object.consul2.name,
panos_address_object.consul3.name
]
}
resource "panos_address_object" "consul1" {
name = "consul1"
value = "10.1.2.70"
}
resource "panos_address_object" "consul2" {
name = "consul2"
value = "10.1.2.71"
}
resource "panos_address_object" "consul3" {
name = "consul3"
value = "10.1.2.72"
}
resource "panos_address_group" "shared-infra" {
name = "shared infra servers"
description = "shared infra servers"
static_addresses = [
panos_address_object.tfagent.name
]
}
resource "panos_address_object" "tfagent" {
name = "tfagent"
value = "10.1.1.42"
}

Security Groups

Next we will take a look at the security.tf and build our security rule. These rules will be used to allow communication between out front end servers, consul servers, databases and provide access to the internet for updates.

resource "panos_security_rule_group" "egress-web-secure-outside" {
rule {
name = "egress-web-secure-outside"
source_zones = [panos_zone.web.name, panos_zone.secure.name]
source_addresses = ["any"]
source_users = ["any"]
destination_zones = [panos_zone.untrust.name]
destination_addresses = ["any"]
applications = ["any"]
services = ["application-default"]
categories = ["any"]
action = "allow"
}
}
resource "panos_security_rule_group" "web-secure" {
rule {
name = "Allow web to talk to secure"
source_zones = [panos_zone.web.name]
source_addresses = ["any"]
source_users = ["any"]
destination_zones = [panos_zone.secure.name]
destination_addresses = ["any"]
applications = ["any"]
services = ["application-default"]
categories = ["any"]
action = "allow"
}
}
resource "panos_security_rule_group" "secure-db-web" {
rule {
name = "Allow secure db to talk to web"
source_zones = [panos_zone.secure.name]
source_addresses = ["any"]
source_users = ["any"]
destination_zones = [panos_zone.web.name]
destination_addresses = ["any"]
applications = ["any"]
services = ["application-default"]
categories = ["any"]
action = "allow"
}
}
resource "panos_security_rule_group" "consul-web" {
rule {
name = "Allow consul to talk to front end"
source_zones = [panos_zone.untrust.name]
source_addresses = [panos_address_group.consul-servers.name]
source_users = ["any"]
destination_zones = [panos_zone.web.name]
destination_addresses = ["any"]
applications = ["any"]
services = ["application-default"]
categories = ["any"]
action = "allow"
}
}
resource "panos_security_rule_group" "consul-secure" {
rule {
name = "Allow consul to talk to secure zone"
source_zones = [panos_zone.untrust.name]
source_addresses = [panos_address_group.consul-servers.name]
source_users = ["any"]
destination_zones = [panos_zone.secure.name]
destination_addresses = ["any"]
applications = ["any"]
services = ["application-default"]
categories = ["any"]
action = "allow"
}
}
resource "panos_security_rule_group" "shared-infra-internal" {
rule {
name = "Allow tf agent to talk to frontend and secure zones"
source_zones = [panos_zone.untrust.name]
source_addresses = [panos_address_group.shared-infra.name]
source_users = ["any"]
destination_zones = [panos_zone.secure.name, panos_zone.web.name]
destination_addresses = ["any"]
applications = ["any"]
services = ["application-default"]
categories = ["any"]
action = "allow"
}
}

Network Address Translation

Finally to allow the web front and secure zones to communicate to the internet we will build out a dynamic IP and Port NAT policy. You can see the code located in nat.tf

resource "panos_nat_rule_group" "egress-web-secure-untrust-nat" {
rule {
name = "egress-web-untrust-nat"
audit_comment = "Ticket 12345"
original_packet {
source_zones = [panos_zone.web.name, panos_zone.secure.name]
destination_zone = panos_zone.untrust.name
destination_interface = panos_ethernet_interface.e1.name
source_addresses = ["any"]
destination_addresses = ["any"]
}
translated_packet {
source {
dynamic_ip_and_port {
interface_address {
interface = panos_ethernet_interface.e1.name
}
}
}
destination {}
}
}
}

Conclusion

If you really take a look at this code, its very simple and with Terraform it’s very easy to get started with infrastructure as code. The next tutorial I will share my code on how you can use the power of HashiCorp #Consul to automate network infrastructure with Palo Alto Next-Generation Firewall (NGFW).

Feel free to connect if you have any questions.

--

--

No responses yet