How to filter results from Palo Alto firewall

I have what’s probably a newbie question about automating our Palo Alto firewall with Ansible.

I want to create a playbook that accepts an IP address or FQDN as a variable and returns all the objects with that IP/FQDN and all rules that apply to those objects. By adding this as a template in Tower, I’m trying to let developers answer the question, “My code isn’t working, could the firewall be my problem?” They enter the IP and get back a list of all the rules that apply to it.

My playbook authenticates and returns all objects or all rules with gathered_filter: *. So far, so good. I’d like to use gathered_filter to get only those rules that apply to the IP provided.

I want something like gathered_filter: "<field> contains {{ ip_user_entered }}" but I don’t know what I should put in the <field>. Where should I look for possible values for <field>?

The examples in the documentation show three options: description, ‘name’ and ‘interfaces’. Are those the only fields available for filtering? Or should I be looking at the gathered_xml?

All suggestions, links, pointers welcome. Thanks!

I’m unable to assist specifically with filtering the initial gathered facts or with what PA returns, but you will probably need to do some jmespath magic to get the results you want.

Thanks for chiming in @Denney-tech!

It turns out that using state: gathered turns anything in the Ansible return values in the section marked gathered into a field you can filter. And strange as it seems, in this case the field to filter on turned out to be value.

I tracked this down by trial and error. I first created a task that retrieved all address objects using the paloaltonetworks.panos.panos_address_object module:

    - name: find address stuff with panos_address_object
      paloaltonetworks.panos.panos_address_object:
        provider: "{{ panos_provider }}"
        state: gathered
        gathered_filter: "*"
      register: address_stuff

Then I added a debug task with var: address_stuff, which gave me output like this (details scrubbed/anonymized):

{
  "address_stuff": {
    "changed": false,
    "gathered": [
      {
        "value": "123.456.78.90/32",
        "description": null,
        "tag": null,
        "name": "MyAddressObject",
        "address_type": "ip-netmask"
      },
      {
        "value": "123.456.0.0/16",
        "description": null,
        "tag": null,
        "name": "MySubnet",
        "address_type": "ip-netmask"
      },
      {
        "value": "10.10.10.0/18",
        "description": "other-subnetprivate",
        "tag": null,
        "name": "MyPrivateSubnet",
        "address_type": "ip-netmask"
      }
    ],
    "gathered_xml": [
      "details omitted here . . . "
    ],
    "failed": false
  },
  "_ansible_verbose_always": true,
  "_ansible_no_log": null,
  "changed": false
}

Then I tried a bunch of different things, most of which failed . . . and eventually I tried this and it worked:

    - name: find object with known IP
      paloaltonetworks.panos.panos_address_object:
        provider: "{{ panos_provider }}"
        state: gathered
        gathered_filter: "value contains 123.456.78.90"
      register: test_object

So it seems that in the pattern gathered_filter: "<field> <operator> <value>", the available values for <field> include anything inside gathered in the Ansible return values, however odd it may look.

2 Likes

Glad you got it figured out! That’s actually pretty straightforward considering you didn’t need to do anything weird with jmespath.

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.