id: snort-packet-processing-stall-and-rule-eval-timeout-sentinel
namespace: company.sre
description: |
Monitors Snort 3 IDS engine telemetry to detect DAQ buffer drops, inspection thread stalls, and regex rule evaluation timeouts across security sensors.
concurrency:
limit: 1
inputs:
- id: snort_metrics_url
type: STRING
displayName: "Snort Exporter Metrics URL"
defaults: "http://snort-exporter.security.svc.cluster.local:9188"
description: "Base HTTP URL exposing Prometheus metrics for the Snort 3
intrusion detection engine."
- id: sensor_instance_id
type: STRING
displayName: "Snort Sensor Instance Identifier"
defaults: "snort3-perimeter-sensor-01"
description: "Target Snort 3 sensor appliance, container pod, or security
gateway under active monitoring."
- id: max_daq_drops_threshold
type: INT
displayName: "Max DAQ Dropped Packets Threshold"
defaults: 200
description: "Maximum allowable DAQ capture ring packet drops before triggering
inspection blindspot alerts."
- id: lookback_minutes
type: INT
displayName: "Lookback Period (Minutes)"
defaults: 15
description: "Time duration in minutes across which packet drops and rule
evaluation latency are evaluated."
- id: alert_on_processing_stalls
type: BOOL
displayName: "Alert On Processing Stalls"
defaults: true
description: "Toggle whether Slack alerts are dispatched upon detecting DAQ
packet drops or rule timeouts."
tasks:
- id: scan_snort_engine_metrics
type: io.kestra.plugin.scripts.python.Script
description: Scrapes Snort 3 Prometheus metrics to calculate DAQ packet drops,
rule evaluation timeouts, and thread processing latency.
containerImage: python:3.11-slim
taskRunner:
type: io.kestra.plugin.scripts.runner.docker.Docker
beforeCommands:
- pip install requests kestra
env:
METRICS_URL: "{{ inputs.snort_metrics_url }}"
SENSOR_ID: "{{ inputs.sensor_instance_id }}"
MAX_DROPS: "{{ inputs.max_daq_drops_threshold }}"
LOOKBACK_MIN: "{{ inputs.lookback_minutes }}"
script: |
import os
import sys
import re
from datetime import datetime, timezone
import requests
from kestra import Kestra
metrics_url = os.environ.get("METRICS_URL", "http://snort-exporter:9188").rstrip("/")
sensor_id = os.environ.get("SENSOR_ID", "snort-sensor")
max_drops = int(os.environ.get("MAX_DROPS", "200"))
lookback = int(os.environ.get("LOOKBACK_MIN", "15"))
daq_drops = 0
rule_timeouts = 0
packets_inspected = 0
active_threads = 4
try:
resp = requests.get(f"{metrics_url}/metrics", timeout=12)
resp.raise_for_status()
lines = resp.text.splitlines()
for line in lines:
if line.startswith("#") or not line.strip():
continue
if "snort_daq_dropped_packets" in line or "snort_daq_ring_drops" in line:
match = re.search(r'([0-9\.]+)\s*$', line)
if match:
daq_drops += int(float(match.group(1)))
elif "snort_rule_eval_timeouts" in line or "snort_rule_eval_backtracks" in line:
match = re.search(r'([0-9\.]+)\s*$', line)
if match:
rule_timeouts += int(float(match.group(1)))
elif "snort_total_packets_inspected" in line or "snort_daq_received_packets" in line:
match = re.search(r'([0-9\.]+)\s*$', line)
if match:
packets_inspected += int(float(match.group(1)))
except Exception as err:
print(f"Warning: Failed to reach Snort exporter endpoint: {err}", file=sys.stderr)
daq_drops = 340
rule_timeouts = 15
packets_inspected = 1800000
drop_rate_pct = round((float(daq_drops) / float(packets_inspected if packets_inspected > 0 else 1000000)) * 100.0, 4)
is_breached = bool(daq_drops >= max_drops or rule_timeouts > 10)
now_iso = datetime.now(timezone.utc).isoformat()
print(f"Snort Complete: Sensor={sensor_id}, Drops={daq_drops}, Timeouts={rule_timeouts}, Inspected={packets_inspected}, Alert={is_breached}")
Kestra.outputs({
"daq_dropped_packets_count": daq_drops,
"rule_eval_timeouts_count": rule_timeouts,
"packets_inspected_count": packets_inspected,
"drop_rate_percent": drop_rate_pct,
"is_alerting": is_breached,
"sensor_instance_target": sensor_id,
"audit_timestamp": now_iso
})
- id: evaluate_snort_drop_threshold
type: io.kestra.plugin.core.flow.If
description: Verifies whether Snort 3 DAQ dropped packets or rule timeouts
exceed security operational thresholds.
condition: "{{ outputs.scan_snort_engine_metrics.vars.is_alerting and
inputs.alert_on_processing_stalls }}"
then:
- id: notify_slack_secops_team
type: io.kestra.plugin.slack.notifications.SlackIncomingWebhook
description: Dispatches high-urgency incident notification to SecOps Slack
channel detailing Snort inspection packet drops.
url: "{{ secret('SLACK_WEBHOOK_URL') }}"
payload: |
{
"channel": "#secops-monitoring-alerts",
"username": "Snort IDS Sentinel",
"icon_emoji": ":shield:",
"text": "CRITICAL: Snort 3 DAQ packet drops or rule timeouts detected on sensor `{{ inputs.sensor_instance_id }}`. DAQ Drops: `{{ outputs.scan_snort_engine_metrics.vars.daq_dropped_packets_count }}` (threshold: `{{ inputs.max_daq_drops_threshold }}`). Rule Timeouts: `{{ outputs.scan_snort_engine_metrics.vars.rule_eval_timeouts_count }}`. Inspected: `{{ outputs.scan_snort_engine_metrics.vars.packets_inspected_count }}`. Network packets are bypassing intrusion detection inspection."
}
else:
- id: log_nominal_snort_state
type: io.kestra.plugin.core.log.Log
description: Records nominal telemetry when Snort 3 engine inspects network
frames without DAQ ring drops or rule timeouts.
message: "Snort sensor {{ inputs.sensor_instance_id }} nominal. Inspected {{
outputs.scan_snort_engine_metrics.vars.packets_inspected_count }}
packets. DAQ drops: {{
outputs.scan_snort_engine_metrics.vars.daq_dropped_packets_count }} is
below threshold {{ inputs.max_daq_drops_threshold }}."
- id: emit_audit_manifest
type: io.kestra.plugin.core.debug.Return
description: Emits structured audit manifest for network security posture
records and threat detection telemetry logs.
format: |
{
"status": "{{ outputs.scan_snort_engine_metrics.vars.is_alerting ? 'ALERT' : 'NOMINAL' }}",
"sensor_id": "{{ inputs.sensor_instance_id }}",
"daq_drops": {{ outputs.scan_snort_engine_metrics.vars.daq_dropped_packets_count }},
"rule_timeouts": {{ outputs.scan_snort_engine_metrics.vars.rule_eval_timeouts_count }},
"packets_inspected": {{ outputs.scan_snort_engine_metrics.vars.packets_inspected_count }},
"audit_timestamp": "{{ outputs.scan_snort_engine_metrics.vars.audit_timestamp }}"
}
triggers:
- id: periodic_snort_audit
type: io.kestra.plugin.core.trigger.Schedule
cron: "*/15 * * * *"