How To
Summary
This tutorial will outline how you can use the QPyLib Encdec module to securely store your app's data.
Environment
Steps
This tutorial also requires an IBM X-Force Exchange API key and password, which can be made by following these steps:
- Go to IBM X-Force Exchange.
- Log in, or make an account if you don't have one.
- Go to your settings page.
- Generate a new API key and password and copy them, don't lose this as you can't get it again after this point.
Create the App
Create a new directory for the app:
mkdir VulnerabilitiesApp && cd VulnerabilitiesApp
Use the QRadar App SDK to initialise the app code:
qapp create
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": "Recent X-Force Vulnerabilities",
"description": "App showing recent X-Force Exchange vulnerabilities",
"version": "1.0.0",
"image": "qradar-app-base:2.0.0",
"areas": [
{
"id": "QRecentVulnerabilities",
"text": "Recent Vulnerabilities",
"description": "Area showing 10 most recent X-Force Exchange Vulnerabilities",
"url": "index",
"required_capabilities": []
}
],
"uuid": "<your unique app UUID>"
}
This manifest defines an area called QRecentVulnerabilities
that will serve the app user interface.
Write the App Jinja Template
Delete app/templates/hello.html
and create a new file app/templates/index.html
:
<!DOCTYPE html>
<html>
<head>
<title>Recent IBM X-Force Exchange Vulnerabilities</title>
<script type="text/javascript" src='./static/qjslib/qappfw.min.js'></script>
</head>
<body>
<h1>Recent IBM X-Force Exchange Vulnerabilities</h1>
{% if xforce_auth_set %}
<ul>
{% for vulnerability in vulnerabilities %}
<li>
{{vulnerability.type}} - {{vulnerability.title}}
</li>
{% endfor %}
</ul>
{% else %}
<p>Error decrypting API key: {{ decryption_error }}</p>
<h2>No API key, submit one to fetch recent vulnerabilities</h2>
<input id="api-key-input" type="text" placeholder="IBM X-Force Exchange API Key"/>
<input id="api-pass-input" type="text" placeholder="IBM X-Force Exchange API Password"/>
<input id="api-key-submit" type="submit">
<script>
// Using QJSLib library to make HTTP request
var QRadar = window.qappfw.QRadar;
document.getElementById("api-key-submit").addEventListener("click", function() {
// Get input values
var apiKey = document.getElementById("api-key-input").value;
var apiPass = document.getElementById("api-pass-input").value;
// POST xforce API details to set-api-key endpoint
QRadar.fetch("set-api-key", {
method: "post",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
key: apiKey,
pass: apiPass
})
})
.then(function(response) {
if (response.ok) {
// Success setting api auth details, refresh
window.location.reload(true);
return;
}
})
.catch(function(error) {
// Error, display error to user
alert(error)
});
});
</script>
{% endif %}
</body>
</html>
This Jinja template provides the entire user interface for the app, with two key pieces of functionality. The template handles displaying a list of vulnerabilities if they are provided to the template, and the X-Force API auth is set. If there is no X-Force API auth set it will instead provide a simple form to allow the user to submit an X-Force API key and password.
The submission of the X-Force API auth uses the QJSLib library to make an HTTP POST request to the set-api-key
endpoint, populating the body with the API auth details input to the textboxes.
Create the App Endpoints
Add the app HTTP endpoints by editing app/views.py
:
import json
import requests
from flask import Blueprint, render_template, request
from qpylib.encdec import Encryption, EncryptionError
# pylint: disable=invalid-name
viewsbp = Blueprint('viewsbp', __name__, url_prefix='/')
# Endpoint that decrypts the xforce api key and password, then uses it to get
# the 10 most recent X-Force Exchange vulnerabilities. If xforce details are
# retrieved successfully it will show the 10 vulnerabilities, if there is an
# error decrypting/reading the xforce secrets it will show an interface for the
# user to provide these details
@viewsbp.route('/')
@viewsbp.route('/index')
def index():
try:
# Decrypt the X-Force API Key
encKey = Encryption({'name': 'xforce_key', 'user': 'shared'})
key = encKey.decrypt()
# Decrypt the X-Force Password
encPass = Encryption({'name': 'xforce_pass', 'user': 'shared'})
passwd = encPass.decrypt()
# Get the 10 most recent X-Force Exchange vulnerabilities
response = requests.get("https://api.xforce.ibmcloud.com/vulnerabilities/?limit=10", auth=(key, passwd))
vulnerabilities = response.json()
return render_template('index.html', xforce_auth_set=True, vulnerabilities=vulnerabilities)
except EncryptionError as err:
# An error occured, ask the user to input the API details again
return render_template('index.html', xforce_auth_set=False, decryption_error=str(err))
# Endpoint that takes xforce api auth details, and encrypts and stores them
# using the QPyLib encdec module, if successful returns a 204 no content
# response
@viewsbp.route('/set-api-key', methods=['POST'])
def set_api_key():
# Load provided API details from JSON
xforce_data = json.loads(request.data)
# Encrypt the API Key
encKey = Encryption({'name': 'xforce_key', 'user': 'shared'})
encKey.encrypt(xforce_data["key"])
# Encrypt the API Password
encPass = Encryption({'name': 'xforce_pass', 'user': 'shared'})
encPass.encrypt(xforce_data["pass"])
# Success, return a 204 no content
return ('', 204)
This sets up the app's two HTTP endpoints, one to serve the templated user interface, injected with the 10 most recent vulnerabilities
Test the App Locally
The app is now ready to test out, which can be done by running the app locally using the QRadar App SDK.
There is one extra step before you can run this app, you must add a line to the qenv.ini
file to inject the required QRADAR_APP_UUID
environment variable into the app. This is required for the QPyLib Encdec module to work when running a QRadar app locally, it is not required when deployed on a QRadar instance. The qenv.ini
file should look like this:
[qradar]
QRADAR_CONSOLE_FQDN=
QRADAR_CONSOLE_IP=
[proxy]
QRADAR_REST_PROXY=
[app]
SEC_ADMIN_TOKEN=
QRADAR_APP_UUID=<your unique app UUID>
Once this has been added, you can run your app with the QRadar App SDK:
qapp run
The QRadar App SDK will report the port that the app is running on, allowing you to access the app at http://localhost:<app port>
.
QPyLib Encdec
To find out more about the QPyLib Encdec module, see the Secure Data Storage and Encryption page.
Document Location
Worldwide
Was this topic helpful?
Document Information
Modified date:
30 March 2021
UID
ibm16437431