Skip to content

SIEM Integration

The Telovix Console forwards runtime events from ClickHouse to SIEM destinations on a continuous background loop. Each destination has its own event filter, minimum severity threshold, and cursor position so multiple SIEMs can receive different subsets of events independently.

Prerequisites

  • admin role
  • SIEM destination URL and credentials already obtained
  • Console has ClickHouse configured and receiving events

Supported destination types

TypeTransportFormatAuth
splunkHTTPSSplunk HEC JSONSplunk <token> header
sentinelHTTPSAzure Monitor JSONHMAC-SHA256 shared key
elasticsearchHTTPSECS 1.12.0 JSONApiKey <token> header
qradarUDP or TCP socketLEEF 2.0 textNone (socket-based)
observeHTTPSTelovix JSONBearer <token> header
huntressHTTPSTelovix JSONBearer <api_key> header
sumologicHTTPSTelovix JSONNone (URL auth)
syslogUDP or TCP socketRFC5424 or RFC3164 textNone (socket-based)

How the forwarding loop works

The run_siem_forward_loop background task runs every 15 seconds. On each cycle it:

  1. Loads all enabled destinations from the database.
  2. For each destination, fetches up to 100 events per cycle from ClickHouse filtered by the destination's forward_event_kinds and min_severity.
  3. Dispatches each event to the destination with a 10-second HTTP timeout.
  4. Advances the cursor (last_forwarded_at) after each successful dispatch.
  5. Stops forwarding for the current cycle after 10 consecutive errors on the same destination to avoid overwhelming a degraded endpoint.

The cursor is per-destination and stored in console_siem_forward_cursor. If no cursor exists for a destination (first run or reset), the Console fetches events from the last 900 seconds.

Events are queried from the runtime_events ClickHouse table and forwarded in ascending observed_at order.


Managing SIEM destinations

In the Console, go to Settings > Integrations > SIEM to create, update, test, enable, disable, or delete destinations.

Create a destination

In the Console, go to Settings > Integrations > SIEM and click Add Destination. The Console UI presents these fields:

FieldRequiredDescription
nameYesDisplay name (max 128 characters)
destination_typeYesOne of the 8 supported types
configYesDestination-specific configuration (see reference below)
forward_event_kindsNoEvent kinds to forward; leave empty to forward all kinds
min_severityNoMinimum severity to forward: low, medium, high, critical (empty = all)
forward_anomaliesNoWhether to include anomaly score events (default off)
SIEM destination creation form showing destination type selector, configuration fields, event kind filter, and severity threshold.
SIEM destination creation form showing destination type selector, configuration fields, event kind filter, and severity threshold. Click to enlarge

Update a destination

In the Console, go to Settings > Integrations > SIEM, click the destination row, and edit the fields. Omitted fields retain their current values. To update a sensitive config field (token, key), enter the new value. To keep the existing value, leave the field blank.

Delete a destination

In the Console, go to Settings > Integrations > SIEM, click the destination row, and select Delete.

Test a destination

In the Console, go to Settings > Integrations > SIEM, click the destination row, and click Send Test Event. The Console sends a single test event to the destination and records the result in last_test_ok and last_test_message.

Enable and disable

In the Console, go to Settings > Integrations > SIEM and toggle the enabled state on the destination row. Disabled destinations receive no forwarded events.


Destination configuration reference

The Console UI presents these configuration fields when creating or editing a destination. The JSON structures below show the exact fields the Console expects for each type.

Splunk (HEC)

json
{
  "destination_type": "splunk",
  "config": {
    "url": "https://splunk.example.com:8088/services/collector/event",
    "token": "<hec-token>"
  }
}

Events are posted to the Splunk HTTP Event Collector. Authorization header: Splunk <token>. The payload uses Splunk HEC JSON format with sourcetype: "_json" and source: <event_kind>.

Microsoft Sentinel

json
{
  "destination_type": "sentinel",
  "config": {
    "workspace_id": "<log-analytics-workspace-id>",
    "shared_key": "<primary-or-secondary-key>"
  }
}

Events are posted to https://{workspace_id}.ods.opinsights.azure.com/api/logs?api-version=2016-04-01. Authorization uses HMAC-SHA256 signed with the shared key. The Log-Type header is set to TelovixSecurityEvents.

Elasticsearch / OpenSearch

json
{
  "destination_type": "elasticsearch",
  "config": {
    "url": "https://elastic.example.com:9200",
    "token": "<api-key>",
    "index": "telovix-events"
  }
}

Events are posted to {url}/{index}/_doc. Authorization header: ApiKey <token>. The payload uses Elastic Common Schema (ECS) 1.12.0 format. The index field defaults to telovix-events if omitted. OpenSearch uses the same configuration.

QRadar (LEEF)

json
{
  "destination_type": "qradar",
  "config": {
    "host": "qradar.example.com",
    "port": 514,
    "protocol": "udp"
  }
}

