はじめに
以前の記事で、CSV形式のACL要件資料とJinja2テンプレートから「名前付き拡張ACL」のConfigファイルを生成し、設定変更を行ってみました。
AnsibleでACL Config作成&設定変更を自動化してみた
一方その後、Ansible Collectionでxxx_acls
モジュールがリリースされ、Configを用意しなくても、オプション内でIPアドレスやポート番号を指定すれば、名前付き・番号付き、標準・拡張ACLのConfig作成と設定変更が出来るようになりました。
[Ansible] cisco.ios collection 0.0.3 リリース、ACL や OSPF などのモジュールなどが追加
本記事は、Cisco IOS、NX-OS、ASA用の以下モジュールで動作確認した時のメモです。
cisco.ios.ios_acls – ACLs resource module
cisco.nxos.nxos_acls – ACLs resource module
cisco.asa.asa_acls – Access-Lists resource module
1. 用意した環境
1-1. Ansible
CentOS上にAnsible2.10.1をインストールの上、Ansible Galaxyから以下のCollectionをインストールしました。
$ ansible-galaxy collection list
# /home/centos/.ansible/collections/ansible_collections
Collection Version
----------------- ----------
ansible.netcommon 1.5.1-dev9
cisco.asa 1.0.5-dev4
cisco.ios 1.3.1-dev5
cisco.nxos 1.4.1-dev9
1-2. NW機器
Cisco CML-P 2.1の仮想環境上に、IOS機器iosvl2-0
iosvl2-1
、NX-OS機器nxos-0
、ASA機器asav-1
を同一セグメント内に構築し、外部環境のCentOSとext-conn-0
経由で接続しました。
2. ACL要件資料
各OS機器で、名前付き拡張ACLと番号付き拡張ACLをそれぞれ3要件ずつ、計18要件を追加してみます。
acl_requests4.csv(生データ)
hostname,change,acl_type,acl_name,seq_no,action,protocol,src_addr,src_oper,src_port,dest_addr,dest_oper,dest_port,modifier,description
iosvl2-0,add,name_extended,TEST1,110,deny,udp,192.168.1.1/32,,,192.168.2.1/32,eq,ntp,,ACL_TEST1
iosvl2-0,add,name_extended,TEST1,120,deny,tcp,192.168.1.2/32,gt,1023,192.168.2.0/24,eq,www,,
iosvl2-0,add,name_extended,TEST1,130,permit,ip,192.168.1.0/24,,,192.168.2.0/24,,,log,
iosvl2-0,add,number_extended,100,110,deny,udp,any,,,any,eq,ntp,,ACL_100
iosvl2-0,add,number_extended,100,120,deny,tcp,,gt,1023,,eq,www,,
iosvl2-0,add,number_extended,100,130,permit,ip,any,,,192.168.2.0/24,,,log,
nxos-0,add,name_extended,TEST1,110,deny,udp,192.168.1.1/32,,,192.168.2.1/32,eq,ntp,,ACL_TEST1
nxos-0,add,name_extended,TEST1,120,deny,tcp,192.168.1.2/32,range,1024-65535,192.168.2.0/24,eq,www,,
nxos-0,add,name_extended,TEST1,130,permit,ip,192.168.1.0/24,,,192.168.2.0/24,,,log,
nxos-0,add,number_extended,100,110,deny,udp,any,,,any,eq,ntp,,ACL_100
nxos-0,add,number_extended,100,120,deny,tcp,,range,1024-65535,,eq,www,,
nxos-0,add,number_extended,100,130,permit,ip,any,,,192.168.2.0/24,,,log,
asav-1,add,name_extended,TEST1,1,deny,udp,192.168.1.1/32,,,192.168.2.1/32,eq,ntp,,ACL_TEST1
asav-1,add,name_extended,TEST1,2,deny,tcp,192.168.1.2/32,gt,1023,192.168.2.0/24,eq,www,,
asav-1,add,name_extended,TEST1,3,permit,ip,192.168.1.0/24,,,192.168.2.0/24,,,log,
asav-1,add,number_extended,100,1,deny,udp,any,,,any,eq,ntp,,ACL_100
asav-1,add,number_extended,100,2,deny,tcp,,gt,1023,,eq,www,,
asav-1,add,number_extended,100,3,permit,ip,any,,,192.168.2.0/24,,,log,
各項目の内容は以下の通りです。
項目名 | 内容 |
---|---|
hostname | 対象機器のホスト名 |
change | 設定変更種別 例:add(追加)、delete(削除) |
acl_type | ACL種別 例:name_extended(名前付き拡張)、name_standard(名前付き標準)、number_extended(番号付き拡張)、number_standard(番号付き標準)※今回の実装対象はname_extended、number_extendedのみ |
acl_name | ACL名 or ACL番号 |
seq_no | シーケンス番号 |
action | 通信許可 or 拒否 例:permit、deny |
protocol | プロトコル 例:ip、tcp、udp |
src_addr | 送信元アドレス アドレス/プレフィックス長の形式で指定 |
src_oper | 送信元演算子(任意) 例:eq、gt、lt、range |
src_port | 送信元ポート番号(任意) rangeの場合、FromとToをハイフンで区切って指定 |
dest_addr | 宛先アドレス アドレス/プレフィックス長の形式で指定 |
dest_oper | 宛先演算子(任意) 例:eq、neq、gt、lt、range |
dest_port | 宛先ポート番号(任意) rangeの場合、FromとToをハイフンで区切って指定 |
3. Playbook
各タスクの内容は以下の通りです。
-
read_csv
モジュールを使い、ACL要件資料の各行を[{ "hostname": "xx", "acl_name": "aa", ~ }, { "hostname": "yy", "acl_name": "bb", ~ }, ~]
のように、リスト内の要素として定義。 -
debug
モジュールで、タスク1のリストを表示。 -
set_fact
モジュールで、上記のリストを変数acls
に格納。ここまでは機器毎の実行は不要なためrun_once: yes
で1回のみ実行。 -
template
モジュールで、変数acls
と後述のJinja2テンプレートをレンダリングし、xxx_acls
モジュールのアーギュメントとして読み込めるJSON形式に変換してファイル出力。 -
include_vars
モジュールで、タスク4のJSONファイルを読み込み、変数acl_option
に格納。 -
debug
モジュールで、タスク5の内容を表示。 - ~9.
cisco.ios.ios_acls
cisco.nxos.nxos_acls
cisco.asa.asa_acls
モジュールで、各OS機器のACL Config生成と設定変更を実施。config
、state
アーギュメントは、タスク5の変数をループで読み取り。
---
- hosts: cisco
gather_facts: no
vars:
template: acl_module_template3.j2
acl_list: acl_requests4.csv
acl_option_file: acl_option_{{ inventory_hostname }}.json
tasks:
- name: read acl requests from CSV file and return a list # (1)
read_csv:
path: "{{ acl_list }}"
run_once: yes
register: acl_requests
- name: display acl requests # (2)
debug:
msg: "{{ acl_requests.list }}"
run_once: yes
- name: set acl requests # (3)
set_fact:
acls: "{{ acl_requests.list }}"
run_once: yes
- name: build template # (4)
template:
src: "{{ template }}"
dest: "{{ acl_option_file }}"
- name: set acl options # (5)
include_vars:
file: "{{ acl_option_file }}"
name: acl_option
- name: display acl options # (6)
debug:
msg: "{{ acl_option }}"
- name: merge acl config (ios) # (7)
cisco.ios.ios_acls:
config: "{{ item.config }}"
state: "{{ item.state }}"
loop: "{{ acl_option.acl_config }}"
when: ansible_network_os == 'cisco.ios.ios'
- name: merge acl config (nxos) # (8)
cisco.nxos.nxos_acls:
config: "{{ item.config }}"
state: "{{ item.state }}"
loop: "{{ acl_option.acl_config }}"
when: ansible_network_os == 'cisco.nxos.nxos'
- name: merge acl config (asa) # (9)
cisco.asa.asa_acls:
config: "{{ item.config[0] }}"
state: "{{ item.state }}"
loop: "{{ acl_option.acl_config }}"
when: ansible_network_os == 'cisco.asa.asa'
4. Jinja2テンプレート
詳細は割愛しますが、大まかなポイントは以下の通りです。
acl_module_template3.j2
{
"acl_config": [
{% for item in acls -%}
{% if item.hostname == inventory_hostname and item.change == 'add' -%}
{% set src_prefix = item.src_addr | ansible.netcommon.ipaddr('prefix') -%}
{% set dest_prefix = item.dest_addr | ansible.netcommon.ipaddr('prefix') -%}
{
"config": [
{
"acls": [
{
"aces": [
{
"destination": {
{% if item.dest_addr == '' or item.dest_addr == 'any' -%}
"any": yes,
{% elif dest_prefix == 32 -%}
"host": "{{ item.dest_addr | ansible.netcommon.ipaddr('network') }}",
{% elif dest_prefix < 32 -%}
"address": "{{ item.dest_addr | ansible.netcommon.ipaddr('network') }}",
{% if ansible_network_os == 'cisco.asa.asa' -%}
"netmask": "{{ item.dest_addr | ansible.netcommon.ipaddr('netmask') }}",
{% else -%}
"wildcard_bits": "{{ item.dest_addr | ansible.netcommon.ipaddr('wildcard') }}",
{% endif -%}
{% endif -%}
{% if item.dest_oper == 'range' -%}
"port_protocol": {
"range": {
{% if ansible_network_os == 'cisco.nxos.nxos' -%}
"end": "{{ item.dest_port.split('-')[1] }}",
"start": "{{ item.dest_port.split('-')[0] }}"
{% else -%}
"end": {{ item.dest_port.split('-')[1] }},
"start": {{ item.dest_port.split('-')[0] }}
{% endif -%}
}
}
{% elif item.dest_oper != '' and item.dest_oper != 'any' -%}
"port_protocol": {
"{{ item.dest_oper }}": "{{ item.dest_port }}"
}
{% endif -%}
},
"grant": "{{ item.action }}",
"protocol": "{{ item.protocol }}",
{% if ansible_network_os == 'cisco.asa.asa' -%}
"line": {{ item.seq_no }},
{% else -%}
"sequence": {{ item.seq_no }},
{% endif -%}
"source": {
{% if item.src_addr == '' or item.src_addr == 'any' -%}
"any": yes,
{% elif src_prefix == 32 -%}
"host": "{{ item.src_addr | ansible.netcommon.ipaddr('network') }}",
{% elif src_prefix < 32 -%}
"address": "{{ item.src_addr | ansible.netcommon.ipaddr('network') }}",
{% if ansible_network_os == 'cisco.asa.asa' -%}
"netmask": "{{ item.src_addr | ansible.netcommon.ipaddr('netmask') }}",
{% else -%}
"wildcard_bits": "{{ item.src_addr | ansible.netcommon.ipaddr('wildcard') }}",
{% endif -%}
{% endif -%}
{% if item.src_oper == 'range' -%}
"port_protocol": {
"range": {
{% if ansible_network_os == 'cisco.nxos.nxos' -%}
"end": "{{ item.src_port.split('-')[1] }}",
"start": "{{ item.src_port.split('-')[0] }}"
{% else -%}
"end": {{ item.src_port.split('-')[1] }},
"start": {{ item.src_port.split('-')[0] }}
{% endif -%}
}
}
{% elif item.src_oper != '' and item.src_oper != 'any' -%}
"port_protocol": {
"{{ item.src_oper }}": "{{ item.src_port }}"
}
{% endif -%}
}
}
],
{% if ansible_network_os != 'cisco.nxos.nxos' -%}
"acl_type": "{{ item.acl_type | regex_replace('^(name|number)_(.*)$', '\\2') }}",
{% endif -%}
"name": "{{ item.acl_name }}"
}
],
{% if ansible_network_os != 'cisco.asa.asa' -%}
"afi": "ipv4"
{% endif -%}
}
],
"state": {% if item.change == 'add' -%}"merged"{% elif item.change == 'delete' -%}"deleted"{% endif -%}
},
{% endif -%}
{% endfor -%}
]
}
-
テンプレートのフォーマットはJSONを使用。当初、Playbookのフォーマットと合わせてYAMLで作っていましたが、余分なWhitespaceがYAML内でインデントとして扱われてしまう可能性を考慮し、途中で修正しました
-
冒頭の
{% if item.hostname == inventory_hostname and item.change == 'add' -%}
で、ACL追加対象が自分自身の要件のみレンダリングを行い、機器毎にファイルacl_option_{{ inventory_hostname }}.json
が生成されるようにした。※inventory_hostname=Ansible実行対象のホスト名 -
1つの機器で要件が複数ある場合、リスト形式で要素を追加していき、Playbook内で読み込んだ時にループで回せるようにした。
-
IPアドレス(ホスト/ネットワーク/any)、ポート番号(eq/neq/gt/lt/range)、OS(IOS/NX-OS/ASA)で利用するアーギュメントやデータ型が異なるため、テンプレート内で条件分岐させた。
例えば、IOS/NX-OSでは、送信元/宛先ネットワークをワイルドカードマスク用のアーギュメントwildcard_bits
で指定するが、ASAではネットマスク用のアーギュメントnetmask
で指定する。
5. 実行結果
こちらも詳細は割愛しますが、3台ともFailせず完了しています。もう1台の、Inventoryファイルでは指定したものの、ACL設定要件がなかったiosvl2-1
も、changed=0
で完了しています。
実行結果
$ ansible-playbook -i inventory_cml.ini playbook_acl_extend.yml
PLAY [cisco] *****************************************************************************************************
TASK [read acl requests from CSV file and return a list] *********************************************************
ok: [iosvl2-0]
TASK [display acl requests] **************************************************************************************
ok: [iosvl2-0] => {
"msg": [
{
"acl_name": "TEST1",
"acl_type": "name_extended",
"action": "deny",
"change": "add",
"description": "ACL_TEST1",
"dest_addr": "192.168.2.1/32",
"dest_oper": "eq",
"dest_port": "ntp",
"hostname": "iosvl2-0",
"modifier": "",
"protocol": "udp",
"seq_no": "110",
"src_addr": "192.168.1.1/32",
"src_oper": "",
"src_port": ""
},
{
"acl_name": "TEST1",
"acl_type": "name_extended",
"action": "deny",
"change": "add",
"description": "",
"dest_addr": "192.168.2.0/24",
"dest_oper": "eq",
"dest_port": "www",
"hostname": "iosvl2-0",
"modifier": "",
"protocol": "tcp",
"seq_no": "120",
"src_addr": "192.168.1.2/32",
"src_oper": "gt",
"src_port": "1023"
},
{
"acl_name": "TEST1",
"acl_type": "name_extended",
"action": "permit",
"change": "add",
"description": "",
"dest_addr": "192.168.2.0/24",
"dest_oper": "",
"dest_port": "",
"hostname": "iosvl2-0",
"modifier": "log",
"protocol": "ip",
"seq_no": "130",
"src_addr": "192.168.1.0/24",
"src_oper": "",
"src_port": ""
},
{
"acl_name": "100",
"acl_type": "number_extended",
"action": "deny",
"change": "add",
"description": "ACL_100",
"dest_addr": "any",
"dest_oper": "eq",
"dest_port": "ntp",
"hostname": "iosvl2-0",
"modifier": "",
"protocol": "udp",
"seq_no": "110",
"src_addr": "any",
"src_oper": "",
"src_port": ""
},
{
"acl_name": "100",
"acl_type": "number_extended",
"action": "deny",
"change": "add",
"description": "",
"dest_addr": "",
"dest_oper": "eq",
"dest_port": "www",
"hostname": "iosvl2-0",
"modifier": "",
"protocol": "tcp",
"seq_no": "120",
"src_addr": "",
"src_oper": "gt",
"src_port": "1023"
},
{
"acl_name": "100",
"acl_type": "number_extended",
"action": "permit",
"change": "add",
"description": "",
"dest_addr": "192.168.2.0/24",
"dest_oper": "",
"dest_port": "",
"hostname": "iosvl2-0",
"modifier": "log",
"protocol": "ip",
"seq_no": "130",
"src_addr": "any",
"src_oper": "",
"src_port": ""
},
{
"acl_name": "TEST1",
"acl_type": "name_extended",
"action": "deny",
"change": "add",
"description": "ACL_TEST1",
"dest_addr": "192.168.2.1/32",
"dest_oper": "eq",
"dest_port": "ntp",
"hostname": "nxos-0",
"modifier": "",
"protocol": "udp",
"seq_no": "110",
"src_addr": "192.168.1.1/32",
"src_oper": "",
"src_port": ""
},
{
"acl_name": "TEST1",
"acl_type": "name_extended",
"action": "deny",
"change": "add",
"description": "",
"dest_addr": "192.168.2.0/24",
"dest_oper": "eq",
"dest_port": "www",
"hostname": "nxos-0",
"modifier": "",
"protocol": "tcp",
"seq_no": "120",
"src_addr": "192.168.1.2/32",
"src_oper": "range",
"src_port": "1024-65535"
},
{
"acl_name": "TEST1",
"acl_type": "name_extended",
"action": "permit",
"change": "add",
"description": "",
"dest_addr": "192.168.2.0/24",
"dest_oper": "",
"dest_port": "",
"hostname": "nxos-0",
"modifier": "log",
"protocol": "ip",
"seq_no": "130",
"src_addr": "192.168.1.0/24",
"src_oper": "",
"src_port": ""
},
{
"acl_name": "100",
"acl_type": "number_extended",
"action": "deny",
"change": "add",
"description": "ACL_100",
"dest_addr": "any",
"dest_oper": "eq",
"dest_port": "ntp",
"hostname": "nxos-0",
"modifier": "",
"protocol": "udp",
"seq_no": "110",
"src_addr": "any",
"src_oper": "",
"src_port": ""
},
{
"acl_name": "100",
"acl_type": "number_extended",
"action": "deny",
"change": "add",
"description": "",
"dest_addr": "",
"dest_oper": "eq",
"dest_port": "www",
"hostname": "nxos-0",
"modifier": "",
"protocol": "tcp",
"seq_no": "120",
"src_addr": "",
"src_oper": "range",
"src_port": "1024-65535"
},
{
"acl_name": "100",
"acl_type": "number_extended",
"action": "permit",
"change": "add",
"description": "",
"dest_addr": "192.168.2.0/24",
"dest_oper": "",
"dest_port": "",
"hostname": "nxos-0",
"modifier": "log",
"protocol": "ip",
"seq_no": "130",
"src_addr": "any",
"src_oper": "",
"src_port": ""
},
{
"acl_name": "TEST1",
"acl_type": "name_extended",
"action": "deny",
"change": "add",
"description": "ACL_TEST1",
"dest_addr": "192.168.2.1/32",
"dest_oper": "eq",
"dest_port": "ntp",
"hostname": "asav-1",
"modifier": "",
"protocol": "udp",
"seq_no": "1",
"src_addr": "192.168.1.1/32",
"src_oper": "",
"src_port": ""
},
{
"acl_name": "TEST1",
"acl_type": "name_extended",
"action": "deny",
"change": "add",
"description": "",
"dest_addr": "192.168.2.0/24",
"dest_oper": "eq",
"dest_port": "www",
"hostname": "asav-1",
"modifier": "",
"protocol": "tcp",
"seq_no": "2",
"src_addr": "192.168.1.2/32",
"src_oper": "gt",
"src_port": "1023"
},
{
"acl_name": "TEST1",
"acl_type": "name_extended",
"action": "permit",
"change": "add",
"description": "",
"dest_addr": "192.168.2.0/24",
"dest_oper": "",
"dest_port": "",
"hostname": "asav-1",
"modifier": "log",
"protocol": "ip",
"seq_no": "3",
"src_addr": "192.168.1.0/24",
"src_oper": "",
"src_port": ""
},
{
"acl_name": "100",
"acl_type": "number_extended",
"action": "deny",
"change": "add",
"description": "ACL_100",
"dest_addr": "any",
"dest_oper": "eq",
"dest_port": "ntp",
"hostname": "asav-1",
"modifier": "",
"protocol": "udp",
"seq_no": "1",
"src_addr": "any",
"src_oper": "",
"src_port": ""
},
{
"acl_name": "100",
"acl_type": "number_extended",
"action": "deny",
"change": "add",
"description": "",
"dest_addr": "",
"dest_oper": "eq",
"dest_port": "www",
"hostname": "asav-1",
"modifier": "",
"protocol": "tcp",
"seq_no": "2",
"src_addr": "",
"src_oper": "gt",
"src_port": "1023"
},
{
"acl_name": "100",
"acl_type": "number_extended",
"action": "permit",
"change": "add",
"description": "",
"dest_addr": "192.168.2.0/24",
"dest_oper": "",
"dest_port": "",
"hostname": "asav-1",
"modifier": "log",
"protocol": "ip",
"seq_no": "3",
"src_addr": "any",
"src_oper": "",
"src_port": ""
}
]
}
TASK [set acl requests] ******************************************************************************************
ok: [iosvl2-0]
TASK [build template] ********************************************************************************************
[WARNING]: The value '' is not a valid IP address or network, passing this value to ipaddr filter might result in
breaking change in future.
[WARNING]: The value '' is not a valid IP address or network, passing this value to ipaddr filter might result in
breaking change in future.
[WARNING]: The value '' is not a valid IP address or network, passing this value to ipaddr filter might result in
breaking change in future.
ok: [iosvl2-1]
changed: [nxos-0]
changed: [asav-1]
changed: [iosvl2-0]
TASK [set acl options] *******************************************************************************************
ok: [iosvl2-0]
ok: [nxos-0]
ok: [asav-1]
ok: [iosvl2-1]
TASK [display acl options] ***************************************************************************************
ok: [nxos-0] => {
"msg": {
"acl_config": [
{
"config": [
{
"acls": [
{
"aces": [
{
"destination": {
"host": "192.168.2.1",
"port_protocol": {
"eq": "ntp"
}
},
"grant": "deny",
"protocol": "udp",
"sequence": 110,
"source": {
"host": "192.168.1.1"
}
}
],
"name": "TEST1"
}
],
"afi": "ipv4"
}
],
"state": "merged"
},
{
"config": [
{
"acls": [
{
"aces": [
{
"destination": {
"address": "192.168.2.0",
"port_protocol": {
"eq": "www"
},
"wildcard_bits": "0.0.0.255"
},
"grant": "deny",
"protocol": "tcp",
"sequence": 120,
"source": {
"host": "192.168.1.2",
"port_protocol": {
"range": {
"end": "65535",
"start": "1024"
}
}
}
}
],
"name": "TEST1"
}
],
"afi": "ipv4"
}
],
"state": "merged"
},
{
"config": [
{
"acls": [
{
"aces": [
{
"destination": {
"address": "192.168.2.0",
"wildcard_bits": "0.0.0.255"
},
"grant": "permit",
"protocol": "ip",
"sequence": 130,
"source": {
"address": "192.168.1.0",
"wildcard_bits": "0.0.0.255"
}
}
],
"name": "TEST1"
}
],
"afi": "ipv4"
}
],
"state": "merged"
},
{
"config": [
{
"acls": [
{
"aces": [
{
"destination": {
"any": true,
"port_protocol": {
"eq": "ntp"
}
},
"grant": "deny",
"protocol": "udp",
"sequence": 110,
"source": {
"any": true
}
}
],
"name": "100"
}
],
"afi": "ipv4"
}
],
"state": "merged"
},
{
"config": [
{
"acls": [
{
"aces": [
{
"destination": {
"any": true,
"port_protocol": {
"eq": "www"
}
},
"grant": "deny",
"protocol": "tcp",
"sequence": 120,
"source": {
"any": true,
"port_protocol": {
"range": {
"end": "65535",
"start": "1024"
}
}
}
}
],
"name": "100"
}
],
"afi": "ipv4"
}
],
"state": "merged"
},
{
"config": [
{
"acls": [
{
"aces": [
{
"destination": {
"address": "192.168.2.0",
"wildcard_bits": "0.0.0.255"
},
"grant": "permit",
"protocol": "ip",
"sequence": 130,
"source": {
"any": true
}
}
],
"name": "100"
}
],
"afi": "ipv4"
}
],
"state": "merged"
}
]
}
}
ok: [asav-1] => {
"msg": {
"acl_config": [
{
"config": [
{
"acls": [
{
"aces": [
{
"destination": {
"host": "192.168.2.1",
"port_protocol": {
"eq": "ntp"
}
},
"grant": "deny",
"line": 1,
"protocol": "udp",
"source": {
"host": "192.168.1.1"
}
}
],
"acl_type": "extended",
"name": "TEST1"
}
]
}
],
"state": "merged"
},
{
"config": [
{
"acls": [
{
"aces": [
{
"destination": {
"address": "192.168.2.0",
"netmask": "255.255.255.0",
"port_protocol": {
"eq": "www"
}
},
"grant": "deny",
"line": 2,
"protocol": "tcp",
"source": {
"host": "192.168.1.2",
"port_protocol": {
"gt": "1023"
}
}
}
],
"acl_type": "extended",
"name": "TEST1"
}
]
}
],
"state": "merged"
},
{
"config": [
{
"acls": [
{
"aces": [
{
"destination": {
"address": "192.168.2.0",
"netmask": "255.255.255.0"
},
"grant": "permit",
"line": 3,
"protocol": "ip",
"source": {
"address": "192.168.1.0",
"netmask": "255.255.255.0"
}
}
],
"acl_type": "extended",
"name": "TEST1"
}
]
}
],
"state": "merged"
},
{
"config": [
{
"acls": [
{
"aces": [
{
"destination": {
"any": true,
"port_protocol": {
"eq": "ntp"
}
},
"grant": "deny",
"line": 1,
"protocol": "udp",
"source": {
"any": true
}
}
],
"acl_type": "extended",
"name": "100"
}
]
}
],
"state": "merged"
},
{
"config": [
{
"acls": [
{
"aces": [
{
"destination": {
"any": true,
"port_protocol": {
"eq": "www"
}
},
"grant": "deny",
"line": 2,
"protocol": "tcp",
"source": {
"any": true,
"port_protocol": {
"gt": "1023"
}
}
}
],
"acl_type": "extended",
"name": "100"
}
]
}
],
"state": "merged"
},
{
"config": [
{
"acls": [
{
"aces": [
{
"destination": {
"address": "192.168.2.0",
"netmask": "255.255.255.0"
},
"grant": "permit",
"line": 3,
"protocol": "ip",
"source": {
"any": true
}
}
],
"acl_type": "extended",
"name": "100"
}
]
}
],
"state": "merged"
}
]
}
}
ok: [iosvl2-0] => {
"msg": {
"acl_config": [
{
"config": [
{
"acls": [
{
"aces": [
{
"destination": {
"host": "192.168.2.1",
"port_protocol": {
"eq": "ntp"
}
},
"grant": "deny",
"protocol": "udp",
"sequence": 110,
"source": {
"host": "192.168.1.1"
}
}
],
"acl_type": "extended",
"name": "TEST1"
}
],
"afi": "ipv4"
}
],
"state": "merged"
},
{
"config": [
{
"acls": [
{
"aces": [
{
"destination": {
"address": "192.168.2.0",
"port_protocol": {
"eq": "www"
},
"wildcard_bits": "0.0.0.255"
},
"grant": "deny",
"protocol": "tcp",
"sequence": 120,
"source": {
"host": "192.168.1.2",
"port_protocol": {
"gt": "1023"
}
}
}
],
"acl_type": "extended",
"name": "TEST1"
}
],
"afi": "ipv4"
}
],
"state": "merged"
},
{
"config": [
{
"acls": [
{
"aces": [
{
"destination": {
"address": "192.168.2.0",
"wildcard_bits": "0.0.0.255"
},
"grant": "permit",
"protocol": "ip",
"sequence": 130,
"source": {
"address": "192.168.1.0",
"wildcard_bits": "0.0.0.255"
}
}
],
"acl_type": "extended",
"name": "TEST1"
}
],
"afi": "ipv4"
}
],
"state": "merged"
},
{
"config": [
{
"acls": [
{
"aces": [
{
"destination": {
"any": true,
"port_protocol": {
"eq": "ntp"
}
},
"grant": "deny",
"protocol": "udp",
"sequence": 110,
"source": {
"any": true
}
}
],
"acl_type": "extended",
"name": "100"
}
],
"afi": "ipv4"
}
],
"state": "merged"
},
{
"config": [
{
"acls": [
{
"aces": [
{
"destination": {
"any": true,
"port_protocol": {
"eq": "www"
}
},
"grant": "deny",
"protocol": "tcp",
"sequence": 120,
"source": {
"any": true,
"port_protocol": {
"gt": "1023"
}
}
}
],
"acl_type": "extended",
"name": "100"
}
],
"afi": "ipv4"
}
],
"state": "merged"
},
{
"config": [
{
"acls": [
{
"aces": [
{
"destination": {
"address": "192.168.2.0",
"wildcard_bits": "0.0.0.255"
},
"grant": "permit",
"protocol": "ip",
"sequence": 130,
"source": {
"any": true
}
}
],
"acl_type": "extended",
"name": "100"
}
],
"afi": "ipv4"
}
],
"state": "merged"
}
]
}
}
ok: [iosvl2-1] => {
"msg": {
"acl_config": []
}
}
TASK [merge acl config (ios)] ************************************************************************************
skipping: [nxos-0] => (item={'config': [{'acls': [{'aces': [{'destination': {'host': '192.168.2.1', 'port_protocol': {'eq': 'ntp'}}, 'grant': 'deny', 'protocol': 'udp', 'sequence': 110, 'source': {'host': '192.168.1.1'}}], 'name': 'TEST1'}], 'afi': 'ipv4'}], 'state': 'merged'})
skipping: [nxos-0] => (item={'config': [{'acls': [{'aces': [{'destination': {'address': '192.168.2.0', 'wildcard_bits': '0.0.0.255', 'port_protocol': {'eq': 'www'}}, 'grant': 'deny', 'protocol': 'tcp', 'sequence': 120, 'source': {'host': '192.168.1.2', 'port_protocol': {'range': {'end': '65535', 'start': '1024'}}}}], 'name': 'TEST1'}], 'afi': 'ipv4'}], 'state': 'merged'})
skipping: [nxos-0] => (item={'config': [{'acls': [{'aces': [{'destination': {'address': '192.168.2.0', 'wildcard_bits': '0.0.0.255'}, 'grant': 'permit', 'protocol': 'ip', 'sequence': 130, 'source': {'address': '192.168.1.0', 'wildcard_bits': '0.0.0.255'}}], 'name': 'TEST1'}], 'afi': 'ipv4'}], 'state': 'merged'})
skipping: [nxos-0] => (item={'config': [{'acls': [{'aces': [{'destination': {'any': True, 'port_protocol': {'eq': 'ntp'}}, 'grant': 'deny', 'protocol': 'udp', 'sequence': 110, 'source': {'any': True}}], 'name': '100'}], 'afi': 'ipv4'}], 'state': 'merged'})
skipping: [nxos-0] => (item={'config': [{'acls': [{'aces': [{'destination': {'any': True, 'port_protocol': {'eq': 'www'}}, 'grant': 'deny', 'protocol': 'tcp', 'sequence': 120, 'source': {'any': True, 'port_protocol': {'range': {'end': '65535', 'start': '1024'}}}}], 'name': '100'}], 'afi': 'ipv4'}], 'state': 'merged'})
skipping: [nxos-0] => (item={'config': [{'acls': [{'aces': [{'destination': {'address': '192.168.2.0', 'wildcard_bits': '0.0.0.255'}, 'grant': 'permit', 'protocol': 'ip', 'sequence': 130, 'source': {'any': True}}], 'name': '100'}], 'afi': 'ipv4'}], 'state': 'merged'})
skipping: [asav-1] => (item={'config': [{'acls': [{'aces': [{'destination': {'host': '192.168.2.1', 'port_protocol': {'eq': 'ntp'}}, 'grant': 'deny', 'protocol': 'udp', 'line': 1, 'source': {'host': '192.168.1.1'}}], 'acl_type': 'extended', 'name': 'TEST1'}]}], 'state': 'merged'})
skipping: [asav-1] => (item={'config': [{'acls': [{'aces': [{'destination': {'address': '192.168.2.0', 'netmask': '255.255.255.0', 'port_protocol': {'eq': 'www'}}, 'grant': 'deny', 'protocol': 'tcp', 'line': 2, 'source': {'host': '192.168.1.2', 'port_protocol': {'gt': '1023'}}}], 'acl_type': 'extended', 'name': 'TEST1'}]}], 'state': 'merged'})
skipping: [asav-1] => (item={'config': [{'acls': [{'aces': [{'destination': {'address': '192.168.2.0', 'netmask': '255.255.255.0'}, 'grant': 'permit', 'protocol': 'ip', 'line': 3, 'source': {'address': '192.168.1.0', 'netmask': '255.255.255.0'}}], 'acl_type': 'extended', 'name': 'TEST1'}]}], 'state': 'merged'})
skipping: [asav-1] => (item={'config': [{'acls': [{'aces': [{'destination': {'any': True, 'port_protocol': {'eq': 'ntp'}}, 'grant': 'deny', 'protocol': 'udp', 'line': 1, 'source': {'any': True}}], 'acl_type': 'extended', 'name': '100'}]}], 'state': 'merged'})
skipping: [asav-1] => (item={'config': [{'acls': [{'aces': [{'destination': {'any': True, 'port_protocol': {'eq': 'www'}}, 'grant': 'deny', 'protocol': 'tcp', 'line': 2, 'source': {'any': True, 'port_protocol': {'gt': '1023'}}}], 'acl_type': 'extended', 'name': '100'}]}], 'state': 'merged'})
skipping: [asav-1] => (item={'config': [{'acls': [{'aces': [{'destination': {'address': '192.168.2.0', 'netmask': '255.255.255.0'}, 'grant': 'permit', 'protocol': 'ip', 'line': 3, 'source': {'any': True}}], 'acl_type': 'extended', 'name': '100'}]}], 'state': 'merged'})
changed: [iosvl2-0] => (item={'config': [{'acls': [{'aces': [{'destination': {'host': '192.168.2.1', 'port_protocol': {'eq': 'ntp'}}, 'grant': 'deny', 'protocol': 'udp', 'sequence': 110, 'source': {'host': '192.168.1.1'}}], 'acl_type': 'extended', 'name': 'TEST1'}], 'afi': 'ipv4'}], 'state': 'merged'})
changed: [iosvl2-0] => (item={'config': [{'acls': [{'aces': [{'destination': {'address': '192.168.2.0', 'wildcard_bits': '0.0.0.255', 'port_protocol': {'eq': 'www'}}, 'grant': 'deny', 'protocol': 'tcp', 'sequence': 120, 'source': {'host': '192.168.1.2', 'port_protocol': {'gt': '1023'}}}], 'acl_type': 'extended', 'name': 'TEST1'}], 'afi': 'ipv4'}], 'state': 'merged'})
changed: [iosvl2-0] => (item={'config': [{'acls': [{'aces': [{'destination': {'address': '192.168.2.0', 'wildcard_bits': '0.0.0.255'}, 'grant': 'permit', 'protocol': 'ip', 'sequence': 130, 'source': {'address': '192.168.1.0', 'wildcard_bits': '0.0.0.255'}}], 'acl_type': 'extended', 'name': 'TEST1'}], 'afi': 'ipv4'}], 'state': 'merged'})
changed: [iosvl2-0] => (item={'config': [{'acls': [{'aces': [{'destination': {'any': True, 'port_protocol': {'eq': 'ntp'}}, 'grant': 'deny', 'protocol': 'udp', 'sequence': 110, 'source': {'any': True}}], 'acl_type': 'extended', 'name': '100'}], 'afi': 'ipv4'}], 'state': 'merged'})
changed: [iosvl2-0] => (item={'config': [{'acls': [{'aces': [{'destination': {'any': True, 'port_protocol': {'eq': 'www'}}, 'grant': 'deny', 'protocol': 'tcp', 'sequence': 120, 'source': {'any': True, 'port_protocol': {'gt': '1023'}}}], 'acl_type': 'extended', 'name': '100'}], 'afi': 'ipv4'}], 'state': 'merged'})
changed: [iosvl2-0] => (item={'config': [{'acls': [{'aces': [{'destination': {'address': '192.168.2.0', 'wildcard_bits': '0.0.0.255'}, 'grant': 'permit', 'protocol': 'ip', 'sequence': 130, 'source': {'any': True}}], 'acl_type': 'extended', 'name': '100'}], 'afi': 'ipv4'}], 'state': 'merged'})
TASK [merge acl config (nxos)] ***********************************************************************************
skipping: [iosvl2-0] => (item={'config': [{'acls': [{'aces': [{'destination': {'host': '192.168.2.1', 'port_protocol': {'eq': 'ntp'}}, 'grant': 'deny', 'protocol': 'udp', 'sequence': 110, 'source': {'host': '192.168.1.1'}}], 'acl_type': 'extended', 'name': 'TEST1'}], 'afi': 'ipv4'}], 'state': 'merged'})
skipping: [iosvl2-0] => (item={'config': [{'acls': [{'aces': [{'destination': {'address': '192.168.2.0', 'wildcard_bits': '0.0.0.255', 'port_protocol': {'eq': 'www'}}, 'grant': 'deny', 'protocol': 'tcp', 'sequence': 120, 'source': {'host': '192.168.1.2', 'port_protocol': {'gt': '1023'}}}], 'acl_type': 'extended', 'name': 'TEST1'}], 'afi': 'ipv4'}], 'state': 'merged'})
skipping: [iosvl2-0] => (item={'config': [{'acls': [{'aces': [{'destination': {'address': '192.168.2.0', 'wildcard_bits': '0.0.0.255'}, 'grant': 'permit', 'protocol': 'ip', 'sequence': 130, 'source': {'address': '192.168.1.0', 'wildcard_bits': '0.0.0.255'}}], 'acl_type': 'extended', 'name': 'TEST1'}], 'afi': 'ipv4'}], 'state': 'merged'})
skipping: [iosvl2-0] => (item={'config': [{'acls': [{'aces': [{'destination': {'any': True, 'port_protocol': {'eq': 'ntp'}}, 'grant': 'deny', 'protocol': 'udp', 'sequence': 110, 'source': {'any': True}}], 'acl_type': 'extended', 'name': '100'}], 'afi': 'ipv4'}], 'state': 'merged'})
skipping: [iosvl2-0] => (item={'config': [{'acls': [{'aces': [{'destination': {'any': True, 'port_protocol': {'eq': 'www'}}, 'grant': 'deny', 'protocol': 'tcp', 'sequence': 120, 'source': {'any': True, 'port_protocol': {'gt': '1023'}}}], 'acl_type': 'extended', 'name': '100'}], 'afi': 'ipv4'}], 'state': 'merged'})
skipping: [iosvl2-0] => (item={'config': [{'acls': [{'aces': [{'destination': {'address': '192.168.2.0', 'wildcard_bits': '0.0.0.255'}, 'grant': 'permit', 'protocol': 'ip', 'sequence': 130, 'source': {'any': True}}], 'acl_type': 'extended', 'name': '100'}], 'afi': 'ipv4'}], 'state': 'merged'})
skipping: [asav-1] => (item={'config': [{'acls': [{'aces': [{'destination': {'host': '192.168.2.1', 'port_protocol': {'eq': 'ntp'}}, 'grant': 'deny', 'protocol': 'udp', 'line': 1, 'source': {'host': '192.168.1.1'}}], 'acl_type': 'extended', 'name': 'TEST1'}]}], 'state': 'merged'})
skipping: [asav-1] => (item={'config': [{'acls': [{'aces': [{'destination': {'address': '192.168.2.0', 'netmask': '255.255.255.0', 'port_protocol': {'eq': 'www'}}, 'grant': 'deny', 'protocol': 'tcp', 'line': 2, 'source': {'host': '192.168.1.2', 'port_protocol': {'gt': '1023'}}}], 'acl_type': 'extended', 'name': 'TEST1'}]}], 'state': 'merged'})
skipping: [asav-1] => (item={'config': [{'acls': [{'aces': [{'destination': {'address': '192.168.2.0', 'netmask': '255.255.255.0'}, 'grant': 'permit', 'protocol': 'ip', 'line': 3, 'source': {'address': '192.168.1.0', 'netmask': '255.255.255.0'}}], 'acl_type': 'extended', 'name': 'TEST1'}]}], 'state': 'merged'})
skipping: [asav-1] => (item={'config': [{'acls': [{'aces': [{'destination': {'any': True, 'port_protocol': {'eq': 'ntp'}}, 'grant': 'deny', 'protocol': 'udp', 'line': 1, 'source': {'any': True}}], 'acl_type': 'extended', 'name': '100'}]}], 'state': 'merged'})
skipping: [asav-1] => (item={'config': [{'acls': [{'aces': [{'destination': {'any': True, 'port_protocol': {'eq': 'www'}}, 'grant': 'deny', 'protocol': 'tcp', 'line': 2, 'source': {'any': True, 'port_protocol': {'gt': '1023'}}}], 'acl_type': 'extended', 'name': '100'}]}], 'state': 'merged'})
skipping: [asav-1] => (item={'config': [{'acls': [{'aces': [{'destination': {'address': '192.168.2.0', 'netmask': '255.255.255.0'}, 'grant': 'permit', 'protocol': 'ip', 'line': 3, 'source': {'any': True}}], 'acl_type': 'extended', 'name': '100'}]}], 'state': 'merged'})
changed: [nxos-0] => (item={'config': [{'acls': [{'aces': [{'destination': {'host': '192.168.2.1', 'port_protocol': {'eq': 'ntp'}}, 'grant': 'deny', 'protocol': 'udp', 'sequence': 110, 'source': {'host': '192.168.1.1'}}], 'name': 'TEST1'}], 'afi': 'ipv4'}], 'state': 'merged'})
changed: [nxos-0] => (item={'config': [{'acls': [{'aces': [{'destination': {'address': '192.168.2.0', 'wildcard_bits': '0.0.0.255', 'port_protocol': {'eq': 'www'}}, 'grant': 'deny', 'protocol': 'tcp', 'sequence': 120, 'source': {'host': '192.168.1.2', 'port_protocol': {'range': {'end': '65535', 'start': '1024'}}}}], 'name': 'TEST1'}], 'afi': 'ipv4'}], 'state': 'merged'})
changed: [nxos-0] => (item={'config': [{'acls': [{'aces': [{'destination': {'address': '192.168.2.0', 'wildcard_bits': '0.0.0.255'}, 'grant': 'permit', 'protocol': 'ip', 'sequence': 130, 'source': {'address': '192.168.1.0', 'wildcard_bits': '0.0.0.255'}}], 'name': 'TEST1'}], 'afi': 'ipv4'}], 'state': 'merged'})
changed: [nxos-0] => (item={'config': [{'acls': [{'aces': [{'destination': {'any': True, 'port_protocol': {'eq': 'ntp'}}, 'grant': 'deny', 'protocol': 'udp', 'sequence': 110, 'source': {'any': True}}], 'name': '100'}], 'afi': 'ipv4'}], 'state': 'merged'})
changed: [nxos-0] => (item={'config': [{'acls': [{'aces': [{'destination': {'any': True, 'port_protocol': {'eq': 'www'}}, 'grant': 'deny', 'protocol': 'tcp', 'sequence': 120, 'source': {'any': True, 'port_protocol': {'range': {'end': '65535', 'start': '1024'}}}}], 'name': '100'}], 'afi': 'ipv4'}], 'state': 'merged'})
changed: [nxos-0] => (item={'config': [{'acls': [{'aces': [{'destination': {'address': '192.168.2.0', 'wildcard_bits': '0.0.0.255'}, 'grant': 'permit', 'protocol': 'ip', 'sequence': 130, 'source': {'any': True}}], 'name': '100'}], 'afi': 'ipv4'}], 'state': 'merged'})
TASK [merge acl config (asa)] ************************************************************************************
skipping: [iosvl2-0] => (item={'config': [{'acls': [{'aces': [{'destination': {'host': '192.168.2.1', 'port_protocol': {'eq': 'ntp'}}, 'grant': 'deny', 'protocol': 'udp', 'sequence': 110, 'source': {'host': '192.168.1.1'}}], 'acl_type': 'extended', 'name': 'TEST1'}], 'afi': 'ipv4'}], 'state': 'merged'})
skipping: [iosvl2-0] => (item={'config': [{'acls': [{'aces': [{'destination': {'address': '192.168.2.0', 'wildcard_bits': '0.0.0.255', 'port_protocol': {'eq': 'www'}}, 'grant': 'deny', 'protocol': 'tcp', 'sequence': 120, 'source': {'host': '192.168.1.2', 'port_protocol': {'gt': '1023'}}}], 'acl_type': 'extended', 'name': 'TEST1'}], 'afi': 'ipv4'}], 'state': 'merged'})
skipping: [nxos-0] => (item={'config': [{'acls': [{'aces': [{'destination': {'host': '192.168.2.1', 'port_protocol': {'eq': 'ntp'}}, 'grant': 'deny', 'protocol': 'udp', 'sequence': 110, 'source': {'host': '192.168.1.1'}}], 'name': 'TEST1'}], 'afi': 'ipv4'}], 'state': 'merged'})
skipping: [nxos-0] => (item={'config': [{'acls': [{'aces': [{'destination': {'address': '192.168.2.0', 'wildcard_bits': '0.0.0.255', 'port_protocol': {'eq': 'www'}}, 'grant': 'deny', 'protocol': 'tcp', 'sequence': 120, 'source': {'host': '192.168.1.2', 'port_protocol': {'range': {'end': '65535', 'start': '1024'}}}}], 'name': 'TEST1'}], 'afi': 'ipv4'}], 'state': 'merged'})
skipping: [nxos-0] => (item={'config': [{'acls': [{'aces': [{'destination': {'address': '192.168.2.0', 'wildcard_bits': '0.0.0.255'}, 'grant': 'permit', 'protocol': 'ip', 'sequence': 130, 'source': {'address': '192.168.1.0', 'wildcard_bits': '0.0.0.255'}}], 'name': 'TEST1'}], 'afi': 'ipv4'}], 'state': 'merged'})
skipping: [nxos-0] => (item={'config': [{'acls': [{'aces': [{'destination': {'any': True, 'port_protocol': {'eq': 'ntp'}}, 'grant': 'deny', 'protocol': 'udp', 'sequence': 110, 'source': {'any': True}}], 'name': '100'}], 'afi': 'ipv4'}], 'state': 'merged'})
skipping: [iosvl2-0] => (item={'config': [{'acls': [{'aces': [{'destination': {'address': '192.168.2.0', 'wildcard_bits': '0.0.0.255'}, 'grant': 'permit', 'protocol': 'ip', 'sequence': 130, 'source': {'address': '192.168.1.0', 'wildcard_bits': '0.0.0.255'}}], 'acl_type': 'extended', 'name': 'TEST1'}], 'afi': 'ipv4'}], 'state': 'merged'})
skipping: [iosvl2-0] => (item={'config': [{'acls': [{'aces': [{'destination': {'any': True, 'port_protocol': {'eq': 'ntp'}}, 'grant': 'deny', 'protocol': 'udp', 'sequence': 110, 'source': {'any': True}}], 'acl_type': 'extended', 'name': '100'}], 'afi': 'ipv4'}], 'state': 'merged'})
skipping: [iosvl2-0] => (item={'config': [{'acls': [{'aces': [{'destination': {'any': True, 'port_protocol': {'eq': 'www'}}, 'grant': 'deny', 'protocol': 'tcp', 'sequence': 120, 'source': {'any': True, 'port_protocol': {'gt': '1023'}}}], 'acl_type': 'extended', 'name': '100'}], 'afi': 'ipv4'}], 'state': 'merged'})
skipping: [nxos-0] => (item={'config': [{'acls': [{'aces': [{'destination': {'any': True, 'port_protocol': {'eq': 'www'}}, 'grant': 'deny', 'protocol': 'tcp', 'sequence': 120, 'source': {'any': True, 'port_protocol': {'range': {'end': '65535', 'start': '1024'}}}}], 'name': '100'}], 'afi': 'ipv4'}], 'state': 'merged'})
skipping: [iosvl2-0] => (item={'config': [{'acls': [{'aces': [{'destination': {'address': '192.168.2.0', 'wildcard_bits': '0.0.0.255'}, 'grant': 'permit', 'protocol': 'ip', 'sequence': 130, 'source': {'any': True}}], 'acl_type': 'extended', 'name': '100'}], 'afi': 'ipv4'}], 'state': 'merged'})
skipping: [nxos-0] => (item={'config': [{'acls': [{'aces': [{'destination': {'address': '192.168.2.0', 'wildcard_bits': '0.0.0.255'}, 'grant': 'permit', 'protocol': 'ip', 'sequence': 130, 'source': {'any': True}}], 'name': '100'}], 'afi': 'ipv4'}], 'state': 'merged'})
changed: [asav-1] => (item={'config': [{'acls': [{'aces': [{'destination': {'host': '192.168.2.1', 'port_protocol': {'eq': 'ntp'}}, 'grant': 'deny', 'protocol': 'udp', 'line': 1, 'source': {'host': '192.168.1.1'}}], 'acl_type': 'extended', 'name': 'TEST1'}]}], 'state': 'merged'})
changed: [asav-1] => (item={'config': [{'acls': [{'aces': [{'destination': {'address': '192.168.2.0', 'netmask': '255.255.255.0', 'port_protocol': {'eq': 'www'}}, 'grant': 'deny', 'protocol': 'tcp', 'line': 2, 'source': {'host': '192.168.1.2', 'port_protocol': {'gt': '1023'}}}], 'acl_type': 'extended', 'name': 'TEST1'}]}], 'state': 'merged'})
changed: [asav-1] => (item={'config': [{'acls': [{'aces': [{'destination': {'address': '192.168.2.0', 'netmask': '255.255.255.0'}, 'grant': 'permit', 'protocol': 'ip', 'line': 3, 'source': {'address': '192.168.1.0', 'netmask': '255.255.255.0'}}], 'acl_type': 'extended', 'name': 'TEST1'}]}], 'state': 'merged'})
changed: [asav-1] => (item={'config': [{'acls': [{'aces': [{'destination': {'any': True, 'port_protocol': {'eq': 'ntp'}}, 'grant': 'deny', 'protocol': 'udp', 'line': 1, 'source': {'any': True}}], 'acl_type': 'extended', 'name': '100'}]}], 'state': 'merged'})
changed: [asav-1] => (item={'config': [{'acls': [{'aces': [{'destination': {'any': True, 'port_protocol': {'eq': 'www'}}, 'grant': 'deny', 'protocol': 'tcp', 'line': 2, 'source': {'any': True, 'port_protocol': {'gt': '1023'}}}], 'acl_type': 'extended', 'name': '100'}]}], 'state': 'merged'})
changed: [asav-1] => (item={'config': [{'acls': [{'aces': [{'destination': {'address': '192.168.2.0', 'netmask': '255.255.255.0'}, 'grant': 'permit', 'protocol': 'ip', 'line': 3, 'source': {'any': True}}], 'acl_type': 'extended', 'name': '100'}]}], 'state': 'merged'})
PLAY RECAP *******************************************************************************************************
asav-1 : ok=4 changed=2 unreachable=0 failed=0 skipped=2 rescued=0 ignored=0
iosvl2-0 : ok=7 changed=2 unreachable=0 failed=0 skipped=2 rescued=0 ignored=0
iosvl2-1 : ok=3 changed=0 unreachable=0 failed=0 skipped=3 rescued=0 ignored=0
nxos-0 : ok=4 changed=2 unreachable=0 failed=0 skipped=2 rescued=0 ignored=0
6. Config確認
6-1. IOS機器
6行のACL要件に対し、4行しか設定されていませんでした。入っていないのは名前付きACLの120番と番号付きACLの130番です。
ip access-list extended TEST1
deny udp host 192.168.1.1 host 192.168.2.1 eq ntp
permit ip 192.168.1.0 0.0.0.255 192.168.2.0 0.0.0.255
!
access-list 100 deny udp any any eq ntp
access-list 100 deny tcp any gt 1023 any eq www
iosvl2-0#sh ip access-list
Extended IP access list 100
110 deny udp any any eq ntp
120 deny tcp any gt 1023 any eq www
Extended IP access list TEST1
110 deny udp host 192.168.1.1 host 192.168.2.1 eq ntp
130 permit ip 192.168.1.0 0.0.0.255 192.168.2.0 0.0.0.255
切り分けしたところ、送信元と宛先でアーギュメント指定方法が異なり、かつ宛先がネットワークだとうまく行きませんでした。(前者はホスト/ネットワーク、後者はany/ネットワークの混在。)
以下URLのcisco.iosのConfig生成用コードを見ると、送信元と宛先共通の関数の中で、本来**config_data[type]
とすべきところが、**config_data["source"]
となっていました。ここを修正したら6行出力されました。
GitHub - cisco.ios/plugins/module_utils/network/ios/rm_templates/acls.py
また、ここには記載していませんが、ポート番号をrange指定するケースでも、Configを生成する処理に失敗し、Failedになりました。上記URLのコードを見る限り、rangeは未実装のようです。
現状Configにコマンドip access-list TEST1
のみが設定され、エントリが1行も存在しない状態でPlaybookを実行したケースでもFailedとなりました。
6-2. NX-OS機器
問題なく設定されていました。
ip access-list 100
110 deny udp any any eq ntp
120 deny tcp any range 1024 65535 any eq www
130 permit ip any 192.168.2.0/24
ip access-list TEST1
110 deny udp 192.168.1.1/32 192.168.2.1/32 eq ntp
120 deny tcp 192.168.1.2/32 range 1024 65535 192.168.2.0/24 eq www
130 permit ip 192.168.1.0/24 192.168.2.0/24
6-3. ASA機器
今回の要件では特に問題ありませんでしたが、IOS機器と同様range指定がFailedとなりました。
access-list TEST1 extended deny udp host 192.168.1.1 host 192.168.2.1 eq ntp
access-list TEST1 extended deny tcp host 192.168.1.2 gt 1023 192.168.2.0 255.255.255.0 eq www
access-list TEST1 extended permit ip 192.168.1.0 255.255.255.0 192.168.2.0 255.255.255.0
access-list 100 extended deny udp any any eq ntp
access-list 100 extended deny tcp any gt 1023 any eq www
access-list 100 extended permit ip any 192.168.2.0 255.255.255.0
7. 冪等性確認
同じPlaybookを再度実行したところ、IOS、NX-OS機器の一部要件、ASA機器の全要件でchanged
になり、冪等性が担保されませんでした。
どのようなConfigが再投入されているか、xxx_acls
モジュールの実行結果をregister変数に格納し、変数内のcommands
を確認してみました。
7-1. IOS機器
同じシーケンス番号の既存Configを削除しようとしているようですが、コマンドが途切れています。もしこれが既存Configとして扱われているとしたら、追加Configと異なるので再投入されてしまうのも説明が付く気がします。
"ip access-list extended TEST1",
"no 120 deny tcp host 192.168.1.2",
"120 deny tcp host 192.168.1.2 gt 1023 192.168.2.0 0.0.0.255 eq www"
"ip access-list extended 100",
"no 120 deny tcp any",
"120 deny tcp any gt 1023 any eq www"
7-2. NX-OS機器
既存ConfigはIPアドレス/プレフィックス
で表示され、追加Configはhost ホストアドレス
もしくはネットワークアドレス ワイルドカード
の形で表示されるせいかと思いましたが、名前付き拡張ACLの110番の冪等性が担保される理由が付きませんね。謎ですw
"ip access-list TEST1",
"no 120",
"120 deny tcp host 192.168.1.2 range 1024 65535 192.168.2.0 0.0.0.255 eq www"
"ip access-list TEST1",
"no 130",
"130 permit ip 192.168.1.0 0.0.0.255 192.168.2.0 0.0.0.255"
"ip access-list 100",
"no 120",
"120 deny tcp any range 1024 65535 any eq www"
"ip access-list 100",
"no 130",
"130 permit ip any 192.168.2.0 0.0.0.255"
7-3. ASA機器
既存Configの削除は行われず、新規の扱いでした。これも謎ですw
"access-list TEST1 line 1 extended deny udp host 192.168.1.1 host 192.168.2.1 eq ntp"
"access-list TEST1 line 2 extended deny tcp host 192.168.1.2 gt 1023 192.168.2.0 255.255.255.0 eq www"
(省略)
最後に
ACL設定変更のような単純作業とAnsibleは相性が良く、かつxxx_acls
はサポートするアーギュメントの種類が多いため、かなり有用なモジュールだと思います。ただ、今回の動作確認でいくつか想定通りの結果にならない点もあったので、本番作業で使えるのはもう少し先かなと感じました。今回見つかったバグは、GitHubにIssueを上げたいと思います。