Directly contact our Support Team

Sending events from GravityZone Cloud to SIEMs lacking HTTPS listeners

This article aims to help you build a connector between GravityZone and SIEM solutions that don’t have HTTPS listeners for events.

Bitdefender GravityZone – the cloud platform, is able to provide alerts about security events in CEF and JSON message standards.
These alerts are sent through the Event Push Service API. The GravityZone APIs are exposed using JSON-RPC 2.0 protocol specified here. For details on GravityZone API, refer to the available documentation:

If your SIEM does not have any HTTP/HTTPS listeners, but supports a Syslog service, you need to build a Node.js connector.

The connector uses the POST method to receive authenticated and secured messages from the GravityZone Event Push Service API. It parses the message and then forwards it to a local or a remote Syslog server. You can use the Syslog server to feed these messages to the SIEM.

To build the connector, follow the steps described in the sections below:

  1. Make sure you meet the prerequisites
  2. Configure GravityZone to send messages to the SIEM
  3. Create the security certificate for authentication
  4. Build the Node.js connector
  5. Test the connector

Prerequisites

  • Linux basic knowledge
  • Node.js advanced knowledge
  • GravityZone cloud solution
  • A GravityZone API key that covers Event Push Service API
  • Ubuntu 20.04 LTS server with the following configuration:
    • Hardware:
      • 1 CPU
      • 2 GB RAM
      • 1 Gbit virtual NIC
      • 80 GB HDD
    • Node.js installed with Node version 8.1.x or higher
    • OpenSSL installed
    note Note:
    This configuration can sustain an environment up to 15000 endpoints. The CPU and network usage will increase proportionally with the number of endpoints.

Configure GravityZone to send messages to the SIEM

All settings for Event Push Service API are configured via the setPushEventSettings method. For detailed information about these settings, refer to the Push section of the GravityZone API Guide.

Access the right guide for you:

Once configured, wait about 10 minutes until the settings take effect, and then make a request using getPushEventSettings. The method returns the autorization string as “authorization”: ”. Save the authorization string because you will need it later.

Create the security certificate for authentication

Unless you already have a security certificate from a Certificate Authority, which is trusted by your devices, you need to create a self-signed certificate to secure the communication between Event Push Service API and the connector.

This section describes a method that uses OpenSSL to create such self-signed certificates.

important Important:
All commands must run with root privileges.

Create a directory for the certificates

For example: /tmp/auth/mycerts

# cd /tmp
# mkdir auth
# cd auth
# mkdir mycerts
# cd mycerts

Create the bash scripts

  1. Create the createroot.sh file using a text editor such as vim:
    # vim createroot.sh
  2. Enter in edit mode and copy the commands below into the editor:
    #!/bin/bash
    openssl req -newkey rsa:2048 -days 365 -x509 -keyout rootkey.pem -out root.cer -sha256 -subj "/C=XX/O=XX/CN=XX/"
    note Note:
    Replace the Country C=XX, the Organization O=XX and the Common Name CN=XX suitable for you.
    For example: "/C=RO/O=Bitdefender/CN=GravityZoneConnectorRoot/"
  3. Save the file and quit vim.
  4. Create the createssl.sh script using vim:
    # vim createssl.sh
  5. Enter in edit mode and copy the commands below into the editor:
    #!/bin/bash
    openssl req -new -newkey rsa:2048 -keyout sslkey.pem -out ssl.csr -sha256 -subj "/CN=$1/" -batch
    openssl x509 -req -days 365 -sha256 -in ssl.csr -CA root.cer -CAkey rootkey.pem -CAcreateserial -CAserial root.serial -out ssl.cer -extfile <(printf "extendedKeyUsage = serverAuth \n subjectAltName=IP:$1")
    note Note:
    For subjectAltName, you can also use DNS or FQHN instead of IP address.
    For example: subjectAltName=DNS:$1
  6. Save the file and quit vim.

Generate the certificates using the previously created scripts

  1. Run createroot.sh to create the root certificate:
    # chmod +x createroot.sh
    # ./createroot.sh
    Remember the password protecting the private key.
    Result files: root.cer, rootkey.pem
  2. Run createssl.sh to create the server certificate:
    # chmod +x createssl.sh
    # ./createssl.sh IP|FQHN
    Provide either the IP address or FQDN depending on the configuration of the server.
    As always, remember the password.
    Result files: the SSL certificate - ssl.cer, the private key - sslkey.pem.

