IBM Support

Replacing Flask with Gunicorn

How To


Summary

This tutorial will outline how to replace Flask with Gunicorn as an alternative HTTP server. The app will be a simple hello world app.

Steps

Prerequisites

  • QRadar App SDK v2
  • Python 3
  • pip

Create the App

Create a new folder for your app:

mkdir GunicornApp && cd GunicornApp

Use the QRadar App SDK to initialise the app code:

qapp create

Add the Gunicorn pip Dependency

Make a new folder for storing the Gunicorn pip dependencies that will be installed called container/pip.

mkdir container/pip

Download the Gunicorn pip and any of its dependencies using pip download:

pip download                \
    --only-binary=:all:     \
    --platform linux_x86_64 \
    --dest container/pip    \
    gunicorn

This should download the Gunicorn pip and any of its dependencies into the container/pip folder.

Add the Supervisord configuration

Create a new folder to hold our supervisord configuration files called container/conf/supervisord.d:

mkdir -p container/conf/supervisord.d

This container/conf/supervisord.d folder holds Supervisord configuration and all configuration in this folder is copied into /etc/supervisord.d on startup.

Create your app's Gunicorn configuration file container/conf/supervisord.d/gunicorn.conf:

[program:gunicorn]
directory=/opt/app-root
command=/usr/local/bin/gunicorn -b 0.0.0.0:5000 --timeout 120 --access-logfile - --workers=4 --preload "app:create_app()"
autostart=true
autorestart=unexpected
stdout_logfile=/opt/app-root/store/log/gunicorn.log
stderr_logfile=/opt/app-root/store/log/gunicorn.log

This configuration file defines how Supervisord should run Gunicorn as part of this app, with log files defined, automatic restarts and the command to start Gunicorn (with all of its command line parameters) stated.

Write the Manifest

Open the manifest.json file to edit some values to make it more relevant to the app, making it look like this:

{
  "name": "Gunicorn App",
  "description": "Custom supervisord configuration which starts gunicorn as a replacement for flask and exposes port 5000 as the webserver port",
  "version": "1.0.0",
  "image": "qradar-app-base:2.0.0",
  "load_flask": "false",
  "areas": [
    {
      "id": "GunicornSupervisordTab",
      "text": "Gunicorn supervisord",
      "description": "Dummy tab that displays text from the flask app",
      "url": "index",
      "required_capabilities": []
    }
  ],
  "services": [
    {
      "name": "gunicorn",
      "port": 5000,
      "version": "1.0"
    }
  ],
  "uuid": "<your unique app UUID>"
}

This manifest defines a lot, first the Flask webserver is overridden and QRadar is informed it should not be loaded with:

"load_flask": "false",

The manifest then defines an 'area' in the QRadar UI to display the app, called GunicornSupervisordTab that is populated by calling the /index endpoint:

"areas": [
  {
    "id": "GunicornSupervisordTab",
    "text": "Gunicorn supervisord",
    "description": "Dummy tab that displays text from the flask app",
    "url": "index",
    "required_capabilities": []
  }
],

Finally the manifest describes and defines a named service which will run the Supervisord program we have configured above called gunicorn alongside the port it should serve on, exposing the path /index:

"services": [
  {
    "name": "gunicorn",
    "port": 5000,
    "version": "1.0"
  }
],

Since this named service is running on port 5000 the area does not need to include a reference to the named service that it is querying - it can be accessed directly. This is only the case if the named service is running on port 5000.

Run the App/Package the App

The app can then be run locally from the project root with:


qapp run

Or packaged and deployed from the project root with:


qapp package -p <app zip name>

qapp deploy -p <app zip name> -q <qradar console> -u <qradar user>

Document Location

Worldwide

[{"Line of Business":{"code":"LOB24","label":"Security Software"},"Business Unit":{"code":"BU059","label":"IBM Software w\/o TPS"},"Product":{"code":"SSBQAC","label":"IBM Security QRadar SIEM"},"ARM Category":[{"code":"a8m0z000000cwt3AAA","label":"QRadar Apps"}],"ARM Case Number":"","Platform":[{"code":"PF025","label":"Platform Independent"}],"Version":"All Version(s)"}]

Document Information

Modified date:
30 March 2021

UID

ibm16437467