Files
ja4-platform/tests/integration/nginx-varnish/platform/entrypoint.sh
Jacquin Antoine 742f4420c0 fix(test): add ClickHouse readiness check before starting ja4ebpf
Fixed race condition where ja4ebpf would fail to connect to
ClickHouse at startup because ClickHouse HTTP port wasn't ready yet,
even though Docker healthcheck passed.

Changes:
- Add 30s wait loop with ClickHouse /ping endpoint check
- Log success message when ClickHouse is ready
- Applied to all 4 stacks: nginx, apache, nginx-varnish, hitch-varnish

Test results after fix:
- nginx: 240 rows, 175 JA4 fingerprints 
- apache: 257 rows, 191 JA4 fingerprints 
- nginx-varnish: 298 rows, 242 JA4 fingerprints 
- hitch-varnish: 247 rows, 177 JA4 fingerprints 

All L3/L4 metadata (TTL, MSS, Window), TLS fingerprinting (JA4, SNI),
and HTTP layer data are correctly captured and persisted.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-19 15:11:22 +02:00

131 lines
4.9 KiB
Bash
Executable File

#!/usr/bin/env bash
# =============================================================================
# Entrypoint — stack nginx + varnish + backend HTTP + ja4ebpf
# Ordre : backend → varnish → nginx → ja4ebpf
# =============================================================================
set -eo pipefail
log() { echo "[entrypoint:nginx-varnish] $(date +%H:%M:%S) $*"; }
BACKEND_PID="" VARNISH_PID="" NGINX_PID="" JA4EBPF_PID=""
cleanup() {
log "Arrêt des processus…"
for pid in "$JA4EBPF_PID" "$NGINX_PID" "$VARNISH_PID" "$BACKEND_PID"; do
[ -n "$pid" ] && kill "$pid" 2>/dev/null || true
done
wait 2>/dev/null || true
}
trap cleanup EXIT SIGTERM SIGINT
# ── 1. Backend HTTP simple (Python) ──────────────────────────────────────────
log "Démarrage du backend HTTP (port 8080)…"
python3 -c "
import http.server, socketserver, json
class H(http.server.BaseHTTPRequestHandler):
def log_message(self, *a): pass
def do_GET(self):
body = json.dumps({'status':'ok','backend':'python','path':self.path}).encode()
self.send_response(200)
self.send_header('Content-Type','application/json')
self.send_header('Content-Length', len(body))
self.end_headers()
self.wfile.write(body)
def do_POST(self):
n = int(self.headers.get('Content-Length',0))
self.rfile.read(n)
body = b'{\"result\":\"accepted\"}'
self.send_response(200)
self.send_header('Content-Type','application/json')
self.send_header('Content-Length', len(body))
self.end_headers()
self.wfile.write(body)
with socketserver.TCPServer(('127.0.0.1', 8080), H) as s:
s.serve_forever()
" &
BACKEND_PID=$!
sleep 1
log "Backend HTTP démarré (PID $BACKEND_PID)"
# ── 2. Démarrage de Varnish ───────────────────────────────────────────────────
log "Démarrage de Varnish (port 6081)…"
varnishd \
-F \
-f /etc/varnish/default.vcl \
-a "0.0.0.0:6081,HTTP" \
-p feature=+http2 \
-s malloc,64m \
-T 127.0.0.1:6082 &
VARNISH_PID=$!
for i in $(seq 1 20); do
if varnishadm -T 127.0.0.1:6082 status 2>/dev/null | grep -q "Child in state running"; then
log "Varnish opérationnel (PID $VARNISH_PID)"; break
fi
sleep 0.5
done
# ── 3. Démarrage de nginx ─────────────────────────────────────────────────────
log "Démarrage de nginx…"
nginx
NGINX_PID=$(cat /run/nginx/nginx.pid 2>/dev/null || echo "")
for i in $(seq 1 20); do
if curl -sf http://localhost/health >/dev/null 2>&1; then
log "nginx opérationnel (PID $NGINX_PID)"; break
fi
sleep 0.5
done
# ── 4. Démarrage de ja4ebpf ───────────────────────────────────────────────────
# Attendre que ClickHouse soit prêt (connection refused possible sinon)
log "Attente de ClickHouse (max 30s)…"
for i in $(seq 1 30); do
if curl -sf http://clickhouse:8123/ping >/dev/null 2>&1; then
log "ClickHouse est prêt (http://clickhouse:8123/ping OK)"
break
fi
if [ $i -eq 30 ]; then
log "⚠ ClickHouse toujours pas prêt après 30s, démarrage ja4ebpf quand même"
fi
sleep 1
done
log "Démarrage de ja4ebpf (uprobes nginx/libssl + hook TC)…"
ja4ebpf -config /etc/ja4ebpf/config.yml &
JA4EBPF_PID=$!
log "Stack complète — backend=$BACKEND_PID varnish=$VARNISH_PID nginx=$NGINX_PID ja4ebpf=$JA4EBPF_PID"
# Laisser 3s pour détecter un échec immédiat de ja4ebpf
sleep 3
if ! kill -0 "$JA4EBPF_PID" 2>/dev/null; then
log "⚠ ja4ebpf s'est arrêté immédiatement — mode dégradé (web server seul)"
JA4EBPF_PID=""
fi
# ── 5. Supervision ────────────────────────────────────────────────────────────
while true; do
for pid_var in BACKEND_PID VARNISH_PID; do
pid="${!pid_var}"
if [ -n "$pid" ] && ! kill -0 "$pid" 2>/dev/null; then
log "$pid_var (PID $pid) s'est arrêté — fin"
exit 1
fi
done
# ja4ebpf est optionnel : loguer si arrêté mais ne pas quitter
if [ -n "$JA4EBPF_PID" ] && ! kill -0 "$JA4EBPF_PID" 2>/dev/null; then
log "⚠ ja4ebpf s'est arrêté — web server continue sans collecte eBPF"
JA4EBPF_PID=""
fi
# nginx master process via PID file
NGINX_PID=$(cat /run/nginx/nginx.pid 2>/dev/null || echo "")
if [ -z "$NGINX_PID" ] || ! kill -0 "$NGINX_PID" 2>/dev/null; then
log "nginx master s'est arrêté — fin"
exit 1
fi
sleep 2
done