Build the Node.js connector

The connector uses the following files:

  • package.json
  • config.json
  • server.js
  • epsSyslogHelper.js

You can either modify the template files available here, or create them from scratch as described in this section.

To build the Node.js connector, follow these steps:

Create a directory on your server in which you would like to place the connector application

# mkdir folder_name 
# cd folder_name

Create the package.json file

  1. Create the file:
    #vim package.json
  2. Enter in edit mode and copy the JSON content:
    {
    	"name": "app-name",
    	"version": "1.0.0",
    	"private": true,
    	"description": "client that will be able to receive authenticated POST requests and write each row in the local or remote syslog",
    	"main": "server.js",
    	"scripts": {
    		"test": "echo \"Error: no test specified\" && exit 1"
    	},
    	"author": "",
    	"license": "MIT",
    	"dependencies": {
    	}
    }
  3. Save the file and quit vim.

Test the validity of the JSON file

You can use an online tool to test the file.

For example: https://jsonformatter.curiousconcept.com/#

Fetch dependencies

Express framework

Express is a minimal and flexible Node.js web application framework that provides a robust set of features for web and mobile applications.

Use Express to create the HTTP server and enter the following command to put it within your package.json file:

$ npm install express --save

Body parser

Follow Node.js body parsing middleware instructions to parse incoming request bodies in a middleware before your handlers, available under the req.body property.

$ npm install body-parser --save

Syslog client

Follow the Syslog client module instructions to send event notification messages across networks.

$ npm install syslog-client --save

Create the config.json file

This file contains the settings used by server.js when starting.

  1. Create the following directory for the configuration file: APP_ROUTE/api/config
    # mkdir api
    # cd api
    # mkdir config 
    # cd config
  2. Create the file:
    #vim config.json
  3. Enter in edit mode and copy the JSON content:
    {
    	"port":3200,
    	"syslog_port":514,
    	"transport":"Tcp",
    	"target":"10.17.23.68",
    	"authorization_string":"Basic dGVzdDp0ZXN0",
    	"secure":{
    		"key":"path/to/sslkey.pem",
    		"cert":"path/to/ssl.cer",
    		"passphrase":"xxxx"
    	}
    }
  4. Replace the values of the following fields with your actual data:
    • port – the port number on which the connector will run
    • syslog_port – the TCP or UDP port number on which to send messages
    • transport – the network protocol
    • target – the IP address of the Syslog server
    • passphrase – the password of the security certificate
    • authorization_string – the authorization string configured earlier via setPushEventSettings
  5. Save the file and quit vim.
  6. Move sslkey.pem and ssl.cer to the api/config/ directory.

Create the server.js file in the APP_ROUTE/ directory

  1. Create the file:
    #vim server.js
  2. Enter in edit mode and copy the following code:
    'use strict';
    
    const express = require('express');
    const app = express();
    const fs = require('fs');
    const https = require("https");
    const path = require('path');
    const bodyParser = require('body-parser');
    const textParser = bodyParser.json();
    const epsSyslogHelper = require('./api/epsSyslogHelper');
    
    if (!process.argv[2]) {
        throw "Missing input file parameter";
    }
    let configPath = process.argv[2];
    const config = JSON.parse(fs.readFileSync(configPath, 'utf8'));
    
    console.log('Load Config file');
    console.log('\n');
    console.log(config);
    console.log('\n');
    
    // use basic HTTP auth to secure the api
    app.use('/api', (req, res, next) => {
    
        console.log(req.headers.authorization);
        // check for basic auth header
        if (!req.headers.authorization) {
            return res.status(401).json({ message: 'Missing Authorization Header' });
        }
    
        // verify auth credentials
        const authorizationString =  req.headers.authorization;
        if (config.authorization_string !== authorizationString) {
            return res.status(401).json({ message: 'Invalid Authentication Credentials' });
        }
    
        next();
    });
    
    // url: http://localhost:3000/api/
    app.post('/api', textParser, (request, response) => {
    
        const body =  request.body;
        let syslogHelper = new epsSyslogHelper(config);
        syslogHelper.log(body);
        response.sendStatus(200);
    });
    
    if (!config.secure || !config.secure.key || !config.secure.cert) {
    
        console.error(`please provide secure options in the config file: ${JSON.stringify(config)}`)
        process.exit(1)
    }
    
    try{
        const options = {
            key: fs.readFileSync(path.resolve(__dirname, config.secure.key)),
            cert: fs.readFileSync(path.resolve(__dirname, config.secure.cert)),
            passphrase: config.secure.passphrase
        };
    
    https
        .createServer(options, app)
        .listen(config.port, () => console.log(`Listening on port ${config.port}`));
    
    }catch (e) {
        console.error('error on starting server')
        process.exit(1)
    }
  3. Save the file and quit vim.

