Skip to main content

SIEM/SOAR Integration

Pavri can forward alerts to your existing SIEM or SOAR platform in addition to delivering them through the standard alert channels (webhook, Slack, email). SIEM forwarding is best-effort and fail-open — a SIEM outage never blocks alert delivery through primary channels.

Supported Platforms

PlatformProtocolFree TierLocal Testing
SplunkHTTP Event Collector (HEC)Splunk Free (500MB/day)Docker
ElasticsearchBulk API (NDJSON)Open source, fully freeDocker
Azure SentinelLog Analytics Data Collector API31-day free trial + $200 Azure creditAzure account
IBM QRadarSyslog RFC5424 + CEFQRadar Community Edition (free, 50 EPS)VM image

Configuration

SIEM targets are configured via environment variables. Multiple targets can be enabled simultaneously.

Splunk HTTP Event Collector

SIEM_SPLUNK_ENDPOINT=https://your-splunk-host:8088
SIEM_SPLUNK_TOKEN=your-hec-token
SIEM_SPLUNK_INDEX=pavri_alerts # optional, default: pavri_alerts

Elasticsearch

SIEM_ELASTIC_ENDPOINT=https://your-elastic-host:9200
SIEM_ELASTIC_TOKEN=base64(user:password) # optional, leave empty for open access
SIEM_ELASTIC_INDEX=pavri-alerts # optional, default: pavri-alerts

Azure Sentinel (Log Analytics Data Collector API)

SIEM_SENTINEL_ENDPOINT=https://YOUR_WORKSPACE_ID.ods.opinsights.azure.com
SIEM_SENTINEL_WORKSPACE=YOUR_WORKSPACE_ID
SIEM_SENTINEL_TOKEN=YOUR_WORKSPACE_PRIMARY_KEY
SIEM_SENTINEL_INDEX=PavriAlerts # optional, default: PavriAlerts

IBM QRadar (Syslog)

SIEM_QRADAR_ENDPOINT=your-qradar-host:514      # UDP by default
# For TCP syslog:
SIEM_QRADAR_ENDPOINT=tcp:your-qradar-host:514

TLS Configuration

# Skip TLS certificate verification (development/self-signed certs only):
SIEM_TLS_SKIP_VERIFY=true
warning

SIEM_TLS_SKIP_VERIFY=true should never be used in production. It disables certificate verification for all SIEM targets.


Event Format

Splunk HEC Payload

{
"time": 1742987200.0,
"host": "pavri-alert-svc",
"source": "pavri",
"sourcetype": "pavri_alerts",
"event": {
"alert_id": "alert-abc123",
"org_id": "org-tenant-1",
"rule_name": "High Confidence Prompt Injection",
"threat_type": "prompt_injection",
"severity": "high",
"confidence": 0.94,
"action": "block",
"agent_id": "agent-xyz",
"session_id": "sess-123",
"deep_link": "/sessions/sess-123?event=evt-456",
"created_at": "2026-03-26T12:00:00Z"
}
}

Elasticsearch Document

{
"@timestamp": "2026-03-26T12:00:00.000Z",
"alert_id": "alert-abc123",
"org_id": "org-tenant-1",
"threat_type": "prompt_injection",
"severity": "high",
"confidence": 0.94,
"source": "pavri"
}

QRadar CEF (via syslog)

<9>1 2026-03-26T12:00:00Z pavri-alert-svc - - - - \
CEF:0|Pavri|PavriAlertService|1.0|prompt_injection|High Confidence Prompt Injection|8|\
src=pavri suser=agent-xyz msg=prompt_injection cs1Label=OrgId cs1=org-1 \
cs3Label=AlertId cs3=alert-abc123 rt=2026-03-26T12:00:00Z

Free Tier Setup Guides

Splunk (Docker — Fully Local)

The easiest way to test Splunk HEC locally:

docker run -d \
-p 8088:8088 \
-p 8000:8000 \
-e SPLUNK_START_ARGS=--accept-license \
-e SPLUNK_PASSWORD=changeme123 \
--name splunk \
splunk/splunk:latest

Then:

  1. Wait for Splunk to start (~2-3 minutes): docker logs -f splunk | grep "Splunk is up"
  2. Open http://localhost:8000 (admin / changeme123)
  3. Go to Settings → Data Inputs → HTTP Event Collector
  4. Click Global Settings → Enable HEC → Save
  5. Click New Token → Name: pavri → Source Type: pavri_alerts → Submit
  6. Copy the token and set SIEM_SPLUNK_TOKEN=<token>
  7. Set SIEM_SPLUNK_ENDPOINT=https://localhost:8088 and SIEM_TLS_SKIP_VERIFY=true (self-signed cert)

Free tier limit: 500MB/day indexing. Sufficient for development and small production workloads.


Elasticsearch (Docker — Fully Free, Open Source)

docker run -d \
-p 9200:9200 \
-e "discovery.type=single-node" \
-e "xpack.security.enabled=false" \
--name elasticsearch \
docker.elastic.co/elasticsearch/elasticsearch:8.12.0

Verify it's running:

curl http://localhost:9200

Set environment variables:

SIEM_ELASTIC_ENDPOINT=http://localhost:9200
# No token needed when xpack.security.enabled=false

