Using Named Services
A named service is a feature that allows other apps and parts of the QRadar UI to interact with an app. These named services can fit a variety of use cases.
Using this tutorial, create four different apps, each using a different configuration of named services:
- A named service with just a command as a background process.
- A named service with just a port exposing Flask as a named service.
- A named service with a command and a port replacing Flask.
- A named service with a command, a port, and endpoints; running in parallel to Flask.
Prerequisites
Each of the four apps require QRadar app SDK version 2
Named service with a command as a background process
This app serves a Flask app over port 5000, but uses a named service as a background process to repeatedly update a file that is 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 initialize the app code:
qapp create
Write the Background Process app manifest
Edit the manifest.json
file to make it more relevant to the app:
{
"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 the following key properties:
- A named service called
NamedServiceBackgroundCommand
that runs a script (/opt/app-root/app/background.sh
) 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 reads the output of the named service defined above and returns 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 a script called app/background.sh
to be the background named service. This is a simple bash script that repeatedly updates the /opt/app-root/store/background_output
file with a message and timestamp.
#!/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 the app/views.py
script:
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 reads the /opt/app-root/store/background_output
file generated by the named service script and returns it.
Background Process conclusion
The completed QRadar app runs 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
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 case, 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
Edit the manifest.json
file to to make it more relevant to the app:
{
"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 the following key properties:
- A named service
NamedServicePort
that exposes Flask, running on default port5000
, which allows it to be queried from different parts of QRadar.
"services": [
{
"port": 5000,
"name": "NamedServicePort",
"path": "/",
"version": "1"
}
],
- A configuration page that displays the
/index
value queried from theNamedServicePort
named service on the QRadar Admin tab.
"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 the app/views.py
script:
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
The completed QRadar app exposes Flask as a named service and uses a configuration page (which is visible on the QRadar Admin tab) to query the named service.
Named service with a command and a port replacing Flask
This app replaces Flask with a named service running on the default port (5000
) that instead uses 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 initialize the app code:
qapp create
Write the Replacing Flask app manifest
Edit the manifest.json
file to make it more relevant to the app:
{
"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 the following 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/opt/app-root/app/named_service
directory 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 called
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 a directory to hold the content to serve from the named service from the top-level directory of your app workspace:
mkdir -p app/named_service
Create the app/named_service/index.html
file to be served by the named service and requested by the area defined in the manifest:
<!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>
Create a debug
file that responds to QRadar App Framework healthchecks. This is a requirement of QRadar apps. It 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/debug. This can be any minimal content. The only requirements are that it must return 200 OK
when queried and return a small amount of data.
Example:
File to return 200 to the /debug endpoint
Replacing Flask conclusion
The completed QRadar app uses the built-in Python HTTP server running as a named service to present an HTML webpage as a QRadar area.
Named service with a command, a port, and endpoints running in parallel to Flask
This app runs Flask and a named service in Parallel. The named service runs using the Python built-in HTTP server. The app serves 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
Edit the manifest.json
file to make it more relevant to the app:
{
"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 a directory to contain 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 app/named_service/index.html
file to be served by the named service and requested by the configuration page defined in the manifest:
<!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
The completed QRadar app uses both Flask and the built-in Python HTTP server to return content for both an area and a configuration page.