fix(crowdsec): Fix alerts extraction in overview collector

Replace failing awk-based JSON parsing with jsonfilter per-alert extraction.
Alerts now correctly populate in CrowdSec dashboard.

Changes:
- Use jsonfilter to extract created_at, scenario, source_ip per alert
- Loop through up to 8 alerts with index-based access
- Remove Python dependency (not available on OpenWrt)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
CyberMind-FR 2026-02-10 06:07:57 +01:00
parent 8b1c82ab5c
commit a694241604

View File

@ -0,0 +1,155 @@
#!/bin/sh
# SecuBox CrowdSec Overview Collector v5
# Generates JSON cache for dashboard - simplified alerts collection
CACHE_DIR="/tmp/secubox"
CACHE_FILE="$CACHE_DIR/crowdsec-overview.json"
CACHE_TMP="$CACHE_DIR/crowdsec-overview.tmp"
CSCLI="/usr/bin/cscli"
. /usr/share/libubox/jshn.sh
mkdir -p "$CACHE_DIR"
generate_overview() {
local cs_running=0
pgrep crowdsec >/dev/null 2>&1 && cs_running=1
local bouncer_running=0
pgrep -f "crowdsec-firewall-bouncer" >/dev/null 2>&1 && bouncer_running=1
local version="unknown"
[ -x "$CSCLI" ] && version=$("$CSCLI" version 2>/dev/null | grep -oE '[0-9]+\.[0-9]+\.[0-9]+' | head -1)
[ -z "$version" ] && version="unknown"
local decisions_count=0 local_decisions=0 capi_decisions=0
local alerts_count=0 bouncers_count=0 scenario_count=0
if [ "$cs_running" = "1" ] && [ -x "$CSCLI" ]; then
local_decisions=$("$CSCLI" decisions list --no-api -o json 2>/dev/null | jsonfilter -e '@[*]' 2>/dev/null | wc -l)
[ -z "$local_decisions" ] && local_decisions=0
decisions_count=$local_decisions
alerts_count=$("$CSCLI" alerts list -o json --since 24h --limit 500 2>/dev/null | jsonfilter -e '@[*]' 2>/dev/null | wc -l)
[ -z "$alerts_count" ] && alerts_count=0
bouncers_count=$("$CSCLI" bouncers list -o json 2>/dev/null | jsonfilter -e '@[*]' 2>/dev/null | wc -l)
[ -z "$bouncers_count" ] && bouncers_count=0
scenario_count=$("$CSCLI" scenarios list -o json 2>/dev/null | jsonfilter -e '@[*]' 2>/dev/null | wc -l)
[ -z "$scenario_count" ] && scenario_count=0
fi
local geoip_enabled=0
[ -f "/srv/crowdsec/data/GeoLite2-City.mmdb" ] && geoip_enabled=1
[ -f "/var/lib/crowdsec/data/GeoLite2-City.mmdb" ] && geoip_enabled=1
local acquisition_count=0
[ -d "/etc/crowdsec/acquis.d" ] && acquisition_count=$(ls -1 /etc/crowdsec/acquis.d/*.yaml 2>/dev/null | wc -l)
local lapi_ok=0
local lapi_port=8080
lapi_port=$(grep -oE ':[0-9]+/?$' /etc/crowdsec/local_api_credentials.yaml 2>/dev/null | tr -d ':/' || echo 8080)
[ -z "$lapi_port" ] && lapi_port=8080
local lapi_port_hex=$(printf '%04X' "$lapi_port")
[ "$cs_running" = "1" ] && grep -qi ":${lapi_port_hex} " /proc/net/tcp 2>/dev/null && lapi_ok=1
local capi_enrolled=0
[ -f /etc/crowdsec/online_api_credentials.yaml ] && capi_enrolled=1
local waf_autoban_enabled=$(uci -q get mitmproxy.autoban.enabled 2>/dev/null || echo 0)
local waf_sensitivity=$(uci -q get mitmproxy.autoban.sensitivity 2>/dev/null || echo "moderate")
local waf_bans_today=0 waf_threats_today=0 waf_autoban_total=0
[ "$cs_running" = "1" ] && waf_bans_today=$("$CSCLI" decisions list -o json 2>/dev/null | grep -c "mitmproxy-waf" 2>/dev/null || echo 0)
local threats_log="/srv/mitmproxy/threats.log"
if [ -f "$threats_log" ]; then
local today=$(date -u +%Y-%m-%d)
waf_threats_today=$(grep -c "\"timestamp\": \"$today" "$threats_log" 2>/dev/null || echo 0)
fi
local autoban_log="/srv/mitmproxy/autoban-processed.log"
[ -f "$autoban_log" ] && waf_autoban_total=$(wc -l < "$autoban_log" 2>/dev/null || echo 0)
# Countries
local countries_json="[]"
if [ "$cs_running" = "1" ]; then
countries_json=$("$CSCLI" alerts list -o json --limit 200 2>/dev/null | \
jsonfilter -e '@[*].source.cn' 2>/dev/null | \
grep -v '^$' | sort | uniq -c | sort -rn | head -10 | \
awk 'BEGIN{printf "["} NR>1{printf ","} {printf "{\"country\":\"%s\",\"count\":%d}", $2, $1} END{printf "]"}')
[ -z "$countries_json" ] && countries_json="[]"
fi
# Alerts - extract using jsonfilter per-alert
local alerts_json="[]"
if [ "$cs_running" = "1" ]; then
local alerts_tmp="/tmp/cs_alerts_$$.json"
"$CSCLI" alerts list -o json --limit 8 2>/dev/null > "$alerts_tmp"
if [ -s "$alerts_tmp" ]; then
alerts_json="["
local first=1
for i in 0 1 2 3 4 5 6 7; do
local created=$(jsonfilter -i "$alerts_tmp" -e "@[$i].created_at" 2>/dev/null)
[ -z "$created" ] && break
local scenario=$(jsonfilter -i "$alerts_tmp" -e "@[$i].scenario" 2>/dev/null)
local source_ip=$(jsonfilter -i "$alerts_tmp" -e "@[$i].source.ip" 2>/dev/null)
[ "$first" = "1" ] && first=0 || alerts_json="$alerts_json,"
alerts_json="$alerts_json{\"created_at\":\"$created\",\"scenario\":\"$scenario\",\"source_ip\":\"$source_ip\"}"
done
alerts_json="$alerts_json]"
fi
rm -f "$alerts_tmp"
fi
# Build JSON
json_init
json_add_string "crowdsec" "$([ "$cs_running" = "1" ] && echo running || echo stopped)"
json_add_string "bouncer" "$([ "$bouncer_running" = "1" ] && echo running || echo stopped)"
json_add_string "version" "$version"
json_add_int "total_decisions" "${decisions_count:-0}"
json_add_int "local_decisions" "${local_decisions:-0}"
json_add_int "capi_decisions" "0"
json_add_int "active_bans" "${local_decisions:-0}"
json_add_int "alerts_24h" "${alerts_count:-0}"
json_add_int "bouncer_count" "${bouncers_count:-0}"
json_add_int "scenario_count" "${scenario_count:-0}"
json_add_int "acquisition_count" "${acquisition_count:-0}"
json_add_boolean "geoip_enabled" "$geoip_enabled"
json_add_string "dropped_packets" "0"
json_add_string "dropped_bytes" "0"
json_add_string "processed_packets" "0"
json_add_string "processed_bytes" "0"
json_add_string "lapi_status" "$([ "$lapi_ok" = "1" ] && echo available || echo unavailable)"
json_add_boolean "capi_enrolled" "$capi_enrolled"
json_add_boolean "waf_autoban_enabled" "$waf_autoban_enabled"
json_add_string "waf_sensitivity" "$waf_sensitivity"
json_add_int "waf_bans_today" "${waf_bans_today:-0}"
json_add_int "waf_threats_today" "${waf_threats_today:-0}"
json_add_int "waf_autoban_total" "${waf_autoban_total:-0}"
json_add_string "last_update" "$(date -Iseconds)"
local base_json=$(json_dump)
base_json=$(echo "$base_json" | sed 's/}$//')
{
echo "$base_json,"
printf '"countries": %s,\n' "$countries_json"
printf '"alerts_raw": %s\n' "$alerts_json"
echo "}"
} > "$CACHE_TMP"
if jsonfilter -i "$CACHE_TMP" -e "@" >/dev/null 2>&1; then
mv -f "$CACHE_TMP" "$CACHE_FILE"
echo "CrowdSec overview cache updated: $CACHE_FILE"
else
{
echo "$base_json,"
printf '"countries": %s,\n' "$countries_json"
printf '"alerts_raw": []\n'
echo "}"
} > "$CACHE_TMP"
mv -f "$CACHE_TMP" "$CACHE_FILE"
echo "CrowdSec overview cache updated (fallback): $CACHE_FILE"
fi
}
generate_overview