From 375f0689626c091f41e1f965c35065c238355a52 Mon Sep 17 00:00:00 2001 From: jjediny Date: Sun, 26 Jul 2026 15:22:59 -0400 Subject: [PATCH] feat: deploy rsigma daemon sidecar and OTel logging pipeline --- alerts/webhook/notify.sh | 19 +++++---- docker-compose.yaml | 23 +++++++++++ otel-collector-config.yaml | 7 ++++ rules/sigma/rsigma.yaml | 4 +- rules/sigma/webhooks/alert_receiver.yaml | 10 +++++ tests/test_alert_receiver_integration.py | 49 ++++++++++++++++++++++++ tests/test_infrastructure_health.py | 4 +- tools/health-monitor.sh | 2 +- 8 files changed, 107 insertions(+), 11 deletions(-) create mode 100644 rules/sigma/webhooks/alert_receiver.yaml diff --git a/alerts/webhook/notify.sh b/alerts/webhook/notify.sh index aa285c7..238b9fd 100644 --- a/alerts/webhook/notify.sh +++ b/alerts/webhook/notify.sh @@ -45,16 +45,21 @@ ALERT_ID="$(date +%s%N | cut -c1-13)" # --- Output 1: Log to stdout (captured by Docker) --- echo "[${TIMESTAMP}] ALERT | ${TITLE} | ${BODY}" -# --- Output 2: File-based bridge for host notifications --- -# Write alert to a file that the host-side watcher reads and triggers notify-send +# Escape double quotes for JSON safety +SAFE_ALERT_NAME=$(echo "$ALERT_NAME" | sed 's/"/\\"/g') +SAFE_SEVERITY=$(echo "$SEVERITY" | sed 's/"/\\"/g') +SAFE_DESCRIPTION=$(echo "$DESCRIPTION" | sed 's/"/\\"/g') +SAFE_TITLE=$(echo "$TITLE" | sed 's/"/\\"/g') +SAFE_BODY=$(echo "$BODY" | sed 's/"/\\"/g') + cat > "${ALERT_DIR}/${ALERT_ID}.json" <= start - 1: + newest = candidate + break + time.sleep(0.5) + + assert newest is not None, "No alert file created by alert-receiver for RSigma" + + data = json.loads(newest.read_text(encoding="utf-8")) + assert data.get("alert_name") == "Suspicious Namespace Unshare Command" + assert data.get("severity") == "high" + assert "Rule ID: 718c5dbc-b1a3-419b-a329-e7721d294257" in data.get("description", "") + + # cleanup the alert file created by this test + try: + newest.unlink() + except OSError: + pass diff --git a/tests/test_infrastructure_health.py b/tests/test_infrastructure_health.py index 6df10ba..8424550 100644 --- a/tests/test_infrastructure_health.py +++ b/tests/test_infrastructure_health.py @@ -27,7 +27,7 @@ def test_compose_has_healthchecks_for_critical_services() -> None: compose = _load_compose() services = compose.get("services", {}) - critical_services = {"falco", "openobserve", "otel-collector", "alert-receiver"} + critical_services = {"falco", "openobserve", "otel-collector", "alert-receiver", "rsigma"} for svc_name in critical_services: svc = services.get(svc_name, {}) assert "healthcheck" in svc, ( @@ -71,7 +71,7 @@ def test_health_monitor_has_dead_mans_switch() -> None: def test_health_monitor_checks_all_services() -> None: """Health monitor must check required services and account for optional scan services.""" script = (REPO_ROOT / "tools" / "health-monitor.sh").read_text() - for svc in ("falco", "openobserve", "otel-collector"): + for svc in ("falco", "openobserve", "otel-collector", "rsigma"): assert svc in script, f"Health monitor should check {svc}" for svc in ("clamav", "clamav-scanner"): assert svc in script, f"Health monitor should mention optional service {svc}" diff --git a/tools/health-monitor.sh b/tools/health-monitor.sh index 4a69076..36cf05a 100755 --- a/tools/health-monitor.sh +++ b/tools/health-monitor.sh @@ -14,7 +14,7 @@ DISK_WARN_PERCENT=85 DISK_CRIT_PERCENT=95 LOG_FILE="${DATA_DIR}/health/health-monitor.log" -SERVICES=("falco" "openobserve" "otel-collector") +SERVICES=("falco" "openobserve" "otel-collector" "rsigma") OPTIONAL_SERVICES=("clamav" "clamav-scanner") mkdir -p "$(dirname "$HEARTBEAT_FILE")"