Avatar

Transforming networking infrastructure into Intent-Based Networking

Cisco was recently chosen by one of the two largest banks in Israel to be the networking solution for the bank’s next generation network. The project includes replacing the entire access network (across dozens of campus location and 240 remote branches) with Cisco SD-Access using Catalyst 9000 switches, replacing the existing NAC solution with Cisco ISE and the entire Data-center network with Cisco ACI using Nexus 9000 switches.

I was immersed in a 2-year thorough technical evaluation process led by the bank’s architects resulting in this amazing project, transforming the networking infrastructure into Intent-Based Networking solutions.

The timing is surprisingly aligned with Cisco’s 2020 global networking trends report.

During the thorough POC we conducted in the bank’s lab environment, one of the bank’s security specialists wanted to make sure all audit logs of Cisco DNA Center were sent to their SIEM via syslog in a certain format. A legitimate request. But at that time Cisco DNA Center did not support audit log or network event export via syslog. As a modern platform, Cisco DNA Center supported webhook notifications, which the legacy SIEM did not support.

We don’t have to compromise

In the past, if we were not able to support a customer request, we would try to get to the bottom of it and understand the actual need, which may be addressed in a different manner. However, that was the past. These days if we want tailored functionality that is not provided out of the box – we don’t have to compromise. We can build it!

Summarizing customer’s requirements

  1. Send Cisco DNA Center’s audit log notifications via syslog to the SIEM system.
  2. Send selected Cisco DNA Assurance network events via syslog.

The path to success

We had two slightly different requirements. Network events generated by Cisco DNA Assurance engine are being pushed via Webhook to a webhook receiver whereas (at the time) the audit log was not pushed and had to be fetched. I’ll focus on the DNA Assurance part.

Webhook AKA “push API” AKA “reverse API” is a method used for real time notification. Instead of polling a device frequently, we can subscribe to a Webhook and ask for the device to push the information when it’s available/relevant. In order to receive the Webhook notification, our server must listen to HTTPS in a predefined port.

Robert Csapo has generously offered to help and together we created a three layer program: HTTPS listener, Parsers and Transmission.

Skipping to the end…. Customer demonstration

Before diving into the code itself, I’d like to share the end result – we met with the banks’ architects, explained the program we’ve created and demonstrated how their SIEM is able to receive the events coming from Cisco DNA Center. Phew… live demonstrations are always stressful, and I always pray to the demo gods not to have any unexpected surprises.

The formatting of the messages was not exactly aligned with the formatting they asked for, resulting in missing data on the SIEM. However, explaining the code the architects saw how easy it will be to get the formatting fixed – and gave us the approval we needed to proceed.

Conclusion

As I wrote in the beginning, the bank chose Cisco’s solution and we are now in the process of implementing the project. I would like to believe that without the specific capability we would have won the project. But undoubtedly, addressing the bank’s request face on, and demonstrating the flexibility and openness of our solutions, made the choice easier for them to make.

Back to the code itself

HTTPS listener
We used Flask, a lean Python framework, to create a HTTPS listener on port 5000.
The HTTPS listener had very basic functionality:
When receiving a GET request – return a string telling the requestor this is our listener.
When receiving a POST to the /dna/ URL – send the received data to processing (the second part of the program).

app = Flask(__name__)

@app.route('/', methods=['GET', 'POST'])
def mainPage():
    if request.method == 'GET':
        if args.verbose:
            print("returning: cisco-dnac-platform-syslog-notifications -> 
by Robert Csapo (robert@nigma.org) and Oren Brigg (Oren.Brigg@gmail.com)")
        return("cisco-dnac-platform-syslog-notifications -> by Robert Csapo 
(robert@nigma.org) and Oren Brigg (Oren.Brigg@gmail.com)")
    elif request.method == 'POST':
        return("cisco dna center healthcheck")

@app.route('/dnac', methods=['POST'])
def dnacPayload():
    data = request.json
    if not len(data) == 0:
        return(sendData (data, args))
    else:
        return("Connection Alive")

app.run(host="0.0.0.0", port=5000, threaded=True, debug=False, 
ssl_context='adhoc')

Parsers
Information received by the listener was already structured data in JSON format, we broke it down to different variables in order to allow future manipulations and verification of the data we’re processing.

def sendData (data, args):
    if args.verbose:
        print()
        print(data)
        print()
    issueTitle = (data["details"]["Type"] + " " +data["details"]["Device"])
    issuePriority = data["details"]["Assurance Issue Priority"]
    issueSeverity = data["severity"]
    issueSummary = data["details"]["Assurance Issue Details"]
    data = "Warning Severity %s (%s)! %s - %s" % (issueSeverity, 
issuePriority, issueTitle, issueSummary)
    dnac_logger.info(str(data))
    return("Cisco DNA Center JSON Payload received")

Transmission
Python has a built in logging capability we can leverage to send data over syslog. That’s why we’ve imported “logging.handlers”, created a logger and set the IP destination for the syslog messages.
Once the data was constructed by the parser section, we used the logger to send out the crafted message via syslog.

    dnac_logger = logging.getLogger('dnac_logger')
    dnac_logger.setLevel(logging.INFO)

    #Creating the logging handler, directing to the syslog server
    handler = logging.handlers.SysLogHandler(address = 
(args.syslog,args.port))
    dnac_logger.addHandler(handler)

Wrapping the code into a Docker container
At this point we had a working program running on our laptops. Which is a success on its own. However, where will an actual customer run this code? This tiny program requires minimal compute power, but it still needs to run somewhere. Dedicated server/VM is out of the question, waste of resources. Running it on an existing Linux server doing something else? Too risky in terms of dependencies and requires someone to remember our program is there.
That’s when we decided to containerize the code and enable it to run on any platform that can run Docker. It can easily run on a Catalyst 9000 or a Nexus 9000 switch.

Dockerfile
The Dockerfile is the instruction book for creating the Docker container that will run our program.
In this case we’re starting with a minimal Linux container with Python 3.7 installed called “3.7-slim-buster.” After updating the Linux packages, we use “git clone” to copy the code into the container and “pip install” to install the relevant packages.
Once the container is ready, running it will initiate the command “python run.py” which will run our code.

FROM python:3.7-slim-buster
RUN apt-get update && apt-get install -y git
RUN git clone -b 1.3.1 https://github.com/obrigg/cisco-dnac-platform-syslog-notifications.git
WORKDIR /cisco-dnac-platform-syslog-notifications/
RUN pip install -r requirements.txt
ENTRYPOINT ["python", "run.py"]

Related Resources