diff --git a/package/secubox/luci-app-crowdsec-dashboard/htdocs/luci-static/resources/view/crowdsec-dashboard/overview.js b/package/secubox/luci-app-crowdsec-dashboard/htdocs/luci-static/resources/view/crowdsec-dashboard/overview.js index cebcb868..06bfebea 100644 --- a/package/secubox/luci-app-crowdsec-dashboard/htdocs/luci-static/resources/view/crowdsec-dashboard/overview.js +++ b/package/secubox/luci-app-crowdsec-dashboard/htdocs/luci-static/resources/view/crowdsec-dashboard/overview.js @@ -91,11 +91,14 @@ return view.extend({ }, renderStats: function(d) { + var totalBans = (d.total_decisions || 0) + (d.capi_decisions || 0) + (d.local_decisions || 0); + // Use total_decisions if set, otherwise sum capi + local + if (d.total_decisions > 0) totalBans = d.total_decisions; var stats = [ - { label: 'Active Bans', value: d.total_decisions || 0, type: (d.total_decisions || 0) > 0 ? 'danger' : '' }, + { label: 'CAPI Blocklist', value: d.capi_decisions || 0, type: (d.capi_decisions || 0) > 0 ? 'success' : '' }, + { label: 'Local Bans', value: d.local_decisions || 0, type: (d.local_decisions || 0) > 0 ? 'danger' : '' }, { label: 'Alerts (24h)', value: d.alerts_24h || 0, type: (d.alerts_24h || 0) > 10 ? 'warning' : '' }, { label: 'Scenarios', value: d.scenario_count || 0, type: 'success' }, - { label: 'Parsers', value: d.parser_count || 0, type: '' }, { label: 'Bouncers', value: d.bouncer_count || 0, type: (d.bouncer_count || 0) > 0 ? 'success' : 'warning' }, { label: 'Countries', value: Object.keys(d.countries || {}).length, type: '' } ]; diff --git a/package/secubox/luci-app-crowdsec-dashboard/root/usr/libexec/rpcd/luci.crowdsec-dashboard b/package/secubox/luci-app-crowdsec-dashboard/root/usr/libexec/rpcd/luci.crowdsec-dashboard index 6218762e..a791d7a4 100755 --- a/package/secubox/luci-app-crowdsec-dashboard/root/usr/libexec/rpcd/luci.crowdsec-dashboard +++ b/package/secubox/luci-app-crowdsec-dashboard/root/usr/libexec/rpcd/luci.crowdsec-dashboard @@ -265,17 +265,21 @@ get_dashboard_stats() { check_cscli json_init - - # Count decisions - local decisions_count - decisions_count=$(run_cscli decisions list -o json 2>/dev/null | jsonfilter -e '@[*]' 2>/dev/null | wc -l) + + # Count decisions - local + CAPI + local local_decisions capi_decisions decisions_count + local_decisions=$(run_cscli decisions list --no-api -o json 2>/dev/null | jsonfilter -e '@[*]' 2>/dev/null | wc -l) + capi_decisions=$(run_cscli metrics 2>/dev/null | grep 'CAPI.*ban' | awk -F'|' '{sum += $5} END {print sum+0}') + decisions_count=$((local_decisions + capi_decisions)) json_add_int "total_decisions" "${decisions_count:-0}" - + json_add_int "local_decisions" "${local_decisions:-0}" + json_add_int "capi_decisions" "${capi_decisions:-0}" + # Count alerts (last 24h) local alerts_count alerts_count=$(run_cscli alerts list -o json --since 24h 2>/dev/null | jsonfilter -e '@[*]' 2>/dev/null | wc -l) json_add_int "alerts_24h" "${alerts_count:-0}" - + # Count bouncers local bouncers_count bouncers_count=$(run_cscli bouncers list -o json 2>/dev/null | jsonfilter -e '@[*]' 2>/dev/null | wc -l) @@ -1893,17 +1897,22 @@ get_health_check() { fi json_add_int "bouncer_count" "${bouncer_count:-0}" - # Total decisions count - local decisions_count=0 + # Total decisions count (local + CAPI from metrics) + local local_decisions=0 capi_decisions=0 decisions_count=0 if [ -x "$CSCLI" ]; then - decisions_count=$(run_cscli decisions list -o json 2>/dev/null | jsonfilter -e '@[*].decisions[*]' 2>/dev/null | wc -l) + local_decisions=$(run_cscli decisions list --no-api -o json 2>/dev/null | jsonfilter -e '@[*]' 2>/dev/null | wc -l) + capi_decisions=$(run_cscli metrics 2>/dev/null | grep 'CAPI.*ban' | awk -F'|' '{sum += $5} END {print sum+0}') + decisions_count=$((local_decisions + capi_decisions)) fi json_add_int "decisions_count" "${decisions_count:-0}" + json_add_int "local_decisions" "${local_decisions:-0}" + json_add_int "capi_decisions" "${capi_decisions:-0}" json_dump } # Get CAPI blocklist metrics (decisions by origin and reason) +# Parses from cscli metrics output since decisions list doesn't show CAPI decisions get_capi_metrics() { json_init @@ -1914,59 +1923,37 @@ get_capi_metrics() { return fi - # Get all decisions - local decisions_output="" - decisions_output=$(run_cscli decisions list -o json 2>/dev/null) - - if [ -z "$decisions_output" ] || [ "$decisions_output" = "null" ]; then - json_add_boolean "available" 1 - json_add_int "total_capi" 0 - json_add_int "total_local" 0 - json_add_string "breakdown" "[]" - json_dump - return - fi - json_add_boolean "available" 1 - # Count by origin - local capi_count=0 - local local_count=0 + # Get metrics output + local metrics_output="" + metrics_output=$(run_cscli metrics 2>/dev/null) - # Parse decisions and count by origin - # The structure is: [{decisions: [...], ...}, ...] - # We need to count decisions where origin = "CAPI" or "crowdsec" + # Parse Local API Decisions section from metrics + # Format: | reason | origin | action | count | + local capi_total=0 + local local_total=0 - # Use a temp file for aggregation - local tmp_file="/tmp/capi_metrics.$$" + # Extract CAPI decisions count + capi_total=$(echo "$metrics_output" | grep 'CAPI.*ban' | awk -F'|' '{sum += $5} END {print sum+0}') - # Extract all decisions with their origin and scenario - echo "$decisions_output" | jsonfilter -e '@[*].decisions[*]' 2>/dev/null | while read -r decision; do - local origin=$(echo "$decisions_output" | jsonfilter -e '@[*].decisions[*].origin' 2>/dev/null | head -1) - local scenario=$(echo "$decisions_output" | jsonfilter -e '@[*].scenario' 2>/dev/null | head -1) - echo "$origin|$scenario" - done > "$tmp_file" 2>/dev/null + # Extract local decisions count (origin = crowdsec or cscli) + local_total=$(echo "$metrics_output" | grep -E '(crowdsec|cscli).*ban' | awk -F'|' '{sum += $5} END {print sum+0}') - # Count CAPI decisions by scenario using awk - capi_count=$(echo "$decisions_output" | grep -o '"origin":"CAPI"' 2>/dev/null | wc -l) - local_count=$(echo "$decisions_output" | grep -o '"origin":"crowdsec"' 2>/dev/null | wc -l) + json_add_int "total_capi" "${capi_total:-0}" + json_add_int "total_local" "${local_total:-0}" - json_add_int "total_capi" "${capi_count:-0}" - json_add_int "total_local" "${local_count:-0}" - - # Build breakdown by scenario for CAPI decisions - # Parse the JSON more carefully + # Build breakdown by scenario from metrics - parse lines with ban action json_add_array "breakdown" - # Extract unique scenarios and their counts from CAPI decisions - local scenarios="" - scenarios=$(echo "$decisions_output" | grep -oE '"scenario":"[^"]*"' | sort | uniq -c | sort -rn | head -10) - - echo "$scenarios" | while read -r count scenario; do - if [ -n "$count" ] && [ -n "$scenario" ]; then - local name=$(echo "$scenario" | sed 's/"scenario":"//; s/"$//') + echo "$metrics_output" | grep '|.*ban.*|' | grep -v "Action" | while IFS='|' read -r _ reason origin action count _; do + reason=$(echo "$reason" | xargs) + origin=$(echo "$origin" | xargs) + count=$(echo "$count" | xargs) + if [ -n "$reason" ] && [ -n "$count" ] && [ "$count" != "Count" ]; then json_add_object "" - json_add_string "scenario" "$name" + json_add_string "scenario" "$reason" + json_add_string "origin" "$origin" json_add_int "count" "$count" json_close_object fi @@ -1974,8 +1961,6 @@ get_capi_metrics() { json_close_array - rm -f "$tmp_file" 2>/dev/null - json_dump } @@ -2184,16 +2169,28 @@ get_overview() { # Quick stats local decisions_count=0 + local local_decisions=0 + local capi_decisions=0 local alerts_count=0 local bouncers_count=0 if [ "$cs_running" = "1" ] && [ -x "$CSCLI" ]; then - decisions_count=$(run_cscli decisions list -o json 2>/dev/null | jsonfilter -e '@[*]' 2>/dev/null | wc -l) + # Local decisions (from local scenarios) + local_decisions=$(run_cscli decisions list --no-api -o json 2>/dev/null | jsonfilter -e '@[*]' 2>/dev/null | wc -l) + + # CAPI decisions (blocklists) - parse from metrics output + capi_decisions=$(run_cscli metrics 2>/dev/null | grep 'CAPI.*ban' | awk -F'|' '{sum += $5} END {print sum+0}') + + # Total decisions + decisions_count=$((local_decisions + capi_decisions)) + alerts_count=$(run_cscli alerts list -o json --since 24h --limit 100 2>/dev/null | jsonfilter -e '@[*]' 2>/dev/null | wc -l) bouncers_count=$(run_cscli bouncers list -o json 2>/dev/null | jsonfilter -e '@[*]' 2>/dev/null | wc -l) fi json_add_int "total_decisions" "${decisions_count:-0}" + json_add_int "local_decisions" "${local_decisions:-0}" + json_add_int "capi_decisions" "${capi_decisions:-0}" json_add_int "alerts_24h" "${alerts_count:-0}" json_add_int "bouncers" "${bouncers_count:-0}"