#!/usr/bin/env bash
#
# deploy-all.sh — Déploie Nginx PUIS fail2ban durci, en une commande.
#
#   Étape 1  Nginx  : backup -> install -> `nginx -t` (gate) -> reload
#   Étape 2  f2b    : backup -> install -> `fail2ban-client -t` (gate) -> restart
#
# Sécurités :
#   - refuse de partir si ignoreip contient encore A.B.C.D (risque de self-ban SSH)
#   - `nginx -t` échoue  -> STOP, fail2ban n'est pas touché, Nginx rollback
#   - `fail2ban -t` échoue -> rollback fail2ban (Nginx déjà déployé reste en place)
#   - une seule session ssh -tt => un seul prompt sudo
#
# Usage :
#   ./deploy-all.sh                        # hôte par défaut
#   ./deploy-all.sh user@host              # override

set -uo pipefail

SRV="${1:-${SRV:-sgwsnlcupaqyxdqux@163.172.71.169}}"
DEP="${DEP:-$(cd "$(dirname "$0")" && pwd)/deploy}"

NGX="$DEP/nginx"
JAIL="$DEP/jail.local"
BADSCAN="$DEP/filter.d/nginx-badscan.conf"

# ------------------------------------------------------------------ preflight
echo "==> Préflight..."

for f in "$JAIL" "$BADSCAN" \
         "$NGX/nginx.conf" "$NGX/conf.d/10-ratelimit.conf" \
         "$NGX/conf.d/10-upgrade-map.conf" "$NGX/sites-available/dash.seoinsight.app"; do
  [ -f "$f" ] || { echo "!! Fichier manquant : $f" >&2; exit 1; }
done

# Attente que SSH réponde (survit à un blip d'activation socket après un reload récent).
for i in 1 2 3 4 5; do
  ssh -o ConnectTimeout=8 -o BatchMode=yes "$SRV" 'true' 2>/dev/null && break
  echo "    SSH pas encore prêt (tentative $i/5)..."; sleep 3
done

# Pas d'IP fixe -> la protection anti-lockout est le SSH par clé.
# Vérif SANS sudo : le serveur impose-t-il la clé publique ? (AuthenticationMethods publickey)
echo "    Vérif SSH clé-only sur $SRV..."
HARDENED=$(ssh -o ConnectTimeout=10 "$SRV" \
  'grep -hqE "^[[:space:]]*AuthenticationMethods[[:space:]]+publickey" /etc/ssh/sshd_config /etc/ssh/sshd_config.d/*.conf 2>/dev/null && echo YES || echo NO' \
  2>/dev/null | tr -d '\r')

if [ "$HARDENED" = "YES" ]; then
  echo "    OK — SSH impose la clé publique (password brute-force impossible). Anti-lockout assuré."
else
  echo "!! ATTENTION : SSH n'impose pas la clé (pas d'AuthenticationMethods publickey)." >&2
  echo "   Sans IP fixe, ta protection anti-lockout = SSH par clé. Lance d'abord :" >&2
  echo "     ./harden-ssh.sh" >&2
  echo "   Puis relance. (Pour passer outre : ALLOW_PASSWORD_AUTH=1 ./deploy-all.sh)" >&2
  [ "${ALLOW_PASSWORD_AUTH:-0}" = "1" ] || exit 1
  echo "   -> ALLOW_PASSWORD_AUTH=1 : on continue malgré tout (sshd reste en mode=normal, maxretry=3)." >&2
fi

echo "    OK — cible : $SRV"
echo

# ------------------------------------------------------------------ upload (clé SSH, pas de sudo)
echo "==> Envoi des fichiers dans /tmp..."
scp "$NGX/nginx.conf"                          "$SRV:/tmp/nginx.conf"
scp "$NGX/conf.d/10-ratelimit.conf"            "$SRV:/tmp/10-ratelimit.conf"
scp "$NGX/conf.d/10-upgrade-map.conf"          "$SRV:/tmp/10-upgrade-map.conf"
scp "$NGX/sites-available/dash.seoinsight.app" "$SRV:/tmp/dash.seoinsight.app"
scp "$JAIL"                                    "$SRV:/tmp/jail.local"
scp "$BADSCAN"                                 "$SRV:/tmp/nginx-badscan.conf"
echo

