Ansible L100 ---------------------- Hands-on tasks for this workshop will be using Ansible playbooks against a PAN-OS firewall, from your command-line environment. 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 the following installed: curl, git, `Python 3 `_, `Ansible `_, `PAN-OS-Python `_, `PAN-OS Ansible Collection `_, and all prerequisite requirements for those items. Plus some form of text editor on your host. And, 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. Ansible pre-flight checks =============================================== First let's check that Ansible is installed on our host: .. code-block:: :class: copy-button $ ansible-playbook --version The output should look something like this: .. code-block:: ansible-playbook [core 2.11.5] config file = None configured module search path = ['/Users/jholland/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules'] ansible python module location = /usr/local/lib/python3.9/site-packages/ansible ansible collection location = /Users/jholland/.ansible/collections:/usr/share/ansible/collections executable location = /usr/local/bin/ansible-playbook python version = 3.9.7 (default, Oct 13 2021, 06:45:31) [Clang 13.0.0 (clang-1300.0.29.3)] jinja version = 2.11.3 libyaml = True The PAN-OS Collection has been pre-installed for you. We can check the Collection is present using this command: .. code-block:: :class: copy-button $ ansible-galaxy collection list The output should list all the collections installed, including the PAN-OS collection, and the list should look something like this: .. code-block:: Collection Version ---------------------- ------- community.general 4.0.2 paloaltonetworks.panos 2.9.0 Download Ansible playbooks ================================================ In this workshop, we're going to be using some existing playbooks. We'll use git to download the playbooks from a repository... .. code-block:: :class: copy-button $ git clone https://github.com/jamesholland-uk/automation-workshops.git ...then move into the Ansible directory .. code-block:: :class: copy-button $ cd automation-workshops/ansible Setup the inventory ================================================ Ansible needs to know the details for the hosts against which it should execute playbooks. This ``inventory`` can take many formats and locations, and for this workshop we will use the inventory format from the example playbooks repository. In the ansible-playbooks directory, the ``inventory`` file contains a list of available hosts for us to run playbooks against: .. code-block:: :class: copy-button $ cat inventory .. code-block:: firewall ha_pair panorama panorama_ha_pair All our example playbooks begin with a reference to a default target host from our ``inventory`` file, which is ``firewall``: .. code-block:: - hosts: '{{ target | default("firewall") }}' We provide the ``firewall``'s IP address in the ``host_vars/firewall.yml`` file: .. code-block:: :class: copy-button $ cat host_vars/firewall.yml .. code-block:: --- ip_address: '192.168.55.10' Change the IP address in this file to match your firewalls's management IP address, either use your preferred text editor to replace the IP address in ``host_vars/firewall.yml``, or use this command: .. code-block:: :class: copy-button $ cat > host_vars/firewall.yml < { "msg": [ "Hostname: vm-series-01", "Serial: 01234567890", "Model: PA-VM", "Version: 10.1.3", "Uptime: 46 days, 3:03:16", "HA Enabled: True", "HA Type: Active-Passive", "HA Status: active", "Multi-VSYS: off", "1546 out of 256000 sessions in use" ] } PLAY RECAP ******************************************************************************************************************************** firewall : ok=3 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0 Ansible Playbook 2 - Are you ready? ================================================ Our second playbook executes the ``show chassis-ready`` command. This is useful to ensure the firewall is ready to accept further operations such as configuration changes, software downloads and upgrades, and more. The ``check_ready.yml`` playbook runs the ``show chassis-ready`` command on a loop until it gets the positive ``yes`` result that the firewall is ready. Run the playbook using the following: .. code-block:: :class: copy-button $ ansible-playbook -i inventory check_ready.yml --extra-vars "username=$panos_username password=$panos_password" The playbook has the same opening sections for the hosts, connection, and variables. The tasks section is different, where this time we use a single task ( using`panos_op` to run `show chassis-ready`), then use Ansible's `retries` and `until` to create the loop which waits for the firewall to be ready by virtue of the `yes` response. It will retry 50 times, trying every 30 seconds, until the output from the `show chassis-ready` is `yes`. .. code-block:: tasks: - name: Check to see if device is ready paloaltonetworks.panos.panos_op: provider: '{{ device }}' cmd: 'show chassis-ready' changed_when: false register: result until: result is not failed and (result.stdout | from_json).response.result == 'yes' retries: 50 delay: 30 The successful output should look something like this, specifically the highlighted line showing the "ok" response to checking if the firewall is ready: .. code-block:: :emphasize-lines: 7 PLAY [firewall] ************************************************************************************************** TASK [Gathering Facts] ******************************************************************************************* ok: [firewall] TASK [Check to see if device is ready] *************************************************************************** ok: [firewall] PLAY RECAP ******************************************************************************************************* firewall : ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0 If the firewall is booting up, or not reachable, you would receive failure messages, and the loop of checking would kick in, like this: .. code-block:: :emphasize-lines: 7,8 PLAY [firewall] ************************************************************************************************** TASK [Gathering Facts] ******************************************************************************************* ok: [firewall] TASK [Check to see if device is ready] *************************************************************************** FAILED - RETRYING: Check to see if device is ready (50 retries left). FAILED - RETRYING: Check to see if device is ready (49 retries left). Ansible Playbook 3 - More firewall information ================================================ The third example playbook, ``some_more_info.yml`` again gathers ``facts`` in order to display information about the running configuration and state of the firewall. This could be useful information on its own, but could also be used to feed into other tasks later on. Run the playbook using the following: .. code-block:: :class: copy-button $ ansible-playbook -i inventory some_more_info.yml --extra-vars "username=$panos_username password=$panos_password" The playbook should provide information about the security policy rules, the network interfaces, and the route table. Ansible Playbook 4 - Config backup/export ================================================ The next Ansible playbook uses the `panos_export module `_ to export the running config to a local file. Run the playbook using the following: .. code-block:: :class: copy-button $ ansible-playbook -i inventory backup_config.yml --extra-vars "username=$panos_username password=$panos_password" Once executed, you should be able to see the exported config file on yours host: .. code-block:: :class: copy-button $ ls -l running-config.xml Confirm the exported file has a recent timestamp: .. code-block:: -rw-rw-r-- 1 labadmin labadmin 96164 Jun 22 10:00 running-config.xml Optionally inspect the config: .. code-block:: :class: copy-button $ cat running-config.xml | xmllint --format - Ansible Playbook 5 - Firewall configuration tasks ==================================================================== Our next playbook is focused on configuration tasks, and this playbook configures all the required items for a basic firewall setup, including zones, interfaces, objects and more: .. code-block:: tasks: - name: Create DMZ zone paloaltonetworks.panos.panos_zone: provider: "{{ device }}" zone: "dmz" mode: "layer3" . . . You can see all the configuration items by viewing the playbook: .. code-block:: :class: copy-button $ cat simple_config.yml By logging into the firewall web GUI, you should be able to observe that these configuration items do not already exist. Let's execute the playbook: .. code-block:: :class: copy-button $ ansible-playbook -i inventory simple_config.yml --extra-vars "username=$panos_username password=$panos_password" By observing the firewall web GUI, you should be able to see the new configuration items. Modify a playbook ================================== The `panos_op module `_ is very useful within playbooks for gathering information and executing operational commands like gathering system information, software upgrades, content downloads, and more. It was used in the second playbook, ``check_ready.yml``, to run the ``show chassis-ready`` command. Choose one (or more) of the following operational commands to run with Ansible. * show clock * show admins all * show system disk-space Edit the ``template.yml`` playbook (shown below) playbook with your preferred text editor, then execute your chosen commands. The output from the commands should be displayed. .. code-block:: :class: copy-button - name: Perform an op command paloaltonetworks.panos.panos_op: provider: '{{ device }}' cmd: 'command goes here' register: op_command_output - name: Show output debug: msg: - "{{ op_command_output }}"