Skip to main content

Working with Address Groups

This tutorial covers how to add & populate Static and Dynamic Address Groups to PAN-OS using API. If you are looking into adding IPs to Dynamic Address Groups using the Dynamic Address Group API, please refer to the dedicated tutorial.

This tutorial has 2 sections: the first section covers static Address Groups, the second section covers Dynamic Address Groups.

Requirements

To follow this tutorial, it is recommended that that you are familiar with the concepts of Palo Alto Networks Next-Generation Firewalls, Security Policies and APIs. Some basic understanding of XML is also recommended.

Make sure you have a Palo Alto Networks Next-Generation Firewall deployed and that you have administrative access to its Management interface via HTTPS. To avoid potential disruptions, it's recommended to run all the tests on a non-production environment.

No specific programming language expertise is required, although Python is recommended. Examples with both XML API, REST API and pan-python are provided.

Static Address Groups

Static Address Groups are address groups whose content is statically defined inside the PAN-OS configuration. They are traditional Address Groups. To change the members of a static address groups, you should change the PAN-OS config and commit.

Steps

  1. Grab the API Key
  2. Create an Address object (optional)
  3. Create an Address Group
  4. Edit the Address Group (optional)
  5. Commit!

Step 1: Grab the API Key

Please refer to the XML API Quickstart for instructions.

Step 2: Create an Address object (optional)

Static Address Groups cannot be empty. If you don't have an Address object already defined or you don't want to use it, you should create at least an Address object before creating the Address Group.

The following code will create a new Address object called TutorialEntry with IP 1.1.1.1/32 (Hello there Cloudflare!)

The following code is for a Unix shell. To avoid fighting with string escapes, we use environment variables to store API Key, XPath and the new entry.

export API_KEY="<Your API Key here>"
export ELEMENT_VALUE="<ip-netmask>1.1.1.1/32</ip-netmask>"
export ELEMENT_XPATH="/config/devices/entry[@name='localhost.localdomain']/vsys/entry[@name='vsys1']/address/entry[@name='TutorialEntry']"
curl -g "https://<firewall>/api/?type=config&action=set&key=$API_KEY&xpath=$ELEMENT_XPATH&element=$ELEMENT_VALUE"

Response should be:

<response status="success" code="20"><msg>command succeeded</msg></response>

Step 3: Create the Address Group

Now we can create our static Address Group, we will call it TutorialAddressGroup.

The following code is for a Unix shell. To avoid fighting with string escapes, we use environment variables to store API Key, XPath and the new entry.

export API_KEY="<Your API Key here>"
export ELEMENT_VALUE="<member>TutorialEntry</member>"
export ELEMENT_XPATH="/config/devices/entry[@name='localhost.localdomain']/vsys/entry[@name='vsys1']/address-group/entry[@name='TutorialAddressGroup']/static"
curl -g "https://<firewall>/api/?type=config&action=set&key=$API_KEY&xpath=$ELEMENT_XPATH&element=$ELEMENT_VALUE"

Response should be:

<response status="success" code="20"><msg>command succeeded</msg></response>

Step 4: Edit the Address Group (optional)

We could commit now, but for the sake of this tutorial let's edit the address group we created to add a new entry and remove the existing one.

Before starting, create a new Address object called TutorialEntry2 following Step 2.

We can use an edit request here for the PAN-OS XML API. It is a bit weird, as the element should overlap with the XPath (<static> appears on both XPath and inside the element).

export API_KEY="<Your API Key here>"
export ELEMENT_XPATH="/config/devices/entry[@name='localhost.localdomain']/vsys/entry[@name='vsys1']/address-group/entry[@name='TutorialAddressGroup']/static"
export ELEMENT_VALUE="<static><member>TutorialEntry2</member></static>"
curl -g "https://<firewall>/api/?type=config&action=edit&key=$API_KEY&xpath=$ELEMENT_XPATH&element=$ELEMENT_VALUE"

Response should be:

<response status="success" code="20"><msg>command succeeded</msg></response>

Step 5: Commit!

