#!/usr/bin/env bash
set -euo pipefail

require_root() { [ "${EUID:-$(id -u)}" -eq 0 ] || { echo "Veuillez exécuter en root."; exit 1; }; }
ask() { read -r -p "$1" REPLY; echo "${REPLY}"; }
ok()  { echo "[OK] $*"; }

require_root
apt update && apt -y upgrade
apt -y install apache2 openssl
a2enmod ssl >/dev/null || true
systemctl enable --now apache2

# Répertoires (bonnes pratiques)
CERT_DIR="/etc/ssl/certs"
KEY_DIR="/etc/ssl/private"
SITE_DIR_BASE="/var/www"
mkdir -p "$CERT_DIR" "$KEY_DIR" "$SITE_DIR_BASE"
chmod 700 "$KEY_DIR"

site="$(ask 'Nom de domaine (ex: www.exemple.local): ')"
site_dir="$SITE_DIR_BASE/$site"
mkdir -p "$site_dir"
chown -R www-data:www-data "$site_dir"
[ -f "$site_dir/index.html" ] || echo "Bienvenue sur $site" > "$site_dir/index.html"

mode="$(ask 'Choisir: [1] Auto-signé (CA locale)  [2] CSR pour AC distante  [3] Intégrer un cert signé: ')"

# Génère une clé privée si absente
KEY="$KEY_DIR/${site}.key"
[ -f "$KEY" ] || openssl genpkey -algorithm RSA -pkeyopt rsa_keygen_bits:4096 -out "$KEY"
chmod 600 "$KEY"

# Fichier openssl.cnf temporaire pour SAN
SAN="DNS:${site}"
alt="$(ask "Ajouter d'autres SAN? (ex: DNS:${site},DNS:ex2.local) [Entrée=non]: ")"
[ -n "${alt:-}" ] && SAN="$alt"

OPENSSL_CNF="$(mktemp)"
cat >"$OPENSSL_CNF" <<EOF
[ req ]
distinguished_name = dn
prompt = no
req_extensions = san
[ dn ]
CN = $site
O = Intranet
C = FR
[ san ]
subjectAltName = $SAN
EOF

VHOST="/etc/apache2/sites-available/${site}-ssl.conf"

case "$mode" in
  1)
    # CA locale + cert serveur signé par la CA
    CA_KEY="$KEY_DIR/ca-${site}.key"
    CA_CRT="$CERT_DIR/ca-${site}.crt"
    [ -f "$CA_KEY" ] || openssl genpkey -algorithm RSA -pkeyopt rsa_keygen_bits:4096 -out "$CA_KEY"
    chmod 600 "$CA_KEY"
    [ -f "$CA_CRT" ] || openssl req -x509 -new -key "$CA_KEY" -days 365 -out "$CA_CRT" -subj "/CN=CA $site/O=Intranet/C=FR"

    CSR="$(mktemp)"
    openssl req -new -key "$KEY" -out "$CSR" -config "$OPENSSL_CNF"
    CRT="$CERT_DIR/${site}.crt"
    openssl x509 -req -in "$CSR" -CA "$CA_CRT" -CAkey "$CA_KEY" -CAcreateserial -out "$CRT" -days 365 -extfile "$OPENSSL_CNF" -extensions san
    ;;

  2)
    # CSR pour AC distante
    CSR_PATH="$CERT_DIR/${site}.csr"
    openssl req -new -key "$KEY" -out "$CSR_PATH" -config "$OPENSSL_CNF"
    ok "CSR générée: $CSR_PATH"
    echo "Envoyez-la à votre AC. Une fois le certificat obtenu, relancez en mode [3]."
    exit 0
    ;;

  3)
    CRT="$(ask 'Chemin du certificat signé (fullchain si possible): ')"
    [ -r "$CRT" ] || { echo "Certificat introuvable: $CRT"; exit 1; }
    # Optionnel: préciser un chain file si AC fournit une chaîne séparée (Apache <2.4.8)
    CHAIN="$(ask 'Chemin du certificat intermédiaire (optionnel): ')"
    ;;

  *) echo "Choix invalide"; exit 1 ;;
esac

# VHost (ne pas écraser default-ssl.conf)
cat >"$VHOST" <<EOF
<VirtualHost *:443>
    ServerName $site
    DocumentRoot $site_dir

    ErrorLog \${APACHE_LOG_DIR}/${site}-error.log
    CustomLog \${APACHE_LOG_DIR}/${site}-access.log combined

    SSLEngine on
    SSLCertificateFile ${CRT}
    SSLCertificateKeyFile ${KEY}
EOF

# Ajoute ChainFile si fourni et utile (anciens Apache)
if [ "${CHAIN:-}" != "" ]; then
  echo "    SSLCertificateChainFile ${CHAIN}" >> "$VHOST"
fi

cat >>"$VHOST" <<'EOF'
    # Durcir un peu TLS (adapter selon votre politique)
    SSLProtocol all -SSLv3 -TLSv1 -TLSv1.1
    SSLOpenSSLConfCmd Curves X25519:P-256
    SSLHonorCipherOrder on

    <Directory />
        Options FollowSymLinks
        AllowOverride None
    </Directory>
</VirtualHost>
EOF

a2ensite "$(basename "$VHOST")" >/dev/null
apache2ctl configtest
systemctl reload apache2
rm -f "$OPENSSL_CNF"

echo
ok "Site prêt: https://$site"
echo "DocumentRoot: $site_dir"
[ "${mode}" = "1" ] && echo "CA locale: importez ${CA_CRT} sur les postes (Autorités)."

