top of page

Automating Cisco ASA Change Tracking with REST API

At CDA, our goal is to make mundane and repeatable tasks automated where possible. Tasks such as tracking firewall configuration changes for each firewall in the environment.


This article will explore how to track ASA changes using the Cisco REST API. This approach can be adapted effortlessly for various tasks, including:

  • Checking interface status

  • Verifying dynamic routing protocol status

  • Examining the configuration at an object level

Development Process Overview

To remove the burden of requiring an administrator to log onto all firewalls and manually pull configurations daily, the following approach is taken to automate the process.

  • Understand the Business Case

  • Build Use Case/Pseudo Code

    • Connect

    • Login

    • Backup Configuration

    • Compare vs template

  • Design and set up a lab for testing

  • Build script

  • Test script

  • Document script

Lab Overview

The lab environment for this exercise is outlined below:

  • ASAv01: (192.168.1.23) The table below outlines the basic configuration required to use the script in your test environment.

hostname ASAv01
enable password Cisco123
interface GigabitEthernet0/0
 nameif inside
 security-level 100
 ip address 192.168.1.23 255.255.255.0 
!
router rip
 network 10.0.0.0
 version 2
!
route inside 0.0.0.0 0.0.0.0 192.168.1.1 1
aaa authentication http console LOCAL 
aaa authentication login-history
http server enable
http 0.0.0.0 0.0.0.0 inside
username admin password Cisco123 privilege 15 
!
  • ASAv02: (192.168.1.24)

The configuration for ASAv02 is the same as above with a different IP Address

  • Workstation:

    • PyCharm IDE

    • Python 3.9

Installing the Cisco ASA REST API

As the Cisco ASA REST API installation has already been discussed in a previous article, it will not be covered in detail here. However, you can refer to the link below for a comprehensive guide on how to install the REST API.

Script Workflow Overview

The process required to complete the comparison is simple and documented below:

  • Connect

  • Login

  • Backup the Configuration

  • Compare Configuration to template

  • Report Differences

import requests
import urllib3
import json
import getpass
from datetime import datetime
import conf_diff

date =datetime.now()
date_time = date.strftime("%m-%d-%Y-%H-%M-%S")


#IGNORE CERTIFICATE WARNINGS. CHANCES ARE YOU DID NOT CREATE A TRUSTED CERT FOR ALL YOUR FIREWALL DEVICES 

urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)

#DEFINE VARIABLES FOR USE IN FUNCTIONS

headers = {'Content-Type': 'application/json', 'User-Agent':'REST API Agent'}
cli_path = "/api/cli/"
backup_payload={"commands": ["show run"]}
fw_user="admin"
fw_pwd="Cisco123"

def get_creds():
  fw_user=input(“Username: “)
  try:
      fw_pwd=getpass.getpass(prompt=’Password: ‘, stream=None)
  except Exception as error:
      print (‘ERROR’,error)

def get_backups():
   hosts_file = open('hosts.txt', 'r+')
   with open('hosts.txt') as hosts_file:
       hosts_array = hosts_file.read().splitlines()
       for host in hosts_array:
           log_file = host + "-" + date_time + ".log"
           openlog = open(log_file, "a")
           url = "https://" + host + cli_path
           print(f"*****Connecting to " + host + "*****\n")
           backupresponse = requests.post(url, auth=(fw_user, fw_pwd), data=json.dumps(backup_payload), headers=headers,
                           verify=False) #Connect to REST API and 
            backup_data = json.dumps(backupresponse.text)
           bd = backup_data.replace('\\n', '\n')
           print(f"*****Writing configuration to " + log_file + "*****\n") 
           openlog.write(bd) #Write configuration to log file


   openlog.close()
   pass


def compare_conf():
   hosts_file = open('hosts.txt', 'r+')
   with open('hosts.txt') as hosts_file:
       hosts_array = hosts_file.read().splitlines()
       for host in hosts_array:
           change_file = host + "-" + date_time + "-changes.log"
           changelog = open(change_file, "a")
           log_file = host + "-" + date_time + ".log"
           print("*****Comparing Configuration to Template for " + host + "*****\n")
           config_change = conf_diff.ConfDiff(host + "-template.log", log_file) #write differences to log file
           cc = config_change.diff()
           cc = cc.replace('[31m', '') #Clean up color codes from console output
           cc = cc.replace('[39m[32m', '')
           cc = cc.replace('[32m', '')
           cc = cc.replace('[39m', '')
           cc = cc.replace('[33m', '')
           changelog.write(cc)
           print(config_change.diff()) #print differences to console

   pass


#MAIN FUNCTION, ONE FUNCTION TO RULE THEM ALL!

if __name__ == "__main__":
   #get_creds()#Get credentials for Login and access to your script to run
   get_backups()# Back it up before you start.
compare_conf()#compare to template config

The script does a simple “show run” command to grab the entire configuration and writes it to a file. The conf-diff library is then used to compare the new configuration to the baseline. The script outputs both a console output and a file with all changes. A sample output can be found below.


NOTE: Lines with “+” indicate a line was added to the configuration compared to the template. While lines with “-“ indicate the line was removed in the new configuration. Lines with “!” are spaced in the configuration to allow for easy reading.

--- 192.168.1.23-template.log
+++ 192.168.1.23-04-23-2023-17-20-33.log
@@ -64,8 +64,12 @@
+!\
+router ospf 1\
+ network 10.0.0.0 255.0.0.0 area 0\
+ log-adj-changes\
 !\
 route inside 0.0.0.0 0.0.0.0 192.168.1.1 1\
 timeout xlate 3:00:00\
 timeout pat-xlate 0:00:30\
@@ -216,7 +229,7 @@
   destination transport-method http\
 !\
rest-api image disk0:asa-restapi-132346-lfbff-k8.SPA\
 rest-api agent \
-Cryptochecksum:31425622ce3408b172a7f08cf600ab5e\
+Cryptochecksum:6ff5cc24fbc3c67a3ba11baa507ffb7f\
 : end\
\"]}"

Script/Solution Overview

The prototype script can be added to any job scheduler or automation engine (Jenkins), with some production-ready refinements to run on a schedule. This is merely a prototype you can use to get up and running with security automation. Critical Design Associates is happy to assist with building production-ready automation tools.


If you plan on using this script, you'll want to make sure you have the following:

  • Install Python

  • Install and creat a Python Virtual Environment

  • Clone the repository

  • Set up your hosts.txt file with your list of Cisco ASA devices (inventory). This file is required to support managing multiple devices.

  • Test functions IN A TESTING ENVIRONMENT. Don’t be that guy/girl!

Script Download/Source

Disclaimer: While this may go without saying, “Do NOT test this in your production environment.


You can access this script and supporting files on GitHub. Simply “git clone” the repository and run it against your test environment.

Let us help you unlock the power of automation! If you are looking to develop a robust automation tool for your production environment, contact CDA! You'll receive expert assistance in building a cutting-edge solution tailored to your specific needs. Contact us today.


bottom of page