Files
Cerbero-mcp/tests/smoke/run.sh
T
AdrianoDev 867180f4bf feat(gateway): TLS auto + rate limit + IP allowlist su write endpoint
Configura il gateway Caddy per il deploy su cerbero-mcp.tielogic.xyz:

- Build custom Caddy con plugin mholt/caddy-ratelimit (Dockerfile +
  build via xcaddy).
- TLS automatico via Let's Encrypt (richiede DNS A record + porte
  80/443 raggiungibili), HSTS preload, header di sicurezza.
- Rate limit per IP (60 req/min sui read, 10 req/min sui write,
  sliding window).
- Allowlist IP sui write endpoint (place_*, cancel_*, set_*, close_*,
  transfer_*, amend_*, switch_*): IP non in WRITE_ALLOWLIST → 403.
- Default WRITE_ALLOWLIST copre loopback + Docker bridge: bot sulla
  stessa macchina (host o container) funziona senza configurazione,
  IP pubblici esterni vanno aggiunti esplicitamente.
- Smoke test e README aggiornati per il nuovo URL gateway.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-27 23:24:06 +02:00

112 lines
3.2 KiB
Bash
Executable File

#!/usr/bin/env bash
# Smoke test locale per Cerbero_mcp.
# Presuppone: docker compose up -d già eseguito da repo root.
# Verifica: ogni MCP risponde /health; i 4 exchange espongono environment_info.
set -euo pipefail
cd "$(dirname "$0")/../.."
GATEWAY="${GATEWAY:-http://localhost}"
TOKEN_FILE="${TOKEN_FILE:-secrets/observer.token}"
if [ ! -f "$TOKEN_FILE" ]; then
echo "ERROR: token file $TOKEN_FILE not found" >&2
exit 2
fi
TOKEN="$(cat "$TOKEN_FILE")"
fail=0
echo "=== /health ==="
for svc in mcp-deribit mcp-bybit mcp-hyperliquid mcp-alpaca mcp-macro mcp-sentiment; do
code=$(curl -s -o /dev/null -w "%{http_code}" \
-H "Authorization: Bearer $TOKEN" \
"$GATEWAY/$svc/health" || echo "000")
if [ "$code" = "200" ]; then
echo " $svc: OK"
else
echo " $svc: FAIL ($code)"
fail=$((fail + 1))
fi
done
echo
echo "=== environment_info on 4 exchange MCPs ==="
for ex in deribit bybit hyperliquid alpaca; do
body=$(curl -s -X POST \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{}' \
"$GATEWAY/mcp-${ex}/tools/environment_info" 2>/dev/null || echo '{}')
if [ -z "$body" ] || [ "$body" = "{}" ]; then
echo " $ex: FAIL (empty body)"
fail=$((fail + 1))
continue
fi
if echo "$body" | jq -e '.environment, .source, .base_url, .max_leverage' > /dev/null 2>&1; then
env=$(echo "$body" | jq -r '.environment')
src=$(echo "$body" | jq -r '.source')
cap=$(echo "$body" | jq -r '.max_leverage')
echo " $ex: OK (env=$env source=$src max_leverage=$cap)"
else
echo " $ex: FAIL (shape mismatch)"
echo " body: $body"
fail=$((fail + 1))
fi
done
echo
echo "=== live tool check (read-only contro upstream testnet) ==="
_check_tool() {
local label="$1" url="$2" body="$3"
local resp
resp=$(curl -s -X POST \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d "$body" \
"$url" 2>/dev/null || echo '{}')
if echo "$resp" | jq -e 'has("error") | not' > /dev/null 2>&1 \
&& [ -n "$resp" ] && [ "$resp" != "null" ] && [ "$resp" != "{}" ]; then
echo " $label: OK"
else
echo " $label: FAIL"
echo " body: $(echo "$resp" | head -c 200)"
fail=$((fail + 1))
fi
}
_check_tool "deribit get_ticker BTC-PERPETUAL" \
"$GATEWAY/mcp-deribit/tools/get_ticker" \
'{"instrument_name":"BTC-PERPETUAL"}'
_check_tool "bybit get_ticker BTCUSDT" \
"$GATEWAY/mcp-bybit/tools/get_ticker" \
'{"symbol":"BTCUSDT","category":"linear"}'
_check_tool "hyperliquid get_ticker BTC" \
"$GATEWAY/mcp-hyperliquid/tools/get_ticker" \
'{"instrument":"BTC"}'
_check_tool "alpaca get_clock (richiede ALPACA_PAPER credenziali valide)" \
"$GATEWAY/mcp-alpaca/tools/get_clock" \
'{}'
_check_tool "macro get_treasury_yields" \
"$GATEWAY/mcp-macro/tools/get_treasury_yields" \
'{}'
_check_tool "sentiment get_funding_rates BTC" \
"$GATEWAY/mcp-sentiment/tools/get_funding_rates" \
'{"asset":"BTC"}'
echo
if [ "$fail" -gt 0 ]; then
echo "SMOKE FAILED: $fail check(s) failed"
exit 1
fi
echo "SMOKE OK"