[python]Push ACL to Cisco ASA with Nornir. Passing in dictionary.

Introduction

On previous post testing was done to push ACL to Cisco ASA with static information, however in production preparing static information directly to the run method of Nornir is not practical, if the information is passed as a dictionary through API gateway the payload will have to be passed to the add_acl function.

So there is a modification of the code to make the code more practical.

Modification to the original code and template

This is a testing code to accept dynamic payload and nornir uses jinja2 template to render the commands and push the ACL commands directly to Cisco ASA with netmiko.

Keyword argument is added to the original add_acl.

def add_acl(task, **kwargs):
    cmd = task.run(task=template_file,
                   name="Generating template",
                   template="asa_acl.j2",
                   path="./templates/",
                   acl_attr=kwargs
                   )
    task.host["config"] = cmd.result
    task.run(task=netmiko_send_config,
             name="Sending configuration",
             config_commands=task.host["config"])
    task.run(task=netmiko_save_config,
             name="Saving configuration",
             cmd="write memory")

Modification of the template as follows:

{% 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 %}

You can study the jinja2 documentation to understand how to pass in dictionary values.

Entire code for testing

from nornir import InitNornir
from nornir.plugins.tasks.networking import netmiko_send_config, netmiko_save_config
from nornir.plugins.tasks.text import template_file
from nornir.plugins.functions.text import print_result
from pyvault2.vault.hvault2 import get_kv2_secret

"""
The credential_from_vault function can be found here:
https://github.com/sirbowen78/pyvault2/blob/master/vault/hvault2.py
"""
credential_from_vault = get_kv2_secret(mount_path="cisco_asa", path="fw01", find="data")

"""
Reference:
https://nornir.readthedocs.io/en/stable/tutorials/intro/grouping_tasks.html
"""


def change_host_data(host):
    host.username = credential_from_vault["username"]
    host.password = credential_from_vault["password"]
    host.hostname = credential_from_vault["ip"]
    host.platform = "cisco_asa"


def add_acl(task, **kwargs):
    cmd = task.run(task=template_file,
                   name="Generating template",
                   template="asa_acl.j2",
                   path="./templates/",
                   acl_attr=kwargs
                   )
    task.host["config"] = cmd.result
    task.run(task=netmiko_send_config,
             name="Sending configuration",
             config_commands=task.host["config"])
    task.run(task=netmiko_save_config,
             name="Saving configuration",
             cmd="write memory")


nr = InitNornir(
    inventory={
        "plugin": "nornir.plugins.inventory.simple.SimpleInventory",
        "options": {
            "host_file": "templates/hosts.yaml"
        },
        "transform_function": change_host_data
    }
)

payload = {
        "acl_name": "abc",
        "action": "deny",
        "protocol": "tcp",
        "src_fw_object_type": "host",
        "src_object": "192.168.1.122",
        "dst_fw_object_type": "host",
        "dst_object": "172.16.1.1",
        "svc_object_group_type": "eq",
        "svc_object_group": "65000"
    }


r = nr.run(task=add_acl, **payload)
print_result(r)

Demonstration

Insert a deny rule.

payload = {
        "acl_name": "abc",
        "action": "deny",
        "protocol": "tcp",
        "src_fw_object_type": "host",
        "src_object": "10.168.10.200",
        "dst_fw_object_type": "host",
        "dst_object": "192.168.100.100",
        "svc_object_group_type": "eq",
        "svc_object_group": "8443"
    }
r = nr.run(task=add_acl, **payload)
print_result(r)

acl6

acl7

Insert a deny rule to the top of the entire acl:

payload = {
        "acl_name": "abc",
        "action": "deny",
        "line_number": "1",
        "protocol": "tcp",
        "src_fw_object_type": "host",
        "src_object": "10.1.10.200",
        "dst_fw_object_type": "host",
        "dst_object": "172.32.100.100",
        "svc_object_group_type": "eq",
        "svc_object_group": "443"
    }

acl8

acl9

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s