User Guide Functional Overview Requirements Architecture System Installation NetEye Additional Components Installation Setup The neteye Command Director NetEye Self Monitoring Tornado Business Service Monitoring IT Operation Analytics - Telemetry Geo Maps NagVis Audit Log Shutdown Manager Reporting ntopng Visual Monitoring with Alyvix Elastic Stack IT Operations (Command Orchestrator) Asset Management Service Level Management Cyber Threat Intelligence - SATAYO NetEye Update & Upgrade How To NetEye Extension Packs Troubleshooting Security Policy Glossary
module icon Tornado
Concepts Collecting Events Add a Filter Node WHERE Conditions Iterating over Event fields Retrieving Payload of an Event Extract Variables Create a Rule Tornado Actions Test your Configuration Export and Import Configuration Example Under the hood Development Retry Strategy Configuration Thread Pool Configuration API Reference
Director NetEye Self Monitoring Tornado Business Service Monitoring IT Operation Analytics - Telemetry Geo Maps NagVis Audit Log Shutdown Manager Reporting Introduction to NetEye Monitoring Business Service Monitoring IT Operation Analytics Visualization Network Visibility Log Management & Security Orchestrated Datacenter Shutdown Application Performance Monitoring User Experience Service Management Service Level Management & Reporting Requirements for a Node Cluster Requirements and Best Practices NetEye Satellite Requirements TCP and UDP Ports Requirements Additional Software Installation Introduction Single Node Cluster NetEye Master Master-Satellite Architecture Underlying Operating System Acquiring NetEye ISO Image Installing ISO Image Single Nodes and Satellites Cluster Nodes Configuration of Tenants Satellite Nodes Only Nodes behind a Proxy Additional NetEye Components Single Node Cluster Node Satellites Nodes only Verify if a module is running correctly Accessing the New Module Cluster Satellite Security Identity and Access Management External Identity Providers Configure federated LDAP/AD Emergency Reset of Keycloak Configuration Advanced Configuration Authorization Resources Tuning Advanced Topics Basic Concepts & Usage Advanced Topics Monitoring Environment Templates Monitored Objects Import Monitored Objects Data Fields Deployment Icinga 2 Agents Configuration Baskets Dashboard Monitoring Status VMD Permissions Notifications Jobs API Configuring Icinga Monitoring Retention Policy NetEye Self Monitoring 3b Concepts Collecting Events Add a Filter Node WHERE Conditions Iterating over Event fields Retrieving Payload of an Event Extract Variables Create a Rule Tornado Actions Test your Configuration Export and Import Configuration Example Under the hood Development Retry Strategy Configuration Thread Pool Configuration API Reference Configure a new Business Process Create your first Business Process Node Importing Processes Operators The ITOA Module Configuring User Permissions Telegraf Metrics in NetEye Telegraf Configuration Telegraf on Monitored Hosts Visualizing Dashboards Customizing Performance Graph The NetEye Geo Map Visualizer Map Viewer Configuring Geo Maps NagVis 3b Audit Log 3b Overview Shutdown Manager user Shutdown Manager GUI Shutdown Commands Advanced Topics Overview User Role Management Cube Use Cases ntopng and NetEye Integration Permissions Retention Advanced Topics Overview User Roles Nodes Test Cases Dashboard Use Cases Overview Architecture Authorization Elasticsearch Overview Enabling El Proxy Sending custom logs to El Proxy Configuration files Commands Elasticsearch Templates and Retentions El Proxy DLQ Blockchain Verification Handling Blockchain Corruptions El Proxy Metrics El Proxy Security El Proxy REST Endpoints Agents Logstash Elastic APM Elastic RUM Log Manager - Deprecated Overview Authorization in the Command Orchestrator Module Configuring CLI Commands Executing Commands Overview Permissions Installation Single Tenancy Multitenancy Communication through a Satellite Asset collection methods Display asset information in monitoring host page Overview Customers Availability Event Adjustment Outages Resource Advanced Topics Introduction Getting Started SATAYO Items Settings Managed Service Mitre Attack Coverage Changelog Before you start Update Procedure Single Node Upgrade from 4.41 to 4.42 Cluster Upgrade from 4.41 to 4.42 Satellite Upgrade from 4.41 to 4.42 DPO machine Upgrade from 4.41 to 4.42 Create a mirror of the RPM repository Sprint Releases Feature Troubleshooting Tornado Networking Service Management - Incident Response IT Operation Analytics - Telemetry Identity Provider (IdP) Configuration Introduction to NEP Getting Started with NEPs Online Resources Obtaining NEP Insights Available Packages Advanced Topics Upgrade to NetEye 4.31 Setup Configure swappiness Restarting Stopped Services Enable stack traces in web UI How to access standard logs Director does not deploy when services assigned to a host have the same name How to enable/disable debug logging Activate Debug Logging for Tornado Modules/Services do not start Sync Rule fails when trying to recreate Icinga object How to disable InfluxDB query logging Managing an Elasticsearch Cluster with a Full Disk Some logs are not indexed in Elasticsearch Elasticsearch is not functioning properly Reporting: Error when opening a report Debugging Logstash file input filter Bugfix Policy Reporting Vulnerabilities Glossary 3b