This is where pan-python and the SDKs start shining. The commit process via the API is asynchronous and has 2 steps:

  1. Send the commit request. This will start a commit job and return a job id
  2. Periodically check with the API the status of the job. When the job has finished the API response includes the commit result

This process is easy to implement with the SDKs as they include functions to issue the commit request and automatically follow the resulting job.

Let's do a commit in the hard way. First we send the request and then we follow the job using curl.

export API_KEY="<Your API Key here>"
curl -g "https://<firewall>/api/?key=$API_KEY&type=commit&cmd=<commit></commit>"

Response should be (jobid will be different):

<response status="success" code="19"><result><msg><line>Commit job enqueued with jobid 271</line></msg><job>271</job></result></response>

Now with the jobid we can poll the API to check the status of the job:

curl -g "https://<firewall>/api/?type=op&cmd=<show><jobs><id>271</id></jobs></show>"

When the commit job is still running, the status will be ACT:

<response status="success">
<result>
<job>
<tenq>2019/11/19 10:45:11</tenq>
<tdeq>10:45:11</tdeq>
<id>271</id>
<user>XMLTutorial</user>
<type>Commit</type>
<status>ACT</status>
<queued>NO</queued>
<stoppable>yes</stoppable>
<result>PEND</result>
<tfin>Still Active</tfin>
<description></description>
<positionInQ>0</positionInQ>
<progress>0</progress>
<warnings></warnings>
<details></details>
</job>
</result>
</response>

Once finished, the status will be FIN and you can check if the commit was successful by looking at the <result> tag:

<response status="success">
<result>
<job>
<tenq>2019/11/19 10:45:11</tenq>
<tdeq>10:45:11</tdeq>
<id>271</id>
<user>XMLTutorial</user>
<type>Commit</type>
<status>FIN</status>
<queued>NO</queued>
<stoppable>no</stoppable>
<result>OK</result>
<tfin>10:47:27</tfin>
<description></description>
<positionInQ>0</positionInQ>
<progress>100</progress>
<details>
<line>Partial changes to commit: changes to configuration by all administrators </line>
<line>Changes to policy and objects configuration</line>
<line>Changes to configuration in device and network</line>
<line>Changes to shared configuration</line>
<line>Configuration committed successfully</line>
</details>
<warnings></warnings>
</job>
</result>
</response>

Dynamic Address Groups

Dynamic Address Groups are defined as boolean expressions over IP tags. Every time an IP is tagged using the Dynamic Address Group API, PAN-OS evaluates the expression associated with a Dynamic Address Group. If the result is true, then the IP is automatically added to the Dynamic Address Group.

Dynamic Address Groups is a powerful mechanism that could be used to cover many use cases, for details about populating the Dynamic Address Group refer to the dedicated tutorial.

Steps

  1. Grab the API Key
  2. Add a new Dynamic Address Group
  3. Commit!
  4. Populate the Dynamic Address Group

Step 1: Grab the API Key

See Step 1 of Static Address Groups

Step 2: Add a new Dynamic Address Group

The content of a Dynamic Address Group is not a static list of Address objects, like for Static Address Groups, but a filter. A filter is a boolean expression built on IP tags.

In this example we will create a new Dynamic Address Group called TutorialDAG with filter tag1 AND tag2. All the IPs pushed via the DAG API with both tag1 and tag2 will be automatically added to this DAG.

Note the element content is URL encoded:

export API_KEY="<Your API Key here>"
export ELEMENT_VALUE="<filter>tag1%20AND%20tag2</filter>"
export ELEMENT_XPATH="/config/devices/entry[@name='localhost.localdomain']/vsys/entry[@name='vsys1']/address-group/entry[@name='TutorialDAG']/dynamic"
curl -g "https://<firewall>/api/?type=config&action=set&key=$API_KEY&xpath=$ELEMENT_XPATH&element=$ELEMENT_VALUE"

Response should be:

<response status="success" code="20"><msg>command succeeded</msg></response>

Step 3: Commit!

See Step 5 of Static Address Group section

Step 4: Populate the Dynamic Address Group

Not covered here, check the dedicated tutorial