Supporting Multi-Tenancy
You can designate that an app supports running in a multi-tenanted environment, with a designated app instance per tenant.
You can designate an app as “multitenancy safe,” meaning the app has been tested and is ready to be used in a multi-tenanted environment.
This app simply reports the instance ID of the app instance that is serving the app content, allowing you to verify that the app is serving from a different app instance for each tenant.
Prerequisites
This tutorial requires the following dependencies:
- QRadar app SDK version 2
- An IBM QRadar configuration set up with multiple tenants
Create the app
Create a new folder for the app:
mkdir MultitenancyMultipleInstance && cd MultitenancyMultipleInstance
Use the QRadar App SDK to initialize the app code:
qapp create
Write the manifest
Edit the manifest.json
file to to make it more relevant to the app:
{
"name": "Multitenancy Multiple Instance",
"description": "App showing multitenancy capabilities, with each tenant having a dedicated app instance",
"version": "1.0",
"image": "qradar-app-base:2.0.0",
"areas": [
{
"id": "QMultitenancyMultipleInstance",
"text": "Multitenancy Multiple Instance",
"description": "Area reporting the app instance ID",
"url": "index",
"required_capabilities": []
}
],
"uuid": "<your unique app UUID>",
"multitenancy_safe": "true"
}
This manifest defines an area called QMultitenancyMultipleInstance
that will serve the app user interface.
The "multitenancy_safe": "true"
flag in the manifest.json
file designates this app as tested and ready for use in a multi-tenanted environment. This allows a QRadar administrator to provision a dedicated app instance per tenant.
Write the Jinja template
Delete app/templates/hello.html
and create a new file called app/templates/index.html
using the following code:
<!DOCTYPE html>
<html>
<head>
<title>Multitenancy Sample</title>
</head>
<body>
<h1 id="title">Multitenancy app</h1>
<label id="label">This instance's ID is:</label>
<span id="app_id"></span>
</body>
</html>
This sets up the Jinja template, which will display the app instance ID that allows verification that each tenant has their own app instance.
Create the app endpoint
Add the app HTTP endpoints by editing app/views.py
:
from flask import Blueprint, render_template
from qpylib import qpylib
# pylint: disable=invalid-name
viewsbp = Blueprint('viewsbp', __name__, url_prefix='/')
# Simple endpoint that grabs the instance's app ID and surfaces it by injecting
# it into HTML and returning it
@viewsbp.route('/index')
def index():
app_id = qpylib.get_app_id()
return render_template('index.html', app_id=app_id)
This sets up the app endpoint to retrieve the app instance ID and then injects the app instance ID into the Jinja template. The endpoint name must match the name of the endpoint listed in the manifest.
Package and deploy the app
Use the following commands to package and deploy the app:
qapp package -p <app zip name>
qapp deploy -p <app zip name> -q <qradar console> -q <qradar user>
Creating an app instance for each tenant
Once the app is deployed onto a QRadar system, you can provision an app instance for specific tenants, either using the QRadar Assistant or through the QRadar API.
To provision an app instance through the QRadar API, get the ID of the security profile associated with the tenant and the deployed app’s definition ID. With these two values, you can use an API call to create a new instance of the app for a tenant:
curl
-X POST \
-u <qradar user>:<qradar password> \
-H 'Version: 16.0' \
-H 'Accept: application/json' \
'https://<qradar console>/api/gui_app_framework/applications?application_definition_id=<app definition id>&security_profile_id=<security profile id>'