In this blog post, we'll explore how to use the
pan-os-python library with Panorama. Working with Panorama is a bit different because of device-groups and templates. I'll show you the differences between connecting to Panorama and a regular firewall. We'll also go through some examples, like making objects and setting up rules. If you're new to the
pan-os-python library, please take a look at my other blog post linked below.
Connecting to a Regular Firewall
In the snippet below, we're connecting to a regular Palo Alto firewall using the
from panos.firewall import Firewall from panos.objects import AddressObject fw_object = Firewall('FIREWALL_IP', 'USERNAME', 'PASSWORD') new_address = AddressObject( name='server_1', value='192.168.10.10/32', type='ip-netmask', description='This is server_1 IP' ) fw_object.add(new_address) new_address.create()
First, we import the necessary modules. The
Firewall class lets us establish a connection to the firewall by providing its IP, username, and password.
We then define a new address object with the
AddressObject class, setting its name, IP address, type, and a brief description. After establishing the connection with
fw_object, we add our new address object and instruct it to be created on the firewall.
Now that we've covered this, in the next section, we'll dive into how to create this same object in Panorama.
Connecting to Panorama
In this section, the primary focus is on connecting to Panorama instead of a standalone firewall.
from panos.panorama import Panorama, DeviceGroup from panos.objects import AddressObject panorama_object = Panorama('PANORAMA_IP', 'USERNAME', 'PASSWORD' ) dg_object = DeviceGroup("test_dg") panorama_object.add(dg_object) new_address = AddressObject( name='server_1', value='192.168.10.10/32', type='ip-netmask', description='This is server_1 IP' ) dg_object.add(new_address) new_address.create()
Here's what's different
- Connection to Panorama - The first notable change is the use of the
Panoramaclass for establishing a connection. We pass in the Panorama IP, username, and password to get our
- Working with Device Groups - A key difference when dealing with Panorama is the introduction of the
DeviceGroup. Panorama uses device groups to manage similar firewalls as one logical unit. Our script defines a device group named 'test_dg' and adds it to our
- Adding Address to Device Group -Instead of adding the new address directly to the firewall, we're adding it to our device group (
dg_object). By doing this, the new address object will be available to all firewalls under this device group in Panorama.
Here is another example of creating a Security Rule in Panorama under a specific device-group.
from panos.panorama import Panorama, DeviceGroup from panos.objects import AddressObject from panos.policies import PreRulebase, SecurityRule panorama_object = Panorama('PANORAMA_IP', 'USERNAME', 'PASSWORD' ) dg_object = DeviceGroup("test_dg") panorama_object.add(dg_object) rules_object = dg_object.add(PreRulebase()) new_rule_object = SecurityRule( name='Allow DNS', fromzone=['any'], tozone=['any'], source=['any'], destination=['22.214.171.124'], application=['dns'], service=['application-default'], action='allow' ) rules_object.add(new_rule_object) response = new_rule_object.create() print(response)
You might be thinking how do I know which Classes to use and how to associate them with each other? Well, it takes a bit of time to figure out which Classes to use. I typically start from the Panorama Class and then make my way through the hierarchy.
This hierarchy and relationship between these Classes help ensure that when you're pushing configurations from your Python script, they are applied in the correct order and to the right set of devices as it would if you were manually configuring them through the Panorama GUI.
In the provided code, we start by importing the necessary classes. Just like with the device-group, we first create an instance of the Panorama Class with the Panorama's IP, username, and password.
from panos.panorama import Panorama, Template from panos import network panorama_object = Panorama('PANORAMA_IP', 'USERNAME', 'PASSWORD') tp_object = Template("lab") panorama_object.add(tp_object) new_zone = network.Zone( name="test_zone", mode="layer3" ) tp_object.add(new_zone) new_zone.create()
The next step is the creation of a template. We initiate an instance of the
Template Class and name it
tp_object. After defining the template, we associate it with the Panorama instance by using the
Now, once the template is associated with Panorama, we can begin to define objects that fall under this template. In this example, a new zone named 'test_zone' with mode set to 'layer3' is created using the
Finally, this zone is associated with the template by using the
add() method on the template object. The
create() method is then used to send the configuration to Panorama.
Please note that even though I only used two parameters while creating the new zone (name and mode), there are other parameters available as shown here.
You can find more details by navigating to the pan-os-python Library guide here.
Python OOP Inheritance
In Python, inheritance is a core principle of object-oriented programming that allows one class to inherit attributes and methods from another class. This facilitates the creation of a new class based on an existing class, encouraging code reusability and establishing a relationship between the parent (base) and child (derived) class.
In the context of the
pan-os-python library, when you associate a device-group with Panorama, you are setting up a hierarchical relationship. Here's what happens in a more detailed manner.
- Initialization - When you create an instance of the
DeviceGroupclass, you're essentially defining a logical representation of a device-group in your Python script.
- Association - When you add this device-group to the Panorama object, you're establishing a relationship that signifies the device-group exists within that Panorama object.
- Meaning in the Context of the Library - By setting this relationship, you are effectively telling the library, 'All subsequent operations or configurations that I perform on this device-group will be in the context of this specific Panorama instance'. This ensures that when configurations are pushed or pulled, they are done so for this device-group on this specific Panorama.
- No Actual API Calls Yet - At this point, no API calls to Panorama have been made. The library is merely organizing objects in a hierarchical manner locally within your script.
- Actual Configuration Push - Once you've set up the objects and relationships in your script, you'll use specific methods like
.apply()etc., to actually make API calls to Panorama to perform configuration tasks. The library will use the relationships you've defined to determine the correct API endpoints and structure the API requests appropriately.
In summary, inheritance helps structure your configuration in a way that mirrors how Panorama organizes configurations. It ensures that when you're ready to push configurations or perform other operations, the library knows how to correctly structure the API requests based on the relationships you've set up in your script.