How To
Summary
This tutorial will outline how to create four different apps, each using named services. The four apps will each utilise a different configuration of named service.
Steps
Prerequisites
Each of the four apps will require the following:
- QRadar App SDK v2
Named Service with a Command as a Background Process
This app will serve a normal Flask app over port 5000, but use a named service as a background process to repeatedly update a file that is being served with a timestamp.
Create the Background Process App
Create a new folder for the app:
mkdir NamedServiceCommand && cd NamedServiceCommand
Use the QRadar App SDK to initialise the app code:
qapp create
Write the Background Process App Manifest
Open the manifest.json
file to edit some values to make it more relevant to the app, making it look like this:
{
"name": "NamedServiceCommand",
"description": "An app serving a data that is generated by a named service running in the background",
"version": "1.0",
"image": "qradar-app-base:2.0.0",
"areas": [
{
"id": "FlaskArea",
"text": "Area Served from Flask",
"description": "Area Serving File Generated by Named Service from Flask",
"url": "index",
"required_capabilities": []
}
],
"services": [
{
"command": "/bin/bash /opt/app-root/app/background.sh",
"directory": "/",
"name": "NamedServiceBackgroundCommand",
"path": "/",
"version": "1"
}
],
"uuid": "<your unique app UUID>"
}
This manifest defines some key properties:
- A background named service called
NamedServiceBackgroundCommand
that runs a script/opt/app-root/app/background.sh
; this script will run in the background.
"services": [
{
"command": "/bin/bash /opt/app-root/app/background.sh",
"directory": "/",
"name": "NamedServiceBackgroundCommand",
"path": "/",
"version": "1"
}
],
- An area in the QRadar UI that serves a normal Flask endpoint; this Flask endpoint will read the output of the named service defined above and return it.
"areas": [
{
"id": "FlaskArea",
"text": "Area Served from Flask",
"description": "Area Serving File Generated by Named Service from Flask",
"url": "index",
"required_capabilities": []
}
],
Add Named Service Background Process Script
Create the script which will be the background named service, this is a simple bash script that will repeatedly update the /opt/app-root/store/background_output
file with a message and timestamp; create the file app/background.sh
.
#!/bin/bash
while true
do
echo "Background named service last updated: $(date)" > /opt/app-root/store/background_output
sleep 5
done
Update Flask Background Process Endpoints
Update the app HTTP endpoints by editing app/views.py
:
from flask import Blueprint
# pylint: disable=invalid-name
viewsbp = Blueprint('viewsbp', __name__, url_prefix='/')
# A simple endpoint that returns the 'background_output' file that is managed by the background named service
@viewsbp.route('/')
def background_output_read():
with open('/opt/app-root/store/background_output', 'r') as file:
background_content = file.read()
return background_content
This sets up a simple endpoint under the path /
that will read the /opt/app-root/store/background_output
file generated by the named service script defined above and returns it.
Background Process Conclusion
Following these steps results in a full QRadar app that has two parallel processes, Flask to serve HTTP endpoints, and a background script running that repeatedly updates a file that the endpoints serve.
Named Service with a Port Exposing Flask as a Named Service
This app will use a named service with a port to expose Flask, allowing the app's Flask endpoints to be called from different parts of QRadar; in this instance as a configuration page.
Create the Exposing Flask App
Create a new folder for the app:
mkdir NamedServicePort && cd NamedServicePort
Use the QRadar App SDK to initialise the app code:
qapp create
Write the Exposing Flask App Manifest
Open the manifest.json
file to edit some values to make it more relevant to the app, making it look like this:
{
"name": "NamedServicePort",
"description": "An app that uses a named service to expose Flask as a named service",
"version": "1.0",
"image": "qradar-app-base:2.0.0",
"configuration_pages": [
{
"text": "Flask Exposed through Named Service Config Page",
"description": "Configuration page exposing Flask as a named service",
"url": "/index",
"named_service": "NamedServicePort",
"required_capabilities":[]
}
],
"services": [
{
"port": 5000,
"name": "NamedServicePort",
"path": "/",
"version": "1"
}
],
"uuid": "<your unique app UUID>"
}
This manifest defines some key properties:
- A named service
NamedServicePort
exposes Flask, running on default port5000
, as a named service - allowing it to be queried from different parts of QRadar.
"services": [
{
"port": 5000,
"name": "NamedServicePort",
"path": "/",
"version": "1"
}
],
- A configuration page, which will show up on the 'Admin' section of QRadar, displaying the
/index
value queried from theNamedServicePort
named service.
"configuration_pages": [
{
"text": "Flask Exposed through Named Service Config Page",
"description": "Configuration page exposing Flask as a named service",
"url": "/index",
"named_service": "NamedServicePort",
"required_capabilities":[]
}
],
Update Exposing Flask App Flask Endpoints
Update the app HTTP endpoints by editing app/views.py
:
from flask import Blueprint
# pylint: disable=invalid-name
viewsbp = Blueprint('viewsbp', __name__, url_prefix='/')
# A simple endpoint that returns a string, to be called from a configuration page using a named service
@viewsbp.route('/index')
def index():
return "This is returned from Flask running through a named service"
This sets up a simple Flask HTTP endpoint that returns a string when /index
is queried.
Exposing Flask Conclusion
Following these steps results in a full QRadar app that exposes Flask as a named service, and uses a configuration page (which is visible on the 'Admin' section of the QRadar UI) to query the named service.
Named Service with a Command and a Port Replacing Flask
This app will replace Flask with a named service running on the default port (5000
), this named service will instead use the built in Python HTTP server.
Create the Replacing Flask App
Create a new folder for the app:
mkdir NamedServiceCommandAndPort && cd NamedServiceCommandAndPort
Use the QRadar App SDK to initialise the app code:
qapp create
Write the Replacing Flask App Manifest
Open the manifest.json
file to edit some values to make it more relevant to the app, making it look like this:
{
"name": "NamedServiceCommandAndPort",
"description": "An app serving using a named service running with a command and port",
"version": "1.0",
"image": "qradar-app-base:2.0.0",
"load_flask": "false",
"areas": [
{
"id": "NamedServiceCommandAndPortArea",
"text": "Area Served from Named Service",
"description": "Area Served from Named Service with Command and Port",
"named_service": "NamedServiceCommandAndPort",
"url": "index.html",
"required_capabilities": []
}
],
"services": [
{
"command": "python3 -m http.server 5000",
"directory": "/opt/app-root/app/named_service",
"name": "NamedServiceCommandAndPort",
"path": "/",
"version": "1",
"port": 5000
}
],
"uuid": "<your unique app UUID>"
}
This manifest defines some key properties:
- The app does not load Flask, instead it uses a named service running on the default port
5000
.
"load_flask": "false",
- A named service called
NamedServiceWithCommand
using the built in Python HTTP server to serve files out of the directory/opt/app-root/app/named_service
over port5000
.
"services": [
{
"command": "python3 -m http.server 5000",
"directory": "/opt/app-root/app/named_service",
"name": "NamedServiceWithCommand",
"path": "/",
"version": "1",
"port": 5000
}
],
- An area in the QRadar UI that queries this named service for a file
index.html
.
"areas": [
{
"id": "NamedServiceCommandAndPort",
"text": "Area Served from Named Service",
"description": "Area Served from Named Service with Command and Port",
"url": "index.html",
"required_capabilities": []
}
],
Add Content to Serve to the Replacing Flask
Create the directory for holding the content to serve from the named service from the top-level directory of your app workspace:
mkdir -p app/named_service
Now create the index.html
file that will be served by the named service and requested by the area defined in the manifest; create the file app/named_service/index.html
:
<!DOCTYPE html>
<html>
<head>
<title>Hello from Named Service With Command and Port</title>
</head>
<body>
<h1>This page is being served from a named service</h1>
</body>
</html>
Now create a debug
file that will respond to QRadar App Framework healthchecks - this is a requirement of QRadar apps, this is the only way QRadar can determine if an app is up and running; a 200 OK
response to the /debug
path on the default port (5000
). Create the file app/named_service/debug
, this can be any minimal content - the only requirements are it must return 200 OK
when queried and should be a small amount of data returned; for example:
File to return 200 to the /debug endpoint
Replacing Flask Conclusion
Following these steps results in a full QRadar app that uses the built in Python HTTP server running as a named service that presents an HTML webpage as a QRadar area.
Named Service with a Command, a Port, and Endpoints; Running in Parallel to Flask
This app will run Flask and a named service in Parallel. The named service will run using the Python built in HTTP server. The app will serve an area from Flask, and a configuration page from the named service.
Create the Parallel Flask Process App
Create a new folder for the app:
mkdir NamedServiceCommandPortEndpoints && cd NamedServiceCommandPortEndpoints
Use the QRadar App SDK to initialise the app code:
qapp create
Write the Parallel Flask Process App Manifest
Open the manifest.json
file to edit some values to make it more relevant to the app, making it look like this:
{
"name": "NamedServiceCommandPortEndpoints",
"description": "An app that uses Flask and a Python webserver as a named service running in parallel",
"version": "1.0",
"image": "qradar-app-base:2.0.0",
"areas": [
{
"id": "FlaskIndex",
"text": "Area Served from Flask",
"description": "Area Served from Flask",
"url": "index",
"required_capabilities": []
}
],
"configuration_pages": [
{
"text": "Configuration Page Served through Named Service",
"description": "Configuration page served through named service",
"url": "/index.html",
"named_service": "NamedServiceCommandPortEndpoints",
"required_capabilities":[]
}
],
"services": [
{
"command": "python3 -m http.server 5001",
"directory": "/opt/app-root/app/named_service",
"name": "NamedServiceCommandPortEndpoints",
"path": "/",
"version": "1",
"port": 5001,
"endpoints": [
{
"name":"config_index",
"path":"index.html",
"http_method": "GET",
"parameters": []
}
]
}
],
"uuid": "<your unique app UUID>"
}
Add Content to Serve to the Parallel Flask Process App
Create the directory for holding the content to serve from the named service from the top-level directory of your app workspace
mkdir -p app/named_service
Now create the index.html
file that will be served by the named service and requested by the configuration page defined in the manifest; create the file app/named_service/index.html
:
<!DOCTYPE html>
<html>
<head>
<title>Hello from Named Service With Command, Port, and Endpoints</title>
</head>
<body>
<h1>This page is being served from a named service</h1>
</body>
</html>
Parallel Flask Process Conclusion
Following these steps results in a full QRadar app that uses both Flask and the built in Python HTTP server to return content for both an area and a configuration page.
Document Location
Worldwide
Was this topic helpful?
Document Information
Modified date:
30 March 2021
UID
ibm16437485