Palo Alto

Palo Alto - Remove Unused Address Objects Using pan-os-php

Palo Alto - Remove Unused Address Objects Using pan-os-php
In: Palo Alto, Firewall

If you’ve worked with Palo Alto firewalls, you might have noticed they don’t make it easy to get rid of unused address objects. It seems like such a basic feature should be included, right? While you could use Expedition for this, it requires setting up a separate server and learning a new tool, which might be more hassle than it’s worth.

I’ve talked before about using a simple Python script to clean up unused address objects (link below), but it was pretty basic and I didn't take many scenarios into account. Today, I want to show you an even easier more sophisticated way to handle this using Pan-OS-PHP. This tool is fantastic because you can use it directly from the command line. You don’t need to know any PHP to get started. Let’s look at how this can make managing your firewall a lot easier.

Palo Alto Firewall - Find and Remove Unused Address Objects
In this blog post, I’ll show you a very simple Python script to find unused address objects from the Palo Alto firewall or Panorama and remove them if needed.
Disclaimer - Please proceed with caution when using automated scripts for configuration changes. Always double-check what’s being removed by reviewing the outputs and logs before committing any changes.

Pan-OS-PHP Intro

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 on 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.

  1. 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.
  2. 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
  • --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

As you can see above, I can access the exported configuration from inside the container.

How to Best Use Panorama Templates and Stacks?
A good practice is to always start with creating a ‘global’ template. This is where you define configurations that all firewalls across the company should have.

What's Our Goal Here?

Our goal here is simple. We want to find and remove any unused address objects and address groups from the firewall or Panorama. When I say “unused,” I mean any object that’s sitting there but isn’t being referenced or used anywhere.

Let’s look at a simple example to understand how we can clean up unused address objects in the firewall. In our example, we have six address objects and two address groups. Here’s how they are used.

  • app_server_1 is directly used in a security policy.
  • The three DNS servers are part of two address groups. One of these groups is used in a security policy.

When we do our magic, our goal is to automatically identify and remove app_server_2, app_server_subnet and google_dns_servers because they are not referenced anywhere. Of course, this is a very simplified example, but you could have 1000s of objects and 100s of rules so, doing this manually would take hours and hours.

The object google_dns_2 is slightly complex, and we’ll go over this in a later section to explain why it’s tricky.

Let's Start the Cleanup

Now it’s time for the cleanup, and you only need a single command to start removing those unused objects.

When you try to connect to the firewall the very first time, you will be prompted for an API key or username/password.
pan-os-php in=api:// type=address 'filter=(object is.unused)' actions=delete

To successfully run the cleanup, you’ll need to provide a few mandatory parameters.

  • Calling pan-os-php - This is how you initiate the tool.
  • Type - Specifies the type of resource you’re working with; here, it’s 'address'.
  • In Determines how you want to connect. You can connect directly to the firewall using api, or work with a configuration file if preferred.
  • Actions - Defines what you want to do. In this scenario, we’re deleting unused objects.

While not mandatory, using the filter parameter can refine what objects the tool acts upon. In our example, filter=(object is.unused) specifically targets objects that are marked as unused. You can explore other filters relevant to your needs by running the listfilters command, like this.

pan-os-php type=address listfilters

As you can see from the command output, the unused address objects and the group are now gone. The output also provides clear feedback on what has been removed.

What happened to 'google_dns_2'?

As mentioned earlier, the case of google_dns_2 is a bit tricky. While this address object is technically referenced within an address group, that particular group google_dns_servers itself isn’t referenced anywhere else. As a result, the tool initially sees google_dns_2 as having a reference and doesn’t remove it.

However, now that the address group itself has been removed during the first cleanup run, google_dns_2 no longer has any active references. If you rerun the cleanup command, the tool should now recognize that google_dns_2 is unused and remove it as well.


Please note that there is a filter available filter=(object is.unused.recursive) and here is the official description for it.

"is.unused.recursive' considers an object or a group unused only if they are NOT referenced in any rules, interfaces, static routes AND if they are referenced inside a group which itself is not referenced anywhere"

But even then, the object is not being removed so, keep this in mind when if you come across similar situation.

'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 the same example that uses a specific parameter to get the 'set' commands.

pan-os-php in=api:// type=address 'filter=(object is.unused)' actions=delete out=out.xml outputformatset=setcommand.txt
delete address-group "google_dns_servers"
delete address "app_server_2"
delete address "app_server_subnet"
How to Export Large Traffic Logs from Palo Alto Firewall?
Recently, I faced a unique challenge, I needed to export a massive amount of traffic logs from a Palo Alto Firewall for analysis. Initially, I thought it would be straightforward


Using Pan-OS-PHP with Panorama works in a similar way to managing individual devices, but with a key difference involving device groups. To demonstrate, I’ve copied the same set of objects, groups, and rules into Panorama. I put the addresses and groups into the ‘Shared’ device group, and the rules into a specific device group.

When running the cleanup in Panorama, you need to specify the device group from which you’re cleaning up objects. In this case, I would indicate that I’m targeting the ‘Shared’ device group. The tool will then proceed to check for references across all device groups.

pan-os-php in=api:// type=address location=shared 'filter=(object is.unused)' actions=delete


pan-os-php/PAN-OS-PHP User Guide - shareable outside Palo.pdf at main · swaschkut/pan-os-php
Framework and utilities to easily manage and edit Palo Alto Network PANOS devices - swaschkut/pan-os-php
Written by
Suresh Vina
Tech enthusiast sharing Networking, Cloud & Automation insights. Join me in a welcoming space to learn & grow with simplicity and practicality.
More from Packetswitch
Table of Contents
Great! You’ve successfully signed up.
Welcome back! You've successfully signed in.
You've successfully subscribed to Packetswitch.
Your link has expired.
Success! Check your email for magic link to sign-in.
Success! Your billing info has been updated.
Your billing was not updated.