#!/usr/bin/env bash
# =============================================================================
# PBX Fail2Ban Setup
# Installs fail2ban with PBX-specific jails and filters.
# Run as root: sudo bash scripts/setup-fail2ban.sh
# =============================================================================
set -euo pipefail

RED='\033[0;31m'; GREEN='\033[0;32m'; YELLOW='\033[1;33m'; NC='\033[0m'
ok()   { echo -e "${GREEN}[OK]${NC} $1"; }
warn() { echo -e "${YELLOW}[WARN]${NC} $1"; }

if [[ $EUID -ne 0 ]]; then
    echo -e "${RED}[ERROR]${NC} Run as root: sudo $0"
    exit 1
fi

SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"

echo ""
echo "============================================"
echo "  PBX Fail2Ban Setup"
echo "============================================"
echo ""

# -----------------------------------------------------------------------------
# 1. Install fail2ban if not present
# -----------------------------------------------------------------------------
if ! command -v fail2ban-client &>/dev/null; then
    echo "Installing fail2ban..."
    apt-get update -qq
    apt-get install -y fail2ban ipset nftables
    ok "fail2ban installed"
else
    ok "fail2ban already installed"
fi

# -----------------------------------------------------------------------------
# 2. Install jail configuration
# -----------------------------------------------------------------------------
echo ""
echo "--- Installing jail configuration ---"

cp "${SCRIPT_DIR}/fail2ban/jail.local" /etc/fail2ban/jail.local
chmod 644 /etc/fail2ban/jail.local
ok "jail.local installed"

# -----------------------------------------------------------------------------
# 3. Install custom filters
# -----------------------------------------------------------------------------
echo ""
echo "--- Installing custom filters ---"

for filter in "${SCRIPT_DIR}"/fail2ban/filter.d/*.conf; do
    fname=$(basename "$filter")
    cp "$filter" "/etc/fail2ban/filter.d/${fname}"
    chmod 644 "/etc/fail2ban/filter.d/${fname}"
    ok "Filter installed: ${fname}"
done

# -----------------------------------------------------------------------------
# 4. Ensure Asterisk security logging is enabled
# -----------------------------------------------------------------------------
echo ""
echo "--- Checking Asterisk logging ---"

LOGGER_CONF="/etc/asterisk/logger.conf"
if [ -f "$LOGGER_CONF" ]; then
    # Ensure security log exists
    if ! grep -q "^security" "$LOGGER_CONF"; then
        # Add security log line after [logfiles] section
        sed -i '/^\[logfiles\]/a security => security' "$LOGGER_CONF"
        ok "Added security log to logger.conf"
        # Reload logger
        asterisk -rx "logger reload" 2>/dev/null || true
    else
        ok "Security logging already configured"
    fi
else
    warn "logger.conf not found at ${LOGGER_CONF}"
fi

# Ensure the security log file exists and is writable
touch /var/log/asterisk/security 2>/dev/null || true
chown asterisk:asterisk /var/log/asterisk/security 2>/dev/null || true
chmod 644 /var/log/asterisk/security 2>/dev/null || true

# -----------------------------------------------------------------------------
# 5. Ensure Asterisk messages log has correct permissions
# -----------------------------------------------------------------------------
if [ -f /var/log/asterisk/messages ]; then
    chmod 644 /var/log/asterisk/messages
    ok "Asterisk messages log readable"
fi

# -----------------------------------------------------------------------------
# 6. Configure nftables as the ban action
# -----------------------------------------------------------------------------
echo ""
echo "--- Configuring nftables ban action ---"

# Ensure nftables is running
systemctl enable nftables 2>/dev/null || true
systemctl start nftables 2>/dev/null || true

# Verify nftables-multiport action exists
if [ -f /etc/fail2ban/action.d/nftables-multiport.conf ]; then
    ok "nftables-multiport action available"
else
    warn "nftables-multiport action not found — fail2ban may use iptables fallback"
fi

# -----------------------------------------------------------------------------
# 7. Restart fail2ban
# -----------------------------------------------------------------------------
echo ""
echo "--- Restarting fail2ban ---"

systemctl enable fail2ban
systemctl restart fail2ban

# Wait a moment for jails to initialize
sleep 2

# Verify
JAIL_COUNT=$(fail2ban-client status 2>/dev/null | grep "Number of jail" | awk '{print $NF}' || echo "0")
ok "fail2ban restarted with ${JAIL_COUNT} jail(s)"

# List active jails
echo ""
echo "Active jails:"
fail2ban-client status 2>/dev/null | grep "Jail list" | sed 's/.*Jail list:\s*//' | tr ',' '\n' | while read -r jail; do
    jail=$(echo "$jail" | xargs)
    if [ -n "$jail" ]; then
        BANNED=$(fail2ban-client status "$jail" 2>/dev/null | grep "Currently banned" | awk '{print $NF}')
        echo "  - ${jail}: ${BANNED:-0} banned"
    fi
done

# -----------------------------------------------------------------------------
# 8. Run permissions setup
# -----------------------------------------------------------------------------
echo ""
echo "--- Setting up web GUI permissions ---"
bash "${SCRIPT_DIR}/setup-firewall-permissions.sh"

echo ""
echo "============================================"
echo "  Fail2Ban Setup Complete"
echo "============================================"
echo ""
echo "  Jails configured:"
echo "    - sshd (port 2205, ban 24h after 3 failures)"
echo "    - asterisk-pjsip (SIP auth failures, ban 1h after 5)"
echo "    - asterisk-ami (AMI brute-force, ban 24h after 3)"
echo "    - asterisk-security (all security events, ban 2h after 3)"
echo "    - asterisk-scanner (SIP scanners, ban 24h after 2)"
echo "    - pbx-web (web login brute-force, ban 1h after 5)"
echo "    - recidive (repeat offenders, ban 1 week after 3 bans)"
echo ""
echo "  To check status:  fail2ban-client status"
echo "  To check a jail:  fail2ban-client status asterisk-pjsip"
echo "  To unban an IP:   fail2ban-client set asterisk-pjsip unbanip 1.2.3.4"
echo ""
