#!/bin/bash # SecuBox Wazuh Manager Controller # Manages Wazuh SIEM stack in LXC container set -e WAZUH_VERSION="4.9.2" CONFIG="wazuh-manager" LXC_PATH="/srv/lxc" CONTAINER_NAME="wazuh" DATA_PATH="/srv/wazuh" . /lib/functions.sh log_info() { echo "[INFO] $*"; logger -t wazuh-manager "$*"; } log_warn() { echo "[WARN] $*" >&2; } log_error() { echo "[ERROR] $*" >&2; } uci_get() { uci -q get ${CONFIG}.$1; } uci_set() { uci set ${CONFIG}.$1="$2" && uci commit ${CONFIG}; } load_config() { CONTAINER_NAME=$(uci_get main.container_name) || CONTAINER_NAME="wazuh" LXC_PATH=$(uci_get main.lxc_path) || LXC_PATH="/srv/lxc" DATA_PATH=$(uci_get main.data_path) || DATA_PATH="/srv/wazuh" } usage() { cat <<'EOF' SecuBox Wazuh Manager Controller Usage: wazuh-managerctl [options] Installation: install Create and configure Wazuh LXC container uninstall Remove container and data upgrade Upgrade Wazuh to latest version Service Control: start Start Wazuh Manager container stop Stop container restart Restart container status Show container and service status Configuration: configure-haproxy Add HAProxy vhost for dashboard configure-firewall Open required firewall ports generate-certs Generate SSL certificates reset-password Reset admin password Agent Management: list-agents List registered agents agent-info Show agent details remove-agent Remove agent API: api-status Check API status api-token Generate API token Logs & Monitoring: logs [service] Show logs (manager|indexer|dashboard) alerts [n] Show recent alerts stats Show cluster statistics Shell: shell Open shell in container exec Execute command in container Examples: wazuh-managerctl install wazuh-managerctl start wazuh-managerctl configure-haproxy wazuh-managerctl list-agents EOF } # =========================================== # Container Management # =========================================== container_exists() { [ -d "$LXC_PATH/$CONTAINER_NAME/rootfs" ] } container_running() { lxc-info -n "$CONTAINER_NAME" -s 2>/dev/null | grep -q RUNNING } cmd_install() { load_config if container_exists; then log_warn "Container already exists at $LXC_PATH/$CONTAINER_NAME" return 0 fi log_info "Installing Wazuh Manager v$WAZUH_VERSION..." log_info "This may take 10-15 minutes..." # Create directories mkdir -p "$LXC_PATH/$CONTAINER_NAME" mkdir -p "$DATA_PATH"/{indexer,manager,dashboard} # Get network config local ip_addr=$(uci_get network.ip_address) || ip_addr="192.168.255.50" local gateway=$(uci_get network.gateway) || gateway="192.168.255.1" local bridge=$(uci_get network.bridge) || bridge="br-lan" # Create LXC config cat > "$LXC_PATH/$CONTAINER_NAME/config" </dev/null 2>&1; then debootstrap --arch=arm64 bookworm "$rootfs" http://deb.debian.org/debian else # Download pre-built rootfs local rootfs_url="https://images.linuxcontainers.org/images/debian/bookworm/arm64/default" curl -fsSL "$rootfs_url/rootfs.tar.xz" | tar -xJf - -C "$rootfs" || { log_error "Failed to download rootfs" return 1 } fi # Configure container log_info "Configuring container..." # Set hostname echo "$CONTAINER_NAME" > "$rootfs/etc/hostname" # Configure DNS cat > "$rootfs/etc/resolv.conf" < "$rootfs/root/install-wazuh.sh" <<'INSTALL' #!/bin/bash set -e echo "Installing Wazuh components..." # Install dependencies apt-get update apt-get install -y curl apt-transport-https gnupg2 lsb-release # Add Wazuh repository curl -s https://packages.wazuh.com/key/GPG-KEY-WAZUH | gpg --dearmor -o /usr/share/keyrings/wazuh.gpg echo "deb [signed-by=/usr/share/keyrings/wazuh.gpg] https://packages.wazuh.com/4.x/apt stable main" > /etc/apt/sources.list.d/wazuh.list apt-get update # Install Wazuh Indexer echo "Installing Wazuh Indexer..." apt-get install -y wazuh-indexer # Configure indexer cat > /etc/wazuh-indexer/opensearch.yml < /etc/wazuh-dashboard/opensearch_dashboards.yml </dev/null && echo " Manager: Running" || echo " Manager: Stopped" lxc-attach -n "$CONTAINER_NAME" -- systemctl is-active wazuh-indexer 2>/dev/null && echo " Indexer: Running" || echo " Indexer: Stopped" lxc-attach -n "$CONTAINER_NAME" -- systemctl is-active wazuh-dashboard 2>/dev/null && echo " Dashboard: Running" || echo " Dashboard: Stopped" echo "" echo "Access:" echo " Dashboard: http://$ip_addr:5601" echo " API: https://$ip_addr:55000" else echo "Container: STOPPED" fi } # =========================================== # Configuration # =========================================== cmd_configure_haproxy() { load_config local domain=$(uci_get haproxy.domain) || domain="wazuh.gk2.secubox.in" local ip_addr=$(uci_get network.ip_address) local dashboard_port=$(uci_get ports.dashboard) || dashboard_port="5601" log_info "Configuring HAProxy for $domain..." # Create backend uci set haproxy.wazuh_dashboard=backend uci set haproxy.wazuh_dashboard.name="wazuh_dashboard" uci set haproxy.wazuh_dashboard.mode="http" uci set haproxy.wazuh_dashboard.balance="roundrobin" uci set haproxy.wazuh_dashboard.enabled="1" # Create server uci set haproxy.wazuh_dashboard_srv=server uci set haproxy.wazuh_dashboard_srv.backend="wazuh_dashboard" uci set haproxy.wazuh_dashboard_srv.name="srv" uci set haproxy.wazuh_dashboard_srv.address="$ip_addr" uci set haproxy.wazuh_dashboard_srv.port="$dashboard_port" uci set haproxy.wazuh_dashboard_srv.weight="100" uci set haproxy.wazuh_dashboard_srv.check="1" uci set haproxy.wazuh_dashboard_srv.enabled="1" # Create vhost local vhost_name=$(echo "$domain" | tr '.-' '_') uci set haproxy.${vhost_name}=vhost uci set haproxy.${vhost_name}.domain="$domain" uci set haproxy.${vhost_name}.backend="wazuh_dashboard" uci set haproxy.${vhost_name}.ssl="1" uci set haproxy.${vhost_name}.ssl_redirect="1" uci set haproxy.${vhost_name}.waf_bypass="1" uci set haproxy.${vhost_name}.enabled="1" uci commit haproxy # Add to mitmproxy routes if [ -f /srv/mitmproxy-in/haproxy-routes.json ]; then python3 -c " import json with open('/srv/mitmproxy-in/haproxy-routes.json') as f: data = json.load(f) data['$domain'] = ['$ip_addr', $dashboard_port] with open('/srv/mitmproxy-in/haproxy-routes.json', 'w') as f: json.dump(data, f, indent=2) " 2>/dev/null fi # Regenerate HAProxy config haproxyctl generate 2>/dev/null haproxyctl reload 2>/dev/null log_info "HAProxy configured: https://$domain" } cmd_configure_firewall() { load_config local ip_addr=$(uci_get network.ip_address) log_info "Configuring firewall rules..." # Agent registration (1514 TCP/UDP) # API (55000) # These ports need to be accessible from agents cat >> /etc/firewall.user </dev/null | python3 -m json.tool 2>/dev/null || echo "API not responding" } cmd_api_token() { load_config local ip_addr=$(uci_get network.ip_address) log_info "Getting API token..." curl -sk -X POST "https://$ip_addr:55000/security/user/authenticate" \ -H "Content-Type: application/json" \ -u "wazuh:wazuh" 2>/dev/null | python3 -m json.tool } # =========================================== # Logs & Monitoring # =========================================== cmd_logs() { load_config local service="${1:-manager}" case "$service" in manager) lxc-attach -n "$CONTAINER_NAME" -- tail -100 /var/ossec/logs/ossec.log ;; indexer) lxc-attach -n "$CONTAINER_NAME" -- tail -100 /var/log/wazuh-indexer/wazuh-cluster.log ;; dashboard) lxc-attach -n "$CONTAINER_NAME" -- journalctl -u wazuh-dashboard -n 100 ;; *) log_error "Unknown service: $service (manager|indexer|dashboard)" ;; esac } cmd_alerts() { load_config local count="${1:-20}" lxc-attach -n "$CONTAINER_NAME" -- tail -n "$count" /var/ossec/logs/alerts/alerts.json | \ python3 -m json.tool 2>/dev/null || \ lxc-attach -n "$CONTAINER_NAME" -- tail -n "$count" /var/ossec/logs/alerts/alerts.json } cmd_stats() { load_config echo "=== Wazuh Cluster Statistics ===" lxc-attach -n "$CONTAINER_NAME" -- /var/ossec/bin/cluster_control -l 2>/dev/null || echo "Single-node deployment" echo "" echo "=== Agent Statistics ===" lxc-attach -n "$CONTAINER_NAME" -- /var/ossec/bin/agent_control -l | head -20 } # =========================================== # Shell Access # =========================================== cmd_shell() { load_config if ! container_running; then log_error "Container not running" return 1 fi lxc-attach -n "$CONTAINER_NAME" -- /bin/bash } cmd_exec() { load_config shift if ! container_running; then log_error "Container not running" return 1 fi lxc-attach -n "$CONTAINER_NAME" -- "$@" } # =========================================== # Main # =========================================== case "$1" in install) cmd_install ;; uninstall) cmd_uninstall ;; upgrade) cmd_uninstall && cmd_install ;; start) cmd_start ;; stop) cmd_stop ;; restart) cmd_restart ;; status) cmd_status ;; configure-haproxy) cmd_configure_haproxy ;; configure-firewall) cmd_configure_firewall ;; list-agents) cmd_list_agents ;; agent-info) shift; cmd_agent_info "$@" ;; remove-agent) shift; cmd_remove_agent "$@" ;; api-status) cmd_api_status ;; api-token) cmd_api_token ;; logs) shift; cmd_logs "$@" ;; alerts) shift; cmd_alerts "$@" ;; stats) cmd_stats ;; shell) cmd_shell ;; exec) cmd_exec "$@" ;; -h|--help|help|"") usage ;; *) log_error "Unknown command: $1"; usage; exit 1 ;; esac