Hi,
I have created a reusable Ansible Role that is being used like a function() to manage ACLs on Cisco IOS, in such a way that the ACL rules are individually removed and added using sequence numbers (ordering matches the list order explicitly).
Everything is working great, but the task in the main playbook which invokes the ‘include_rule:’ module is not printing its ‘name:’. In fact the first ‘name:’ which is printed is for the second task within the role!
Ideally we want all the task ‘names:’ to be printed, including the name of the task calling ‘include_rule:’, so you can print something like “Deploying ACL foo for bar… etc” before printing the generic task names within the role.
You can see in my code snips below that I am using a simple list-of-dicts for the sources to permit instead of explicit ACL lines (allows the list to be used as a source for many contexts etc)
NB; It supports standard and extended ACLs, both numbered and named, and works with IOS 12 and 15.
Example all.yml section
mgmt_access_sources:
- { ip: 1.2.3.4, wildcard: 0.0.0.0, subnet: 255.255.255.255 }
- { ip: 172.16.75.0, wildcard: 0.0.0.255, subnet: 255.255.255.0 }
- { ip: 192.168.0.0, wildcard: 0.0.255.255, subnet: 255.255.0.0 }
etc..
Example playbook section using the ACL managment Role to manage the VTY ACL
# MANAGE VTY ACCESS ACL
- name: 'Register list "mgmt_access_sources" as a fact for vty_acl_lines.j2 template'
set_fact:
mgmt_access_sources: "{{ mgmt_access_sources }}"
tags: ["ios", "switch_access", "switch_access_vty_acl"]
- name: 'Manage VTY ACL'
include_role:
name: ios_acl
vars:
- ios_acl_rules: "{{ lookup('template', 'vty_acl_lines.j2').split('\n') | select('match', '.+') | list }}" # Build complete ACL rules list from mgmt_access_sources
- ios_acl_name: "VTY-ACCESS"
- ios_acl_type: "extended"
tags: ["ios", "switch_access", "switch_access_vty_acl"]
vty_acl_lines.j2 (Example Template to build ACL rules)
{% for source in mgmt_access_sources %}
{% if source.ip is defined and source.wildcard is defined and source.wildcard == "0.0.0.0" %}permit tcp host {{ source.ip }} any eq 22
{% elif source.ip is defined and source.wildcard is defined and source.wildcard != "0.0.0.0" %}permit tcp {{ source.ip }} {{ source.wildcard }} any eq 22
{% endif %}
{% endfor %}
ios_acl.yml (ACL management Role)
---
- name: 'Check ios_acl vars'
fail: msg="ios_acl vars are not sane ios_acl_name {{ ios_acl_name }} ios_acl_type {{ ios_acl_type }} ios_acl_rules {{ ios_acl_rules }}"
when: ios_acl_name is not defined or ios_acl_name == '' or ios_acl_type is not defined or ios_acl_type == '' or ios_acl_rules is not defined or ios_acl_rules | length < 1
tags: [ "ios", "ios_acl" ]
- name: "Get current access-list state"
ios_command:
commands:
- "show access-lists {{ ios_acl_name }} | include ^\ +[1-9]"
register: acl_config
tags: [ "ios", "ios_acl" ]
- name: 'Register intended ios_acl_rules as fact for ios_acl.j2 template'
set_fact:
ios_acl_rules: "{{ ios_acl_rules }}"
when: acl_config.stdout is defined and acl_config.stdout != '' and acl_config.stdout != None
tags: [ "ios", "ios_acl" ]
- name: "Remove existing access-list lines not in intended ACL"
with_items: "{{ acl_config.stdout_lines[0] |\
regex_replace('[ \t]{2}') |\
regex_replace(' [(].{9,30}[)]') |\
regex_replace(', wildcard bits') }}"
ios_config:
lines: "no {{ item }}"
parents: "ip access-list {{ ios_acl_type }} {{ ios_acl_name }}"
when: "item not in lookup('template', 'ios_acl.j2') and acl_config.stdout_lines[0][0] is defined and acl_config.stdout_lines[0][0] != '' and acl_config.stdout_lines[0][0] != None"
tags: [ "ios", "ios_acl" ]
- name: "Insert new access-list lines not in existing ACL"
with_items: "{{ lookup('template', 'ios_acl.j2').split('\n') | select('match', '.+') | list }}"
ios_config:
lines: "{{ item }}"
parents: "ip access-list {{ ios_acl_type }} {{ ios_acl_name }}"
when: "(item not in acl_config.stdout_lines[0] |\
regex_replace('[ \t]{2}') |\
regex_replace(' [(].{9,30}[)]') |\
regex_replace(', wildcard bits'))"
tags: [ "ios", "ios_acl" ]
ios_acl.j2 (Role’s Template)
{% for line in ios_acl_rules %}{{ loop.index * 10 }} {{ line }}
{% endfor %}
Below you can see the ansible-playbook stdout which shows it is working and is selectively removing and adding lines, which greatly reduces the risk of chopping off the branch you are sat on… I would also recomend adding an extra check to never negate the ACL line for the Ansible control servers public IP/your office etc…
But you can see that is jumps from task “switch_access : Register list "mgmt_access_sources” as a fact for vty_acl_lines.j2 template" to task “ios_acl : Get current access-list state”. I have confirmed the tasts which do not print are being run correctly, their stdout is just lost.
So, what happend to printing “switch_access : Manage VTY ACL” and “ios_acl : Check ios_acl vars”?!
The issue is positional, and is not an issue with these specific tasks. If I add another random task before “Check ios_acl vars”, I then do see “Check ios_acl vars” printed…
The issue persists on Linux and OSX (Ansible 2.7.4).
Ansible Playbook STDOUT;
TASK [switch_access : Register list “mgmt_access_sources” as a fact for vty_acl_lines.j2 template] ***************************************************************************************************************************************************************************
task path: /local/CAN-Ansible-Playbooks/Network/roles/switch_access/tasks/main.yml:59
ok: [byf-lab-sw-1] => {“ansible_facts”: {“mgmt_access_sources”: [{“ip”: “1.2.3.4”, “subnet”: “255.255.255.255”, “wildcard”: “0.0.0.0”}, {“ip”: “172.16.75.0”, “subnet”: “255.255.255.0”, “wildcard”: “0.0.0.255”}, {“ip”: “192.168.0.0”, “subnet”: “255.255.0.0”, “wildcard”: “0.0.255.255”}]}, “changed”: false}
ok: [byf-lab-sw-2] => {“ansible_facts”: {“mgmt_access_sources”: [{“ip”: “1.2.3.4”, “subnet”: “255.255.255.255”, “wildcard”: “0.0.0.0”}, {“ip”: “172.16.75.0”, “subnet”: “255.255.255.0”, “wildcard”: “0.0.0.255”}, {“ip”: “192.168.0.0”, “subnet”: “255.255.0.0”, “wildcard”: “0.0.255.255”}]}, “changed”: false}
Wednesday 19 December 2018 18:25:16 +0000 (0:00:01.429) 0:01:57.409 ****
TASK [ios_acl : Get current access-list state] *******************************************************************************************************************************************************************************************************************************
task path: /local/CAN-Ansible-Playbooks/Network/roles/ios_acl/tasks/main.yml:7
ok: [byf-lab-sw-2] => {}
ok: [byf-lab-sw-1] => {}
Wednesday 19 December 2018 18:25:18 +0000 (0:00:02.033) 0:01:59.718 ****
TASK [ios_acl : Register intended ios_acl_rules as fact for ios_acl.j2 template] *********************************************************************************************************************************************************************************************
task path: /local/CAN-Ansible-Playbooks/Network/roles/ios_acl/tasks/main.yml:21
ok: [byf-lab-sw-1] => {“ansible_facts”: {“ios_acl_rules”: [“permit tcp host 1.2.3.4 any eq 22”, “permit tcp 172.16.75.0 0.0.0.255 any eq 22”, “permit tcp 192.168.0.0 0.0.255.255 any eq 22”]}, “changed”: false}
ok: [byf-lab-sw-2] => {“ansible_facts”: {“ios_acl_rules”: [“permit tcp host 1.2.3.4 any eq 22”, “permit tcp 172.16.75.0 0.0.0.255 any eq 22”, “permit tcp 192.168.0.0 0.0.255.255 any eq 22”]}, “changed”: false}
Wednesday 19 December 2018 18:25:20 +0000 (0:00:01.452) 0:02:01.170 ****
TASK [ios_acl : Remove existing access-list lines not in intended ACL] *******************************************************************************************************************************************************************************************************
task path: /local/CAN-Ansible-Playbooks/Network/roles/ios_acl/tasks/main.yml:27
changed: [byf-lab-sw-2] => (item=10 permit tcp host any eq 22) => {“banners”: {}, “changed”: true, “commands”: [“ip access-list extended VTY-ACCESS”, “no 10 permit tcp host any eq 22”], “item”: “10 permit tcp host any eq 22”, “updates”: [“ip access-list extended VTY-ACCESS”, “no 10 permit tcp host any eq 22”]}
changed: [byf-lab-sw-2] => (item=20 permit tcp host any eq 22) => {“banners”: {}, “changed”: true, “commands”: [“ip access-list extended VTY-ACCESS”, “no 20 permit tcp host any eq 22”], “item”: “20 permit tcp host any eq 22”, “updates”: [“ip access-list extended VTY-ACCESS”, “no 20 permit tcp host any eq 22”]}
changed: [byf-lab-sw-1] => (item=10 permit tcp host any eq 22) => {“banners”: {}, “changed”: true, “commands”: [“ip access-list extended VTY-ACCESS”, “no 10 permit tcp host any eq 22”], “item”: “10 permit tcp host any eq 22”, “updates”: [“ip access-list extended VTY-ACCESS”, “no 10 permit tcp host any eq 22”]}
changed: [byf-lab-sw-2] => (item=30 permit tcp host any eq 22) => {“banners”: {}, “changed”: true, “commands”: [“ip access-list extended VTY-ACCESS”, “no 30 permit tcp host any eq 22”], “item”: “30 permit tcp host any eq 22”, “updates”: [“ip access-list extended VTY-ACCESS”, “no 30 permit tcp host any eq 22”]}
changed: [byf-lab-sw-2] => (item=40 permit tcp host 1.2.3.4 any eq 22) => {“banners”: {}, “changed”: true, “commands”: [“ip access-list extended VTY-ACCESS”, “no 40 permit tcp host 1.2.3.4 any eq 22”], “item”: “40 permit tcp host 1.2.3.4 any eq 22”, “updates”: [“ip access-list extended VTY-ACCESS”, “no 40 permit tcp host 1.2.3.4 any eq 22”]}
changed: [byf-lab-sw-1] => (item=20 permit tcp host any eq 22) => {“banners”: {}, “changed”: true, “commands”: [“ip access-list extended VTY-ACCESS”, “no 20 permit tcp host any eq 22”], “item”: “20 permit tcp host any eq 22”, “updates”: [“ip access-list extended VTY-ACCESS”, “no 20 permit tcp host any eq 22”]}
changed: [byf-lab-sw-2] => (item=50 permit tcp 0.0.0.127 any eq 22) => {“banners”: {}, “changed”: true, “commands”: [“ip access-list extended VTY-ACCESS”, “no 50 permit tcp 0.0.0.127 any eq 22”], “item”: “50 permit tcp 0.0.0.127 any eq 22”, “updates”: [“ip access-list extended VTY-ACCESS”, “no 50 permit tcp 0.0.0.127 any eq 22”]}
changed: [byf-lab-sw-1] => (item=30 permit tcp host any eq 22) => {“banners”: {}, “changed”: true, “commands”: [“ip access-list extended VTY-ACCESS”, “no 30 permit tcp host any eq 22”], “item”: “30 permit tcp host any eq 22”, “updates”: [“ip access-list extended VTY-ACCESS”, “no 30 permit tcp host any eq 22”]}
changed: [byf-lab-sw-1] => (item=40 permit tcp 0.0.0.127 any eq 22) => {“banners”: {}, “changed”: true, “commands”: [“ip access-list extended VTY-ACCESS”, “no 40 permit tcp 0.0.0.127 any eq 22”], “item”: “40 permit tcp 0.0.0.127 any eq 22”, “updates”: [“ip access-list extended VTY-ACCESS”, “no 40 permit tcp 0.0.0.127 any eq 22”]}
changed: [byf-lab-sw-1] => (item=50 permit tcp host 1.2.3.4 any eq 22) => {“banners”: {}, “changed”: true, “commands”: [“ip access-list extended VTY-ACCESS”, “no 50 permit tcp host 1.2.3.4 any eq 22”], “item”: “50 permit tcp host 1.2.3.4 any eq 22”, “updates”: [“ip access-list extended VTY-ACCESS”, “no 50 permit tcp host 1.2.3.4 any eq 22”]}
Wednesday 19 December 2018 18:27:18 +0000 (0:01:58.338) 0:03:59.509 ****
TASK [ios_acl : Insert new access-list lines not in existing ACL] ************************************************************************************************************************************************************************************************************
task path: /local/CAN-Ansible-Playbooks/Network/roles/ios_acl/tasks/main.yml:38
changed: [byf-lab-sw-2] => (item=10 permit tcp host 1.2.3.4 any eq 22) => {“banners”: {}, “changed”: true, “commands”: [“ip access-list extended VTY-ACCESS”, “10 permit tcp host 1.2.3.4 any eq 22”], “item”: “10 permit tcp host 1.2.3.4 any eq 22”, “updates”: [“ip access-list extended VTY-ACCESS”, “10 permit tcp host 1.2.3.4 any eq 22”]}
changed: [byf-lab-sw-1] => (item=10 permit tcp host 1.2.3.4 any eq 22) => {“banners”: {}, “changed”: true, “commands”: [“ip access-list extended VTY-ACCESS”, “10 permit tcp host 1.2.3.4 any eq 22”], “item”: “10 permit tcp host 1.2.3.4 any eq 22”, “updates”: [“ip access-list extended VTY-ACCESS”, “10 permit tcp host 1.2.3.4 any eq 22”]}
changed: [byf-lab-sw-2] => (item=20 permit tcp 172.16.75.0 0.0.0.255 any eq 22) => {“banners”: {}, “changed”: true, “commands”: [“ip access-list extended VTY-ACCESS”, “20 permit tcp 172.16.75.0 0.0.0.255 any eq 22”], “item”: “20 permit tcp 172.16.75.0 0.0.0.255 any eq 22”, “updates”: [“ip access-list extended VTY-ACCESS”, “20 permit tcp 172.16.75.0 0.0.0.255 any eq 22”]}
changed: [byf-lab-sw-2] => (item=30 permit tcp 192.168.0.0 0.0.255.255 any eq 22) => {“banners”: {}, “changed”: true, “commands”: [“ip access-list extended VTY-ACCESS”, “30 permit tcp 192.168.0.0 0.0.255.255 any eq 22”], “item”: “30 permit tcp 192.168.0.0 0.0.255.255 any eq 22”, “updates”: [“ip access-list extended VTY-ACCESS”, “30 permit tcp 192.168.0.0 0.0.255.255 any eq 22”]}
changed: [byf-lab-sw-1] => (item=20 permit tcp 172.16.75.0 0.0.0.255 any eq 22) => {“banners”: {}, “changed”: true, “commands”: [“ip access-list extended VTY-ACCESS”, “20 permit tcp 172.16.75.0 0.0.0.255 any eq 22”], “item”: “20 permit tcp 172.16.75.0 0.0.0.255 any eq 22”, “updates”: [“ip access-list extended VTY-ACCESS”, “20 permit tcp 172.16.75.0 0.0.0.255 any eq 22”]}
changed: [byf-lab-sw-1] => (item=30 permit tcp 192.168.0.0 0.0.255.255 any eq 22) => {“banners”: {}, “changed”: true, “commands”: [“ip access-list extended VTY-ACCESS”, “30 permit tcp 192.168.0.0 0.0.255.255 any eq 22”], “item”: “30 permit tcp 192.168.0.0 0.0.255.255 any eq 22”, “updates”: [“ip access-list extended VTY-ACCESS”, “30 permit tcp 192.168.0.0 0.0.255.255 any eq 22”]}
Wednesday 19 December 2018 18:27:43 +0000 (0:00:24.506) 0:04:24.016 ****
Thanks in advance for your time and help
Kind regards, Andrew Lemin