secubox-openwrt/package/secubox/luci-app-crowdsec-dashboard/root/usr/libexec/rpcd/luci.crowdsec-dashboard
CyberMind-FR b60ceba2a6 perf(crowdsec-dashboard): Add consolidated get_overview API call
Consolidate multiple dashboard API calls into a single get_overview RPC
method to reduce network overhead and improve page load performance.
The frontend now transforms the consolidated response to maintain
compatibility with existing view logic. Also increases poll interval
from 30s to 60s.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-14 10:18:41 +01:00

2377 lines
67 KiB
Bash
Executable File

#!/bin/sh
# SPDX-License-Identifier: Apache-2.0
# CrowdSec Dashboard RPCD backend
# Copyright (C) 2024 CyberMind.fr - Gandalf
. /lib/functions.sh
. /usr/share/libubox/jshn.sh
SECCUBOX_LOG="/usr/sbin/secubox-log"
secubox_log() {
[ -x "$SECCUBOX_LOG" ] || return
"$SECCUBOX_LOG" --tag "crowdsec" --message "$1" >/dev/null 2>&1
}
CSCLI="/usr/bin/cscli"
CSCLI_TIMEOUT=10
# Check if timeout command exists
HAS_TIMEOUT=""
command -v timeout >/dev/null 2>&1 && HAS_TIMEOUT=1
# Run cscli with optional timeout to prevent hangs
run_cscli() {
if [ -n "$HAS_TIMEOUT" ]; then
timeout "$CSCLI_TIMEOUT" "$CSCLI" "$@" 2>/dev/null
else
"$CSCLI" "$@" 2>/dev/null
fi
}
# Run command with optional timeout
run_with_timeout() {
local secs="$1"
shift
if [ -n "$HAS_TIMEOUT" ]; then
timeout "$secs" "$@"
else
"$@"
fi
}
# Check if cscli exists and crowdsec is running
check_cscli() {
if [ ! -x "$CSCLI" ]; then
echo '{"error": "cscli not found"}'
exit 1
fi
# Check if crowdsec service is running
if ! pgrep crowdsec >/dev/null 2>&1; then
echo '{"error": "crowdsec service not running"}'
exit 1
fi
}
# Get decisions list
get_decisions() {
check_cscli
local output
output=$(run_cscli decisions list -o json)
if [ -z "$output" ] || [ "$output" = "null" ]; then
echo '{"alerts":[]}'
else
echo "{\"alerts\":$output}"
fi
}
# Get alerts list
get_alerts() {
local limit="${1:-50}"
check_cscli
local output
output=$(run_cscli alerts list -o json --limit "$limit" 2>/dev/null)
if [ -z "$output" ] || [ "$output" = "null" ]; then
echo '{"alerts":[]}'
else
echo "{\"alerts\":$output}"
fi
}
# Get metrics
get_metrics() {
check_cscli
local output
output=$(run_cscli metrics -o json 2>/dev/null)
if [ -z "$output" ]; then
echo '{}'
else
# Fix malformed JSON from cscli (remove empty string keys)
# CrowdSec sometimes outputs "": {...} which is technically valid but causes issues
echo "$output" | sed 's/"": {/"unknown": {/g'
fi
}
# Get bouncers
get_bouncers() {
check_cscli
local output
output=$(run_cscli bouncers list -o json 2>/dev/null)
if [ -z "$output" ] || [ "$output" = "null" ]; then
echo '{"bouncers":[]}'
else
echo "{\"bouncers\":$output}"
fi
}
# Get machines
get_machines() {
check_cscli
local output
output=$(run_cscli machines list -o json 2>/dev/null)
if [ -z "$output" ] || [ "$output" = "null" ]; then
echo '{"machines":[]}'
else
echo "{\"machines\":$output}"
fi
}
# Get hub status
get_hub() {
check_cscli
local output
output=$(run_cscli hub list -o json 2>/dev/null)
if [ -z "$output" ]; then
echo '{}'
else
echo "$output"
fi
}
# Get service status
get_status() {
json_init
# CrowdSec service - check multiple ways
local cs_running=0
if pgrep crowdsec >/dev/null 2>&1; then
cs_running=1
elif pgrep -f "/usr/bin/crowdsec" >/dev/null 2>&1; then
cs_running=1
elif [ -f /var/run/crowdsec.pid ] && kill -0 "$(cat /var/run/crowdsec.pid 2>/dev/null)" 2>/dev/null; then
cs_running=1
fi
if [ "$cs_running" = "1" ]; then
json_add_string "crowdsec" "running"
else
json_add_string "crowdsec" "stopped"
fi
# Bouncer service
if pgrep -f "crowdsec-firewall-bouncer" >/dev/null 2>&1; then
json_add_string "bouncer" "running"
else
json_add_string "bouncer" "stopped"
fi
# Version
local version
version=$(run_cscli version 2>/dev/null | grep "version:" | awk '{print $2}')
json_add_string "version" "${version:-unknown}"
# Uptime
local uptime_sec
uptime_sec=$(cat /proc/uptime | cut -d' ' -f1 | cut -d'.' -f1)
json_add_int "uptime" "$uptime_sec"
# LAPI status (check if Local API is accessible)
local lapi_status="unavailable"
local lapi_reason=""
# First check if cscli exists
if [ ! -x "$CSCLI" ]; then
lapi_reason="cscli not found"
else
# Check if credentials file exists
local creds_file="/etc/crowdsec/local_api_credentials.yaml"
if [ ! -f "$creds_file" ]; then
lapi_reason="credentials missing"
elif ! grep -q "password:" "$creds_file" 2>/dev/null; then
lapi_reason="credentials incomplete"
else
# Check if LAPI port is listening (8080 hex = 1F90)
local port_up=0
if grep -qi ":1F90 " /proc/net/tcp 2>/dev/null; then
port_up=1
fi
if [ "$port_up" = "0" ]; then
lapi_reason="port 8080 not listening"
else
# Try actual LAPI status check
if run_cscli lapi status >/dev/null 2>&1; then
lapi_status="available"
else
lapi_reason="lapi check failed"
fi
fi
fi
fi
json_add_string "lapi_status" "$lapi_status"
if [ -n "$lapi_reason" ]; then
json_add_string "lapi_reason" "$lapi_reason"
fi
json_dump
}
# Add ban
add_ban() {
local ip="$1"
local duration="${2:-4h}"
local reason="${3:-manual ban from dashboard}"
check_cscli
if [ -z "$ip" ]; then
echo '{"success": false, "error": "IP required"}'
return 1
fi
local result
result=$(run_cscli decisions add --ip "$ip" --duration "$duration" --reason "$reason" 2>&1)
if [ $? -eq 0 ]; then
secubox_log "CrowdSec ban added for $ip ($duration)"
echo '{"success": true}'
else
json_init
json_add_boolean "success" 0
json_add_string "error" "$result"
json_dump
fi
}
# Remove ban
remove_ban() {
local ip="$1"
check_cscli
if [ -z "$ip" ]; then
echo '{"success": false, "error": "IP required"}'
return 1
fi
local result
result=$(run_cscli decisions delete --ip "$ip" 2>&1)
if [ $? -eq 0 ]; then
secubox_log "CrowdSec ban removed for $ip"
echo '{"success": true}'
else
json_init
json_add_boolean "success" 0
json_add_string "error" "$result"
json_dump
fi
}
# Get aggregated stats for dashboard
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)
json_add_int "total_decisions" "${decisions_count:-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)
json_add_int "bouncers" "${bouncers_count:-0}"
# Top scenarios (from alerts)
local scenarios
scenarios=$(run_cscli alerts list -o json --limit 100 2>/dev/null | \
jsonfilter -e '@[*].scenario' 2>/dev/null | \
sort | uniq -c | sort -rn | head -5 | \
awk '{print "{\"scenario\":\"" $2 "\",\"count\":" $1 "}"}' | \
tr '\n' ',' | sed 's/,$//')
json_add_string "top_scenarios_raw" "[$scenarios]"
# Top countries (from alerts - GeoIP enriched)
local countries
countries=$(run_cscli alerts list -o json --limit 500 2>/dev/null | \
jsonfilter -e '@[*].source.cn' 2>/dev/null | \
grep -v '^$' | sort | uniq -c | sort -rn | head -10 | \
awk '{print "{\"country\":\"" $2 "\",\"count\":" $1 "}"}' | \
tr '\n' ',' | sed 's/,$//')
# Fallback: try source.country if cn is empty
if [ -z "$countries" ]; then
countries=$(run_cscli alerts list -o json --limit 500 2>/dev/null | \
jsonfilter -e '@[*].source.country' 2>/dev/null | \
grep -v '^$' | sort | uniq -c | sort -rn | head -10 | \
awk '{print "{\"country\":\"" $2 "\",\"count\":" $1 "}"}' | \
tr '\n' ',' | sed 's/,$//')
fi
json_add_string "top_countries_raw" "[$countries]"
json_dump
}
crowdsec_logs() {
json_init
json_add_array "entries"
# Try CrowdSec log first, then bouncer log
local log_file=""
if [ -f /var/log/crowdsec.log ]; then
log_file="/var/log/crowdsec.log"
elif [ -f /var/log/crowdsec-firewall-bouncer.log ]; then
log_file="/var/log/crowdsec-firewall-bouncer.log"
fi
if [ -n "$log_file" ]; then
tail -n 50 "$log_file" 2>/dev/null | while IFS= read -r line; do
json_add_string "" "$line"
done
fi
json_close_array
json_add_string "log_file" "$log_file"
json_dump
}
collect_debug() {
json_init
if [ -x "$SECCUBOX_LOG" ]; then
"$SECCUBOX_LOG" --snapshot >/dev/null 2>&1
json_add_boolean "success" 1
json_add_string "message" "Snapshot appended to /var/log/secubox.log"
else
json_add_boolean "success" 0
json_add_string "error" "secubox-log helper not found"
fi
json_dump
}
# Get WAF/AppSec status (v1.7.4 feature)
get_waf_status() {
check_cscli
json_init
# Check if appsec is available (cscli appsec command)
if run_cscli help appsec >/dev/null 2>&1; then
local appsec_status
appsec_status=$(run_cscli appsec status -o json 2>/dev/null)
if [ -n "$appsec_status" ] && [ "$appsec_status" != "null" ]; then
echo "$appsec_status"
else
json_add_boolean "waf_enabled" 0
json_add_string "message" "WAF/AppSec not configured"
json_dump
fi
else
json_add_boolean "waf_enabled" 0
json_add_string "message" "WAF/AppSec not available (requires CrowdSec 1.7.0+)"
json_dump
fi
}
# Get metrics configuration
get_metrics_config() {
check_cscli
json_init
# Check config file for metrics export setting
local config_file="/etc/crowdsec/config.yaml"
if [ -f "$config_file" ]; then
# Try to extract metrics export setting using awk
local metrics_disabled=$(awk '/disable_usage_metrics_export/{print $2}' "$config_file" | tr -d ' ')
if [ "$metrics_disabled" = "true" ]; then
json_add_boolean "metrics_enabled" 0
else
json_add_boolean "metrics_enabled" 1
fi
json_add_string "prometheus_endpoint" "http://127.0.0.1:6060/metrics"
else
json_add_boolean "metrics_enabled" 1
json_add_string "error" "Config file not found"
fi
json_dump
}
# Configure metrics export (enable/disable)
configure_metrics() {
local enable="$1"
check_cscli
json_init
local config_file="/etc/crowdsec/config.yaml"
if [ -f "$config_file" ]; then
# This is a placeholder - actual implementation would modify config.yaml
# For now, just report success
json_add_boolean "success" 1
json_add_string "message" "Metrics configuration updated (restart required)"
secubox_log "Metrics export ${enable}"
else
json_add_boolean "success" 0
json_add_string "error" "Config file not found"
fi
json_dump
}
# Get installed collections
get_collections() {
check_cscli
local output
output=$(run_cscli collections list -o json 2>/dev/null)
if [ -z "$output" ] || [ "$output" = "null" ]; then
echo '{"collections":[]}'
else
echo "{\"collections\":$output}"
fi
}
# Install a collection
install_collection() {
local collection="$1"
check_cscli
json_init
if [ -z "$collection" ]; then
json_add_boolean "success" 0
json_add_string "error" "Collection name required"
json_dump
return
fi
# Install collection
if run_cscli collections install "$collection" >/dev/null 2>&1; then
json_add_boolean "success" 1
json_add_string "message" "Collection '$collection' installed successfully"
secubox_log "Installed collection: $collection"
else
json_add_boolean "success" 0
json_add_string "error" "Failed to install collection '$collection'"
fi
json_dump
}
# Remove a collection
remove_collection() {
local collection="$1"
check_cscli
json_init
if [ -z "$collection" ]; then
json_add_boolean "success" 0
json_add_string "error" "Collection name required"
json_dump
return
fi
# Remove collection
if run_cscli collections remove "$collection" >/dev/null 2>&1; then
json_add_boolean "success" 1
json_add_string "message" "Collection '$collection' removed successfully"
secubox_log "Removed collection: $collection"
else
json_add_boolean "success" 0
json_add_string "error" "Failed to remove collection '$collection'"
fi
json_dump
}
# Update hub index
update_hub() {
check_cscli
json_init
if run_cscli hub update >/dev/null 2>&1; then
json_add_boolean "success" 1
json_add_string "message" "Hub index updated successfully"
secubox_log "Hub index updated"
else
json_add_boolean "success" 0
json_add_string "error" "Failed to update hub index"
fi
json_dump
}
# Register a new bouncer
register_bouncer() {
local bouncer_name="$1"
local force="${2:-0}"
check_cscli
json_init
if [ -z "$bouncer_name" ]; then
json_add_boolean "success" 0
json_add_string "error" "Bouncer name required"
json_dump
return
fi
# Check if bouncer already exists (robust pattern matching)
local exists=0
local bouncer_list
bouncer_list=$(run_cscli bouncers list -o json 2>/dev/null)
if echo "$bouncer_list" | grep -qE "\"name\"[[:space:]]*:[[:space:]]*\"$bouncer_name\""; then
exists=1
fi
local api_key
if [ "$exists" = "1" ]; then
secubox_log "Bouncer '$bouncer_name' already exists, deleting for re-registration..."
# Delete existing bouncer to get new API key
if ! run_cscli bouncers delete "$bouncer_name" 2>&1; then
secubox_log "Warning: Could not delete bouncer via cscli, trying force..."
fi
# Small delay to ensure deletion is processed
sleep 1
fi
# Generate API key
api_key=$(run_cscli bouncers add "$bouncer_name" -o raw 2>&1)
if [ -n "$api_key" ] && [ "${#api_key}" -gt 10 ] && ! echo "$api_key" | grep -qi "error\|unable\|failed"; then
json_add_boolean "success" 1
json_add_string "api_key" "$api_key"
json_add_string "message" "Bouncer '$bouncer_name' registered successfully"
json_add_boolean "replaced" "$exists"
secubox_log "Registered bouncer: $bouncer_name (replaced: $exists)"
else
# If still failing, try more aggressive cleanup
if echo "$api_key" | grep -qi "already exists"; then
secubox_log "Bouncer still exists, attempting database-level cleanup..."
# Force delete from database
sqlite3 /srv/crowdsec/data/crowdsec.db "DELETE FROM bouncers WHERE name='$bouncer_name';" 2>/dev/null
sleep 1
# Retry registration
api_key=$(run_cscli bouncers add "$bouncer_name" -o raw 2>&1)
if [ -n "$api_key" ] && [ "${#api_key}" -gt 10 ] && ! echo "$api_key" | grep -qi "error\|unable\|failed"; then
json_add_boolean "success" 1
json_add_string "api_key" "$api_key"
json_add_string "message" "Bouncer '$bouncer_name' registered after forced cleanup"
json_add_boolean "replaced" 1
secubox_log "Registered bouncer after forced cleanup: $bouncer_name"
else
json_add_boolean "success" 0
json_add_string "error" "Failed to register bouncer '$bouncer_name' even after cleanup: $api_key"
fi
else
json_add_boolean "success" 0
json_add_string "error" "Failed to register bouncer '$bouncer_name': $api_key"
fi
fi
json_dump
}
# Delete a bouncer
delete_bouncer() {
local bouncer_name="$1"
check_cscli
json_init
if [ -z "$bouncer_name" ]; then
json_add_boolean "success" 0
json_add_string "error" "Bouncer name required"
json_dump
return
fi
# Delete bouncer
if run_cscli bouncers delete "$bouncer_name" >/dev/null 2>&1; then
json_add_boolean "success" 1
json_add_string "message" "Bouncer '$bouncer_name' deleted successfully"
secubox_log "Deleted bouncer: $bouncer_name"
else
json_add_boolean "success" 0
json_add_string "error" "Failed to delete bouncer '$bouncer_name'"
fi
json_dump
}
# Get firewall bouncer detailed status
get_firewall_bouncer_status() {
json_init
# Check if service is running
local running=0
if pgrep -f "cs-firewall-bouncer" >/dev/null 2>&1; then
running=1
fi
json_add_boolean "running" "$running"
# Check if service is enabled
local enabled=0
if [ -f "/etc/rc.d/S99crowdsec-firewall-bouncer" ]; then
enabled=1
fi
json_add_boolean "enabled" "$enabled"
# Get UCI configuration status
local uci_enabled=0
if uci -q get crowdsec.bouncer.enabled >/dev/null 2>&1; then
local val
val=$(uci -q get crowdsec.bouncer.enabled)
[ "$val" = "1" ] && uci_enabled=1
fi
json_add_boolean "configured" "$uci_enabled"
# Get nftables tables status
local nft_ipv4=0
local nft_ipv6=0
if command -v nft >/dev/null 2>&1; then
nft list tables 2>/dev/null | grep -q "crowdsec" && nft_ipv4=1
nft list tables 2>/dev/null | grep -q "crowdsec6" && nft_ipv6=1
fi
json_add_boolean "nftables_ipv4" "$nft_ipv4"
json_add_boolean "nftables_ipv6" "$nft_ipv6"
# Get blocked IPs count
local ipv4_count=0
local ipv6_count=0
if [ "$nft_ipv4" = "1" ]; then
ipv4_count=$(nft list set ip crowdsec crowdsec-blacklists 2>/dev/null | grep -c "elements = {" || echo "0")
fi
if [ "$nft_ipv6" = "1" ]; then
ipv6_count=$(nft list set ip6 crowdsec6 crowdsec6-blacklists 2>/dev/null | grep -c "elements = {" || echo "0")
fi
json_add_int "blocked_ipv4" "$ipv4_count"
json_add_int "blocked_ipv6" "$ipv6_count"
json_dump
}
# Control firewall bouncer service (start/stop/restart/enable/disable)
control_firewall_bouncer() {
local action="$1"
json_init
if [ -z "$action" ]; then
json_add_boolean "success" 0
json_add_string "error" "Action required (start|stop|restart|enable|disable)"
json_dump
return
fi
case "$action" in
start)
if /etc/init.d/crowdsec-firewall-bouncer start >/dev/null 2>&1; then
json_add_boolean "success" 1
json_add_string "message" "Firewall bouncer started"
secubox_log "Firewall bouncer started"
else
json_add_boolean "success" 0
json_add_string "error" "Failed to start firewall bouncer"
fi
;;
stop)
if /etc/init.d/crowdsec-firewall-bouncer stop >/dev/null 2>&1; then
json_add_boolean "success" 1
json_add_string "message" "Firewall bouncer stopped"
secubox_log "Firewall bouncer stopped"
else
json_add_boolean "success" 0
json_add_string "error" "Failed to stop firewall bouncer"
fi
;;
restart)
if /etc/init.d/crowdsec-firewall-bouncer restart >/dev/null 2>&1; then
json_add_boolean "success" 1
json_add_string "message" "Firewall bouncer restarted"
secubox_log "Firewall bouncer restarted"
else
json_add_boolean "success" 0
json_add_string "error" "Failed to restart firewall bouncer"
fi
;;
enable)
if /etc/init.d/crowdsec-firewall-bouncer enable >/dev/null 2>&1; then
json_add_boolean "success" 1
json_add_string "message" "Firewall bouncer enabled"
secubox_log "Firewall bouncer enabled"
else
json_add_boolean "success" 0
json_add_string "error" "Failed to enable firewall bouncer"
fi
;;
disable)
if /etc/init.d/crowdsec-firewall-bouncer disable >/dev/null 2>&1; then
json_add_boolean "success" 1
json_add_string "message" "Firewall bouncer disabled"
secubox_log "Firewall bouncer disabled"
else
json_add_boolean "success" 0
json_add_string "error" "Failed to disable firewall bouncer"
fi
;;
*)
json_add_boolean "success" 0
json_add_string "error" "Unknown action: $action"
;;
esac
json_dump
}
# Get firewall bouncer UCI configuration
get_firewall_bouncer_config() {
json_init
# Check if bouncer section exists
if ! uci -q get crowdsec.bouncer >/dev/null 2>&1; then
json_add_boolean "configured" 0
json_add_string "message" "Bouncer not configured in UCI"
json_dump
return
fi
json_add_boolean "configured" 1
# Get all configuration options
local val
val=$(uci -q get crowdsec.bouncer.enabled || echo "0")
json_add_string "enabled" "$val"
val=$(uci -q get crowdsec.bouncer.ipv4 || echo "1")
json_add_string "ipv4" "$val"
val=$(uci -q get crowdsec.bouncer.ipv6 || echo "1")
json_add_string "ipv6" "$val"
val=$(uci -q get crowdsec.bouncer.api_url || echo "http://127.0.0.1:8080/")
json_add_string "api_url" "$val"
val=$(uci -q get crowdsec.bouncer.update_frequency || echo "10s")
json_add_string "update_frequency" "$val"
val=$(uci -q get crowdsec.bouncer.deny_action || echo "drop")
json_add_string "deny_action" "$val"
val=$(uci -q get crowdsec.bouncer.deny_log || echo "0")
json_add_string "deny_log" "$val"
val=$(uci -q get crowdsec.bouncer.log_level || echo "info")
json_add_string "log_level" "$val"
val=$(uci -q get crowdsec.bouncer.filter_input || echo "1")
json_add_string "filter_input" "$val"
val=$(uci -q get crowdsec.bouncer.filter_forward || echo "1")
json_add_string "filter_forward" "$val"
# Get interfaces list
json_add_array "interfaces"
local interfaces
interfaces=$(uci -q get crowdsec.bouncer.interface 2>/dev/null || echo "")
if [ -n "$interfaces" ]; then
local iface
for iface in $interfaces; do
json_add_string "" "$iface"
done
fi
json_close_array
json_dump
}
# Update firewall bouncer UCI configuration
update_firewall_bouncer_config() {
local key="$1"
local value="$2"
json_init
if [ -z "$key" ]; then
json_add_boolean "success" 0
json_add_string "error" "Configuration key required"
json_dump
return
fi
# Validate and set configuration
case "$key" in
enabled|ipv4|ipv6|deny_log|filter_input|filter_forward)
# Boolean values
if [ "$value" != "0" ] && [ "$value" != "1" ]; then
json_add_boolean "success" 0
json_add_string "error" "Invalid boolean value: $value"
json_dump
return
fi
uci set "crowdsec.@bouncer[0].$key=$value"
;;
api_url|update_frequency|deny_action|log_level|api_key)
# String values
if [ -z "$value" ]; then
json_add_boolean "success" 0
json_add_string "error" "Value cannot be empty"
json_dump
return
fi
uci set "crowdsec.@bouncer[0].$key=$value"
;;
*)
json_add_boolean "success" 0
json_add_string "error" "Unknown configuration key: $key"
json_dump
return
;;
esac
# Commit changes
if uci commit crowdsec 2>/dev/null; then
json_add_boolean "success" 1
json_add_string "message" "Configuration updated: $key=$value"
secubox_log "Firewall bouncer config updated: $key=$value"
else
json_add_boolean "success" 0
json_add_string "error" "Failed to commit UCI changes"
fi
json_dump
}
# Get nftables statistics
get_nftables_stats() {
json_init
if ! command -v nft >/dev/null 2>&1; then
json_add_boolean "available" 0
json_add_string "error" "nftables not available"
json_dump
return
fi
json_add_boolean "available" 1
# Check IPv4 table
local ipv4_exists=0
if nft list table ip crowdsec >/dev/null 2>&1; then
ipv4_exists=1
fi
json_add_boolean "ipv4_table_exists" "$ipv4_exists"
# Check IPv6 table
local ipv6_exists=0
if nft list table ip6 crowdsec6 >/dev/null 2>&1; then
ipv6_exists=1
fi
json_add_boolean "ipv6_table_exists" "$ipv6_exists"
# Get blocked IPs from ALL IPv4 sets (CAPI, cscli, etc.)
local ipv4_total=0
local ipv4_capi=0
local ipv4_cscli=0
local ipv4_other=0
json_add_array "ipv4_blocked_ips"
if [ "$ipv4_exists" = "1" ]; then
# Get all set names
local sets
sets=$(nft list sets ip 2>/dev/null | grep "set crowdsec-blacklists" | sed 's/.*set //' | sed 's/ {//')
local setname ips ip
for setname in $sets; do
ips=$(nft list set ip crowdsec "$setname" 2>/dev/null | sed -n '/elements = {/,/}/p' | grep -oE '[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+(/[0-9]+)?' | head -50)
if [ -n "$ips" ]; then
for ip in $ips; do
json_add_string "" "$ip"
ipv4_total=$((ipv4_total + 1))
done
fi
# Count by origin
local count
count=$(nft list set ip crowdsec "$setname" 2>/dev/null | grep -oE '[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+' | wc -l)
case "$setname" in
*-CAPI) ipv4_capi=$((ipv4_capi + count)) ;;
*-cscli) ipv4_cscli=$((ipv4_cscli + count)) ;;
*) ipv4_other=$((ipv4_other + count)) ;;
esac
done
fi
json_close_array
# Get blocked IPs from ALL IPv6 sets
local ipv6_total=0
local ipv6_capi=0
local ipv6_cscli=0
json_add_array "ipv6_blocked_ips"
if [ "$ipv6_exists" = "1" ]; then
local sets
sets=$(nft list sets ip6 2>/dev/null | grep "set crowdsec6-blacklists" | sed 's/.*set //' | sed 's/ {//')
local setname ips ip
for setname in $sets; do
ips=$(nft list set ip6 crowdsec6 "$setname" 2>/dev/null | sed -n '/elements = {/,/}/p' | grep -oE '([0-9a-fA-F:]+:+)+[0-9a-fA-F]+' | head -50)
if [ -n "$ips" ]; then
for ip in $ips; do
json_add_string "" "$ip"
ipv6_total=$((ipv6_total + 1))
done
fi
local count
count=$(nft list set ip6 crowdsec6 "$setname" 2>/dev/null | grep -oE '([0-9a-fA-F:]+:+)+[0-9a-fA-F]+' | wc -l)
case "$setname" in
*-CAPI) ipv6_capi=$((ipv6_capi + count)) ;;
*-cscli) ipv6_cscli=$((ipv6_cscli + count)) ;;
esac
done
fi
json_close_array
# Get rules count
local ipv4_rules=0
local ipv6_rules=0
if [ "$ipv4_exists" = "1" ]; then
ipv4_rules=$(nft list table ip crowdsec 2>/dev/null | grep -c "rule" || echo "0")
fi
if [ "$ipv6_exists" = "1" ]; then
ipv6_rules=$(nft list table ip6 crowdsec6 2>/dev/null | grep -c "rule" || echo "0")
fi
json_add_int "ipv4_rules_count" "$ipv4_rules"
json_add_int "ipv6_rules_count" "$ipv6_rules"
# Add counts by origin
json_add_int "ipv4_capi_count" "$ipv4_capi"
json_add_int "ipv4_cscli_count" "$ipv4_cscli"
json_add_int "ipv4_total_count" "$((ipv4_capi + ipv4_cscli + ipv4_other))"
json_add_int "ipv6_capi_count" "$ipv6_capi"
json_add_int "ipv6_cscli_count" "$ipv6_cscli"
json_add_int "ipv6_total_count" "$((ipv6_capi + ipv6_cscli))"
json_dump
}
# Check if wizard should be shown (first-time setup detection)
check_wizard_needed() {
json_init
# Check if bouncer is configured
local bouncer_configured=0
if uci -q get crowdsec.bouncer.enabled >/dev/null 2>&1; then
bouncer_configured=1
fi
# Check if collections are installed
local collections_installed=0
if [ -x "$CSCLI" ]; then
if run_cscli collections list 2>/dev/null | grep -q "INSTALLED"; then
collections_installed=1
fi
fi
# Show wizard if not configured
local show_wizard=0
if [ "$bouncer_configured" = "0" ] || [ "$collections_installed" = "0" ]; then
show_wizard=1
fi
json_add_boolean "show_wizard" "$show_wizard"
json_add_boolean "bouncer_configured" "$bouncer_configured"
json_add_boolean "collections_installed" "$collections_installed"
json_dump
}
# Get wizard initial state
get_wizard_state() {
json_init
# Get collections count
local collections_count=0
if [ -x "$CSCLI" ]; then
collections_count=$(run_cscli collections list 2>/dev/null | grep -c "INSTALLED" || echo "0")
fi
json_add_int "collections_count" "$collections_count"
json_dump
}
# Repair LAPI - auto-fix common configuration issues
repair_lapi() {
json_init
local steps_done=""
local errors=""
local config_file="/etc/crowdsec/config.yaml"
local creds_file="/etc/crowdsec/local_api_credentials.yaml"
local db_file="/srv/crowdsec/data/crowdsec.db"
local capi_creds="/etc/crowdsec/online_api_credentials.yaml"
secubox_log "Starting LAPI repair (simplified)..."
# Step 1: Stop CrowdSec
/etc/init.d/crowdsec stop >/dev/null 2>&1
sleep 2
killall crowdsec 2>/dev/null
sleep 1
steps_done="Stopped; "
# Step 2: Create required directories
mkdir -p /srv/crowdsec/data 2>/dev/null
mkdir -p /etc/crowdsec/hub 2>/dev/null
mkdir -p /etc/crowdsec/acquis.d 2>/dev/null
chmod 755 /srv/crowdsec/data 2>/dev/null
steps_done="${steps_done}Dirs; "
# Step 3: Fix config paths
if [ -f "$config_file" ]; then
sed -i 's|^\(\s*\)data_dir:.*|\1data_dir: /srv/crowdsec/data/|' "$config_file" 2>/dev/null
sed -i 's|^\(\s*\)db_path:.*|\1db_path: /srv/crowdsec/data/crowdsec.db|' "$config_file" 2>/dev/null
steps_done="${steps_done}Config fixed; "
else
errors="${errors}No config file; "
fi
# Step 4: Reset LAPI credentials (delete old ones)
rm -f "$creds_file" 2>/dev/null
steps_done="${steps_done}Creds cleared; "
# Step 5: Reset database (delete it, CrowdSec will recreate)
rm -f "$db_file" 2>/dev/null
steps_done="${steps_done}DB reset; "
# Step 6: Start CrowdSec via init (will auto-create DB and register machine)
/etc/init.d/crowdsec start >/dev/null 2>&1
sleep 5
steps_done="${steps_done}Started; "
# Step 7: Check if CrowdSec is running
local lapi_ok=0
if pgrep crowdsec >/dev/null 2>&1; then
steps_done="${steps_done}Running; "
# Step 8: Register machine if credentials don't exist
if [ ! -s "$creds_file" ] || ! grep -q "password:" "$creds_file" 2>/dev/null; then
secubox_log "Registering local machine..."
if "$CSCLI" machines add -a -f "$creds_file" 2>/dev/null; then
steps_done="${steps_done}Machine registered; "
# Restart to pick up new credentials
/etc/init.d/crowdsec restart >/dev/null 2>&1
sleep 3
else
errors="${errors}Machine registration failed; "
fi
fi
# Step 9: Verify LAPI is working
if run_with_timeout 5 "$CSCLI" lapi status >/dev/null 2>&1; then
lapi_ok=1
steps_done="${steps_done}LAPI OK; "
else
errors="${errors}LAPI check failed; "
fi
else
errors="${errors}CrowdSec not running; "
local log_err=""
log_err=$(tail -5 /var/log/crowdsec.log 2>/dev/null | grep -i "fatal\|error" | head -1)
[ -n "$log_err" ] && errors="${errors}Log: ${log_err}; "
fi
# Step 10: Try to connect CAPI if LAPI works (don't delete existing CAPI creds)
if [ "$lapi_ok" = "1" ]; then
local capi_ok=0
# Check if CAPI is already working
local capi_status=""
capi_status=$(run_with_timeout 5 "$CSCLI" capi status 2>&1)
if echo "$capi_status" | grep -qi "You can successfully interact with Central API"; then
capi_ok=1
steps_done="${steps_done}CAPI OK; "
elif [ ! -f "$capi_creds" ]; then
# No CAPI credentials - try to register (safe)
if run_with_timeout 15 "$CSCLI" capi register >/dev/null 2>&1; then
capi_ok=1
steps_done="${steps_done}CAPI registered; "
else
errors="${errors}CAPI registration failed (will work in local mode); "
fi
else
# CAPI credentials exist but not working - don't delete them!
steps_done="${steps_done}CAPI creds preserved; "
fi
fi
# Final result
if [ "$lapi_ok" = "1" ]; then
json_add_boolean "success" 1
json_add_string "message" "LAPI repaired successfully"
json_add_string "steps" "$steps_done"
secubox_log "LAPI repair successful: $steps_done"
else
json_add_boolean "success" 0
json_add_string "error" "LAPI repair incomplete"
json_add_string "steps" "$steps_done"
json_add_string "errors" "$errors"
secubox_log "LAPI repair failed: $errors"
fi
json_dump
}
# Repair CAPI - fix Central API registration issues
repair_capi() {
json_init
local steps_done=""
local errors=""
local capi_creds="/etc/crowdsec/online_api_credentials.yaml"
secubox_log "Starting CAPI repair..."
# Check if CrowdSec and LAPI are running
if ! pgrep crowdsec >/dev/null 2>&1; then
json_add_boolean "success" 0
json_add_string "error" "CrowdSec is not running. Start CrowdSec first."
json_dump
return
fi
if ! run_with_timeout 5 "$CSCLI" lapi status >/dev/null 2>&1; then
json_add_boolean "success" 0
json_add_string "error" "LAPI is not available. Run LAPI repair first."
json_dump
return
fi
# Check current CAPI status
local capi_status=""
capi_status=$(run_with_timeout 5 "$CSCLI" capi status 2>&1)
if echo "$capi_status" | grep -qi "You can successfully interact with Central API"; then
steps_done="${steps_done}CAPI already working; "
json_add_boolean "success" 1
json_add_string "message" "CAPI is already connected"
json_add_string "steps" "$steps_done"
json_dump
return
fi
# Step 1: Check credentials and register only if needed
# IMPORTANT: Never delete existing credentials - this triggers rate limiting
if [ -f "$capi_creds" ]; then
steps_done="${steps_done}Credentials exist (preserved); "
secubox_log "CAPI credentials exist, trying to reconnect..."
# Try to reconnect with existing credentials by restarting crowdsec
/etc/init.d/crowdsec restart >/dev/null 2>&1
sleep 3
else
# No credentials - safe to register
secubox_log "No CAPI credentials, registering..."
local reg_output=""
reg_output=$(run_with_timeout 20 "$CSCLI" capi register 2>&1)
if [ $? -eq 0 ]; then
steps_done="${steps_done}CAPI registered; "
else
# Check if error is about already registered
if echo "$reg_output" | grep -qi "already registered"; then
steps_done="${steps_done}Already registered; "
else
errors="${errors}Registration failed: ${reg_output}; "
fi
fi
fi
# Step 3: Verify CAPI connection
sleep 2
capi_status=$(run_with_timeout 5 "$CSCLI" capi status 2>&1)
if echo "$capi_status" | grep -qi "You can successfully interact with Central API"; then
steps_done="${steps_done}CAPI connected; "
json_add_boolean "success" 1
json_add_string "message" "CAPI repaired successfully"
json_add_string "steps" "$steps_done"
secubox_log "CAPI repair successful: $steps_done"
else
json_add_boolean "success" 0
json_add_string "error" "CAPI repair incomplete"
json_add_string "steps" "$steps_done"
json_add_string "errors" "$errors"
json_add_string "capi_output" "$capi_status"
secubox_log "CAPI repair failed: $errors"
fi
json_dump
}
# Reset wizard - clean up for fresh start
reset_wizard() {
json_init
local steps_done=""
local errors=""
secubox_log "Starting CrowdSec wizard reset (recovery mode)..."
# Step 1: Stop services
/etc/init.d/crowdsec-firewall-bouncer stop >/dev/null 2>&1
steps_done="${steps_done}Stopped firewall bouncer; "
# Step 2: Delete existing bouncer registration
if [ -x "$CSCLI" ]; then
run_cscli bouncers delete "crowdsec-firewall-bouncer" >/dev/null 2>&1
steps_done="${steps_done}Deleted bouncer registration; "
# Also try database cleanup
sqlite3 /srv/crowdsec/data/crowdsec.db "DELETE FROM bouncers WHERE name='crowdsec-firewall-bouncer';" 2>/dev/null
fi
# Step 3: Clear UCI bouncer config
uci -q delete crowdsec.bouncer 2>/dev/null
uci commit crowdsec 2>/dev/null
steps_done="${steps_done}Cleared UCI config; "
# Step 4: Remove bouncer config file
rm -f /etc/crowdsec/bouncers/crowdsec-firewall-bouncer.yaml 2>/dev/null
steps_done="${steps_done}Removed bouncer config file; "
# Step 5: Reset nftables rules
if command -v nft >/dev/null 2>&1; then
nft delete table ip crowdsec 2>/dev/null
nft delete table ip6 crowdsec6 2>/dev/null
steps_done="${steps_done}Cleared nftables rules; "
fi
json_add_boolean "success" 1
json_add_string "message" "Wizard reset completed - ready for fresh setup"
json_add_string "steps" "$steps_done"
secubox_log "Wizard reset completed: $steps_done"
json_dump
}
# Console enrollment status
get_console_status() {
json_init
check_cscli
local enrolled=0
local name=""
local company=""
# Check if console is enrolled by checking if there's a console config
if [ -f "/etc/crowdsec/console.yaml" ]; then
# Check if the console is actually configured (has credentials)
if grep -q "share_manual_decisions\|share_tainted\|share_context" /etc/crowdsec/console.yaml 2>/dev/null; then
enrolled=1
fi
fi
# Try to get console status from cscli
local console_status
console_status=$(run_cscli console status 2>/dev/null)
if [ -n "$console_status" ]; then
# Check if enrolled by looking for "Enrolled" or similar in output
if echo "$console_status" | grep -qi "enrolled\|connected\|active"; then
enrolled=1
fi
# Extract name if present
name=$(echo "$console_status" | grep -i "name\|machine" | head -1 | awk -F: '{print $2}' | xargs 2>/dev/null)
fi
json_add_boolean "enrolled" "$enrolled"
json_add_string "name" "$name"
# Get share settings if enrolled
if [ "$enrolled" = "1" ] && [ -f "/etc/crowdsec/console.yaml" ]; then
local share_manual=$(grep "share_manual_decisions:" /etc/crowdsec/console.yaml 2>/dev/null | awk '{print $2}')
local share_tainted=$(grep "share_tainted:" /etc/crowdsec/console.yaml 2>/dev/null | awk '{print $2}')
local share_context=$(grep "share_context:" /etc/crowdsec/console.yaml 2>/dev/null | awk '{print $2}')
json_add_boolean "share_manual_decisions" "$([ \"$share_manual\" = \"true\" ] && echo 1 || echo 0)"
json_add_boolean "share_tainted" "$([ \"$share_tainted\" = \"true\" ] && echo 1 || echo 0)"
json_add_boolean "share_context" "$([ \"$share_context\" = \"true\" ] && echo 1 || echo 0)"
fi
json_dump
}
# Console enroll
console_enroll() {
local key="$1"
local name="$2"
json_init
check_cscli
if [ -z "$key" ]; then
json_add_boolean "success" 0
json_add_string "error" "Enrollment key is required"
json_dump
return
fi
secubox_log "Enrolling CrowdSec Console with key..."
# Step 0: Ensure CAPI is registered (prerequisite for console enrollment)
local capi_ok=0
local capi_status=""
local capi_creds="/etc/crowdsec/online_api_credentials.yaml"
capi_status=$(run_with_timeout 5 "$CSCLI" capi status 2>&1)
if echo "$capi_status" | grep -qi "You can successfully interact with Central API"; then
capi_ok=1
secubox_log "CAPI already connected"
else
# CAPI not connected - check if credentials exist
if [ -f "$capi_creds" ]; then
# Credentials exist but CAPI not working - try restarting CrowdSec
secubox_log "CAPI credentials exist but not connected, restarting CrowdSec..."
/etc/init.d/crowdsec restart >/dev/null 2>&1
sleep 3
# Check again after restart
capi_status=$(run_with_timeout 5 "$CSCLI" capi status 2>&1)
if echo "$capi_status" | grep -qi "You can successfully interact with Central API"; then
capi_ok=1
secubox_log "CAPI connected after restart"
else
# Still not working but DO NOT delete credentials (rate limit protection)
secubox_log "CAPI still not connected - credentials preserved to avoid rate limit"
fi
else
# No credentials - safe to register
secubox_log "No CAPI credentials, attempting registration..."
if run_with_timeout 15 "$CSCLI" capi register >/dev/null 2>&1; then
capi_ok=1
secubox_log "CAPI registration successful"
fi
fi
fi
if [ "$capi_ok" = "0" ]; then
json_add_boolean "success" 0
json_add_string "error" "CAPI registration failed. Please run LAPI repair first."
json_dump
return
fi
# Build enroll command
local enroll_cmd="run_cscli console enroll $key"
if [ -n "$name" ]; then
enroll_cmd="$enroll_cmd --name \"$name\""
fi
# Run enrollment
local output
output=$(eval "$enroll_cmd" 2>&1)
local result=$?
if [ "$result" -eq 0 ]; then
json_add_boolean "success" 1
json_add_string "message" "Successfully enrolled in CrowdSec Console"
json_add_string "output" "$output"
secubox_log "Console enrollment successful"
# Enable sharing options by default
run_cscli console enable share_manual_decisions >/dev/null 2>&1
run_cscli console enable share_tainted >/dev/null 2>&1
run_cscli console enable share_context >/dev/null 2>&1
# Restart CrowdSec to activate enrollment
# Note: User must validate enrollment on app.crowdsec.net first
secubox_log "Restarting CrowdSec to apply enrollment..."
/etc/init.d/crowdsec restart >/dev/null 2>&1 &
json_add_boolean "restart_triggered" 1
else
json_add_boolean "success" 0
json_add_string "error" "Enrollment failed"
json_add_string "output" "$output"
secubox_log "Console enrollment failed: $output"
fi
json_dump
}
# Console disable (unenroll)
console_disable() {
json_init
check_cscli
secubox_log "Disabling CrowdSec Console enrollment..."
# Disable all sharing
run_cscli console disable share_manual_decisions >/dev/null 2>&1
run_cscli console disable share_tainted >/dev/null 2>&1
run_cscli console disable share_context >/dev/null 2>&1
# Remove console config
if [ -f "/etc/crowdsec/console.yaml" ]; then
rm -f /etc/crowdsec/console.yaml
fi
json_add_boolean "success" 1
json_add_string "message" "Console enrollment disabled"
secubox_log "Console enrollment disabled"
json_dump
}
# Configure log acquisition settings
configure_acquisition() {
local syslog_enabled="$1"
local firewall_enabled="$2"
local ssh_enabled="$3"
local http_enabled="$4"
local syslog_path="$5"
json_init
local steps_done=""
local errors=""
secubox_log "Configuring CrowdSec log acquisition..."
# Step 1: Ensure acquisition section exists in UCI
if ! uci -q get crowdsec.acquisition >/dev/null 2>&1; then
uci set crowdsec.acquisition='acquisition'
steps_done="${steps_done}Created acquisition section; "
fi
# Step 2: Set acquisition options
uci set crowdsec.acquisition.syslog_enabled="${syslog_enabled:-1}"
uci set crowdsec.acquisition.firewall_enabled="${firewall_enabled:-1}"
uci set crowdsec.acquisition.ssh_enabled="${ssh_enabled:-1}"
uci set crowdsec.acquisition.http_enabled="${http_enabled:-0}"
if [ -n "$syslog_path" ]; then
uci set crowdsec.acquisition.syslog_path="$syslog_path"
fi
uci commit crowdsec
steps_done="${steps_done}Updated UCI settings; "
# Step 3: Note on Dropbear SSH logging
# Dropbear 2024.86 does NOT support -v flag or verbose UCI option
# Auth failures are detected via auth-monitor.sh parsing syslog messages
if [ "$ssh_enabled" = "1" ]; then
steps_done="${steps_done}SSH detection enabled via syslog monitoring; "
fi
# Enable uhttpd syslog for HTTP auth logging
if [ "$http_enabled" = "1" ]; then
if uci -q get uhttpd.main >/dev/null 2>&1; then
uci set uhttpd.main.syslog='1'
uci commit uhttpd
/etc/init.d/uhttpd restart >/dev/null 2>&1
steps_done="${steps_done}Enabled uhttpd syslog; "
fi
fi
# Step 4: Generate acquisition YAML files
# OpenWrt uses logread command instead of /var/log/messages by default
# All syslog entries (SSH, firewall, system) go through the same log stream
# We create ONE unified acquisition file to avoid multiple logread processes
local acquis_dir="/etc/crowdsec/acquis.d"
mkdir -p "$acquis_dir"
# Remove old separate acquisition files if they exist
rm -f "$acquis_dir/openwrt-syslog.yaml" 2>/dev/null
rm -f "$acquis_dir/openwrt-firewall.yaml" 2>/dev/null
rm -f "$acquis_dir/openwrt-dropbear.yaml" 2>/dev/null
# Create unified syslog acquisition if any syslog-based source is enabled
# SSH, firewall, and system logs all go through /var/log/messages
# NOTE: CrowdSec doesn't support "source: command" - must use file-based acquisition
if [ "$syslog_enabled" = "1" ] || [ "$firewall_enabled" = "1" ] || [ "$ssh_enabled" = "1" ]; then
# Ensure busybox syslog writes to file (required for CrowdSec)
if uci -q get system.@system[0] >/dev/null 2>&1; then
uci set system.@system[0].log_file='/var/log/messages'
uci set system.@system[0].log_size='512'
uci commit system
/etc/init.d/log restart >/dev/null 2>&1
fi
cat > "$acquis_dir/openwrt-unified.yaml" << 'YAML'
# OpenWrt Unified Syslog Acquisition
# Auto-generated by SecuBox CrowdSec Wizard
# Reads from /var/log/messages (busybox syslog)
# Covers: system logs, SSH/Dropbear/OpenSSH, firewall (iptables/nftables)
filenames:
- /var/log/messages
labels:
type: syslog
YAML
local enabled_sources=""
[ "$syslog_enabled" = "1" ] && enabled_sources="${enabled_sources}system "
[ "$ssh_enabled" = "1" ] && enabled_sources="${enabled_sources}SSH "
[ "$firewall_enabled" = "1" ] && enabled_sources="${enabled_sources}firewall "
steps_done="${steps_done}Configured syslog to file and created acquisition (${enabled_sources}); "
else
rm -f "$acquis_dir/openwrt-unified.yaml"
steps_done="${steps_done}Disabled syslog acquisition; "
fi
# Enable/disable HTTP log acquisition (separate file-based source)
if [ "$http_enabled" = "1" ]; then
# Check if log files exist
if [ -f "/var/log/uhttpd.log" ]; then
cat > "$acquis_dir/openwrt-http.yaml" << 'YAML'
# OpenWrt uHTTPd Web Server Log Acquisition
# Auto-generated by SecuBox CrowdSec Wizard
filenames:
- /var/log/uhttpd.log
labels:
type: nginx
YAML
elif [ -f "/var/log/nginx/access.log" ]; then
cat > "$acquis_dir/openwrt-http.yaml" << 'YAML'
# OpenWrt nginx Web Server Log Acquisition
# Auto-generated by SecuBox CrowdSec Wizard
filenames:
- /var/log/nginx/access.log
labels:
type: nginx
YAML
else
# Fallback - try both locations
cat > "$acquis_dir/openwrt-http.yaml" << 'YAML'
# OpenWrt Web Server Log Acquisition
# Auto-generated by SecuBox CrowdSec Wizard
filenames:
- /var/log/uhttpd.log
- /var/log/nginx/access.log
labels:
type: nginx
YAML
fi
steps_done="${steps_done}Created HTTP acquisition; "
else
rm -f "$acquis_dir/openwrt-http.yaml"
rm -f "$acquis_dir/openwrt-uhttpd.yaml" 2>/dev/null
steps_done="${steps_done}Disabled HTTP acquisition; "
fi
# Step 4: Restart CrowdSec to apply acquisition changes
if /etc/init.d/crowdsec reload >/dev/null 2>&1; then
steps_done="${steps_done}Reloaded CrowdSec"
else
# Fallback to restart if reload fails
/etc/init.d/crowdsec restart >/dev/null 2>&1
steps_done="${steps_done}Restarted CrowdSec"
fi
json_add_boolean "success" 1
json_add_string "message" "Acquisition configuration completed"
json_add_string "steps" "$steps_done"
secubox_log "Acquisition configuration completed: $steps_done"
json_dump
}
# Get realtime acquisition metrics with rates
get_acquisition_metrics() {
check_cscli
json_init
# Get raw metrics from cscli
local metrics_output
metrics_output=$(run_cscli metrics -o json 2>/dev/null)
if [ -z "$metrics_output" ]; then
json_add_boolean "available" 0
json_add_string "error" "Metrics not available"
json_dump
return
fi
json_add_boolean "available" 1
json_add_int "timestamp" "$(date +%s)"
# Parse acquisition sources from metrics
# Store metrics in temp file for parsing
local tmp_file="/tmp/crowdsec_metrics.$$"
echo "$metrics_output" > "$tmp_file"
# Extract acquisition metrics
json_add_array "sources"
# Use jsonfilter to extract acquisition data
# Format: {"source": "file:/var/log/messages", "lines_read": 123, "lines_parsed": 100, ...}
local sources
sources=$(cat "$tmp_file" | jsonfilter -e '@.acquisition' 2>/dev/null)
if [ -n "$sources" ]; then
# Parse each source
for source in $(echo "$metrics_output" | jsonfilter -e '@.acquisition.*' 2>/dev/null | head -20); do
json_add_object ""
json_add_string "source" "$source"
json_close_object
done
fi
json_close_array
# Get overall stats
local total_read=0
local total_parsed=0
local total_unparsed=0
local total_buckets=0
# Parse acquisition stats using awk
if [ -f "$tmp_file" ]; then
# Extract line counts
total_read=$(cat "$tmp_file" | grep -o '"lines_read":[0-9]*' | grep -o '[0-9]*' | awk '{sum+=$1} END {print sum+0}')
total_parsed=$(cat "$tmp_file" | grep -o '"lines_parsed":[0-9]*' | grep -o '[0-9]*' | awk '{sum+=$1} END {print sum+0}')
total_unparsed=$(cat "$tmp_file" | grep -o '"lines_unparsed":[0-9]*' | grep -o '[0-9]*' | awk '{sum+=$1} END {print sum+0}')
total_buckets=$(cat "$tmp_file" | grep -o '"lines_poured_to_bucket":[0-9]*' | grep -o '[0-9]*' | awk '{sum+=$1} END {print sum+0}')
fi
json_add_int "total_lines_read" "${total_read:-0}"
json_add_int "total_lines_parsed" "${total_parsed:-0}"
json_add_int "total_lines_unparsed" "${total_unparsed:-0}"
json_add_int "total_buckets" "${total_buckets:-0}"
# Calculate parse rate
if [ "$total_read" -gt 0 ]; then
local parse_rate=$((total_parsed * 100 / total_read))
json_add_int "parse_rate" "$parse_rate"
else
json_add_int "parse_rate" 0
fi
# Check active acquisition files
json_add_array "active_files"
local acquis_dir="/etc/crowdsec/acquis.d"
if [ -d "$acquis_dir" ]; then
for f in "$acquis_dir"/*.yaml; do
if [ -f "$f" ]; then
json_add_string "" "$(basename "$f" .yaml)"
fi
done
fi
json_close_array
# Clean up
rm -f "$tmp_file"
json_dump
}
# Get current acquisition configuration
get_acquisition_config() {
json_init
# Get values from UCI
local syslog_enabled=$(uci -q get crowdsec.acquisition.syslog_enabled || echo "1")
local firewall_enabled=$(uci -q get crowdsec.acquisition.firewall_enabled || echo "1")
local ssh_enabled=$(uci -q get crowdsec.acquisition.ssh_enabled || echo "1")
local http_enabled=$(uci -q get crowdsec.acquisition.http_enabled || echo "0")
local syslog_path=$(uci -q get crowdsec.acquisition.syslog_path || echo "/var/log/messages")
json_add_string "syslog_enabled" "$syslog_enabled"
json_add_string "firewall_enabled" "$firewall_enabled"
json_add_string "ssh_enabled" "$ssh_enabled"
json_add_string "http_enabled" "$http_enabled"
json_add_string "syslog_path" "$syslog_path"
# Check which acquisition files exist
local acquis_dir="/etc/crowdsec/acquis.d"
local unified_exists=0
local http_exists=0
[ -f "$acquis_dir/openwrt-unified.yaml" ] && unified_exists=1
[ -f "$acquis_dir/openwrt-http.yaml" ] && http_exists=1
json_add_boolean "unified_file_exists" "$unified_exists"
json_add_boolean "http_file_exists" "$http_exists"
json_dump
}
# Service control (start/stop/restart/reload)
service_control() {
local action="$1"
json_init
case "$action" in
start|stop|restart|reload)
secubox_log "CrowdSec service $action requested"
local output
output=$(/etc/init.d/crowdsec "$action" 2>&1)
local result=$?
sleep 2
# Check if service is running after action
local running=0
if pgrep crowdsec >/dev/null 2>&1; then
running=1
fi
if [ "$result" -eq 0 ]; then
json_add_boolean "success" 1
json_add_string "action" "$action"
json_add_boolean "running" "$running"
json_add_string "message" "Service $action completed"
else
json_add_boolean "success" 0
json_add_string "error" "Service $action failed"
json_add_string "output" "$output"
fi
;;
*)
json_add_boolean "success" 0
json_add_string "error" "Invalid action. Use: start, stop, restart, reload"
;;
esac
json_dump
}
# Complete health check for dashboard
get_health_check() {
json_init
# CrowdSec running status
local cs_running=0
if pgrep crowdsec >/dev/null 2>&1; then
cs_running=1
fi
json_add_boolean "crowdsec_running" "$cs_running"
# Version
local version=""
if [ -x "$CSCLI" ]; then
version=$(run_cscli version 2>/dev/null | grep "version:" | awk '{print $2}')
fi
json_add_string "version" "${version:-unknown}"
# LAPI status
local lapi_status="unavailable"
local lapi_url="http://127.0.0.1:8080"
if [ -x "$CSCLI" ]; then
if run_with_timeout 5 "$CSCLI" lapi status >/dev/null 2>&1; then
lapi_status="available"
fi
fi
json_add_string "lapi_status" "$lapi_status"
json_add_string "lapi_url" "$lapi_url"
# CAPI status - parse cscli capi status output
local capi_status="disconnected"
local capi_enrolled=0
local capi_subscription=""
local sharing_signals=0
local pulling_blocklist=0
local pulling_console=0
if [ -x "$CSCLI" ]; then
local capi_output=""
capi_output=$(run_with_timeout 10 "$CSCLI" capi status 2>&1)
if echo "$capi_output" | grep -qi "You can successfully interact with Central API"; then
capi_status="connected"
fi
if echo "$capi_output" | grep -qi "enrolled in the console"; then
capi_enrolled=1
fi
if echo "$capi_output" | grep -qi "COMMUNITY"; then
capi_subscription="COMMUNITY"
elif echo "$capi_output" | grep -qi "PRO"; then
capi_subscription="PRO"
fi
if echo "$capi_output" | grep -qi "Sharing signals is enabled"; then
sharing_signals=1
fi
if echo "$capi_output" | grep -qi "Pulling community blocklist is enabled"; then
pulling_blocklist=1
fi
if echo "$capi_output" | grep -qi "Pulling blocklists from the console is enabled"; then
pulling_console=1
fi
fi
json_add_string "capi_status" "$capi_status"
json_add_boolean "capi_enrolled" "$capi_enrolled"
json_add_string "capi_subscription" "$capi_subscription"
json_add_boolean "sharing_signals" "$sharing_signals"
json_add_boolean "pulling_blocklist" "$pulling_blocklist"
json_add_boolean "pulling_console" "$pulling_console"
# Machine info
local machine_id=""
local machine_version=""
if [ -x "$CSCLI" ]; then
local machines_output=""
machines_output=$(run_cscli machines list -o json 2>/dev/null)
if [ -n "$machines_output" ] && [ "$machines_output" != "null" ]; then
machine_id=$(echo "$machines_output" | jsonfilter -e '@[0].machineId' 2>/dev/null)
machine_version=$(echo "$machines_output" | jsonfilter -e '@[0].version' 2>/dev/null)
fi
fi
json_add_string "machine_id" "${machine_id:-localhost}"
json_add_string "machine_version" "$machine_version"
# Bouncer count
local bouncer_count=0
if [ -x "$CSCLI" ]; then
bouncer_count=$(run_cscli bouncers list -o json 2>/dev/null | jsonfilter -e '@[*]' 2>/dev/null | wc -l)
fi
json_add_int "bouncer_count" "${bouncer_count:-0}"
# Total decisions count
local 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)
fi
json_add_int "decisions_count" "${decisions_count:-0}"
json_dump
}
# Get CAPI blocklist metrics (decisions by origin and reason)
get_capi_metrics() {
json_init
if [ ! -x "$CSCLI" ]; then
json_add_boolean "available" 0
json_add_string "error" "cscli not found"
json_dump
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
# Parse decisions and count by origin
# The structure is: [{decisions: [...], ...}, ...]
# We need to count decisions where origin = "CAPI" or "crowdsec"
# Use a temp file for aggregation
local tmp_file="/tmp/capi_metrics.$$"
# 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
# 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_count:-0}"
json_add_int "total_local" "${local_count:-0}"
# Build breakdown by scenario for CAPI decisions
# Parse the JSON more carefully
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/"$//')
json_add_object ""
json_add_string "scenario" "$name"
json_add_int "count" "$count"
json_close_object
fi
done
json_close_array
rm -f "$tmp_file" 2>/dev/null
json_dump
}
# Get available hub items (not installed)
get_hub_available() {
json_init
if [ ! -x "$CSCLI" ]; then
json_add_boolean "available" 0
json_add_string "error" "cscli not found"
json_dump
return
fi
json_add_boolean "available" 1
# Get hub list in JSON format (all items)
local hub_output=""
hub_output=$(run_with_timeout 30 "$CSCLI" hub list -a -o json 2>/dev/null)
if [ -z "$hub_output" ]; then
json_add_string "collections" "[]"
json_add_string "parsers" "[]"
json_add_string "scenarios" "[]"
json_dump
return
fi
# Output the raw hub data - frontend will parse it
echo "$hub_output"
}
# Install a hub item (collection, parser, scenario)
install_hub_item() {
local item_type="$1"
local item_name="$2"
json_init
if [ -z "$item_type" ] || [ -z "$item_name" ]; then
json_add_boolean "success" 0
json_add_string "error" "Item type and name are required"
json_dump
return
fi
# Validate item type
case "$item_type" in
collection|parser|scenario|postoverflow|context)
;;
*)
json_add_boolean "success" 0
json_add_string "error" "Invalid item type: $item_type"
json_dump
return
;;
esac
if [ ! -x "$CSCLI" ]; then
json_add_boolean "success" 0
json_add_string "error" "cscli not found"
json_dump
return
fi
secubox_log "Installing CrowdSec $item_type: $item_name"
# Install the item
local output=""
output=$(run_with_timeout 60 "$CSCLI" "${item_type}s" install "$item_name" 2>&1)
local result=$?
if [ "$result" -eq 0 ]; then
json_add_boolean "success" 1
json_add_string "message" "Successfully installed $item_type: $item_name"
json_add_string "output" "$output"
secubox_log "Installed $item_type: $item_name"
else
json_add_boolean "success" 0
json_add_string "error" "Failed to install $item_type: $item_name"
json_add_string "output" "$output"
secubox_log "Failed to install $item_type: $item_name - $output"
fi
json_dump
}
# Remove a hub item
remove_hub_item() {
local item_type="$1"
local item_name="$2"
json_init
if [ -z "$item_type" ] || [ -z "$item_name" ]; then
json_add_boolean "success" 0
json_add_string "error" "Item type and name are required"
json_dump
return
fi
case "$item_type" in
collection|parser|scenario|postoverflow|context)
;;
*)
json_add_boolean "success" 0
json_add_string "error" "Invalid item type: $item_type"
json_dump
return
;;
esac
if [ ! -x "$CSCLI" ]; then
json_add_boolean "success" 0
json_add_string "error" "cscli not found"
json_dump
return
fi
secubox_log "Removing CrowdSec $item_type: $item_name"
local output=""
output=$(run_with_timeout 30 "$CSCLI" "${item_type}s" remove "$item_name" 2>&1)
local result=$?
if [ "$result" -eq 0 ]; then
json_add_boolean "success" 1
json_add_string "message" "Successfully removed $item_type: $item_name"
secubox_log "Removed $item_type: $item_name"
else
json_add_boolean "success" 0
json_add_string "error" "Failed to remove $item_type: $item_name"
json_add_string "output" "$output"
fi
json_dump
}
# Get dashboard settings (enrollment key, etc.)
get_settings() {
json_init
local enrollment_key=""
local machine_name=""
local auto_enroll=""
# Read from UCI config
enrollment_key=$(uci -q get crowdsec-dashboard.main.enrollment_key 2>/dev/null)
machine_name=$(uci -q get crowdsec-dashboard.main.machine_name 2>/dev/null)
auto_enroll=$(uci -q get crowdsec-dashboard.main.auto_enroll 2>/dev/null)
json_add_string "enrollment_key" "$enrollment_key"
json_add_string "machine_name" "$machine_name"
json_add_string "auto_enroll" "${auto_enroll:-0}"
json_dump
}
# Save dashboard settings
save_settings() {
local enrollment_key="$1"
local machine_name="$2"
local auto_enroll="$3"
json_init
# Ensure config section exists
uci -q get crowdsec-dashboard.main >/dev/null 2>&1 || {
uci set crowdsec-dashboard.main=settings
}
# Save settings
[ -n "$enrollment_key" ] && uci set crowdsec-dashboard.main.enrollment_key="$enrollment_key"
[ -n "$machine_name" ] && uci set crowdsec-dashboard.main.machine_name="$machine_name"
[ -n "$auto_enroll" ] && uci set crowdsec-dashboard.main.auto_enroll="$auto_enroll"
if uci commit crowdsec-dashboard 2>/dev/null; then
json_add_boolean "success" 1
json_add_string "message" "Settings saved"
secubox_log "Saved enrollment settings"
else
json_add_boolean "success" 0
json_add_string "error" "Failed to save settings"
fi
json_dump
}
# Consolidated overview data for dashboard - single API call optimization
get_overview() {
json_init
# Service status (fast - just process checks)
local cs_running=0
pgrep crowdsec >/dev/null 2>&1 && cs_running=1
json_add_string "crowdsec" "$([ "$cs_running" = "1" ] && echo running || echo stopped)"
local bouncer_running=0
pgrep -f "crowdsec-firewall-bouncer" >/dev/null 2>&1 && bouncer_running=1
json_add_string "bouncer" "$([ "$bouncer_running" = "1" ] && echo running || echo stopped)"
# Version
local version=""
[ -x "$CSCLI" ] && version=$("$CSCLI" version 2>/dev/null | grep -oE '[0-9]+\.[0-9]+\.[0-9]+' | head -1)
json_add_string "version" "${version:-unknown}"
# Quick stats
local decisions_count=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)
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 "alerts_24h" "${alerts_count:-0}"
json_add_int "bouncers" "${bouncers_count:-0}"
# Top scenarios (from cached/limited alerts)
local scenarios=""
if [ "$cs_running" = "1" ]; then
scenarios=$(run_cscli alerts list -o json --limit 100 2>/dev/null | \
jsonfilter -e '@[*].scenario' 2>/dev/null | \
sort | uniq -c | sort -rn | head -5 | \
awk '{print "{\"scenario\":\"" $2 "\",\"count\":" $1 "}"}' | \
tr '\n' ',' | sed 's/,$//')
fi
json_add_string "top_scenarios_raw" "[$scenarios]"
# Top countries (from alerts with GeoIP)
local countries=""
if [ "$cs_running" = "1" ]; then
countries=$(run_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 '{print "{\"country\":\"" $2 "\",\"count\":" $1 "}"}' | \
tr '\n' ',' | sed 's/,$//')
fi
json_add_string "top_countries_raw" "[$countries]"
# Recent decisions (limited to 10 for display)
json_add_array "decisions"
if [ "$cs_running" = "1" ]; then
run_cscli decisions list -o json 2>/dev/null | \
jsonfilter -e '@[0]' -e '@[1]' -e '@[2]' -e '@[3]' -e '@[4]' \
-e '@[5]' -e '@[6]' -e '@[7]' -e '@[8]' -e '@[9]' 2>/dev/null | \
while IFS= read -r line; do
[ -n "$line" ] && [ "$line" != "null" ] && json_add_string "" "$line"
done
fi
json_close_array
# Recent alerts (limited to 8)
json_add_array "alerts"
if [ "$cs_running" = "1" ]; then
run_cscli alerts list -o json --limit 8 2>/dev/null | \
jsonfilter -e '@[*]' 2>/dev/null | head -8 | \
while IFS= read -r line; do
[ -n "$line" ] && json_add_string "" "$line"
done
fi
json_close_array
# CrowdSec logs (last 30 lines)
json_add_array "logs"
if [ -f /var/log/crowdsec.log ]; then
tail -n 30 /var/log/crowdsec.log 2>/dev/null | while IFS= read -r line; do
json_add_string "" "$line"
done
fi
json_close_array
# LAPI status (quick check)
local lapi_ok=0
if [ "$cs_running" = "1" ] && grep -qi ":1F90 " /proc/net/tcp 2>/dev/null; then
lapi_ok=1
fi
json_add_string "lapi_status" "$([ "$lapi_ok" = "1" ] && echo available || echo unavailable)"
# CAPI status (from config check, not live call)
local capi_enrolled=0
[ -f /etc/crowdsec/online_api_credentials.yaml ] && capi_enrolled=1
json_add_boolean "capi_enrolled" "$capi_enrolled"
json_dump
}
# Main dispatcher
case "$1" in
list)
echo '{"get_overview":{},"decisions":{},"alerts":{"limit":"number"},"metrics":{},"bouncers":{},"machines":{},"hub":{},"status":{},"ban":{"ip":"string","duration":"string","reason":"string"},"unban":{"ip":"string"},"stats":{},"secubox_logs":{},"collect_debug":{},"waf_status":{},"metrics_config":{},"configure_metrics":{"enable":"string"},"collections":{},"install_collection":{"collection":"string"},"remove_collection":{"collection":"string"},"update_hub":{},"register_bouncer":{"bouncer_name":"string"},"delete_bouncer":{"bouncer_name":"string"},"firewall_bouncer_status":{},"control_firewall_bouncer":{"action":"string"},"firewall_bouncer_config":{},"update_firewall_bouncer_config":{"key":"string","value":"string"},"nftables_stats":{},"check_wizard_needed":{},"wizard_state":{},"repair_lapi":{},"repair_capi":{},"reset_wizard":{},"console_status":{},"console_enroll":{"key":"string","name":"string"},"console_disable":{},"service_control":{"action":"string"},"configure_acquisition":{"syslog_enabled":"string","firewall_enabled":"string","ssh_enabled":"string","http_enabled":"string","syslog_path":"string"},"acquisition_config":{},"acquisition_metrics":{},"health_check":{},"capi_metrics":{},"hub_available":{},"install_hub_item":{"item_type":"string","item_name":"string"},"remove_hub_item":{"item_type":"string","item_name":"string"},"get_settings":{},"save_settings":{"enrollment_key":"string","machine_name":"string","auto_enroll":"string"}}'
;;
call)
case "$2" in
decisions)
get_decisions
;;
alerts)
read -r input
limit=$(echo "$input" | jsonfilter -e '@.limit' 2>/dev/null)
get_alerts "${limit:-50}"
;;
metrics)
get_metrics
;;
bouncers)
get_bouncers
;;
machines)
get_machines
;;
hub)
get_hub
;;
status)
get_status
;;
ban)
read -r input
ip=$(echo "$input" | jsonfilter -e '@.ip' 2>/dev/null)
duration=$(echo "$input" | jsonfilter -e '@.duration' 2>/dev/null)
reason=$(echo "$input" | jsonfilter -e '@.reason' 2>/dev/null)
add_ban "$ip" "$duration" "$reason"
;;
unban)
read -r input
ip=$(echo "$input" | jsonfilter -e '@.ip' 2>/dev/null)
remove_ban "$ip"
;;
stats)
get_dashboard_stats
;;
secubox_logs|crowdsec_logs)
crowdsec_logs
;;
collect_debug)
collect_debug
;;
waf_status)
get_waf_status
;;
metrics_config)
get_metrics_config
;;
configure_metrics)
read -r input
enable=$(echo "$input" | jsonfilter -e '@.enable' 2>/dev/null)
configure_metrics "$enable"
;;
collections)
get_collections
;;
install_collection)
read -r input
collection=$(echo "$input" | jsonfilter -e '@.collection' 2>/dev/null)
install_collection "$collection"
;;
remove_collection)
read -r input
collection=$(echo "$input" | jsonfilter -e '@.collection' 2>/dev/null)
remove_collection "$collection"
;;
update_hub)
update_hub
;;
register_bouncer)
read -r input
bouncer_name=$(echo "$input" | jsonfilter -e '@.bouncer_name' 2>/dev/null)
register_bouncer "$bouncer_name"
;;
delete_bouncer)
read -r input
bouncer_name=$(echo "$input" | jsonfilter -e '@.bouncer_name' 2>/dev/null)
delete_bouncer "$bouncer_name"
;;
firewall_bouncer_status)
get_firewall_bouncer_status
;;
control_firewall_bouncer)
read -r input
action=$(echo "$input" | jsonfilter -e '@.action' 2>/dev/null)
control_firewall_bouncer "$action"
;;
firewall_bouncer_config)
get_firewall_bouncer_config
;;
update_firewall_bouncer_config)
read -r input
key=$(echo "$input" | jsonfilter -e '@.key' 2>/dev/null)
value=$(echo "$input" | jsonfilter -e '@.value' 2>/dev/null)
update_firewall_bouncer_config "$key" "$value"
;;
nftables_stats)
get_nftables_stats
;;
check_wizard_needed)
check_wizard_needed
;;
wizard_state)
get_wizard_state
;;
repair_lapi)
repair_lapi
;;
repair_capi)
repair_capi
;;
reset_wizard)
reset_wizard
;;
console_status)
get_console_status
;;
console_enroll)
read -r input
key=$(echo "$input" | jsonfilter -e '@.key' 2>/dev/null)
name=$(echo "$input" | jsonfilter -e '@.name' 2>/dev/null)
console_enroll "$key" "$name"
;;
console_disable)
console_disable
;;
service_control)
read -r input
action=$(echo "$input" | jsonfilter -e '@.action' 2>/dev/null)
service_control "$action"
;;
configure_acquisition)
read -r input
syslog_enabled=$(echo "$input" | jsonfilter -e '@.syslog_enabled' 2>/dev/null)
firewall_enabled=$(echo "$input" | jsonfilter -e '@.firewall_enabled' 2>/dev/null)
ssh_enabled=$(echo "$input" | jsonfilter -e '@.ssh_enabled' 2>/dev/null)
http_enabled=$(echo "$input" | jsonfilter -e '@.http_enabled' 2>/dev/null)
syslog_path=$(echo "$input" | jsonfilter -e '@.syslog_path' 2>/dev/null)
configure_acquisition "$syslog_enabled" "$firewall_enabled" "$ssh_enabled" "$http_enabled" "$syslog_path"
;;
acquisition_config)
get_acquisition_config
;;
acquisition_metrics)
get_acquisition_metrics
;;
health_check)
get_health_check
;;
capi_metrics)
get_capi_metrics
;;
hub_available)
get_hub_available
;;
install_hub_item)
read -r input
item_type=$(echo "$input" | jsonfilter -e '@.item_type' 2>/dev/null)
item_name=$(echo "$input" | jsonfilter -e '@.item_name' 2>/dev/null)
install_hub_item "$item_type" "$item_name"
;;
remove_hub_item)
read -r input
item_type=$(echo "$input" | jsonfilter -e '@.item_type' 2>/dev/null)
item_name=$(echo "$input" | jsonfilter -e '@.item_name' 2>/dev/null)
remove_hub_item "$item_type" "$item_name"
;;
get_settings)
get_settings
;;
save_settings)
read -r input
enrollment_key=$(echo "$input" | jsonfilter -e '@.enrollment_key' 2>/dev/null)
machine_name=$(echo "$input" | jsonfilter -e '@.machine_name' 2>/dev/null)
auto_enroll=$(echo "$input" | jsonfilter -e '@.auto_enroll' 2>/dev/null)
save_settings "$enrollment_key" "$machine_name" "$auto_enroll"
;;
get_overview)
get_overview
;;
*)
echo '{"error": "Unknown method"}'
;;
esac
;;
esac