In this blog post, I will show you how to use Ansible to deploy configurations to the Palo Alto Firewalls.
Setting up the environment
I'm using Ubuntu 18.04 server for this example.
- Ansible Galaxy Role
- pip
- pan-os SDK
Palo Alto Networks Ansible Galaxy Role
https://ansible-pan.readthedocs.io/en/latest/
The Palo Alto Networks Ansible Galaxy role is a collection of modules that automate configuration and operational tasks on Palo Alto Firewalls and Panorama. The underlying protocol uses API calls that are wrapped within the Ansible framework.
You can install the collection by using ansible-galaxy collection install paloaltonetworks.panos
command
ubuntu@ubuntu_1804:~/palo-ansible/playbooks$ ansible-galaxy collection install paloaltonetworks.panos
Process install dependency map
Starting collection install process
Installing 'paloaltonetworks.panos:2.4.0' to '/home/ubuntu/.ansible/collections/ansible_collections/paloaltonetworks/panos'
Install pip
Pip is a package management system that simplifies the installation and management of software packages written in Python.
You can install it by using sudo apt install python-pip
command
Palo Alto Networks PAN-OS SDK for Python
The PAN-OS SDK for Python (pan-os-python) is a package to help interact with Palo Alto Networks devices
ubuntu@ubuntu_1804:~/palo-ansible/playbooks$ pip install pan-os-python
Collecting pan-os-python
Downloading https://files.pythonhosted.org/packages/7b/3e/94d901ed6fc435307bdb34e5b7a8f2a69902a71f44a44a987c63359c5c1f/pan_os_python-1.0.2-py2.py3-none-any.whl (122kB)
100% |████████████████████████████████| 122kB 2.6MB/s
Collecting pan-python<0.17.0,>=0.16.0 (from pan-os-python)
Using cached https://files.pythonhosted.org/packages/3b/fd/20127311eae9c31b7ae3e47d2279da7aea2aab2bf9f50b19d56ef367735e/pan_python-0.16.0-py2.py3-none-any.whl
Installing collected packages: pan-python, pan-os-python
Successfully installed pan-os-python-1.0.2 pan-python-0.16.0
Ansible Installation
You can install Ansible by using this guide: Installing Ansible — Ansible Documentation
Ansible files
Diagram
I created a local user name and password on the Palo Alto via the GUI
Get your API key
In this example, I'm using the API key instead of using username/password.
To use the API, you must generate the API key required for authenticating API calls. To generate an API key, make a GET
or POST
request to the firewall’s hostname or IP addresses using the administrative credentials and type keygen
curl -k -X GET 'https://<firewall>/api/?type=keygen&user=<username>&password=<password>'
curl -k -X POST 'https://192.168.1.65/api/?type=keygen&user=ansible&password=Cisco123'
A successful API call returns status="success"
along with the API key within the key element.
<response status = 'success'><result><key>LUFRPT1lV0JxY1N0bWp5d2hpeCtIZ0Urc0oxZFdvQWM9c3RPNGhaeGpjLzA1N0JVRjJ5SGduZ252S2FrL09sL0JueUU5dlRITEdxcDl0bllxM3phbGc2K2FCdTNZZWVNdw==</key></result></response>
Playbook
The Playbook creates the following
- Create address-objects for
server1
andusers
- Management Profile which allows ping to the
INSIDE
interface - Create
INSIDE
andUSERS
zones - Adding
eth1/1
andeth1/2
interfaces to each zone. - Security rule allowing
ping
fromusers-subnet
toserver1
Verification
Encrypting sensitive data with Ansible Vault.
Ansible Vault encrypts variables or files so, the sensitive data such as passwords or keys are not visible. In our example, we can see that the api_key
is visible in the Playbook.
I'm going to move the palo_provider
variable to group_vars
directory and add the api_key
to the vault.
Create a vault and move the api_key
ubuntu@ubuntu_1804:~/palo-ansible/inventory/group_vars/palo$ ansible-vault create vault
New Vault password:
Confirm New Vault password:
ubuntu@ubuntu_1804:~/palo-ansible/inventory/group_vars/palo$ ansible-vault view vault
Vault password:
---
vault_api_key: LUFRPT1lV0JxY1N0bWp5d2hpeCtIZ0Urc0oxZFdvQWM9c3RPNGhaeGpjLzA1N0JVRjJ5SGduZ252S2FrL09sL0JueUU5dlRITEdxcDl0bllxM3phbGc2K2FCdTNZZWVNdw==
ubuntu@ubuntu_1804:~/palo-ansible/inventory/group_vars/palo$ cat palo.yml
palo_provider:
ip_address: '192.168.1.65'
api_key: '{{ vault_api_key }}'
ubuntu@ubuntu_1804:~/palo-ansible$ tree
.
├── inventory
│ ├── group_vars <<<
│ │ └── palo <<<
│ │ ├── palo.yml <<<
│ │ └── vault <<<
│ └── host-file
└── playbooks
├── ansible.cfg
└── palo.yml
4 directories, 5 files
---
- name: Palo Alto Playbook
hosts: palo
gather_facts: false
connection: local
collections:
- paloaltonetworks.panos
tasks:
- name: Create Server Object
panos_address_object:
provider: '{{ palo_provider }}'
name: 'server1'
value: '172.16.1.10'
description: 'vmware'
- name: Create Users Object
panos_address_object:
provider: '{{ palo_provider }}'
name: 'users-subnet'
value: '10.10.10.0/24'
description: 'users subnet'
- name: Management Profile
panos_management_profile:
provider: '{{ palo_provider }}'
name: 'Allow Ping'
ping: true
- name: Create INSIDE Zone
panos_zone:
provider: '{{ palo_provider}}'
zone: 'INSIDE'
mode: 'layer3'
- name: Create USERS Zone
panos_zone:
provider: '{{ palo_provider}}'
zone: 'USERS'
mode: 'layer3'
- name: ethernet1/1 config
panos_interface:
provider: '{{ palo_provider }}'
if_name: 'ethernet1/1'
zone_name: 'INSIDE'
management_profile: 'Allow Ping'
mode: 'layer3'
enable_dhcp: false
ip: ['172.16.1.1/24']
- name: ethernet1/2 config
panos_interface:
provider: '{{ palo_provider }}'
if_name: 'ethernet1/2'
zone_name: 'USERS'
mode: 'layer3'
enable_dhcp: false
ip: ['10.10.10.1/24']
- name: Allow ping from users to server1
panos_security_rule:
provider: '{{ palo_provider }}'
rule_name: 'allow ping'
description: 'Allow ping from users to server1'
source_zone: ['USERS']
source_ip: ['users-subnet']
destination_zone: ['INSIDE']
destination_ip: ['server1']
application: ['ping']
action: 'allow'
- name: Commit
panos_commit:
provider: '{{ palo_provider }}'
The most straightforward way of decrypting content at runtime is to have Ansible prompt you for the appropriate credentials. You can do this by adding the --ask-vault-pass
to any ansible
or ansible-playbook
command.
ubuntu@ubuntu_1804:~/palo-ansible/playbooks$ ansible-playbook palo.yml --ask-vault-pass
Vault password:
PLAY [Palo Alto Playbook] ************************************************
Using Ansible Vault with a Password File
If you do not wish to type in the Vault password each time you execute a task, you can add your Vault password to a file and reference the file during execution.
ubuntu@ubuntu_1804:~/palo-ansible/playbooks$ echo 'Cisco123' > .vault_pass
ubuntu@ubuntu_1804:~/palo-ansible/playbooks$ ls -la
total 20
drwxrwxr-x 2 ubuntu ubuntu 4096 Dec 22 15:27 .
drwxrwxr-x 4 ubuntu ubuntu 4096 Dec 21 18:03 ..
-rw-rw-r-- 1 ubuntu ubuntu 96 Dec 21 18:12 ansible.cfg
-rw-rw-r-- 1 ubuntu ubuntu 1931 Dec 22 15:05 palo.yml
-rw-rw-r-- 1 ubuntu ubuntu 9 Dec 22 15:27 .vault_pass <<<
To make Ansible aware of the password file, you can edit your ansible.cfg
file
ubuntu@ubuntu_1804:~/palo-ansible/playbooks$ cat ansible.cfg
[defaults]
inventory = /home/ubuntu/palo-ansible/inventory/host-file
vault_password_file = ./.vault_pass
Now, when you run commands that require decryption, you will no longer be prompted for the vault password.
ubuntu@ubuntu_1804:~/palo-ansible/playbooks$ ansible-playbook palo.yml
PLAY [Palo Alto Playbook] ************************
TASK [Create Server Object] ************************
ok: [PALO-1]
Thanks for reading.
As always, your feedback and comments are more than welcome.