XML API L100 ---------------------- Hands-on tasks for this workshop will be performing XML API calls against a PAN-OS firewall, from your command-line environment, using the ``curl`` command. For each task, you can use the copy button to take the command into the clipboard, but ensure you replace any UPPERCASE_VARIABLES with your own values. Assumptions: A host with ``curl`` installed, access to a PAN-OS next-generation firewall from your host. Note: * Lookout for text in uppercase, such as ``YOUR_FIREWALL_IP``, and replace the text with the relevant value for your environment. * Commands you could/should execute are denoted with ``$`` at the start, and have copy buttons; other text boxes show expected outputs. * You may wish to have a text editor open on your machine, to amend copied commands before pasting them into the host's CLI. Store our firewall's IP as a variable ================================================ First, to make our lives easier, we will assign the management IP address of the firewall to a variable, so we can easily refer to it in our API calls. Today, in this environment, we will assign the API key value to a variable called ``host``, to be used in future API calls. The export command stores the value of ``host`` in memory for the duration of the CLI session. .. code-block:: :class: copy-button $ export host='YOUR_FIREWALL_IP' Generate your API key ======================== Before you can make any API calls, you need to generate an API key. Your API key will allow you to authenticate and authorise yourself for future API calls. .. code-block:: :class: copy-button $ curl -ksd 'type=keygen&user=YOUR_ADMIN_USERNAME&password=YOUR_ADMIN_PASSWORD' https://$host/api -w "\n" | xmllint --format - .. code-block:: LUFRPT16V1ZzaHNFYVJEdlZnb3Buc1dJRWtCVFFPYjFXTzI2N1phVzRsMg== In production environments, credentials should be stored, accessed and used securely, per the security policy and compliance requirements. Today, in this environment, we will assign the API key value to a variable to be used in future API calls. Take the characters between the ``key`` tags from the previous output as your API key, in the example above this is the characters from ``LUFRPT16...`` to ``...Mg==`` .. code-block:: :class: copy-button $ export key='YOUR_API_KEY' For example: .. code-block:: $ export key='LUFRPT16V1ZzaHNFYVJEdlZnb3Buc1dJRWtCVFFPYjFXTzI2N1phVzRsMg==' Make your first real API call ==================================== Your first API call will tell you if the firewall is in a ready and operational state. This operational command is useful to know if the firewall has been recently rebooted, or in the case of software firewalls like VM-Series or CN-Series, recently created. The answer should be ``yes``, within the XML-formatted response. .. code-block:: :class: copy-button $ curl -ksd "type=op&cmd=&key=$key" https://$host/api -w "\n" | xmllint --format - .. code-block:: Get firewall system info ==================================== Next, retrieve information about the firewall system. This too is an operational command, as shown by ``type=op`` within the API call. The ``cmd=`` portion contains the operational command we want to execute. .. code-block:: :class: copy-button $ curl -ksd "type=op&cmd=&key=$key" https://$host/api -w "\n" | xmllint --format - Show the routing table ==================================== Another useful operational command is to display the routing table. .. code-block:: :class: copy-button $ curl -ksd "type=op&cmd=&key=$key" https://$host/api -w "\n" | xmllint --format - Show the rulebase configuration ==================================== Now we look at the firewall configuration. Notice the type of API call this time is ``type=config``, and the action is ``get``, which as expected tells the API we want to do a read operation on the configuration. The ``xpath`` is then used to navigate down through the XML configuration file structure to specifically find the rules within the security policy. .. code-block:: :class: copy-button $ curl -ksd "type=config&action=get&xpath=/config/devices/entry[@name='localhost.localdomain']/vsys/entry[@name='vsys1']/rulebase/security/rules&key=$key" https://$host/api -w "\n" | xmllint --format - Show the rulebase hit counts ==================================== We've seen the rulebase from the configuration, but if we wanted to programmatically retrieve the hit counts for each rule, that would be an operational command. .. code-block:: :class: copy-button $ curl -ksd "type=op&cmd=&key=$key" https://$host/api -w "\n"| xmllint --format - Backup/export configuration ==================================== This is a common API call, given how many people have requirements to automate backing up configurations. This uses ``type=export`` to signify we are exporting something, and ``category=configuration`` describes the exact item we want to export. .. code-block:: :class: copy-button $ curl -ksd "type=export&category=configuration&key=$key" https://$host/api -w "\n" | xmllint --format - The command above sent the config file to the CLI terminal, we could instead save it to a file: .. code-block:: :class: copy-button $ curl -ksd "type=export&category=configuration&key=$key" https://$host/api -w "\n" > exported_config.xml User-ID ================ A frequent use case is to register user-to-IP mappings. The first task here, another operational command, shows the current user-to-IP mapping table, and should give an empty response. .. code-block:: :class: copy-button $ curl -ksd "type=op&cmd=&key=$key" https://$host/api -w "\n" | xmllint --format - .. code-block:: The next API call registers a username to an IP address. This uses ``type=user-id``. Note we pass in the username, the IP address they are currently using, and a timeout value (in seconds). .. code-block:: :class: copy-button $ curl -ksd "type=user-id&cmd=2.0update&key=$key" https://$host/api -w "\n" Replaying the API call to show the mapping table should now display the new user .. code-block:: :class: copy-button $ curl -ksd "type=op&cmd=&key=$key" https://$host/api -w "\n" | xmllint --format - Find An API Command - CLI Debug ================================ One way to find an API call for specific operation is to observe or "debug" the CLI, which itself uses the XML API. Once debugging is enabled, an XML API call will be displayed when a CLI command is executed. Using the example of our first API call in this workshop, the CLI command equivalent is "show chassis-ready". When debugged, this gives the following output: .. code-block:: :emphasize-lines: 1,2,6 admin@firewall> debug cli on admin@firewall> show chassis-ready (container-tag: chassis-ready pop-tag:) ((eol-matched: . #t) (context-inserted-at-end-p: . #f)) 2021-11-05 12:56:57 yes Note the highlighted lines, first the command for turning on CLI debugging, then the execution the command of interest (``show chassis-ready``), then the observation of the XML API equivalent for the CLI command. The XML required to make a call ourselves is between (but not including) the ```` tags. This gives us ````, which becomes the ``cmd=`` portion of the final API command: ``https://$host/api/?type=op&cmd=&key=$key`` Connect to the firewall using SSH: .. code-block:: :class: copy-button $ ssh YOUR_ADMIN_USERNAME@$host Then choose one (or more) of the following operational commands, debug the CLI, then create and execute XML API command equivalents. You may wish to use two CLI windows, your original CLI for performing XML API commands, and a second CLI for SSH to the firewall. * show system masterkey-properties * show arp all * show interface management * clear user-cache all Find An API Command - API Browser ================================== Another way to find an API call for specific operation is to use the API browser, which can be found at ``https://firewall/api``. **Once logged in to the web GUI**, browse to ``https://firewall/api`` and a listing of the types of available XML API request types is displayed. Hyperlinks can be used to browse through the XML API request types until the required request format is found. Again using the example of our first API call in this workshop, ``show chassis-ready``, click the ``Operational Commands`` link, then the ``show`` link, then the ``chassis-ready`` link. You will be shown the XML API format we observed in the CLI (````), as well as the XML API URL structure (``/api/?type=op&cmd=``). Clicking the hyperlinked XML API URL performs the API command and displays a result. Choose one (or more) of the following operational commands, find the command in the API browser, then create and execute XML API command equivalents: * show clock * show admins all * clear counter all * show system disk-space