Introduction
On previous few posts, the ACL was push to the cisco asa with Nornir, but there was limitation that is only one source ip, one destination ip and one service are allowed, if there is more than one in any of these then only one rule is pushed.
But there will be a number of hosts that required to connect to one or more targets, and these targets may have more than one services, hence some changes in template is required to allow more than one source, destination and service in the configuration.
Template modification
This is the original jinja2 template for the acl command, which is limited to single source, dest and service.
{% if acl_attr.line_number is defined %} access-list {{ acl_attr.acl_name }} line {{acl_attr.line_number}} extended {{acl_attr.action}} {{acl_attr.protocol}} {{acl_attr.src_fw_object_type}} {{acl_attr.src_object}} {{acl_attr.dst_fw_object_type}} {{acl_attr.dst_object}} {{acl_attr.svc_object_group_type}} {{acl_attr.svc_object_group}} log {% else %} access-list {{acl_attr.acl_name}} extended {{acl_attr.action}} {{acl_attr.protocol}} {{acl_attr.src_fw_object_type}} {{acl_attr.src_object}} {{acl_attr.dst_fw_object_type}} {{acl_attr.dst_object}} {{acl_attr.svc_object_group_type}} {{acl_attr.svc_object_group}} log {% endif %}
We will need to iterate the list of source, destination and service, hence the original jinja2 template is modified to this:
{% if acl_attr.line_number is defined %} access-list {{ acl_attr.acl_name }} line {{acl_attr.line_number}} extended {{acl_attr.action}} {{acl_attr.protocol}} {{acl_attr.src_fw_object_type}} {{acl_attr.src_object}} {{acl_attr.dst_fw_object_type}} {{acl_attr.dst_object}} {{acl_attr.svc_object_group_type}} {{acl_attr.svc_object_group}} log {% else %} {% for src_object in acl_attr.src_object %} {% for dst_object in acl_attr.dst_object %} {% for svc_object_group in acl_attr.svc_object_group %} access-list {{acl_attr.acl_name}} extended {{acl_attr.action}} {{acl_attr.protocol}} {{acl_attr.src_fw_object_type}} {{src_object}} {{acl_attr.dst_fw_object_type}} {{dst_object}} {{acl_attr.svc_object_group_type}} {{svc_object_group}} log {% endfor %} {% endfor %} {% endfor %} {% endif %}
Demonstration
To clearly see the result, I have use the command clear config access-list abcd
in cisco asa.
Single source, single destination and single service
Multiple sources, single destination and single service
Single source, multiple destinations and single service
Multple sources, multiple destinations and single service
Single source, single destination and multiple services
Multiple sources, single destination and multiple services
Single source, multiple destinations and multiple services
Multiple sources, destinations and services
Some lines are shown, total there are 64 lines.
InitNornir requires to close connection after run method
I realized nornir does not close connection with the cisco asa, so you need to use the with
context when InitNornir
def send_acl_to_asa_host(hostname=None, **kwargs): vault_data = get_asa_credential(hostname=hostname) with InitNornir( inventory={ "plugin": "nornir.plugins.inventory.simple.SimpleInventory", "options": { "host_file": host_file_path } } ) as nr: nr.inventory.hosts.get(hostname, None).username = vault_data["username"] nr.inventory.hosts.get(hostname, None).password = vault_data["password"] asa_host = nr.filter(filter_func=lambda h: h.name == hostname) response = asa_host.run(task=add_acl, **kwargs) # Reference: https://pynet.twb-tech.com/blog/nornir/intro.html return { "status": "success" if not response[hostname][0].failed else "failed", "result": response[hostname][1].result.rsplit("\n") }