Collecting Events

Overview

Tornado provides a number of preconfigured Collectors that handle inputs from various data sources:

  1. Email Collector

  2. Rsyslog Collector

  3. Webhook Collector

  4. Nats JSON Collector

  5. Icinga 2 Collector

  6. SNMP Trap Daemon Collector

  7. SMS Collector

Most of the Tornado Collectors are functioning out of the box and do not require manual configuration. However, there are some, that may be configured to work in accordance with your needs.

The Event Type

All collectors convert the external events they collect to Tornado internal events that are then forwarded to the Tornado Processing Engine. These events share a similar base structure, but every collector adds their own data to the event payload and sets a custom event type. An event consists of the following properties:

Property

Type

Description

type

String

The type/source, of the event. Dependend on the collector that creates the event

created_ms

Integer

A timestamp in milliseconds, when the collector created the event

payload

Object

A JSON object that contains all the data for the event

metadata (Optional)

EventMetadata

Metadata for the event

Note

The Tornado iterator node can also add a new field iterator to the event, which is only present in the processing tree for the children of an iterator node.

EventMetadata

Property

Type

Description

tenant_id (Optional)

String

If the event is received over Nats, the Tornado collector will set this field, dependend on the sender.

Webhook

Out of the box the Webhook Collector is available on the NetEye Master and, if present, on Satellites, and the webhooks are to be configured.

On startup, it creates a dedicated REST endpoint for each configured webhook. Calls received by an endpoint are processed by the embedded JMESPath Collector that uses them to produce Tornado Events. In the final step, the Events are forwarded to the Tornado Engine through the configured connection type.

Webhooks in Tornado Webhook Collector are defined by JSON files, which are stored in the folder /neteye/shared/tornado_webhook_collector/conf/webhooks/.

For each webhook, you must provide the following values in order to successfully create an endpoint:

  • id: The webhook identifier. This will determine the path of the endpoint; it must be unique per webhook.

  • token: A security token that the webhook issuer has to include in the URL as part of the query string (see the example at the bottom of this page for details). If the token provided by the issuer is missing or does not match the one owned by the Collector, then the call will be rejected and an HTTP 401 code (UNAUTHORIZED) will be returned.

  • collector_config: The transformation logic that converts a webhook JSON object into a Tornado Event. It consists of a JMESPath Collector configuration.

  • event_type: A mandatory field to define the event type of the Tornado event generated based on a call received by an endpoint.

Assuming the webhook request is:

curl -v -X POST https://<neteye.master>/tornado/webhook/event/ups?token=my-secret-token -d '{"ups": "001", "type": "critical", "message": "Battery level critical"}'

the configuration file ups_notifications.conf would contain the following values:

{
 "id": "ups",
 "token": "my-secret-token",
 "collector_config": {
   "event_type": "ups_notification",
   "payload": {
     "source": "${@}"
    }
  }
}

the event received is:

{
 "created_ms": 1713266596490,
 "metadata": {
   "tenant_id": "master",
 },
 "payload": {
   "source":{
     "message":"Battery level critical",
     "type":"critical",
     "ups":"001"
     }
   }
 },
 "type": "ups_notification"
}

Detailed information on how to configure webhooks in Tornado can the found inside the official Tornado documentation; in particular, the Webhook Collector documentation describes the architecture of the Webhook Collector and its configuration parameters and options.

Icinga 2

