Palo Alto Object and Policy Cleanup with pan-os-php
Hi all, welcome back to yet another Palo Alto Automation post. If you work with firewalls, you know that one of the most time-consuming tasks is decommissioning a single resource or an entire subnet from the firewall (aka removing all the references related to the resource). Let's imagine you have thousands of address objects and several hundred security policies. Now, suppose we decommissioned a server and our task is to remove any references we may have in the firewall. It could be an address object, a member in an address group, or a reference in a security policy. Removing this manually would take a lot of time, so in this blog post, let's look at a very simple way of cleaning this up using pan-os-php.
The Problem with the Manual Approach
Here is the problem with the manual approach. Let’s say we are trying to decommission the IP address 10.10.10.25. Let's say we have an address object created for this server, and it has been referenced in a few address groups and several security policies. If you try to remove the address object first, the firewall will complain because the object is being referenced elsewhere. So, you have to remove the references first.
If we start with the address group, we need to find all the address groups where this object is referenced and remove them one by one. There could be a problem if you have an address group where this object is the only member. If you try to remove the member, the firewall complains because you can’t have an empty address group, so you have to remove the address group too. Here is another problem, you could be referencing this address group in a security policy. So now you have to remove this address group from the security policy.
If you also have the address object referenced in several hundred rules, you need to remove them one by one. There could be some rules where either the source or destination is this specific address object only. In that case, you also need to remove the security policy completely. I hope you can see the problem here. It’s not as easy as you may think.
My Python Script
I spent a good couple of weeks developing my own Python script to address all of these issues. It works really well, utilizing Palo Alto’s REST API to connect to the Panorama/Firewall and perform the cleanup. Feel free to check it out below. However, I’ve found that pan-os-php does this even better.
Automated Approach with pan-os-php
Pan-OS-PHP is described as a “Framework and utilities to easily manage and edit Palo Alto Networks PAN-OS devices.” This PHP-based tool is hosted on Palo Alto’s official GitHub repository. The official version was last updated in 2023. However, there’s a more recent version maintained by one of the contributors; this fork was updated just two weeks ago, as of July 2024. This active maintenance indicates that the tool continues to evolve.
I’m still getting the hang of using Pan-OS-PHP, and it took me a bit of time to get a good understanding of the basics. Whenever I ran into questions, I reached out to the maintainer on Slack. He was incredibly responsive and always willing to help, so I owe him a massive thanks for all the support he’s given me.
Pan-OS-PHP Installation
Installing Pan-OS-PHP is very straightforward if you’re already familiar with the basics of Docker. This guide assumes you have Docker installed on your machine. I’m using a MacOS for this example and have Docker already set up.
Before diving into the installation process, it’s important to know that you can use Pan-OS-PHP in a couple of different ways.
- Connect to the firewall directly - You can configure the tool to directly connect to your firewall or Panorama via the API. Using this method, the tool will remove the unused objects, but remember, you’ll still need to commit these changes manually.
- XML Configuration File - If you prefer not to connect the tool directly to your devices, you can export the configuration from your firewall, modify it with Pan-OS-PHP, and then import the updated configuration back. This method gives you more control and review over the changes.
The tool can also generate 'set' command outputs that you can execute manually in the CLI for further customisation or control. To make this work, you need to run Docker from a shared directory. This allows the Docker container to read and write files within that directory.
For this example, I just created a directory called pan_os_php
, navigated to it and ran the following single command.
➜ docker run --name panosphp --rm -v ${PWD}:/share -it swaschkut/pan-os-php:latest
root@d8f81d529e8f:/share#
root@d8f81d529e8f:/share#
root@d8f81d529e8f:/share#
--name panosphp
- This names your Docker container 'panosphp'--rm
- This option removes the container once it stops running-v ${PWD}:/share
- This mounts the current working directory (${PWD}) to the/share
directory inside the container, allowing the tool to access and modify files in your directory.-it
- This runs the container in interactive mode, keeping the session open for you to interact with.swaschkut/pan-os-php:latest
- Specifies the Docker image to use, pulling the latest version of Pan-OS-PHP maintained by swaschkut.
root@d8f81d529e8f:/share# ls
running-config.xml
As you can see above, I can access the exported configuration from inside the container.
What's Our Goal Here?
In my firewall, I have a bunch of address objects, address groups, and policies. One specific address object is called app_server_1
, with an IP address of 192.168.10.10
. Here’s what we need to accomplish.
- Let's say this server is no longer in use and we need to remove all the references associated with this IP.
- Address Object - We want to remove the address object
app_server_1
- Address Groups - This address object is referenced in two address groups. In one of these groups,
app_server_1
is the only member, so we need to remove this address group completely. Additionally, we need to removeapp_server_1
as a member from the other address group. - Security Policies - This address object is referenced in two security policies. One of the rules has a single source address, which is this address object. As you may have guessed, we need to remove this rule completely.
Let’s put this to the test and see the results. We’ll use pan-os-php to handle these tasks and see how it simplifies the cleanup process.
To kick off the cleanup process, we can use the pan-os-php CLI tool with the following command.
pan-os-php \
in=api://10.10.0.31 \
type=address \
'filter=(value ip4.match.exact 192.168.10.10)' \
actions=decommission
Here’s a breakdown of the command.
- in - This specifies the connection to the firewall via the API. We’re connecting directly to the device using its IP address.
- type - We’re working with the type address, indicating that the command should target address objects.
- filter - This filter specifies the IP address 192.168.10.10, telling the tool to find this exact address object in the configuration.
- actions - The action decommission tells the library to clean up all references to the specified address object.
With this simple command, you can see in the screenshots that all references are gone. The pan-os-php tool makes the process incredibly straightforward, saving you time and effort in managing your firewall configuration.
Removing an Entire Subnet
Next, let’s look at an example where we want to remove an entire subnet. By specifying a subnet like /24, we remove not only the exact subnet but also all the objects that fall within this range. The only change to the command is the filter. This time, we will use a different filter, as shown below.
pan-os-php \
in=api://10.10.0.31 \
type=address \
'filter=(value ip4.included-in 192.168.10.0/24)' \
actions=decommission
The filter (value ip4.included-in 192.168.10.0/24
) ensures that the tool targets all address objects within the specified subnet range. This means any address object within 192.168.10.0/24
will be decommissioned along with its references.
If you want to see all the available filters for the type address, you can use the command pan-os-php type=address listfilters
I won’t bore you with all three screenshots, but I’ll show you the one from the address object tab where you can see all the references related to the subnet are gone.
/24
subnet only and not the child IP addresses, you can use the filter ip4.match.exact
Using 'set' commands
If you work in a place with strict change control policies or if you are not comfortable running the commands directly via the API, you can also get the 'set' commands output. Here is an example that uses a specific parameter to get the 'set' commands. You just need to add outputformatset=setcommand.txt
at the end of the CLI command.
pan-os-php in=api://10.10.0.31 type=address 'filter=(value ip4.included-in 192.168.10.0/24)' actions=decommission outputformatset=setcommand.txt
And here is the file it outputted with the 'set' commands.
delete rulebase security rules "permite_ad" source app_server_1
delete rulebase security rules "ssh_access"
delete address-group "servers" static app_server_1
delete address-group "servers" static app_server_2
delete address-group "app_group_1"
delete address "app_server_1"
delete address "app_server_2"
delete address "app_server_subnet"
Closing Up
I hope this can help save you a ton of time when managing your Palo Alto firewalls. I’m planning to write more content on pan-os-php, so feel free to subscribe if you want to receive future blog posts. If you have any comments or feedback, please let me know in the comments section. Thank you for reading, and happy automating.