Connecting Components - The socket way @ MajAK | Monday, Jun 21, 2021 | 5 minutes read | Update at Monday, Jun 21, 2021

How I created GUI notification service for OWASP SecureTea using sockets, but with a twist!

The Context - Problem at Hand

I spent my time contributing to SecureTea in the summer of 2020. SecureTea is an open source project under OWASP which provides a one-stop security solution for various devices (personal computers / servers / IoT devices). It contains three major components : A Realtime App hosted in Angular (GUI), a Python app (SecureTea-Core) and a Flask App (ServerApp). As one can guess, SecureTea-Core is the heart of the solution. It contains various modules implemented for security as well as to get notified about pertaining issues. It could be triggered to run from the GUI App as well as CLI. The ServerApp was set up to provide Realtime data corresponding to health metrics and usage of the device being monitored. Now, my task was to introduce a system so that there was some kind of Authentication in the GUI and send notifications/updates of the SecureTea-Core to the GUI. The idea was that the GUI component could be hosted at an enterprise level and various users could connect their local devices/cloud devices to it by hosting the ServerApp (locally/per cluster) and installing securetea library on them. The Authentication part was easy to address. We are going to discuss how I built a simple communication service to achieve Real Time Notifications.

Initial Approach - A Naive one

My initial thought process was to open up a socket connection from SecureTea-Core to GUI and notifications could directly be sent via the socket. This would solve the task of notifications being realtime and provide some level of security. But it had a few shortcomings:

Scalability

When it comes to scalability, the system will not be able to autoscale, unless the new version is installed on the target system every time scalability/ load balancing might be needed. Also considering the use case scenario where a lot of notifications need to be sent to GUI, it consumes a lot of compute power(might slow down/ crash other jobs running on device) as well as blocks the execution of other features.

Failure

On failure occurring in the Socket part of the system, the system would crash which would affect the overall system security, since the securetea also prevents attacks to some scale!

Retry pattern

Retry pattern if required cannot be implemented at this level, since it would further block the functioning of other features for the time being.

Excessive socket connections

Considering a system with a large number of devices, the number of socket connections would be large. With a limited number of socket connections GUI can open(due to fixed number of ports), it would inevitably result in a queue system for socket connections. Hence I settled to try and implement it at the level of ServerApp. The pros are discussed below.

Actual approach - Using ServerApp

The approach is based on the idea of setting up a communication between the SecureTea-Core and ServerApp, which would further pass on the information to GUI. The way it was implemented is that an API was set up to send notification requests to GUI. On receiving anything in log, SecureTea-Core would call the API, which in place would send notification to GUI via socket. These notifications would be shown as toasts in GUI. Although we still require sockets for it to be Realtime. An important aspect to note is that there will be a delay introduced because of API call, but with a fair assumption of everything hosted on the same network, it can be considered negligible. Let us look into how it solves previous shortcomings :

Excessive socket connections

Since the ServerApp might be hosted at a cluster level, it decreases the number of socket connections GUI needs to handle. It might still need an implementation of queue system for socket connection on a very large amount of clusters, but the bound on #devices per GUI instance increases by a large factor.

Scalability

Also since the number of ServerApp resources/copies can be easily scaled horizontally and configured, blocking security features is not an issue anymore. A separate monitoring service could be set up for the ServerApp (like a heartbeat), which would be easy to implement to make sure the ServerApp is healthy.

Failure & Retry Pattern

SecureTea-Core being blocked on failure will no longer be an issue and a retry pattern could be easily implemented if required. Also a proxy of some kind is automatically setup here between SecureTea-Core and ServerApp, making the architecture a bit more secure.

An overview of Code :

You can find some important excerpts from the code here. Refer to this commit to get an idea in detail. Here is an overview of the important components :

ServerApp

app.py

from flask_cors import CORS
from flask_sqlalchemy import SQLAlchemy
from functools import wraps
from flask_socketio import SocketIO, emit

app = Flask(__name__)
CORS(app)
app.config.from_object('config')
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
db = SQLAlchemy(app)
cors = CORS(app,resources={r"*":{"origins":"*"}})
async_mode = None
socketio = SocketIO(app, async_mode=async_mode, cors_allowed_origins="*")

@app.route('/notifs',methods=['GET'])
def notifs():
    if request.remote_addr==DEVICE_ADDR:
        socketio.emit('newmessage', {'message': request.args.get("msg")})
    return 'Notif sent'

run.py

from app import app
app.run()
from app import socketio, app
socketio.run(app)

SecureTea-Core

import requests as req
import time

def printinfo(self, message):
    "Print info.
    Args:
        message (str): Message to log as info
    "
    print(self.LEGEND + self.OKGREEN + message + self.ENDC)
    param={"msg" : "S"+message}
    resp = req.get(SERVER_ADDR+"/notifs",params=param)

def printerror(self, message):
    "Print error.
    Args:
        message (str): Message to log as error
    "
    print(self.LEGEND + self.ERROR + message + self.ENDC)
    param={"msg" : "E"+message}
    resp = req.get(SERVER_ADDR+"/notifs",params=param)
...

GUI App

import * as toastr from 'toastr';
import * as io from 'socket.io-client';

socket: any;
toastr.options ={
      "progressBar": true
    }
    this.socket = io(this.apiRoot);
    this.socket.on('newmessage', (msg) => {
      if(msg.message.charAt(0) === "W")
      {
        toastr.warning(msg.message.substring(1));
      }
      else if(msg.message.charAt(0) === "S")
      {
        toastr.success(msg.message.substring(1));
      }
      else
      {
        toastr.error(msg.message.substring(1));
      }
    });

Give it a thought

  • Does introducing socket make the Angular app one with Backend?
  • What are Node Apps : Frontend, Backend or Something else? Spoiler Alert!
  • Have a look at toastr import and implementation. It is a gem(hyperbole) to find with documentation like theirs!
  • Are sockets optimal or can we do better? (Message queues)

© 2021 MajAK

avatar

The Personal SideThis side is more personal including anything from life aspirations, career or simply life updates!
Use to see more about my tech side!


Feel free to reach out to me or DM me wherever you want!
Who is Kushal?

Kushal is a tech enthusiast, who is a graduate from International Institute of Information technology, Hyderabad! He hails from this small town of Vadodara. He thinks he is good at Mathemetics but is really bad. Apart from nerdy stuff, he loves basketball (is a big Kyrie fan), carelessly likes to spend his money on shoes and has developed a taste for watching competitive CSGO (NiP fan in the house). He gets as childish as one can get when it comes to NERF and the randomest toys ever, but is mature when it comes to life Ig :)

P.S. He likes using PostScripts everywhere!

What the hell is MajAK?

MajAK is something that Kushal has given to himself. His Name is actually Kushal A Majmundar, hence dumbly enough MajAK. MajAK in his mother tounge Gujarati means Kidding in some sorts, but it is hard to understand Kushal’s sense of humour. It is Broken. But now since MajAK is stuck to his brain, he tends to carry it everywhere, from acads, to corp, to accounts and in gaming too! Kushal gets funny only if your sense of humour is broken too :|

P.S. He loves emoticons!

What does Kushal do for a living?

Kushal does a 9-5 job like any other Software Engineer. He works for a so called “tech giant”. But he keeps on working on a lot of new stuff over the weekends, be it open source or research or randomest apps ever! He can get quite lazy too, doesn’t miss out on good food on weekends, but def. tries to explore as much as the field has to offer.

P.S. He is always open to collabarations if it seems interesting to him!