xpeditis2.0/infra/prod/scripts/smoke-test.sh
2026-09-07 21:40:50 +02:00

82 lines
3.5 KiB
Bash
Executable File

#!/usr/bin/env bash
# =============================================================================
# Tests de fumee post-deploiement
# =============================================================================
# Verifie ce qu'un utilisateur constate reellement, depuis l'exterieur, a
# travers Cloudflare et Traefik -- pas l'etat interne du cluster.
#
# bash scripts/smoke-test.sh
#
# Code de retour 0 = production saine. Utilise par deploy.sh et cd-main.yml
# pour declencher un retour arriere automatique.
set -uo pipefail
API="${PROD_API_URL:-https://api.xpeditis.com}"
APP="${PROD_APP_URL:-https://app.xpeditis.com}"
SITE="${PROD_SITE_URL:-https://xpeditis.com}"
PASS=0
FAIL=0
check() {
local label="$1"; shift
if "$@" >/dev/null 2>&1; then
printf ' [OK] %s\n' "$label"; PASS=$((PASS + 1))
else
printf ' [ECHEC] %s\n' "$label"; FAIL=$((FAIL + 1))
fi
}
http_code() { curl -sS -o /dev/null -w '%{http_code}' --max-time 15 "$1"; }
expect_code() {
local url="$1" expected="$2"
[[ "$(http_code "$url")" == "$expected" ]]
}
expect_header() {
local url="$1" header="$2"
curl -sSI --max-time 15 "$url" | grep -qi "^${header}:"
}
echo "Tests de fumee - $(date -Is)"
echo
echo "Disponibilite"
check "API en ligne (200 sur /api/v1/health)" expect_code "${API}/api/v1/health" 200
check "Frontend en ligne (app)" expect_code "${APP}/" 200
check "Vitrine en ligne (apex)" expect_code "${SITE}/" 200
echo
echo "TLS et redirections"
check "HTTP redirige vers HTTPS" bash -c "[[ \$(curl -sS -o /dev/null -w '%{http_code}' --max-time 15 'http://api.xpeditis.com/api/v1/health') =~ ^30 ]]"
check "Certificat valide (pas d'option -k)" curl -sS --max-time 15 -o /dev/null "${API}/api/v1/health"
check "En-tete HSTS present" expect_header "${API}/api/v1/health" "strict-transport-security"
echo
echo "Durcissement"
check "X-Frame-Options present" expect_header "${APP}/" "x-frame-options"
check "X-Content-Type-Options present" expect_header "${APP}/" "x-content-type-options"
# main.ts desactive Swagger en production sauf si SWAGGER_USERNAME/PASSWORD
# sont definis. 404 = desactive, 401 = protege : les deux sont acceptables,
# 200 signifie que la documentation de l'API est publique.
check "Swagger non accessible librement" bash -c "[[ \$(curl -sS -o /dev/null -w '%{http_code}' --max-time 15 '${API}/api/docs') != '200' ]]"
check "Route protegee refuse l'anonyme (401/403)" bash -c "[[ \$(curl -sS -o /dev/null -w '%{http_code}' --max-time 15 '${API}/api/v1/bookings') =~ ^(401|403)$ ]]"
check "CORS refuse une origine inconnue" bash -c "! curl -sSI --max-time 15 -H 'Origin: https://evil.example' '${API}/api/v1/health' | grep -qi 'access-control-allow-origin: https://evil.example'"
echo
echo "Etat du cluster"
if command -v kubectl >/dev/null && kubectl get ns xpeditis-prod >/dev/null 2>&1; then
check "Aucun pod en erreur" bash -c "! kubectl -n xpeditis-prod get pods --no-headers | grep -qE 'CrashLoopBackOff|ImagePullBackOff|Error'"
check "Certificat cert-manager pret" bash -c "kubectl -n xpeditis-prod get certificate xpeditis-wildcard -o jsonpath='{.status.conditions[?(@.type==\"Ready\")].status}' | grep -q True"
else
echo " [saute] kubectl indisponible : verifications cluster ignorees"
fi
echo
echo "-----------------------------------------"
printf ' Reussis : %d Echecs : %d\n' "$PASS" "$FAIL"
echo "-----------------------------------------"
[[ "$FAIL" -eq 0 ]]