Installing NodeJS as a source dependency
You can install NodeJS as a source dependency for your app and replace the default Flask webserver with a NodeJS Express server.
Prerequisites
- QRadar App SDK v2
- Docker
- NodeJS and NPM installed
Create the app
Create a new folder for your app:
mkdir NodeJSApp && cd NodeJSApp
Use the QRadar App SDK to initialise the app code:
qapp create
Add the NodeJS and NPM RPMs
- Create a new folder for the NodeJS and NPM RPMs that will be installed called
container/rpm
.
mkdir container/rpm
- Download the latest NodeJS and NPM RPMs for RHEL UBI 8 using Docker:
docker run \
-v $(pwd)/container/rpm:/rpm \
registry.access.redhat.com/ubi8/ubi \
yum download nodejs-10.21.0 npm-6.14.4 --downloaddir=/rpm
This uses the RHEL UBI 8 OS running inside Docker to download the NodeJS and NPM RPMs, which can be used by QRadar to install them into the app.
- Create a new file called
container/rpm/ordering.txt
, which tells QRadar where to find the RPMs to install:
nodejs-10.21.0-3.module+el8.2.0+7071+d2377ea3.x86_64.rpm
npm-6.14.4-1.10.21.0.3.module+el8.2.0+7071+d2377ea3.x86_64.rpm
Make these file paths match the file names of the RPMs you downloaded.
Write the manifest
Edit the manifest.json
file to use the following values to make it more relevant to the app.
Example:
{
"name": "NodeJSApp",
"description": "App that uses NodeJS and an Express server",
"version": "1.0.0",
"image": "qradar-app-base:2.0.0",
"load_flask": "false",
"areas": [
{
"description": "Dummy tab that displays text from the node app",
"id": "NodeJSHelloWorld",
"named_service": "nodeservice",
"required_capabilities": [],
"text": "NodeHelloWorld",
"url": "/index"
}
],
"services": [
{
"command": "node /opt/app-root/app/server.js",
"directory": "/opt/app-root/app",
"endpoints": [
{
"name": "appindexpage",
"path": "/index",
"http_method": "GET"
}
],
"name": "nodeservice",
"path": "/index",
"port": 5000,
"version": "1",
"stdout_logfile": "/opt/app-root/store/log/node_out.log",
"stderr_logfile": "/opt/app-root/store/log/node_err.log"
}
],
"uuid": "<your unique app UUID>"
}
This manifest overrides the Flask webserver and instructs QRadar not to load Flask:
"load_flask": "false",
The manifest then defines an area
in the QRadar UI to display the app, called NodeJSHelloWorld
that is populated by calling the /index
endpoint in the named service called nodeservice
:
"areas": [
{
"description": "Dummy tab that displays text from the node app",
"id": "NodeJSHelloWorld",
"named_service": "nodeservice",
"required_capabilities": [],
"text": "NodeHelloWorld",
"url": "/index"
}
],
Finally, the manifest describes and defines a named service, which is a custom command that will run the NodeJS Express server, exposing the path /index
. This named service also includes a command
to run the NodeJS server, alongside paths to output logs:
"services": [
{
"command": "node /opt/app-root/app/server.js",
"directory": "/opt/app-root/app",
"endpoints": [
{
"name": "appindexpage",
"path": "/index",
"http_method": "GET"
}
],
"name": "nodeservice",
"path": "/index",
"port": 5000,
"version": "1",
"stdout_logfile": "/opt/app-root/store/log/node_out.log",
"stderr_logfile": "/opt/app-root/store/log/node_err.log"
}
],
These elements combined define how the NodeJS Express server is called and displayed as part of the QRadar UI.
Set up NPM to manage dependencies
- Remove the
app/
folder, and recreate it as an empty folder:rm -r app/ && mkdir app/ && cd app/
- Use NPM to create a
package.json
file for managing your app’s NodeJS dependencies:
npm init
- Answer the questions when prompted. A
package.json
file is generated.
Example:
{
"name": "nodejs_app",'
"version": "1.0.0",
"description": "App that uses NodeJS and an Express server",
"main": "server.js",
"author": "IBM",
"license": "<your license>"
}
- To install express as a dependency, run the folowing command:
npm install --save-dev express
Express is now a dependency, and a new app/node_modules/
folder is generated to store dependencies.
Tip: Exclude this folder from version control.
Write the NodeJS server
Writing the JavaScript server side code sets up some HTTP endpoints that respond with a simple message when accessed.
Create a new file called app/server.js
with the following code:
const express = require('express')
const app = express()
app.get('/index', (req, res) => res.send('Hello World!'))
app.get('/debug', (req, res) => res.send('Pong!'))
app.listen(5000, () => console.log('Server running on port 5000!'))
Run and Package the app
Before running or packaging your app, ensure that you pull your app’s NPM dependencies down to the app/node_modules
folder. This is vital to ensure that users can install and run the app without internet access:
cd app && npm install && cd ..
To run the app locally from the project root, type the following command:
qapp run
To package and deploy your app from the project root, type the following commands:
qapp package -p <_app zip name_>
qapp deploy -p <_app zip name_> -q <q_radar console_> -u <_qradar user_>