secubox-openwrt/luci-app-secubox/root/usr/libexec/rpcd/luci.secubox
2025-12-29 09:03:49 +01:00

1185 lines
32 KiB
Bash
Executable File

#!/bin/sh
# SPDX-License-Identifier: Apache-2.0
# SecuBox Master RPCD Backend
# Module discovery and unified status
# Copyright (C) 2025 CyberMind.fr
. /lib/functions.sh
. /usr/share/libubox/jshn.sh
get_pkg_version() {
local ctrl="/usr/lib/opkg/info/luci-app-secubox.control"
if [ -f "$ctrl" ]; then
awk -F': ' '/^Version/ { print $2; exit }' "$ctrl"
else
echo "unknown"
fi
}
PKG_VERSION="$(get_pkg_version)"
# Module registry - auto-detected from /usr/libexec/rpcd/
detect_modules() {
local modules=""
local scripts="luci.crowdsec-dashboard luci.netdata-dashboard luci.netifyd-dashboard luci.wireguard-dashboard luci.network-modes luci.client-guardian luci.system-hub luci.bandwidth-manager luci.auth-guardian luci.media-flow luci.vhost-manager luci.cdn-cache luci.traffic-shaper luci.ksm-manager"
for script in $scripts; do
if [ -x "/usr/libexec/rpcd/$script" ]; then
# Remove luci. prefix, remove -dashboard suffix, convert dashes to underscores
local module_id=$(echo "$script" | sed 's/^luci\.//' | sed 's/-dashboard$//' | sed 's/-/_/g')
modules="$modules $module_id"
fi
done
echo "$modules"
}
MODULES=$(detect_modules)
# Check if a module is installed (supports both opkg and apk)
check_module_installed() {
local module="$1"
local package config
config_get package "$module" package ""
config_get config "$module" config ""
# Check if package is installed via apk (OpenWrt 25.12+) or opkg (24.10 and earlier)
if [ -x "/usr/bin/apk" ]; then
# OpenWrt 25.12+ uses apk
if apk list --installed 2>/dev/null | grep -q "^${package}-"; then
echo "1"
return
fi
elif [ -x "/bin/opkg" ] || [ -x "/usr/bin/opkg" ]; then
# OpenWrt 24.10 and earlier uses opkg
if opkg list-installed 2>/dev/null | grep -q "^${package} "; then
echo "1"
return
fi
fi
# Fallback: check if config file exists
if [ -f "/etc/config/${config}" ]; then
echo "1"
else
echo "0"
fi
}
# Check if a module is enabled (UCI config)
check_module_enabled() {
local module="$1"
local enabled
config_load secubox
config_get enabled "$module" enabled "1"
echo "$enabled"
}
# Check if a module service is running
check_module_running() {
local module="$1"
local config
config_load secubox
config_get config "$module" config ""
case "$module" in
crowdsec)
pgrep -f crowdsec > /dev/null 2>&1 && echo "1" || echo "0"
;;
netdata)
pgrep -f netdata > /dev/null 2>&1 && echo "1" || echo "0"
;;
netifyd)
pgrep -f netifyd > /dev/null 2>&1 && echo "1" || echo "0"
;;
wireguard)
[ -n "$(wg show 2>/dev/null)" ] && echo "1" || echo "0"
;;
cdn_cache)
pgrep -f "nginx.*cdn-cache" > /dev/null 2>&1 && echo "1" || echo "0"
;;
*)
# Generic check via init.d
if [ -x "/etc/init.d/${config}" ]; then
/etc/init.d/${config} running > /dev/null 2>&1 && echo "1" || echo "0"
else
echo "0"
fi
;;
esac
}
# Determine module status based on enabled + running
get_module_status() {
local enabled="$1"
local running="$2"
if [ "$enabled" = "1" ] && [ "$running" = "1" ]; then
echo "active"
elif [ "$enabled" = "1" ] && [ "$running" = "0" ]; then
echo "error"
elif [ "$enabled" = "0" ] && [ "$running" = "0" ]; then
echo "disabled"
else
echo "unknown"
fi
}
# Get overall system status
get_status() {
local total=0
local installed=0
local running=0
json_init
json_add_string "version" "$PKG_VERSION"
json_add_string "hostname" "$(uci -q get system.@system[0].hostname || echo 'SecuBox')"
# System info
local uptime=$(cat /proc/uptime | cut -d. -f1)
local load=$(cat /proc/loadavg | cut -d' ' -f1-3)
local mem_total=$(grep MemTotal /proc/meminfo | awk '{print $2}')
local mem_free=$(grep MemAvailable /proc/meminfo | awk '{print $2}')
local mem_used=$((mem_total - mem_free))
local mem_pct=$((mem_used * 100 / mem_total))
json_add_int "uptime" "$uptime"
json_add_string "load" "$load"
json_add_int "memory_total" "$mem_total"
json_add_int "memory_used" "$mem_used"
json_add_int "memory_percent" "$mem_pct"
# Count modules from UCI config (same as get_modules)
config_load secubox 2>/dev/null || true
local module_sections=$(uci -q show secubox | grep "=module$" | cut -d. -f2 | cut -d= -f1)
for module in $module_sections; do
total=$((total + 1))
local is_installed=$(check_module_installed "$module")
local is_running=$(check_module_running "$module")
if [ "$is_installed" = "1" ]; then
installed=$((installed + 1))
fi
if [ "$is_running" = "1" ]; then
running=$((running + 1))
fi
done
json_add_int "modules_total" "$total"
json_add_int "modules_installed" "$installed"
json_add_int "modules_running" "$running"
json_dump
}
# Detect real installed luci-app packages (supports both opkg and apk)
detect_real_modules() {
if [ -x "/usr/bin/apk" ]; then
# OpenWrt 25.12+ uses apk
apk list --installed 2>/dev/null | grep "^luci-app-" | grep -v "^luci-app-secubox-" | while IFS=- read -r pkg rest; do
# Parse apk output: luci-app-network-modes-0.3.1-r1 noarch {...} (license) [installed]
local package=$(echo "$pkg-$rest" | awk '{print $1}')
local version=$(echo "$package" | sed 's/^luci-app-[^-]*-//' | sed 's/-r[0-9]*$//')
local pkg_name=$(echo "$package" | sed 's/-[0-9].*//')
local module_id=$(echo "$pkg_name" | sed 's/^luci-app-//' | sed 's/-dashboard$//' | sed 's/-/_/g')
echo "$module_id:$pkg_name:$version"
done
elif [ -x "/bin/opkg" ] || [ -x "/usr/bin/opkg" ]; then
# OpenWrt 24.10 and earlier uses opkg
opkg list-installed 2>/dev/null | grep "^luci-app-" | grep -v "^luci-app-secubox " | while read package version; do
# Extract module ID from package name
local module_id=$(echo "$package" | sed 's/^luci-app-//' | sed 's/-dashboard$//' | sed 's/-/_/g')
echo "$module_id:$package:$version"
done
fi
}
# Get detailed modules list (UCI + auto-detected)
get_modules() {
json_init
json_add_array "modules"
config_load secubox 2>/dev/null || true
# Create associative array to track processed modules
local processed_modules=""
# First, add modules from UCI config
local module_sections=$(uci -q show secubox | grep "=module$" | cut -d. -f2 | cut -d= -f1)
for module in $module_sections; do
local name desc category icon color package config version
config_get name "$module" name "$module"
config_get desc "$module" description ""
config_get category "$module" category "other"
config_get icon "$module" icon "📦"
config_get color "$module" color "#64748b"
config_get package "$module" package ""
config_get config "$module" config ""
config_get version "$module" version "0.0.9"
local is_installed=$(check_module_installed "$module")
local is_enabled=$(check_module_enabled "$module")
local is_running=$(check_module_running "$module")
local status=$(get_module_status "$is_enabled" "$is_running")
# Get real version from package manager if installed
if [ "$is_installed" = "1" ] && [ -n "$package" ]; then
if [ -x "/usr/bin/apk" ]; then
# OpenWrt 25.12+ uses apk
# apk output: luci-app-network-modes-0.3.1-r1 noarch {...}
local real_version=$(apk list --installed "$package" 2>/dev/null | head -1 | awk '{print $1}' | grep -oE '[0-9]+\.[0-9]+\.[0-9]+')
[ -n "$real_version" ] && version="$real_version"
elif [ -x "/bin/opkg" ] || [ -x "/usr/bin/opkg" ]; then
# OpenWrt 24.10 and earlier uses opkg
local real_version=$(opkg list-installed "$package" 2>/dev/null | awk '{print $3}' | sed 's/-.*$//')
[ -n "$real_version" ] && version="$real_version"
fi
fi
json_add_object ""
json_add_string "id" "$module"
json_add_string "name" "$name"
json_add_string "description" "$desc"
json_add_string "category" "$category"
json_add_string "icon" "$icon"
json_add_string "color" "$color"
json_add_string "package" "$package"
json_add_string "config" "$config"
json_add_string "version" "$version"
json_add_boolean "installed" "$is_installed"
json_add_boolean "enabled" "$is_enabled"
json_add_boolean "running" "$is_running"
json_add_string "status" "$status"
json_add_boolean "in_uci" "1"
json_close_object
processed_modules="$processed_modules $module"
done
# Second, add auto-detected modules not in UCI
detect_real_modules | while IFS=: read module_id package version; do
# Skip if already processed
echo "$processed_modules" | grep -q " $module_id " && continue
# Auto-detect properties based on package name
local name=$(echo "$package" | sed 's/^luci-app-//' | sed 's/-/ /g' | awk '{for(i=1;i<=NF;i++){$i=toupper(substr($i,1,1)) substr($i,2)}}1')
local category="other"
local icon="📦"
local color="#64748b"
# Auto-categorize
case "$package" in
*crowdsec*|*guardian*|*auth*)
category="security"; icon="🛡️"; color="#22c55e"
;;
*netdata*|*monitoring*)
category="monitoring"; icon="📊"; color="#00ab44"
;;
*network*|*wireguard*|*bandwidth*|*traffic*)
category="network"; icon="🌐"; color="#3b82f6"
;;
*system*|*hub*)
category="system"; icon="⚙️"; color="#6366f1"
;;
esac
local clean_module=$(echo "$module_id" | sed 's/_/-/g')
local is_enabled=$(check_module_enabled "$module_id")
local is_running=$(check_module_running "$module_id")
local status=$(get_module_status "$is_enabled" "$is_running")
json_add_object ""
json_add_string "id" "$module_id"
json_add_string "name" "$name"
json_add_string "description" "Auto-detected module"
json_add_string "category" "$category"
json_add_string "icon" "$icon"
json_add_string "color" "$color"
json_add_string "package" "$package"
json_add_string "config" "$clean_module"
json_add_string "version" "$version"
json_add_boolean "installed" "1"
json_add_boolean "enabled" "$is_enabled"
json_add_boolean "running" "$is_running"
json_add_string "status" "$status"
json_add_boolean "in_uci" "0"
json_close_object
done
json_close_array
json_dump
}
# Get modules by category
get_modules_by_category() {
local category="$1"
json_init
json_add_array "modules"
config_load secubox 2>/dev/null || true
local processed_modules=""
# List all module sections from UCI config
local module_sections=$(uci -q show secubox | grep "=module$" | cut -d. -f2 | cut -d= -f1)
# First pass: UCI-defined modules in this category
for module in $module_sections; do
local mod_category
config_get mod_category "$module" category "other"
if [ "$mod_category" = "$category" ]; then
local name desc icon color package config version
config_get name "$module" name "$module"
config_get desc "$module" description ""
config_get icon "$module" icon "box"
config_get color "$module" color "#64748b"
config_get package "$module" package ""
config_get config "$module" config ""
config_get version "$module" version "0.0.9"
local is_installed=$(check_module_installed "$module")
local is_enabled=$(check_module_enabled "$module")
local is_running=$(check_module_running "$module")
local status=$(get_module_status "$is_enabled" "$is_running")
# Get real version from opkg if installed
if [ "$is_installed" = "1" ] && [ -n "$package" ]; then
local real_version=$(opkg list-installed "$package" 2>/dev/null | awk '{print $3}' | sed 's/-.*$//')
[ -n "$real_version" ] && version="$real_version"
fi
json_add_object ""
json_add_string "id" "$module"
json_add_string "name" "$name"
json_add_string "description" "$desc"
json_add_string "icon" "$icon"
json_add_string "color" "$color"
json_add_string "version" "$version"
json_add_string "package" "$package"
json_add_boolean "installed" "$is_installed"
json_add_boolean "enabled" "$is_enabled"
json_add_boolean "running" "$is_running"
json_add_string "status" "$status"
json_add_boolean "in_uci" "1"
json_close_object
processed_modules="$processed_modules $module"
fi
done
# Second pass: Auto-detected modules not in UCI
detect_real_modules | while IFS=: read module_id package version; do
# Skip if already processed from UCI
echo "$processed_modules" | grep -q " $module_id " && continue
# Auto-categorize
local mod_category icon color name
case "$package" in
*crowdsec*|*guardian*|*auth*)
mod_category="security"; icon="🛡️"; color="#22c55e"
;;
*netdata*|*monitoring*)
mod_category="monitoring"; icon="📊"; color="#00ab44"
;;
*network*|*wireguard*|*bandwidth*|*traffic*|*cdn*)
mod_category="network"; icon="🌐"; color="#3b82f6"
;;
*system*|*hub*|*vhost*)
mod_category="system"; icon="⚙️"; color="#6366f1"
;;
*)
mod_category="other"; icon="📦"; color="#64748b"
;;
esac
# Only include if matches requested category
if [ "$mod_category" = "$category" ]; then
# Generate nice name from package
name=$(echo "$package" | sed 's/^luci-app-//' | sed 's/-dashboard$//' | sed 's/-/ /g' | sed 's/\b\(.\)/\u\1/g')
local is_installed="1" # Must be installed if detected
local is_enabled=$(check_module_enabled "$module_id")
local is_running=$(check_module_running "$module_id")
local status=$(get_module_status "$is_enabled" "$is_running")
json_add_object ""
json_add_string "id" "$module_id"
json_add_string "name" "$name"
json_add_string "description" "Auto-detected module"
json_add_string "icon" "$icon"
json_add_string "color" "$color"
json_add_string "version" "$version"
json_add_string "package" "$package"
json_add_string "category" "$mod_category"
json_add_boolean "installed" "$is_installed"
json_add_boolean "enabled" "$is_enabled"
json_add_boolean "running" "$is_running"
json_add_string "status" "$status"
json_add_boolean "in_uci" "0"
json_close_object
fi
done
json_close_array
json_dump
}
# Get single module info
get_module_info() {
local module="$1"
config_load secubox
local name desc category icon color package config version
config_get name "$module" name "$module"
config_get desc "$module" description ""
config_get category "$module" category "other"
config_get icon "$module" icon "box"
config_get color "$module" color "#64748b"
config_get package "$module" package ""
config_get config "$module" config ""
config_get version "$module" version "0.0.9"
local is_installed=$(check_module_installed "$module")
local is_enabled=$(check_module_enabled "$module")
local is_running=$(check_module_running "$module")
local status=$(get_module_status "$is_enabled" "$is_running")
json_init
json_add_string "id" "$module"
json_add_string "name" "$name"
json_add_string "description" "$desc"
json_add_string "category" "$category"
json_add_string "icon" "$icon"
json_add_string "color" "$color"
json_add_string "package" "$package"
json_add_string "config" "$config"
json_add_string "version" "$version"
json_add_boolean "installed" "$is_installed"
json_add_boolean "enabled" "$is_enabled"
json_add_boolean "running" "$is_running"
json_add_string "status" "$status"
json_dump
}
# Start a module
start_module() {
local module="$1"
local config
config_load secubox
config_get config "$module" config ""
if [ -x "/etc/init.d/${config}" ]; then
/etc/init.d/${config} start
json_init
json_add_boolean "success" 1
json_add_string "message" "Module started"
json_dump
else
json_init
json_add_boolean "success" 0
json_add_string "message" "Init script not found"
json_dump
fi
}
# Stop a module
stop_module() {
local module="$1"
local config
config_load secubox
config_get config "$module" config ""
if [ -x "/etc/init.d/${config}" ]; then
/etc/init.d/${config} stop
json_init
json_add_boolean "success" 1
json_add_string "message" "Module stopped"
json_dump
else
json_init
json_add_boolean "success" 0
json_add_string "message" "Init script not found"
json_dump
fi
}
# Restart a module (DEPRECATED - use disable/enable instead)
restart_module() {
local module="$1"
local config
config_load secubox
config_get config "$module" config ""
if [ -x "/etc/init.d/${config}" ]; then
/etc/init.d/${config} restart
json_init
json_add_boolean "success" 1
json_add_string "message" "Module restarted"
json_dump
else
json_init
json_add_boolean "success" 0
json_add_string "message" "Init script not found"
json_dump
fi
}
# Enable a module (NEW v0.3.1)
enable_module() {
local module="$1"
# Set enabled flag in UCI (v0.3.1)
# This only activates the module in configuration
# Use start_module() to actually start the service
uci set secubox.${module}.enabled='1'
uci commit secubox
json_init
json_add_boolean "success" 1
json_add_string "message" "Module activé dans la configuration"
json_add_string "note" "Utilisez 'Démarrer' pour lancer le service"
json_dump
}
# Disable a module (NEW v0.3.1)
disable_module() {
local module="$1"
# Set disabled flag in UCI (v0.3.1)
# This only deactivates the module in configuration
# Use stop_module() to actually stop the service
uci set secubox.${module}.enabled='0'
uci commit secubox
json_init
json_add_boolean "success" 1
json_add_string "message" "Module désactivé dans la configuration"
json_add_string "note" "Utilisez 'Arrêter' pour stopper le service"
json_dump
}
# Get health report
get_health() {
json_init
json_add_array "checks"
config_load secubox 2>/dev/null || true
# List all module sections from UCI config
local module_sections=$(uci -q show secubox | grep "=module$" | cut -d. -f2 | cut -d= -f1)
# Check each installed module
for module in $module_sections; do
local is_installed=$(check_module_installed "$module")
if [ "$is_installed" = "1" ]; then
local is_running=$(check_module_running "$module")
local name
config_get name "$module" name "$module"
local status="ok"
local message="Running normally"
if [ "$is_running" != "1" ]; then
status="warning"
message="Service not running"
fi
json_add_object ""
json_add_string "module" "$module"
json_add_string "name" "$name"
json_add_string "status" "$status"
json_add_string "message" "$message"
json_close_object
fi
done
json_close_array
# Overall health
local overall="healthy"
# Could add more sophisticated health checks here
json_add_string "overall" "$overall"
json_add_int "timestamp" "$(date +%s)"
json_dump
}
# Generate diagnostics bundle
get_diagnostics() {
json_init
# System info
json_add_object "system"
json_add_string "hostname" "$(uci -q get system.@system[0].hostname)"
json_add_string "model" "$(cat /tmp/sysinfo/model 2>/dev/null || echo 'Unknown')"
json_add_string "openwrt_version" "$(cat /etc/openwrt_release | grep DISTRIB_RELEASE | cut -d= -f2 | tr -d \"\')"
json_add_string "kernel" "$(uname -r)"
json_add_int "uptime" "$(cat /proc/uptime | cut -d. -f1)"
json_close_object
# Modules status
json_add_array "modules"
config_load secubox 2>/dev/null || true
local module_sections=$(uci -q show secubox | grep "=module$" | cut -d. -f2 | cut -d= -f1)
for module in $module_sections; do
local is_installed=$(check_module_installed "$module")
local is_running=$(check_module_running "$module")
json_add_object ""
json_add_string "id" "$module"
json_add_boolean "installed" "$is_installed"
json_add_boolean "running" "$is_running"
json_close_object
done
json_close_array
# Network interfaces
json_add_array "interfaces"
for iface in $(ls /sys/class/net/); do
local mac=$(cat /sys/class/net/$iface/address 2>/dev/null)
local state=$(cat /sys/class/net/$iface/operstate 2>/dev/null)
json_add_object ""
json_add_string "name" "$iface"
json_add_string "mac" "$mac"
json_add_string "state" "$state"
json_close_object
done
json_close_array
json_add_int "generated" "$(date +%s)"
json_dump
}
# Get system health metrics
get_system_health() {
json_init
# CPU usage (based on load average)
local load=$(cat /proc/loadavg | cut -d' ' -f1)
local cpu_cores=$(grep -c processor /proc/cpuinfo)
local cpu_pct=$(awk "BEGIN {printf \"%.0f\", ($load / $cpu_cores) * 100}")
# Memory
local mem_total=$(grep MemTotal /proc/meminfo | awk '{print $2}')
local mem_avail=$(grep MemAvailable /proc/meminfo | awk '{print $2}')
local mem_used=$((mem_total - mem_avail))
local mem_pct=$((mem_used * 100 / mem_total))
# Disk usage (root filesystem)
local disk_info=$(df / | tail -1)
local disk_total=$(echo "$disk_info" | awk '{print $2}')
local disk_used=$(echo "$disk_info" | awk '{print $3}')
local disk_pct=$(echo "$disk_info" | awk '{print $5}' | tr -d '%')
# Network stats (sum all interfaces)
local net_rx=0
local net_tx=0
for iface in $(ls /sys/class/net/ | grep -v lo); do
if [ -f "/sys/class/net/$iface/statistics/rx_bytes" ]; then
local rx=$(cat /sys/class/net/$iface/statistics/rx_bytes 2>/dev/null || echo 0)
local tx=$(cat /sys/class/net/$iface/statistics/tx_bytes 2>/dev/null || echo 0)
net_rx=$((net_rx + rx))
net_tx=$((net_tx + tx))
fi
done
# Uptime
local uptime=$(cat /proc/uptime | cut -d. -f1)
# Load averages
local load_1min=$(cat /proc/loadavg | cut -d' ' -f1)
local load_5min=$(cat /proc/loadavg | cut -d' ' -f2)
local load_15min=$(cat /proc/loadavg | cut -d' ' -f3)
json_add_object "cpu"
json_add_int "percent" "$cpu_pct"
json_add_int "cores" "$cpu_cores"
json_add_string "load_1min" "$load_1min"
json_add_string "load_5min" "$load_5min"
json_add_string "load_15min" "$load_15min"
json_close_object
json_add_object "memory"
json_add_int "percent" "$mem_pct"
json_add_int "total_kb" "$mem_total"
json_add_int "used_kb" "$mem_used"
json_add_int "available_kb" "$mem_avail"
json_close_object
json_add_object "disk"
json_add_int "percent" "$disk_pct"
json_add_int "total_kb" "$disk_total"
json_add_int "used_kb" "$disk_used"
json_close_object
json_add_object "network"
json_add_int "rx_bytes" "$net_rx"
json_add_int "tx_bytes" "$net_tx"
json_close_object
json_add_int "uptime" "$uptime"
json_add_int "timestamp" "$(date +%s)"
json_dump
}
# Get aggregated alerts from all modules
get_alerts() {
json_init
json_add_array "alerts"
local alert_count=0
# Check each installed module for alerts
config_load secubox 2>/dev/null || true
# List all module sections from UCI config
local module_sections=$(uci -q show secubox | grep "=module$" | cut -d. -f2 | cut -d= -f1)
for module in $module_sections; do
local is_installed=$(check_module_installed "$module")
if [ "$is_installed" = "1" ]; then
# Check if module service is not running
local is_running=$(check_module_running "$module")
if [ "$is_running" != "1" ]; then
local name
config_get name "$module" name "$module"
json_add_object ""
json_add_string "module" "$module"
json_add_string "message" "$name service is not running"
json_add_string "severity" "warning"
json_add_int "timestamp" "$(date +%s)"
json_close_object
alert_count=$((alert_count + 1))
fi
fi
done
json_close_array
json_add_int "count" "$alert_count"
json_add_int "timestamp" "$(date +%s)"
json_dump
}
# Execute quick actions
quick_action() {
local action="$1"
json_init
case "$action" in
restart_rpcd)
/etc/init.d/rpcd restart >/dev/null 2>&1
json_add_boolean "success" 1
json_add_string "message" "RPCD service restarted"
;;
restart_uhttpd)
/etc/init.d/uhttpd restart >/dev/null 2>&1
json_add_boolean "success" 1
json_add_string "message" "uHTTPd service restarted"
;;
clear_cache)
sync
echo 3 > /proc/sys/vm/drop_caches 2>/dev/null
json_add_boolean "success" 1
json_add_string "message" "System cache cleared"
;;
backup_config)
local backup_file="/tmp/backup-$(date +%Y%m%d-%H%M%S).tar.gz"
sysupgrade -b "$backup_file" >/dev/null 2>&1
if [ -f "$backup_file" ]; then
json_add_boolean "success" 1
json_add_string "message" "Configuration backup created"
json_add_string "file" "$backup_file"
else
json_add_boolean "success" 0
json_add_string "message" "Backup failed"
fi
;;
restart_network)
/etc/init.d/network restart >/dev/null 2>&1
json_add_boolean "success" 1
json_add_string "message" "Network services restarted"
;;
restart_firewall)
/etc/init.d/firewall restart >/dev/null 2>&1
json_add_boolean "success" 1
json_add_string "message" "Firewall restarted"
;;
*)
json_add_boolean "success" 0
json_add_string "message" "Unknown action: $action"
;;
esac
json_add_int "timestamp" "$(date +%s)"
json_dump
}
# Get all dashboard data in one call
get_dashboard_data() {
json_init
# Get status info
local uptime=$(cat /proc/uptime | cut -d. -f1)
local load=$(cat /proc/loadavg | cut -d' ' -f1-3)
local mem_total=$(grep MemTotal /proc/meminfo | awk '{print $2}')
local mem_free=$(grep MemAvailable /proc/meminfo | awk '{print $2}')
local mem_used=$((mem_total - mem_free))
local mem_pct=$((mem_used * 100 / mem_total))
json_add_object "status"
json_add_string "version" "$PKG_VERSION"
json_add_string "hostname" "$(uci -q get system.@system[0].hostname || echo 'SecuBox')"
json_add_int "uptime" "$uptime"
json_add_string "load" "$load"
json_add_int "memory_total" "$mem_total"
json_add_int "memory_used" "$mem_used"
json_add_int "memory_percent" "$mem_pct"
json_close_object
# Load config once for all modules
config_load secubox 2>/dev/null || true
# Get modules list
json_add_array "modules"
local total=0 installed=0 running=0
# List all module sections from UCI config
local module_sections=$(uci -q show secubox | grep "=module$" | cut -d. -f2 | cut -d= -f1)
for module in $module_sections; do
local name desc category icon color package version
config_get name "$module" name "$module"
config_get desc "$module" description ""
config_get category "$module" category "other"
config_get icon "$module" icon "box"
config_get color "$module" color "#64748b"
config_get package "$module" package ""
config_get version "$module" version "0.0.9"
local is_installed=$(check_module_installed "$module")
local is_enabled="0"
local is_running="0"
local status="disabled"
total=$((total + 1))
if [ "$is_installed" = "1" ]; then
is_enabled=$(check_module_enabled "$module")
is_running=$(check_module_running "$module")
status=$(get_module_status "$is_enabled" "$is_running")
installed=$((installed + 1))
[ "$is_running" = "1" ] && running=$((running + 1))
# Get real version from package manager if installed
if [ -n "$package" ]; then
if [ -x "/usr/bin/apk" ]; then
# OpenWrt 25.12+ uses apk
local real_version=$(apk list --installed "$package" 2>/dev/null | head -1 | awk '{print $1}' | grep -oE '[0-9]+\.[0-9]+\.[0-9]+')
[ -n "$real_version" ] && version="$real_version"
elif [ -x "/bin/opkg" ] || [ -x "/usr/bin/opkg" ]; then
# OpenWrt 24.10 and earlier uses opkg
local real_version=$(opkg list-installed "$package" 2>/dev/null | awk '{print $3}' | sed 's/-.*$//')
[ -n "$real_version" ] && version="$real_version"
fi
fi
fi
json_add_object ""
json_add_string "id" "$module"
json_add_string "name" "$name"
json_add_string "description" "$desc"
json_add_string "category" "$category"
json_add_string "icon" "$icon"
json_add_string "color" "$color"
json_add_string "version" "$version"
json_add_boolean "installed" "$is_installed"
json_add_boolean "enabled" "$is_enabled"
json_add_boolean "running" "$is_running"
json_add_string "status" "$status"
json_close_object
done
json_close_array
json_add_object "counts"
json_add_int "total" "$total"
json_add_int "installed" "$installed"
json_add_int "running" "$running"
json_close_object
# Get system health
local cpu_cores=$(grep -c processor /proc/cpuinfo)
local load_val=$(echo "$load" | cut -d' ' -f1)
local cpu_pct=$(awk "BEGIN {printf \"%.0f\", ($load_val / $cpu_cores) * 100}" 2>/dev/null || echo "0")
local disk_pct=$(df / | tail -1 | awk '{print $5}' | tr -d '%')
json_add_object "health"
json_add_int "cpu_percent" "$cpu_pct"
json_add_int "memory_percent" "$mem_pct"
json_add_int "disk_percent" "$disk_pct"
json_close_object
# Empty alerts array
json_add_array "alerts"
json_close_array
json_add_int "timestamp" "$(date +%s)"
json_dump
}
# Get theme setting
get_theme() {
local theme="dark"
# Load secubox config
if [ -f "/etc/config/secubox" ]; then
config_load secubox
config_get theme main theme "dark"
fi
json_init
json_add_string "theme" "$theme"
json_dump
}
# Dismiss a specific alert
dismiss_alert() {
local alert_id="$1"
# Store dismissed alerts in tmp file
local dismissed_file="/tmp/secubox_dismissed_alerts"
# Append alert_id to dismissed list
echo "$alert_id" >> "$dismissed_file"
json_init
json_add_boolean "success" 1
json_add_string "message" "Alert dismissed"
json_dump
}
# Clear all alerts
clear_alerts() {
# Clear dismissed alerts file
local dismissed_file="/tmp/secubox_dismissed_alerts"
rm -f "$dismissed_file"
json_init
json_add_boolean "success" 1
json_add_string "message" "All alerts cleared"
json_dump
}
# Fix permissions (v0.3.1)
fix_permissions() {
local fix_script="/usr/libexec/secubox/fix-permissions.sh"
if [ ! -x "$fix_script" ]; then
json_init
json_add_boolean "success" 0
json_add_string "message" "Fix script not found or not executable"
json_dump
return 1
fi
# Run the fix script and capture output
local output=$($fix_script 2>&1)
local exit_code=$?
json_init
if [ $exit_code -eq 0 ]; then
json_add_boolean "success" 1
json_add_string "message" "Permissions fixed successfully"
else
json_add_boolean "success" 0
json_add_string "message" "Failed to fix permissions"
fi
json_add_string "output" "$output"
json_dump
}
# Main dispatcher
case "$1" in
list)
json_init
json_add_object "status"
json_close_object
json_add_object "modules"
json_close_object
json_add_object "modules_by_category"
json_add_string "category" "string"
json_close_object
json_add_object "module_info"
json_add_string "module" "string"
json_close_object
json_add_object "start_module"
json_add_string "module" "string"
json_close_object
json_add_object "stop_module"
json_add_string "module" "string"
json_close_object
json_add_object "restart_module"
json_add_string "module" "string"
json_close_object
json_add_object "enable_module"
json_add_string "module" "string"
json_close_object
json_add_object "disable_module"
json_add_string "module" "string"
json_close_object
json_add_object "check_module_enabled"
json_add_string "module" "string"
json_close_object
json_add_object "health"
json_close_object
json_add_object "diagnostics"
json_close_object
json_add_object "get_system_health"
json_close_object
json_add_object "get_alerts"
json_close_object
json_add_object "quick_action"
json_add_string "action" "string"
json_close_object
json_add_object "get_dashboard_data"
json_close_object
json_add_object "get_theme"
json_close_object
json_add_object "dismiss_alert"
json_add_string "alert_id" "string"
json_close_object
json_add_object "clear_alerts"
json_close_object
json_add_object "fix_permissions"
json_close_object
json_dump
;;
call)
case "$2" in
status)
get_status
;;
modules)
get_modules
;;
modules_by_category)
read -r input
json_load "$input"
json_get_var category category "security"
get_modules_by_category "$category"
;;
module_info)
read -r input
json_load "$input"
json_get_var module module ""
get_module_info "$module"
;;
start_module)
read -r input
json_load "$input"
json_get_var module module ""
start_module "$module"
;;
stop_module)
read -r input
json_load "$input"
json_get_var module module ""
stop_module "$module"
;;
restart_module)
read -r input
json_load "$input"
json_get_var module module ""
restart_module "$module"
;;
enable_module)
read -r input
json_load "$input"
json_get_var module module ""
enable_module "$module"
;;
disable_module)
read -r input
json_load "$input"
json_get_var module module ""
disable_module "$module"
;;
check_module_enabled)
read -r input
json_load "$input"
json_get_var module module ""
local enabled=$(check_module_enabled "$module")
json_init
json_add_boolean "enabled" "$enabled"
json_dump
;;
health)
get_health
;;
diagnostics)
get_diagnostics
;;
get_system_health)
get_system_health
;;
get_alerts)
get_alerts
;;
quick_action)
read -r input
json_load "$input"
json_get_var action action ""
quick_action "$action"
;;
get_dashboard_data)
get_dashboard_data
;;
get_theme)
get_theme
;;
dismiss_alert)
read -r input
json_load "$input"
json_get_var alert_id alert_id ""
dismiss_alert "$alert_id"
;;
clear_alerts)
clear_alerts
;;
fix_permissions)
fix_permissions
;;
*)
echo '{"error":"Unknown method"}'
;;
esac
;;
*)
echo '{"error":"Unknown command"}'
;;
esac