1. Ansible のPAN-OS対応
Ansible 2.3 では、PAN-OSに対応した様々なモジュールが導入されました。
https://docs.ansible.com/ansible/list_of_network_modules.html#panos
- 例
- panos_security_policy: セキュリティポリシーを作成する
- panos_mgtconfig: 管理系設定を行う
今回は panos_address
を利用して、アドレスオブジェクトを作成してみます。
2. インストール
2.1. Ansible
pip install ansible
2.2. pan-python, pandevice
PAN-OS 関連のモジュールは内部でpan-pythonとpandeviceというPythonのモジュールを利用しているためインストールしておきます。
pip install pan-python pandevice
2.3. バージョン確認
[root@localhost ~]# ansible --version
ansible 2.3.0.0
config file =
configured module search path = Default w/o overrides
python version = 2.7.8 (default, Oct 22 2016, 09:02:55) [GCC 4.4.7 20120313 (Red Hat 4.4.7-17)]
ansible.cfg は特に作成していません。
3. インベントリファイルの作成
[palo]
192.168.0.15 # 今回は1台だけ
[palo:vars]
ansible_user=admin
ansible_password=passwordpassword
4. Plyaybookの作成
以下のファイルを palo_addr.yml として作成します。
---
- hosts: palo
gather_facts: no
connection: local
tasks:
- name: create address object
panos_address:
ip_address: "{{ inventory_hostname }}" # オブジェクトのアドレスではなくPaloaltoのアドレス
username: "{{ ansible_user }}"
password: "{{ ansible_password }}"
address_name: "client_pc01"
address: "192.168.0.101/32"
commit: False # 今回はcommitまでしない
本モジュールの公式ドキュメントが参考になります。
5. 動作確認
5.1. アドレス追加
5.1.1 事前確認
アドレスオブジェクトが何もない状態から始めます。
admin@PA-2050# show address
address;
[edit]
admin@PA-2050#
5.1.2 Playbook実行
[root@localhost ~]# ansible-playbook palo_addr.yml
PLAY [palo] **************************************************************************************************
TASK [create address Object] *********************************************************************************
ok: [192.168.1.15]
PLAY RECAP ***************************************************************************************************
192.168.1.15 : ok=1 changed=1 unreachable=0 failed=0
5.1.3 コンフィグ確認
ポリシーが追加されました。
admin@PA-2050# show address
address {
client_pc01 {
ip-netmask 192.168.0.101/32;
}
}
5.2 アドレス変更
ここで、既存アドレスオブジェクトのアドレスを変更することにします。
5.2.1. Playbook変更
address
を "192.168.0.101/32"
に変更します。
---
- hosts: palo
gather_facts: no
connection: local
- name: create address Object
panos_address:
ip_address: "{{ inventory_hostname }}"
username: "{{ ansible_user }}"
password: "{{ ansible_password }}"
address_name: "client_pc01"
address: "192.168.0.102/32" # ここ変更
commit: False
5.2.2 Playbook再実行
Playbookを変更したところで、もう一度実行します。
[root@localhost ~]# ansible-playbook palo_addr.yml
PLAY [palo] **************************************************************************************************
TASK [create address Object] *********************************************************************************
ok: [192.168.1.15]
PLAY RECAP ***************************************************************************************************
192.168.1.15 : ok=1 changed=0 unreachable=0 failed=0
おやおや? changed=0
とあるように、で変更がかかりませんでした。
IPアドレスの変更は変更とはみなされないようです。
5.3 アドレス名変更
今度は、アドレスではなく、アドレス名を変更することにします。
5.3.1. Playbook変更
address_name
を "client_pc02"
に変更します。
---
- hosts: palo
gather_facts: no
connection: local
- name: create address Object
panos_address:
ip_address: "{{ inventory_hostname }}"
username: "{{ ansible_user }}"
password: "{{ ansible_password }}"
address_name: "client_pc02" # ここ変更
address: "192.168.0.101/32"
commit: False
5.3.2 Playbook再実行
[root@localhost ~]# ansible-playbook palo_addr.yml
PLAY [palo] **************************************************************************************************
TASK [create address Object] *********************************************************************************
changed: [192.168.1.15]
PLAY RECAP ***************************************************************************************************
192.168.1.15 : ok=1 changed=1 unreachable=0 failed=0
今度は changed=1
となりました。
5.3.3 コンフィグ確認
変更ではなく、アドレス名が別のオブジェクトが追加されました。
admin@PA-2050# show address
address {
client_pc01 {
ip-netmask 192.168.0.101/32;
}
client_pc02 {
ip-netmask 192.168.0.101/32;
}
}
オブジェクト名があるかないかを見て、無ければ追加という扱いのようです。
6. (補足)Python 2.6 でのエラーについて
Python 2.6 環境では ansible-playbook
実行時に pandevice
内で以下エラーとなり、正常に実行できませんでした。そのため、今回はPython 2.7 の環境で実行しています。
Using module file /root/ansible/ansible/lib/ansible/modules/network/panos/panos_security_policy.py
<192.168.1.15> ESTABLISH LOCAL CONNECTION FOR USER: root
<192.168.1.15> EXEC /bin/sh -c 'echo ~ && sleep 0'
<192.168.1.15> EXEC /bin/sh -c '( umask 77 && mkdir -p "` echo /root/.ansible/tmp/ansible-tmp-1491081586.53-46889509406412 `" && echo ansible-tmp-1491081586.53-46889509406412="` echo /root/.ansible/tmp/ansible-tmp-1491081586.53-46889509406412 `" ) && sleep 0'
<192.168.1.15> PUT /tmp/tmpKdGZ_T TO /root/.ansible/tmp/ansible-tmp-1491081586.53-46889509406412/panos_security_policy.py
<192.168.1.15> EXEC /bin/sh -c 'chmod u+x /root/.ansible/tmp/ansible-tmp-1491081586.53-46889509406412/ /root/.ansible/tmp/ansible-tmp-1491081586.53-46889509406412/panos_security_policy.py && sleep 0'
<192.168.1.15> EXEC /bin/sh -c '/usr/bin/python /root/.ansible/tmp/ansible-tmp-1491081586.53-46889509406412/panos_security_policy.py; rm -rf "/root/.ansible/tmp/ansible-tmp-1491081586.53-46889509406412/" > /dev/null 2>&1 && sleep 0'
The full traceback is:
Traceback (most recent call last):
File "/tmp/ansible_JzsakO/ansible_module_panos_security_policy.py", line 264, in <module>
import pandevice.firewall
File "/usr/lib/python2.6/site-packages/pandevice/firewall.py", line 27, in <module>
from pandevice import device
File "/usr/lib/python2.6/site-packages/pandevice/device.py", line 19, in <module>
from base import PanObject, Root, MEMBER, ENTRY
File "/usr/lib/python2.6/site-packages/pandevice/base.py", line 1224
option_paths = {opt: re.sub(r"\([\w\d|-]*\)", opt, path) for opt in options}
^
SyntaxError: invalid syntax
fatal: [192.168.1.15]: FAILED! => {
"changed": false,
"failed": true,
"module_stderr": "Traceback (most recent call last):\n File \"/tmp/ansible_JzsakO/ansible_module_panos_security_policy.py\", line 264, in <module>\n import pandevice.firewall\n File \"/usr/lib/python2.6/site-packages/pandevice/firewall.py\", line 27, in <module>\n from pandevice import device\n File \"/usr/lib/python2.6/site-packages/pandevice/device.py\", line 19, in <module>\n from base import PanObject, Root, MEMBER, ENTRY\n File \"/usr/lib/python2.6/site-packages/pandevice/base.py\", line 1224\n option_paths = {opt: re.sub(r\"\\([\\w\\d|-]*\\)\", opt, path) for opt in options}\n ^\nSyntaxError: invalid syntax\n",
"module_stdout": "",
"msg": "MODULE FAILURE",
"rc": 0
}
7. おわりに
多少クセがあるようなので、いろいろ検証してみた方がよさそうです。