The Icinga 2 Collector subscribes to the Icinga 2 API event streams, generates Tornado Events from the Icinga 2 Events, and publishes them on the Tornado Engine.

On startup, it connects to Icinga 2 Server API and subscribes to user defined Event Streams.

In order to configure the stream, create a JSON file in /neteye/shared/tornado_icinga2_collector/conf/streams/. More than one stream subscription can be defined.

For each stream, you must provide two values in order to successfully create a subscription:

  • stream: the stream configuration composed of:

    • types: An array of Icinga 2 Event types;

    • queue: A unique queue name used by Icinga 2 to identify the stream;

    • filter: An optional Event Stream filter. Additional information about the filter can be found in the official documentation.

  • collector_config: The transformation logic that converts an Icinga 2 Event into a Tornado Event.

Below you may find examples of valid content for a stream configuration JSON file:

For all Icinga 2 events

{
  "stream": {
    "types": ["CheckResult",
              "StateChange",
              "Notification",
              "AcknowledgementSet",
              "AcknowledgementCleared",
              "CommentAdded",
              "CommentRemoved",
              "DowntimeAdded",
              "DowntimeRemoved",
              "DowntimeStarted",
              "DowntimeTriggered"],
    "queue": "icinga2_AllEvents_all"
  },
  "collector_config": {
    "event_type": "icinga2_AllEvents_all",
    "payload": {
      "response": "${@}"
    }
  }
}

For check result events

{
  "stream": {
    "types": ["CheckResult"],
    "queue": "icinga2_CheckResult_all"
  },
  "collector_config": {
    "event_type": "icinga2_CheckResult_all",
    "payload": {
      "response": "${@}"
    }
  }
}

For notification events

{
  "stream": {
    "types": ["Notification"],
    "queue": "icinga2_Notification_all"
  },
  "collector_config": {
    "event_type": "icinga2_Notification_all",
    "payload": {
      "response": "${@}"
    }
  }
}

For statechange events

{
  "stream": {
    "types": ["StateChange"],
    "queue": "icinga2_StateChange_all"
   },
  "collector_config": {
    "event_type": "icinga2_StateChange_all",
    "payload": {
      "response": "${@}"
    }
  }
}

Note

Based on the Icinga 2 Event Streams documentation, multiple HTTP clients can use the same queue name as long as they use the same event types and filter.

After configuring the streams, restart tornado_icinga2_collector resource.

Email

The Email Collector generates Tornado Events from valid MIME email messages as inputs.

In NetEye, the incoming email messages are managed by the Postfix mail server. Only the emails sent to the local NetEye user eventgw are forwarded to the Tornado Email Collector. You or your Administrator will need to configure the NetEye Postfix mail server to receive emails for the user eventgw.

All the emails received to the before mentioned mailbox are then out of the box forwarded to the Tornado Email Collector that will parse them and convert in Tornado Events with the extracted data.

To check if the Email Collector is working properly, send an email to the dedicated eventgw user which will then be processed by Tornado: # echo "TestContent" | mail -s TestSubject eventgw@localhost

Now test that an email sent to that address makes it to Tornado (the timestamp reported by journalctl should be at most a second or two after you send the email):

# journalctl -u tornado_email_collector.service
Jun 21 15:11:59 host.example.com tornado_email_collector[12240]: [2019-06-21][15:11:59]
[tornado_common::actors::uds_server][INFO] UdsServerActor - new client connected to [/var/run/tornado/email.sock]``

With the attachments included, the ones that are text files will be in plain text, otherwise they will be encoded in base64.

For example, passing this email with attachments:

From: "Francesco" <francesco@example.com>
Subject: Test for Mail Collector - with attachments
To: "Benjamin" <benjamin@example.com>,
 francesco <francesco@example.com>
Cc: thomas@example.com, francesco@example.com
Date: Sun, 02 Oct 2016 07:06:22 -0700 (PDT)
MIME-Version: 1.0
Content-Type: multipart/mixed;
 boundary="------------E5401F4DD68F2F7A872C2A83"
Content-Language: en-US

This is a multi-part message in MIME format.
--------------E5401F4DD68F2F7A872C2A83
Content-Type: text/html; charset=utf-8
Content-Transfer-Encoding: 7bit

<html>Test for Mail Collector with attachments</html>

