paloalto adapter

Features

The paloalto module manages Palo Alto Networks NGFW configuration through a Panorama (PAN-OS) management server, using the pan-os-python SDK. All resources connect to a single Panorama entity and are dispatched to a handler agent keyed on the Panorama hostname. The module models the core Panorama object hierarchy:

  • Device groups (DeviceGroup) — including parent hierarchy, reference templates and firewall membership.

  • Templates and template stacks (Template, TemplateStack) — with default vsys support.

  • Security zones (Zone) and network interfaces (Interface, L3SubInterface).

  • Logical routers / VRFs with BGP (RouteDomain) and BFD profiles (BfdProfile).

  • BGP peer groups and peers (BgpPeerGroup, BgpPeer) within a logical router’s VRF.

Beyond object CRUD, the module implements the Panorama commit/push workflow. A standalone Commit resource commits candidate config to Panorama (optionally scoped by admins, device_groups, templates, or forced), while Push pushes committed config from Panorama out to device groups or template stacks. In addition, DeviceGroup, Template and TemplateStack each carry committed and pushed booleans, letting a resource optionally commit (and push) its own scoped changes inline as part of its deploy. A FirewallConnection gate resource waits until a firewall is a connected member of a device group (useful for VM-Series bootstrap flows where the serial is unknown up front), and a DeploymentProfile entity plus generate_auth_key plugin provision Software NGFW licensing.

Api configuration

Resources connect through a paloalto::panorama::Panorama entity:

Attribute

Description

hostname

Panorama management address

username

API username

password

API password

Authentication is via the PAN-OS API username and password; the SDK obtains and uses an API key internally from these credentials. Every managed resource holds a panorama relation back to this entity, and runs on an agent selected by the Panorama hostname.

:bulb: Credentials for the Panorama connection are passed as plain entity attributes; the module reads no environment variables or config files for the connection itself. (The separate Licensing API used by DeploymentProfile takes its own OAuth2 client_id/client_secret.)

Usage example

import paloalto::panorama as pano

# Connect to Panorama (username/password auth)
p = pano::Panorama(
    hostname = "panorama.example.com",
    username = "admin",
    password = "<panorama-password>",
)

# A device group, with an inline scoped commit of its own changes
pano::DeviceGroup(
    panorama = p,
    name = "CustomerA",
    parent = "Shared",
    committed = true,
)

# A layer-3 interface in a template, and a security zone bound to it
interface = pano::Interface(
    panorama = p,
    name = "ethernet1/7",
    template = "zone_test_template",
    type = "layer3",
    ip_addresses = ["10.70.0.1/24"],
    mtu = 1400,
    comment = "zone-test-uplink",
    enable_dhcp = false,
)

zone = pano::Zone(
    panorama = p,
    name = "zone_test_integration",
    template = "zone_test_template",
    mode = "layer3",
    enable_user_id = true,
    log_setting = "zone-log-setting",
    interfaces = ["ethernet1/7"],
    enable_packet_buffer_protection = true,
    requires = [interface],
)

# A BGP peer group on the logical router's VRF, with one peer per remote node
peer_group = pano::BgpPeerGroup(
    panorama = p,
    name = "l3out_dif_diameter_a",
    template = "zone_test_template",
    route_domain = "effortel_diameter_a",
    filtering_profile_ipv4 = "allow_in_out",
)

peer_an1 = pano::BgpPeer(
    panorama = p,
    name = "aci_fl3out_an1_dif_diameter_a",
    template = peer_group.template,
    route_domain = peer_group.route_domain,
    peer_group = peer_group.name,
    peer_as = 4194305608,
    local_address_interface = "ethernet1/3.2267",
    peer_address = "172.29.132.17",
    requires = [peer_group],
)

peer_an2 = pano::BgpPeer(
    panorama = p,
    name = "aci_fl3out_an2_dif_diameter_a",
    template = peer_group.template,
    route_domain = peer_group.route_domain,
    peer_group = peer_group.name,
    peer_as = 4194305608,
    local_address_interface = "ethernet1/3.2267",
    peer_address = "172.29.132.18",
    requires = [peer_group],
)

