Cisco ASA’s show run object network
will show the subnet, host and range objects, netmiko has a textfsm template to match the result in dictionary, however there is no template to match show run object service
hence for the service part you will need to write your own textfsm template.
On this example I will be using nornir framework, however you can use netmiko directly as well, there is no difference between these two.
I will be using a self written package to get the device, this is a portion of the functions of my package which I will be using:
from pyvault2.vault.hvault2 import get_kv2_secret from nornir import InitNornir from pathlib import Path from os.path import join host_file_path = join(Path(__file__).parent.absolute(), "inventory", "hosts.yaml") def connect_asa_host(hostname=None): 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"] return nr.filter(filter_func=lambda h: h.name == hostname) def get_asa_credential(hostname=None): """ Get asa's device credentials. :param hostname: :return: credential in json """ return get_kv2_secret(mount_path="cisco_asa", path=hostname, find="data") def sh_run_object_network(hostname=None, object_id=None): """ Netmiko will return a dictionary of show run object network. if no object_id specified all dictionary is displayed. :param hostname: hostname of Cisco ASA :param object_id: The firewall object name :return: dictionary """ target_device = connect_asa_host(hostname=hostname) response = target_device.run(task=netmiko_send_command, command_string="show run object network", use_textfsm=True) result = response[hostname][0].result if object_id is not None: object_id_result = next(filter(lambda x: x["name"] == object_id, result), None) return object_id_result return result
sh_run_object_network
function returns a dictionary of all network objects if no object_id is specified, if an object_id is specified, the filter
function will be use to match the item in iterables (tuple or list), next function is to find the next item to match if the first item is not match, next function can define a default value if there is no match found from the iterables, hence the line is written as next(filter(lambda x: x["name"] == object_id, result), None)
.
Filter function takes in two arguments, one function and one iterable, lambda function is used to find a match of the dictionary’s key “name” with object_id, if the match is found the result will be shown.
The firewall has these network objects:
To get all network objects dictionary:
from network.ciscoasa import sh_run_object_network from pprint import pprint pprint(sh_run_object_network(hostname="fw02"))
The result of the script to return all network objects:
[{'cidr': '', 'desc': 'Test object', 'end_ip': '', 'host': '192.168.1.1', 'mask': '', 'name': 'centos', 'network': '', 'start_ip': '', 'type': 'host'}, {'cidr': '', 'desc': 'Test object', 'end_ip': '192.168.1.120', 'host': '', 'mask': '', 'name': 'host1', 'network': '', 'start_ip': '192.168.1.100', 'type': 'range'}, {'cidr': '', 'desc': 'test subnet', 'end_ip': '', 'host': '', 'mask': '255.255.255.0', 'name': 'test2', 'network': '192.168.1.0', 'start_ip': '', 'type': 'subnet'}, {'cidr': '', 'desc': 'test host', 'end_ip': '', 'host': '192.168.1.100', 'mask': '', 'name': 'test3', 'network': '', 'start_ip': '', 'type': 'host'}]
To get the dictionary of specific object, in this example I want to show only “test2” network object:
pprint(sh_run_object_network(hostname="fw02", object_id="test2"))
{'cidr': '', 'desc': 'test subnet', 'end_ip': '', 'host': '', 'mask': '255.255.255.0', 'name': 'test2', 'network': '192.168.1.0', 'start_ip': '', 'type': 'subnet'}
Another test to get only the network object test3 dictionary:
pprint(sh_run_object_network(hostname="fw02", object_id="test3"))
{'cidr': '', 'desc': 'test host', 'end_ip': '', 'host': '192.168.1.100', 'mask': '', 'name': 'test3', 'network': '', 'start_ip': '', 'type': 'host'}
The flexibility is high if the data is structured, and thank to TextFSM unstructured data can easily be converted to structured.