# ------------------------------------------------------------------ déploiement distant (1 seul prompt sudo)
REMOTE=$(cat <<'REMOTE'
set -u
ts=$(date +%Y%m%d-%H%M%S)
say() { printf '\n\033[1m### %s ###\033[0m\n' "$1"; }

# ============================ ÉTAPE 1 : NGINX ============================
say "NGINX — backup & install"
sudo cp -a /etc/nginx/nginx.conf                         /etc/nginx/nginx.conf.bak.$ts
sudo cp -a /etc/nginx/conf.d/10-upgrade-map.conf         /etc/nginx/conf.d/10-upgrade-map.conf.bak.$ts
sudo cp -a /etc/nginx/sites-available/dash.seoinsight.app /etc/nginx/sites-available/dash.seoinsight.app.bak.$ts

sudo install -m 644 -o root -g root /tmp/nginx.conf          /etc/nginx/nginx.conf
sudo install -m 644 -o root -g root /tmp/10-ratelimit.conf   /etc/nginx/conf.d/10-ratelimit.conf
sudo install -m 644 -o root -g root /tmp/10-upgrade-map.conf /etc/nginx/conf.d/10-upgrade-map.conf
sudo install -m 644 -o root -g root /tmp/dash.seoinsight.app /etc/nginx/sites-available/dash.seoinsight.app

say "NGINX — test config"
if ! sudo nginx -t; then
  echo ">> nginx -t ÉCHOUE : rollback Nginx, fail2ban NON touché." >&2
  sudo cp -a /etc/nginx/nginx.conf.bak.$ts                         /etc/nginx/nginx.conf
  sudo cp -a /etc/nginx/conf.d/10-upgrade-map.conf.bak.$ts         /etc/nginx/conf.d/10-upgrade-map.conf
  sudo cp -a /etc/nginx/sites-available/dash.seoinsight.app.bak.$ts /etc/nginx/sites-available/dash.seoinsight.app
  sudo rm -f /etc/nginx/conf.d/10-ratelimit.conf
  exit 10
fi
sudo systemctl reload nginx && echo ">> Nginx rechargé."

# ============================ ÉTAPE 2 : FAIL2BAN =========================
say "FAIL2BAN — backup & install"
sudo cp -a /etc/fail2ban/jail.local /etc/fail2ban/jail.local.bak.$ts
sudo install -m 644 -o root -g root /tmp/jail.local         /etc/fail2ban/jail.local
sudo install -m 644 -o root -g root /tmp/nginx-badscan.conf /etc/fail2ban/filter.d/nginx-badscan.conf

say "FAIL2BAN — test filtre nginx-badscan (info)"
sudo fail2ban-regex /var/log/nginx/access.log /etc/fail2ban/filter.d/nginx-badscan.conf \
  | grep -E "Failregex: [0-9]|lines" || true

say "FAIL2BAN — test config"
if ! sudo fail2ban-client -t; then
  echo ">> fail2ban -t ÉCHOUE : rollback jail.local (Nginx reste déployé)." >&2
  sudo cp -a /etc/fail2ban/jail.local.bak.$ts /etc/fail2ban/jail.local
  sudo rm -f /etc/fail2ban/filter.d/nginx-badscan.conf
  exit 20
fi
sudo systemctl restart fail2ban
sleep 2
sudo systemctl is-active fail2ban >/dev/null && echo ">> fail2ban redémarré."

rm -f /tmp/nginx.conf /tmp/10-ratelimit.conf /tmp/10-upgrade-map.conf \
      /tmp/dash.seoinsight.app /tmp/jail.local /tmp/nginx-badscan.conf

# ============================ VÉRIFICATIONS ============================
say "VÉRIF — HTTP/2 + HSTS + server tokens"
curl -sI https://dash.seoinsight.app | grep -iE "^HTTP|strict-transport|^server:" || true

say "VÉRIF — jails fail2ban"
sudo fail2ban-client status
for j in sshd nginx-botsearch nginx-badscan nginx-limit-req recidive; do
  echo "----- $j -----"; sudo fail2ban-client status "$j" 2>/dev/null | grep -E "Currently|Total banned|Banned IP" || echo "(inactif)"
done

say "VÉRIF — table nftables f2b"
sudo nft list tables | grep -i f2b || echo "(pas de table f2b — vérifier banaction)"

printf '\n\033[1;32m==> Déploiement terminé (Nginx + fail2ban).\033[0m\n'
REMOTE
)

echo "==> Déploiement distant (sudo demandera ton mot de passe une fois)..."
ssh -tt "$SRV" "$REMOTE"
rc=$?

echo
case $rc in
  0)  echo "==> OK. Sauvegardes horodatées .bak.<ts> côté serveur." ;;
  10) echo "!! Nginx a échoué au test — rien d'appliqué, fail2ban intact." ;;
  20) echo "!! fail2ban a échoué au test — Nginx déployé, jail.local restauré." ;;
  *)  echo "!! Interruption (code $rc)." ;;
esac
exit $rc