--------------E5401F4DD68F2F7A872C2A83
Content-Type: application/pdf;
 name="sample.pdf"
Content-Transfer-Encoding: base64
Content-Disposition: attachment;
 filename="sample.pdf"

JVBERi0xLjMNCiXi48/TDQoNCjEgMCBvYmoNCjw8DQovVHlwZSAvQ2F0YWxvZw0KT0YNCg==

--------------E5401F4DD68F2F7A872C2A83
Content-Type: text/plain; charset=UTF-8;
 name="sample.txt"
Content-Transfer-Encoding: base64
Content-Disposition: attachment;
 filename="sample.txt"

dHh0IGZpbGUgY29udGV4dCBmb3IgZW1haWwgY29sbGVjdG9yCjEyMzQ1Njc4OTA5ODc2NTQz
MjEK
--------------E5401F4DD68F2F7A872C2A83--

will generate this Event:

{
  "type": "email",
  "created_ms": 1554130814854,
  "payload": {
    "date": 1475417182,
    "subject": "Test for Mail Collector - with attachments",
    "to": "\"Benjamin\" <benjamin@example.com>, francesco <francesco@example.com>",
    "from": "\"Francesco\" <francesco@example.com>",
    "cc": "thomas@example.com, francesco@example.com",
    "body": "<html>Test for Mail Collector with attachments</html>",
    "attachments": [
      {
        "filename": "sample.pdf",
        "mime_type": "application/pdf",
        "encoding": "base64",
        "content": "JVBERi0xLjMNCiXi48/TDQoNCjEgMCBvYmoNCjw8DQovVHlwZSAvQ2F0YWxvZw0KT0YNCg=="
      },
      {
        "filename": "sample.txt",
        "mime_type": "text/plain",
        "encoding": "plaintext",
        "content": "txt file context for email Collector\n1234567890987654321\n"
      }
    ]
  }
}

Within the Tornado Event, the filename and mime_type properties of each attachment are the values extracted from the incoming email.

Instead, the encoding property refers to the content encoding in the Event itself, which is one of two types:

  • plaintext: The content is included in plain text

  • base64: The content is encoded in base64

SMS

Before Tornado can correctly catch SMS, you should configure your SMS modem to send events to Tornado. You can follow the configuration procedure at SMS Modem Setup.

Tornado SMS Collector will then receive then valid SMS like:

From: 39123456789
From_TOA: 91 international, ISDN/telephone
From_SMSC: 39123456789
Sent: 23-10-09 16:06:52
Received: 23-10-09 16:06:58
Subject: GSM1
Modem: GSM1
IMSI: 222018005102877
Report: no
Alphabet: ISO
Length: 20

Example text message

and based on that will create the following Tornado Event:

{
  "type": "sms",
  "created_ms": 155412314854,
  "payload": {
     "modem":"GSM1",
     "sender": "+39123456789",
     "text": "Example text message"
  }
}

Within the Tornado Event, the modem, sender and text properties are the values extracted from the incoming SMS.

Tornado Nats JSON

The Nats JSON Collector is a standalone Collector that listens for JSON messages on Nats topics, generates Tornado Events, and sends them to the Tornado Engine.

On startup, it connects to a set of topics on a Nats server. Calls received are then processed by the embedded JMESPath Collector that uses them to produce Tornado Events. In the final step, the Events are forwarded to the Tornado Engine through the configured connection type.

For each topic, you must provide two values in order to successfully configure them:

  • nats_topics: A list of Nats topics to which the Collector will subscribe.

  • collector_config: (Optional) The transformation logic that converts a JSON object received from Nats into a Tornado Event. It consists of a JMESPath Collector configuration.

Topics configuration

Two startup parameters config-dir and topics-dir determine the path to the topic configurations, and each topic is configured by providing nats_topics and collector_config. topics-dir is the folder where the topic configurations are saved in JSON format. This folder is relative to the config_dir. The default value is /topics/.

An example of valid content for a Topic configuration JSON file is:

 {
  "nats_topics": ["simple_test_one", "simple_test_two"],
  "collector_config": {
    "event_type": "${content.type}",
    "payload": {
      "ref": "${content.ref}",
      "repository_name": "${repository}"
    }
  }
}

With this configuration, two subscriptions are created to the Nats topics simple_test_one and simple_test_two. Messages received by those topics are processed using the collector_config that determines the content of the Tornado Event associated with them.

