In this blog article we’re going to look at using the Python
requests module to interface with the Palo Alto Networks (PAN-OS) XML API.
Blog Series
Python for Network Engineers - Part 1 - Introduction
Python for Network Engineers - Part 2 - Making REST calls
Python for Network Engineers - Part 3 - Using Cisco Nexus NX-API
Python for Network Engineers - Part 4 - Using Arista EOS eAPI
Python for Network Engineers - Part 5 - Using Junos NETCONF interface
Python for Network Engineers - Part 6 - Using Cisco Nexus NETCONF interface
Python for Network Engineers - Part 7 - Using Palo Alto Networks XML API
Python for Network Engineers - Part 1 - Introduction
Python for Network Engineers - Part 2 - Making REST calls
Python for Network Engineers - Part 3 - Using Cisco Nexus NX-API
Python for Network Engineers - Part 4 - Using Arista EOS eAPI
Python for Network Engineers - Part 5 - Using Junos NETCONF interface
Python for Network Engineers - Part 6 - Using Cisco Nexus NETCONF interface
Python for Network Engineers - Part 7 - Using Palo Alto Networks XML API
Python for Network Engineers - Part 2 - Making REST calls
Python for Network Engineers - Part 3 - Using Cisco Nexus NX-API
Python for Network Engineers - Part 4 - Using Arista EOS eAPI
Python for Network Engineers - Part 5 - Using Junos NETCONF interface
Python for Network Engineers - Part 6 - Using Cisco Nexus NETCONF interface
Python for Network Engineers - Part 7 - Using Palo Alto Networks XML API
Introduction
In previous blog posts, we gave an introduction to using the
requests module to interact with REST APIs and also looked at the ncclient
module for NETCONF interfaces.
In this blog post, we’ll use the requests module again to
interact with the Palo Alto XML API.
It’s a little harder to get started with than examples in previous blog
posts. But once you’ve worked through a
few examples it’s fairly straightforward.
It’s also a little unusual as we are just using HTTP GET
requests and using XML data in the query section of the URI string. So, in this case, it’s not a true REST API,
but as we're using the requests module again, much of the knowledge picked up in parts 2, 3 and 4 will be helpful here too..
Palo Alto XML API
For this example, I’m using a VM-Series Palo Alto firewall
with PAN-OS 6.1.0 and Ubuntu 16.04 linux.
PAN Setup
On the Palo Alto firewall then there is no setup required to
enable the XML API. We just need to have
web browser access to the firewall.
However, before we start trying to query or configure the
firewall we will need to generate an authentication key. We can do this from Python using the
requests module.
Key Generation
First open an interactive Python session and we will setup
all the basic settings and create a session object “s” to the firewall.
import requests, json, xmltodict
from
requests.packages.urllib3.exceptions import InsecureRequestWarning
requests.packages.urllib3.disable_warnings(InsecureRequestWarning)
uri = 'https://192.168.229.71/api/'
s = requests.session()
s.verify = False
The second and third lines will just disable some SSL
warnings which will make the output harder to read. Next we will send a request to the firewall
for a key to be created for the below user “admin”.
uname = upass = "admin"
params = {}
params['type'] = 'keygen'
params['user'] = uname
params['password'] = upass
r = s.request('get', uri,
params=params)
We can then take a look at the key that was sent back and
can also set it into a string called “key” which we will use in the further
examples below
print r.text
d = xmltodict.parse(r.text)
key =
d['response']['result']['key']
print key
Example 1
In this example we’ll just do a few basic show
commands. This assumes that you’ve
already created your session object “s” and you have set a string called “key”
with the correct authentication key.
params = {'type': 'config',
'action': 'show', 'key': key}
params['xpath'] =
'/config/mgt-config'
r = s.get(uri, params=params)
print r.text
One thing to note is that I've switched to using "s.get()" syntax. Above and in previous blog posts I've used "s.request("get") as it's easy to switch to using "post" or "put". However as we'll only be using "get" with PAN then we'll use the shorter command.
This next query will list all the address objects on the firewall
This next query will list all the address objects on the firewall
params['xpath'] =
'/config/devices/entry/vsys/entry/address'
r = s.get(uri, params=params)
print r.text
This next query will list the security
and NAT rulebases on the firewall
params['xpath'] =
'/config/devices/entry/vsys/entry/rulebase'
r = s.get(uri, params=params)
print r.text
Example 2
In this next example, we’ll show a fairly simple
configuration item so we can demonstrate the commit process. Again we assume that you’ve already created
your session object “s” and you have set a string called “key” with the correct
authentication key.
Now we will create an address object :
params = {}
params['type'] = 'config'
params['action'] = 'set'
params['key'] = key
params['xpath'] =
"/config/devices/entry/vsys/entry/address/entry[@name='HST_10.1.1.1']"
params['element'] =
'<ip-netmask>10.1.1.1/32</ip-netmask>'
params['element'] +=
'<description>Test Internal Host IP - added by
python</description>'
r = s.get(uri, params=params)
print r.text
And then commit the configuration:
params = {}
params['type'] = 'commit'
params['cmd'] =
'<commit></commit>'
params['key'] = key
r = s.get(uri, params=params)
However, if we now check the output
from the reply object, it only tells us a job id and not if it completed OK.
print r.text
So to check the job completed we
can run the following (example is where job id id 99):
jobid = 99
params = {}
params['type'] = 'op'
params['cmd'] =
'<show><jobs><id>%s</id></jobs></show>' %
jobid
params['key'] = key
r = s.get(uri, params=params)
print r.text
Conclusion
I’ve only shown a couple of examples here as we basically
need to build the XML for each type of request and understand the xpath for
each task that you want to do. Also if
you’re using VSYS or if you’re using “shared” objects then the xpath will
change for certain tasks. Where I’ve used a
virtual Palo Alto in this blog, it’s made the xpath format a certain way as
there’s no VSYS and no shared objects.
To use this in production then I have developed a module
that does all the heavy lifting such as doing commits, checking the job id
result, storing all the outputs in class parameters, logging and reporting back
with a Boolean True/False for each command run.
This makes it very easy to script changes on top of that and debug when
things aren’t working.
Also please refer to the documentation below to build on top
the examples shown in this blog.
Resources
About the Author
The author of this blog works for Vanguard IT who provide a range of professional services and managed services
For more information go to https://vanguard-it.net
No comments:
Post a Comment