Create the epsSyslogHelper.js file

The path for the config file should be APP_ROUTE/api/epsSyslogHelper.js

  1. Create the file:
    #vim epsSyslogHelper.js
  2. Enter in edit mode and copy the following code:
    'use strict';
    
    let EpsSyslogHelper;
    
    const syslog = require('syslog-client');
    const os = require('os');
    
    /**
     * EventConverter class
     */
    EpsSyslogHelper = function (config) {
    
        let hostName = os.hostname();
        if (!hostName) {
            hostName = 'localhost';
        }
    
        let dot = hostName.indexOf('.');
        if (dot > 0) {
            hostName = hostName.substring(0, dot);
        }
        console.log('Logging using host name %s', hostName);
    
        this._client = syslog.createClient(config.target, {
            syslogHostname: hostName,
            port: config.syslog_port,
            transport: syslog.Transport[config.transport],
        });
        this._client.on('error', function(err) {
            console.error('Error from syslog network: %s', err);
        });
    
    };
    
    
    EpsSyslogHelper.prototype.log = function _log(msg) {
     
        let options = {
            facility: syslog.Facility.Local0,
            severity: syslog.Severity.Informational
        };
        let events;
     
        if(msg.hasOwnProperty('cef')){
            events = msg.events;
        } else if (msg.hasOwnProperty('jsonrpc')) {
             events = msg.params.events;
        }
     
          if(events){
     
            for(let eventKey in events) {
                let syslogMessage = events[eventKey];
     
                if(typeof syslogMessage !== 'string') {
                    syslogMessage = JSON.stringify(syslogMessage);
                }
     
                console.log("Event key = " + eventKey + " is = " + syslogMessage);
                 
                const me  = this;
                this._client.log(syslogMessage, options, function (err) {
                    if (err) {
                        console.error(err);
                    } else {
                        console.log('EventSent to syslog')
                    }
                    me._client.close();
                });
            }
     
        }
    };
    
    
    // export module
    module.exports = EpsSyslogHelper;
  3. Save the file and quit vim.

Start the Node server

To start the Node server, enter the following command:

node server.js api/config/config.json

The connector URL will have the following format:

https://your_web_server_hostname_or_public_IP:port/api

Test the connector

Use this HTTPS message example to test the connector you have just configured:

  • Event Push Service request header
    Authorization: {authorization_string}
  • Event Push Service payload
    {
    "cef": "0",
     "events": [
    	"CEF:0|Bitdefender|GravityZone|6.4.08|70000|Registration|3|BitdefenderGZModule=registrationdvchost=TEST_ENDPOINTasdadBitdefenderGZComputerFQDN=test.example.com dvc=192.168.1.2",
    "CEF:0|Bitdefender|GravityZone|6.4.0-8|35|Product ModulesStatus|5|BitdefenderGZModule=modules dvchost=TEST_ENDPOINTasdadBitdefenderGZComputerFQDN=test.example.com dvc=192.168.1.2",
    "CEF:0|Bitdefender|GravityZone|6.4.0-8|35|Product ModulesStatus|5|BitdefenderGZModule=modules dvchost=TEST_ENDPOINTasdadBitdefenderGZComputerFQDN=test.example.com dvc=192.168.1.2"
    ]
    }

You should now have the events sent to your Syslog server.


Rate this article:

Submit