Overview
Netmiko, a popular Python library used in Network Automation, provides a simple and easy-to-use interface for interacting with Networking Devices.
In this blog post, we will take an in-depth look at Netmiko and explore how it can be used to interact with Palo Alto devices including Panorama. We will cover the basic concepts of Netmiko, including how it works and what it can do.
Installing Netmiko
Netmiko is not part of the standard Python library so, you will have to install it using pip as shown below. The process is similar for other operating systems such as macOS or Linux.
C:\Users\vsurr\Documents>pip install netmiko
Collecting netmiko
Using cached netmiko-4.0.0-py3-none-any.whl (207 kB)
Requirement already satisfied: setuptools>=38.4.0 in
*** TRUNCATED ***
Using cached pycparser-2.21-py2.py3-none-any.whl (118 kB)
Installing collected packages: tenacity, six, future, textfsm, pycparser, cffi, pynacl, cryptography, bcrypt, paramiko, scp, ntc-templates, pyserial, netmiko
Successfully installed bcrypt-3.2.0 cffi-1.15.0 cryptography-36.0.2 future-0.18.2 netmiko-4.0.0 ntc-templates-3.0.0 paramiko-2.10.3 pycparser-2.21 pynacl-1.5.0 pyserial-3.5 scp-0.14.4 six-1.16.0 tenacity-8.0.1 textfsm-1.1.2
WARNING: You are using pip version 20.2.3; however, version 22.0.4 is available.
You should consider upgrading via the 'c:\users\vsurr\appdata\local\programs\python\python39\python.exe -m pip install --upgrade pip' command.
Connecting to the Firewall
Now that we installed the Netmiko library, let's try and connect to a Palo Alto firewall with a simple Python script.
from netmiko import ConnectHandler
import getpass
passwd = getpass.getpass('Please enter your password: ')
firewall = {
"device_type": "paloalto_panos",
"host": "192.168.10.10",
"username": "admin",
"password": passwd
}
connection = ConnectHandler(**firewall) # unpacking the dictionary
output = connection.send_command("show system info", expect_string=r">")
connection.disconnect()
print(output)
Here is the breakdown of the code.
from netmiko import ConnectHandler
: This line imports theConnectHandler
class from thenetmiko
library. TheConnectHandler
class is used to establish a connection with a network device, such as a Palo Alto firewall, and interact with it.import getpass
: This line imports thegetpass
module, which provides a secure way to handle password input without echoing it to the console.passwd = getpass.getpass('Please enter your password: ')
: This line prompts the user to enter their password securely. The entered password is stored in the variablepasswd
.-
firewall = {...}
: This block of code creates a dictionary namedfirewall
containing the required information to connect to the Palo Alto firewall, such as device type, IP address, username, and password. connection = ConnectHandler(**firewall)
: This line establishes a connection with the Palo Alto firewall using theConnectHandler
class. The**firewall
syntax is used to unpack the dictionary, passing its key-value pairs as keyword arguments to the class.output = connection.send_command("show system info", expect_string=r">")
: This line sends the command "show system info" to the Palo Alto firewall and waits for the specifiedexpect_string
(in this case, the ">" prompt) to appear before considering the output complete. The output is then stored in the variableoutput
.connection.disconnect()
: This line gracefully disconnects from the Palo Alto firewall, closing the SSH session.print(output)
: Finally, this line prints the output of the "show system info" command to the console.
#output
hostname: test_fw
ip-address: 192.168.10.10
public-ip-address: unknown
netmask: 255.255.255.0
default-gateway: 192.168.10.1
ip-assignment: static
ipv6-default-gateway:
mac-address: d4:f4:ab:23:6f:3d
time: Thu Apr 27 14:39:45 2023
uptime: 115 days, 15:09:26
{.... abbreviated ....}
You might have noticed that I'm using the expect_string=r">"
argument when executing the command. Strangely, without this argument, the output appears empty, as detailed in this bug report: https://github.com/ktbyers/netmiko/issues/2864.
I believe this behaviour occurs because when you run a 'show' command on the firewall, it initially produces an empty line before displaying the actual output. It seems that Netmiko interprets the blank output as the end of the response.
The expect_string
argument allows you to define a custom string or regular expression pattern that Netmiko should wait for before deeming the output complete and returning it to the user. This is particularly helpful when the default behaviour of waiting for the device prompt isn't adequate, or when you need to wait for specific output from the device.
As you know, when you run show commands
on the firewall, after running the command, the prompt always come back to >
. For example, the prompt of my firewall looks like this.
admin@test_fw>
So, as a workaround, I always use the expect_string
argument with the send_command
method so, Netmiko will wait until the >
prompt appears.
Connecting to Panorama
The process is exactly the same as before, just replace the firewall IP with the Panorama one.
from netmiko import ConnectHandler
import getpass
passwd = getpass.getpass('Please enter your password: ')
firewall = {
"device_type": "paloalto_panos",
"host": "192.168.10.11",
"username": "admin",
"password": passwd
}
connection = ConnectHandler(**firewall) # unpacking the dictionary
output = connection.send_command("show system info", expect_string=r">")
connection.disconnect()
print(output)
I only changed the IP and ran the script and here is the output.
hostname: test_panorama
ip-address: 192.168.10.11
{.... abbreviated ....}
uptime: 105 days, 22:40:21
family: pc
model: Panorama
cloud-mode: cloud
vm-mode: Amazon AWS
Configurations Commands
Now that we've learnt how to send show commands
, let's look at an example of how to make configuration changes. I'm going to create a new Address Object on the Panorama. Please note that the procedure is exactly the same on the firewall (except for the set
commands of course)
from netmiko import ConnectHandler
import getpass
passwd = getpass.getpass('Please enter your password: ')
firewall = {
"device_type": "paloalto_panos",
"host": "192.168.10.11",
"username": "admin",
"password": passwd
}
connection = ConnectHandler(**firewall) # unpacking the dictionary
connection.config_mode() # enter configuration mode
connection.send_command("set device-group global address netmiko_test ip-netmask 8.8.8.8/32")
connection.disconnect()
connection.config_mode()
: This line instructs Netmiko to enter the configuration mode on the Palo Alto firewall. In configuration mode, you can make changes to the device configuration.connection.send_command("set device-group global address netmiko_test ip-netmask 8.8.8.8/32")
: This line sends a command to the Palo Alto firewall to create a new address object named "netmiko_test" with an IP address of8.8.8.8
and a subnet mask of/32
, in theglobal
device-group.connection.disconnect()
: This line gracefully disconnects from the Palo Alto firewall, closing the SSH session.
As you can see above, the script has just created the Address Object in the Panorama.