XML API for Palo Alto Firewall’s debug commands.

Recently I came across a scenario where the requirement was to have an XML API for debug commands in Palo Alto firewalls. Unfortunately, the Rest API does not work for debug command, so alternatively, I wrote a script to login i.e ssh into the firewall and issue the debug commands.

I have written a very basic python script (for reference to SSH into the firewall and trigger the command.

#|*********************************************************************
# Project : SSH into the PA firewall and execute commands.
#
# Program name : PADebugCmd.py
#
# Author : Anil Kumar | Palo Alto Networks
#
# Date created : 26th Jan 2017
#
# Purpose : Workaround for a case.
#
#|*********************************************************************

import paramiko
import time

HOSTNAME = '10.10.10.1'  #Firewalls IP
PORT = 22 

def ssh_command(username, password, cmd, hostname=HOSTNAME, port=PORT):
    ssh_client = paramiko.SSHClient()
    ssh_client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
    ssh_client.load_system_host_keys()
    ssh_client.connect(hostname, port, username=username, password=password)
    remote_conn = ssh_client.invoke_shell()
    print "Interactive SSH session established"
    remote_conn.send("set cli pager off\n")
    remote_conn.send(""+cmd+"\n")
    time.sleep(8)
    buff = ''
    while not buff.endswith('>'):
        resp = remote_conn.recv(15000)
        buff += resp
        print(resp)

if __name__ == '__main__':
    username = input("Enter username: ")
    password = input("Enter password: ")  
    cmd = 'debug log-receiver statistics'
    ssh_command(username, password, cmd)

NOTE :

  1. You may tweak the script as per your requirements.
  2. I tried using exec_command(), but the SSH client gets stuck at execute command. I think I did hit a bug with python paramiko. As a work around I used send() and recv() methods of the paramiko channel class. This worked absolutely fine for me.
  3. You may disable echo for password using getpass().

 

Using the REST API to add address objects to a Dynamic address group

To add a new entry to a dynamic address object, use the following XML API syntax:

https://<IP>/api/?type=user-id&action=set&key=<KEY>=&file-name=<XMLFILE>

Where IP is the IP address of the firewall under management, KEY is the pre-generated key for the PAN-OS firewall and XMLFILE is the name of the XML file with the needed additions and/or deletions for the dynamic address object.

The XML file must have the following format for adding new IP addresses to an existing object:
<uid-message>
<version>1.0</version>
<type>update</type>
<payload>
<register>
<entry identifier=“OBJECT ID” ip=”IP”/>
</register>
</payload>
</uid-message>

Multiple additions can be made to the same object or to multiple objects in one API call by adding them to the same XML file:
<uid-message>
<version>1.0</version>
<type>update</type>
<payload>
<register>
<entry identifier=“OBJECT ID 1″ ip=”IP1″/>
<entry identifier=“OBJECT ID 1″ ip=”IP2″/>
<entry identifier=“OBJECT ID 2″ ip=”IP3″/>
</register>
</payload>
</uid-message>

Removing an IP address from an object is similar:
<uid-message>
<version>1.0</version>
<type>update</type>
<payload>
<unregister>
<entry identifier=“OBJECT ID 1″ ip=”IP1″/>
<entry identifier=“OBJECT ID 1″ ip=”IP2″/>
<entry identifier=“OBJECT ID 2″ ip=”IP3″/>
</unregister>
</payload>
<uid-message>

Address can be added and removed in same call :
<uid-message>
<version>1.0</version>
<type>update</type>
<payload>
<register>
<entry identifier=“OBJECT ID 3″ ip=”IP4″/>
<entry identifier=“OBJECT ID 3″ ip=”IP5″/>
</register>
<unregister>
<entry identifier=“OBJECT ID 4″ ip=”IP6″/>
</unregister>
</payload>
</uid-message>

Here is something that I replicated in my lab :
1. Used wget in Kali Linux as a REST client.
2. REST API :

wget –no-check-certificate –post-file=Desktop/T11.xml “https://10.50.243.81/api/?type=user-id&action=set&key=LUFRPT14MW5xOEo1R09KVlBZNnpnemh0VHRBOWl6TGM9bXcwM3JHUGVhRlNiY0dCR0srNERUQT09&file-name=T11.xml&client=wget&#8221;  –no-http-keep-alive -O Desktop/TOP 

wget-api-query-1

NOTE :

T11.xml:
——-
<uid-message>
<version>1.0</version>
<type>update</type>
<payload>
<register>
<entry identifier=“palo” ip=”1.1.1.1″/>
</register>
</payload>
</uid-message>

TOP File : ( This reflects the result of the triggered API query)
——–
wget-api-query-output

3.  This is what you should be seeing on the Palo Alto Networks firewall:

CLI :
—-

show object dynamic-address-group all

Dynamic address groups in vsys vsys1:
—————————————————-

—————-defined in vsys ——————–

—————-defined in shared——————-
DynTest
filter: “palo”
members: total 2
1.1.1.1 (R)

O: address object; R: registered ip; D: dynamic group; S: static group
=========================

> show object registered-ip tag palo

registered IP Tags
—————————————- —————–

1.1.1.1 #
“palo”

Total: 1 registered addresses
*: received from user-id agent #: persistent

GUI :
—-
after-commit-and-clicking-more

NOTE :
======
A) I observed buggy behavior with PAN OS 7.1.4 – h2.
Observed Behavior :
—————–
— Could see registered IPs in the CLI.
— But could not see the IPs in Dynamic Address Group.
— Addresses were not visible in the GUI as well.
— Forced commit. (No changes to commit observed so had to force commit)
— Even after commit, could not see the IPs in the dynamic address group.
— Clicked “more”, after which we could see the dynamic addresses in the dynamic address object.
— Checked in CLI, the registered IPs were visible.
— Tested this with different inputs and firewalls, observed the same behavior everytime.
— Unregistered the IP addresses after which we did not see any registered IP but could see those IPs still stuck in Dynamic address group.
— PAN OS 5 had a command to clear the objects using type=op. But the command is no longer available in PAN OS 7.1.

B) This should be filed as a bug shortly. Already shared the results with the concerned PA Team.

Create a template on Panorama in specific vsys using the REST API

You can create a template in a “specific vsys” using API using 2 different APIs. Please use the APIs in the following sequence.

API 1 :
=======

https://<PANORAMA IP>/api/?type=config&action=set&key=<KEY>&xpath=/config/devices/entry[@name=’localhost.localdomain’]/template/
entry[@name=’TEST’]/config/devices/entry[@name=’localhost.localdomain’]/
vsys&element=<entry name=’vsys1’/>

API 2:
======
https://<PANORAMA IP>/api/?type=config&action=set&xpath=/config/devices/entry[@name=’localhost.localdomain’]/template/
entry[@name=’TEST’]/settings&element=<default-vsys>vsys1</default-vsys>&key=<KEY>

 

NOTE : These APIs have been tested and work absolutely fine 🙂