It is important to note that, if a Nats topic name is used more than once, then the collector will perfom multiple subscriptions accordingly. This can happen if a topic name is duplicated into the nats_topics array or in multiple JSON files. So for example, with this JSON message is received:

{
   "content": {
      "type": "content_type",
      "ref": "refs/heads/master"
   },
   "repository": {
      "id": 123456789,
      "name": "webhook-test"
   }
}

then the resulting Event will be:

{
   "type": "content_type",
   "created_ms": 1554130814854,
   "payload": {
      "ref": "refs/heads/master",
      "repository": {
         "id": 123456789,
         "name": "webhook-test"
      }
   }
}

Default values

The collector_config section and all of its internal entries are optional. If not provided explicitly, the collector will use these predefined values:

  • When the collector_config.event_type is not provided, the name of the Nats topic that sent the message is used as Event type.

  • When the collector_config.payload is not provided, the entire source message is included in the payload of the generated Event with the key data.

Consequently, the simplest valid topic configuration contains only the nats_topics:

{
   "nats_topics": ["subject_one", "subject_two"]
}

The above one is equivalent to:

{
   "nats_topics": ["subject_one", "subject_two"],
   "collector_config": {
      "payload": {
       "data": "${@}"
      }
   }
}

In this case the generated Tornado Events have type equals to the topic name and the whole source data in their payload.

Rsyslog

The rsyslog Collector binary is an executable that generates Tornado Events from rsyslog inputs.

The collector is pre-configured and is not to be started manually.

The example of the rsyslog event is:

{
   "type": "syslog",
   "created_ms": 1713881098196,
   "payload": {
      "@timestamp": "2024-04-23T16:04:58.016685+02:00",
      "facility": "daemon",
      "host": "myhostname",
      "message": "my-service.service: Failed with result exit-code.",
      "severity": "WARNING",
      "source": "systemd",
      "syslog-tag": "systemd[1]:"
   },
   "type": "syslog"
}

SNMP Trap Event

The SNMP Trap Collector receives and parses messages coming from snmptrapd. It will then pass those messages as Events through a specific communication channel to Tornado.

The snmptrap is configured out of the box on the NetEye Master and, if present, on Satellites. Thus, in case a trap message received by a tenant will be automatically sent to Tornado via through its dedicated Satellite via NATS Communication channel.

The received messages are kept in an in-memory non-persistent buffer that makes the application resilient to crashes or temporary unavailability of the communication channel. When the connection to the channel is restored, all messages in the buffer will be sent. When the buffer is full, the Collectors will start discarding old messages. The buffer max size is set to 10000 messages.

Consider a snmptrapd message that contains the following information:

PDU INFO:
  version                        1
  errorstatus                    0
  community                      public
  receivedfrom                   UDP: [127.0.1.1]:41543->[127.0.2.2]:162
  transactionid                  1
  errorindex                     0
  messageid                      0
  requestid                      414568963
  notificationtype               TRAP
VARBINDS:
  iso.3.6.1.2.1.1.3.0            type=67 value=Timeticks: (1166403) 3:14:24.03
  iso.3.6.1.6.3.1.1.4.1.0        type=6  value=OID: iso.3.6.1.4.1.8072.2.3.0.1
  iso.3.6.1.4.1.8072.2.3.2.1     type=2  value=INTEGER: 123456

The Collector will produce this Tornado Event:

{
   "type":"snmptrapd",
   "created_ms":"1553765890000",
   "payload":{
      "protocol":"UDP",
      "src_ip":"127.0.1.1",
      "src_port":"41543",
      "dest_ip":"127.0.2.2",
      "PDUInfo":{
         "version":"1",
         "errorstatus":"0",
         "community":"public",
         "receivedfrom":"UDP: [127.0.1.1]:41543->[127.0.2.2]:162",
         "transactionid":"1",
         "errorindex":"0",
         "messageid":"0",
         "requestid":"414568963",
         "notificationtype":"TRAP"
      },
      "oids":{
         "iso.3.6.1.2.1.1.3.0":"67",
         "iso.3.6.1.6.3.1.1.4.1.0":"6",
         "iso.3.6.1.4.1.8072.2.3.2.1":"2"
      }
   }
}

The structure of the generated Event is not configurable.