# A standalone commit, scoped to a device group and template. It must require the
# resources it commits, otherwise it can run before or while they are deployed.
commit = pano::Commit(
    panorama = p,
    device_groups = ["Test_with_device"],
    templates = ["zone_test_template"],
    requires = [interface, zone, peer_group, peer_an1, peer_an2],
)

# Push committed config from Panorama out to the device group's firewalls
pano::Push(
    panorama = p,
    scope = "device_group",
    target = "Test_with_device",
    include_template = true,
    admins = ["admin"],
    requires = [commit],
)

Main entities

  • paloalto::panorama::Panorama — connection target holding Panorama hostname and API credentials.

  • paloalto::panorama::DeviceGroup — a Panorama device group (parent hierarchy, reference template, firewall membership).

  • paloalto::panorama::Firewall — a firewall identified by serial, referenced from a device group’s membership.

  • paloalto::panorama::Template / paloalto::panorama::TemplateStack — a template and an ordered stack of templates.

  • paloalto::panorama::Zone — a security zone within a template.

  • paloalto::panorama::Interface / paloalto::panorama::L3SubInterface — network interfaces and layer-3 subinterfaces.

  • paloalto::panorama::RouteDomain — a logical router / VRF with BGP configuration.

  • paloalto::panorama::BgpPeerGroup / paloalto::panorama::BgpPeer — a BGP peer group under a route-domain’s VRF, and a peer within such a group.

  • paloalto::panorama::BfdProfile — a BFD profile within a template.

  • paloalto::panorama::Commit / paloalto::panorama::Push — commit candidate config / push committed config to a scope.

  • paloalto::panorama::FirewallConnection — gate resource that waits until a named firewall is a connected member of a device group (read-only, not purgeable).

  • paloalto::panorama::DataplaneCores — enforces the VM-Series dataplane core count on a firewall reached through Panorama, using the vm_series plugin’s set-cores/dp-cores operational commands (day-2 drift only, not purgeable).

  • paloalto::DeploymentProfile — Software NGFW flexible-sizing deployment profile provisioned via the Licensing API.

  • generate_auth_key(hostname, username, password, lifetime=60) — plugin generating a Panorama VM auth-key.

Notes and known limitations

  • Push drift cannot be reliably detected. Every deploy reports the push as pending to make sure pushes are attempted, so Push resources (and inline pushed flags) stay non-idempotent by design.

  • Device groups cannot be moved back into Shared. The PAN-OS API does not allow it; the handler raises an error if attempted (it can only be done via the Panorama UI).

  • FirewallConnection is read-only. It only observes membership/connectivity and does not create, update or delete.

  • Push scope constraints. include_template and device filtering are only valid for the device_group scope, not the template scope.

  • A Commit must require the resources it commits. The module does not order a Commit after the configuration on its Panorama, since a device can have several scoped commits. Without requires, the orchestrator may run the commit before or during the changes it is meant to commit. Likewise, a Push should require its Commit.

  • BGP peers must require their peer group. A BgpPeer is nested inside its BgpPeerGroup on PAN-OS, so the group has to be deployed first; the handler fails with a lookup error if the group is missing.

  • A BGP peer always inherits from its peer group. pan-os-python does not model the peer’s inherit toggle, so the peer takes the address family and filtering profiles of its group, which is the PAN-OS default.

  • DataplaneCores never blocks on a reboot. Changing the core count only takes effect after a reboot; the handler issues the reboot and then skips (retrying on later deploys) until the firewall reconnects, rather than blocking the deploy on the reboot/reconnect cycle. Only the deploy that actually changes the configured count reboots — PAN-OS keeps reporting connected to Panorama for a while after accepting a restart, so a retry landing in that window would otherwise read the stale pre-reboot count and restart a firewall that is already going down. The trade-off: if a deploy dies between setting the count and issuing the restart, the resource skips until timeout turns it into a hard failure instead of rebooting the firewall on its own.

  • DataplaneCores is never purged. Tearing down the service that owns the firewall destroys the VM itself, so there is nothing on the (gone) device to reset.

  • DataplaneCores is operational-only. The dataplane/management-plane split lives outside /config on PAN-OS, so it cannot be delivered through a Panorama template/template-stack push; it is only ever set via a per-device operational command.