View alerts: open Kibana or query directly:

curl http://localhost:9200/pavri-alerts/_search?pretty

Cost: Free forever for the open-source distribution. Elastic Cloud offers a 14-day free trial.


Azure Sentinel (Cloud — Free Trial)

  1. Create an Azure free account ($200 credit for 30 days)
  2. Create a Log Analytics workspace in Azure Monitor
  3. In the workspace, go to Agents management → copy Workspace ID and Primary Key
  4. Set the environment variables:
SIEM_SENTINEL_ENDPOINT=https://YOUR_WORKSPACE_ID.ods.opinsights.azure.com
SIEM_SENTINEL_WORKSPACE=YOUR_WORKSPACE_ID
SIEM_SENTINEL_TOKEN=YOUR_PRIMARY_KEY

View logs: Azure Portal → Log Analytics workspace → Logs → query PavriAlerts_CL.

Cost: First 31 days free on a new workspace. After that, pay-per-GB ingestion (~$2.76/GB).

note

The Data Collector API (/api/logs) is a legacy endpoint. For new Azure deployments, consider migrating to the Logs Ingestion API.


IBM QRadar Community Edition (VM — Free, 50 EPS)

  1. Download QRadar CE from the IBM Community (requires free IBM ID)
  2. Deploy the VM image in VMware Workstation or VirtualBox
  3. In QRadar admin console: Admin → Data Sources → Log Sources → Add
  4. Select Syslog as the log source type
  5. Configure the listener IP and port (default: UDP/514)
  6. Set SIEM_QRADAR_ENDPOINT=YOUR_QRADAR_IP:514

Cost: Free. Limited to 50 EPS (events per second). Sufficient for testing and small production deployments.


Helm Chart Configuration

Add SIEM environment variables to your Helm values.yaml:

services:
alert:
env:
SIEM_SPLUNK_ENDPOINT: "https://splunk.internal:8088"
SIEM_SPLUNK_TOKEN: "" # Set via external-secrets or sealed-secrets
SIEM_ELASTIC_ENDPOINT: "https://elastic.internal:9200"

For secrets, use Kubernetes secrets or the external-secrets-operator:

# values.yaml
services:
alert:
envFrom:
- secretRef:
name: pavri-siem-credentials

Observability

SIEM forwarding failures are logged at WARN level by the alert service:

alert-svc: SIEM forwarding enabled for 2 target(s)
siem: forward to splunk failed (alert=alert-abc123): splunk: unexpected status 503

SIEM failures do not appear as alert status=failed — the alert record's delivery status only reflects primary channel delivery.


Integration Testing

Pavri includes end-to-end integration tests that verify alerts are actually ingested by real Splunk and Elasticsearch instances running in Docker containers.

Prerequisites

  • Docker and Docker Compose v2
  • Go 1.21+
  • Ports 8088, 8089, 9200 available on localhost

Quick Start

Run the full test cycle (start containers, run tests, tear down):

./scripts/siem-test.sh

Step-by-Step

  1. Start the SIEM test stack:
./scripts/siem-test.sh --up

This starts Splunk (with HEC pre-configured) and Elasticsearch (single-node, security disabled) in Docker, then waits for both to become healthy. Splunk typically takes 2-3 minutes to start.

  1. Run the integration tests:
go test -tags integration ./services/alert/internal/siem/ -v -count=1 -timeout 120s

The tests will:

  • Forward test alerts to Splunk HEC and verify them via the Splunk REST search API
  • Forward test alerts to Elasticsearch and verify them via the _search API
  • Test the multi-SIEM dispatcher against both systems simultaneously
  1. Tear down:
./scripts/siem-test.sh --down

Test Architecture

The integration tests use the //go:build integration build tag, so they never run during normal go test ./... invocations. Each test also checks TCP reachability before running and calls t.Skip() if the target service is not available.

TestWhat it verifies
TestSplunkForwarder_IntegrationAlert forwarded via HEC, searchable via REST API, correct fields indexed
TestElasticForwarder_IntegrationAlert indexed via Bulk API, searchable via _search, correct document structure
TestMultiSIEMDispatcher_IntegrationSingle alert appears in both Splunk and Elasticsearch

The Docker Compose file is at services/alert/internal/siem/testdata/docker-compose.siem-test.yml.


Troubleshooting

SymptomLikely CauseResolution
No events in SplunkHEC not enabled, or wrong tokenSettings → Data Inputs → HTTP Event Collector → verify token
splunk: unexpected status 401Invalid HEC tokenRegenerate token in Splunk HEC settings
splunk: unexpected status 400Malformed event (sourcetype issue)Verify SIEM_SPLUNK_INDEX matches a valid sourcetype
elastic: unexpected status 400Wrong Content-Type or index routingCheck index template; re-create index if schema mismatch
sentinel: build signature: decode workspace keyWorkspace key is not valid base64Copy the primary key directly from Azure Portal (it is already base64)
No events in QRadarUDP packet lost or wrong portTry TCP: set SIEM_QRADAR_ENDPOINT=tcp:<host>:514
All SIEM errors but alerts still deliveredExpected — SIEM is fail-openCheck logs; primary alert channels are unaffected