Events are sent as LEEF 2.0 formatted text over UDP or TCP. Default port: 514. Default protocol: udp. Protocol values: udp or tcp.

Observe

json
{
  "destination_type": "observe",
  "config": {
    "url": "https://collect.observeinc.com/v1/http/...",
    "token": "<datastream-token>"
  }
}

Authorization header: Bearer <token>.

Huntress

json
{
  "destination_type": "huntress",
  "config": {
    "url": "https://api.huntress.io/v1/...",
    "api_key": "<api-key>"
  }
}

Authorization header: Bearer <api_key>.

Sumo Logic

json
{
  "destination_type": "sumologic",
  "config": {
    "url": "https://endpoint.collection.us2.sumologic.com/receiver/v1/http/..."
  }
}

No Authorization header. Authentication is embedded in the collector URL.

Syslog

json
{
  "destination_type": "syslog",
  "config": {
    "host": "syslog.example.com",
    "port": 514,
    "protocol": "udp",
    "format": "rfc5424"
  }
}

Default port: 514. Default protocol: udp. Format: rfc5424 (default) or rfc3164. Syslog facility is 1 (user-level messages). Events are serialized as JSON inside the syslog structured data field.


Event fields forwarded

Every SIEM event is built from these fields queried from ClickHouse:

FieldDescription
event_idUnique event identifier
sensor_idSensor that generated the event
node_nameDisplay name of the sensor node
event_kindRuntime event category
severitylow, medium, high, or critical
observed_atWhen the event was observed (RFC3339)
messageHuman-readable event description
process_executableBinary path of the process
parent_executableParent process binary path (optional)
pidProcess ID (optional)
uidUser ID (optional)
k8s_namespaceKubernetes namespace (optional)
pod_nameKubernetes pod name (optional)
workload_nameKubernetes workload name (optional)
dns_hostnameDNS hostname from DNS events (optional)
argsProcess arguments (optional)

Telovix JSON payload (used by Observe, Huntress, Sumo Logic)

json
{
  "@timestamp": "2026-04-26T14:22:00Z",
  "telovix": {
    "event_id": "...",
    "sensor_id": "...",
    "node_name": "upf-prod-01",
    "event_kind": "privilege_change",
    "severity": "high",
    "message": "...",
    "process": {
      "executable": "/opt/open5gs/bin/upf",
      "pid": 1234,
      "uid": 1000
    }
  }
}

Kubernetes fields (kubernetes.namespace, kubernetes.pod, kubernetes.workload) are included when present.

ECS payload (Elasticsearch)

json
{
  "@timestamp": "2026-04-26T14:22:00Z",
  "ecs": { "version": "1.12.0" },
  "agent": { "name": "telovix-sensor", "type": "telovix", "version": "1.0" },
  "event": { "kind": "event", "category": ["process"], "type": ["start"], "dataset": "process_exec", "severity": 3 },
  "host": { "name": "upf-prod-01", "id": "{sensor_id}" },
  "process": { "executable": "/opt/open5gs/bin/upf", "pid": 1234 },
  "message": "...",
  "telovix": { "event_id": "...", "sensor_id": "..." }
}

ECS severity mapping: critical=4, high=3, medium=2, low=1.


Destination status fields

The destination detail view in Settings > Integrations > SIEM includes these health tracking fields:

FieldDescription
last_test_atTimestamp of the last test delivery
last_test_okWhether the last test succeeded
last_test_messageResult message from the last test
last_forwarded_atTimestamp of the last successful event forwarding
total_forwardedTotal events forwarded since the destination was created
total_errorsTotal forwarding errors since the destination was created

Operational guidance

Filter by event kind: If you do not filter by forward_event_kinds, all event kinds are forwarded. This includes informational events such as process_exec and network_connect at high volume. Start with a narrow filter covering your highest-value event kinds (fim_alert, privilege_change, module_load, bpf_tampering) and expand as needed.

Sensitive config protection: Tokens, shared keys, and API keys are masked in all read views. When updating a destination config, leave sensitive fields blank to keep the existing values.

Error threshold: If a destination endpoint returns errors consistently, the forwarding loop stops attempting the destination for that cycle after 10 errors and logs a warning. On the next loop tick (15 seconds later) it will try again. If the endpoint is persistently unavailable, events accumulate a growing lag behind the cursor. Events from before the cursor position are not re-queued after the cursor advances.

QRadar and Syslog on non-standard ports: Both use port: 514 as default. Change this to match your QRadar log source or syslog collector's configured port. UDP is the default protocol; use TCP for guaranteed delivery on high-priority events.

Sentinel table naming: Events land in the table named TelovixSecurityEvents in your Log Analytics workspace. Use this name when writing KQL queries or Sentinel analytics rules.


Further reading

Released under the Telovix Commercial License.