172 lines
6.0 KiB
Bash
Executable File
172 lines
6.0 KiB
Bash
Executable File
#!/usr/bin/env zsh
|
|
# scripts/validate-livekit-token.sh
|
|
# Reinicia/arranca livekit-server con la clave API/SECRET adecuada, redirige logs y realiza checks básicos.
|
|
# Uso:
|
|
# ./scripts/validate-livekit-token.sh --api-key KEY --api-secret SECRET --server https://example.com --room test_room --identity test_user
|
|
|
|
set -euo pipefail
|
|
|
|
API_KEY="${LIVEKIT_API_KEY:-}"
|
|
API_SECRET="${LIVEKIT_API_SECRET:-}"
|
|
SERVER_URL="${LIVEKIT_SERVER_URL:-https://livekit-server.bfzqqk.easypanel.host}"
|
|
ROOM="test_room"
|
|
IDENTITY="test_user"
|
|
|
|
usage(){
|
|
cat <<EOF
|
|
Usage: $0 [options]
|
|
Options:
|
|
--api-key KEY LiveKit API key (or set LIVEKIT_API_KEY env)
|
|
--api-secret SECRET LiveKit API secret (or set LIVEKIT_API_SECRET env)
|
|
--server URL Base server URL (default: $SERVER_URL)
|
|
--room NAME Room name (default: test_room)
|
|
--identity ID Participant identity (default: test_user)
|
|
-h, --help Show this help
|
|
|
|
This script requires node and livekit-server-sdk installed (npm i livekit-server-sdk).
|
|
It will: generate a token, call $SERVER_URL/rtc/validate with Authorization: Bearer <token>,
|
|
try a WebSocket handshake to wss://<host>/rtc?access_token=<token> (if wscat/websocat available),
|
|
and print decoded JWT payload.
|
|
EOF
|
|
}
|
|
|
|
while [[ $# -gt 0 ]]; do
|
|
case "$1" in
|
|
--api-key) API_KEY="$2"; shift 2;;
|
|
--api-secret) API_SECRET="$2"; shift 2;;
|
|
--server) SERVER_URL="$2"; shift 2;;
|
|
--room) ROOM="$2"; shift 2;;
|
|
--identity) IDENTITY="$2"; shift 2;;
|
|
-h|--help) usage; exit 0;;
|
|
*) echo "Unknown arg: $1"; usage; exit 1;;
|
|
esac
|
|
done
|
|
|
|
if [ -z "$API_KEY" ] || [ -z "$API_SECRET" ]; then
|
|
echo "ERROR: API_KEY and API_SECRET must be set (via args or env)." >&2
|
|
usage
|
|
exit 2
|
|
fi
|
|
|
|
echo "[validate-livekit-token] api_key=${API_KEY} server=${SERVER_URL} room=${ROOM} identity=${IDENTITY}"
|
|
|
|
# Temp files for outputs
|
|
OUT_DIR="/tmp/validate-livekit"
|
|
mkdir -p "$OUT_DIR"
|
|
TOKEN_FILE="$OUT_DIR/token.txt"
|
|
CURL_FILE="$OUT_DIR/curl_strict.txt"
|
|
CURLK_FILE="$OUT_DIR/curl_insecure.txt"
|
|
WS_FILE="$OUT_DIR/ws_attempt.txt"
|
|
PAYLOAD_FILE="$OUT_DIR/payload.json"
|
|
|
|
# Generar token via Node inline
|
|
# Pass credentials and params via environment to avoid issues with heredoc args
|
|
TOKEN=$(API_KEY="$API_KEY" API_SECRET="$API_SECRET" IDENTITY="$IDENTITY" ROOM="$ROOM" node - <<'NODE'
|
|
try{
|
|
const sdk = require('livekit-server-sdk');
|
|
const AccessToken = sdk.AccessToken || (sdk.default && sdk.default.AccessToken);
|
|
const VideoGrant = sdk.VideoGrant || (sdk.default && sdk.default.VideoGrant);
|
|
const identity = process.env.IDENTITY || 'anon';
|
|
const room = process.env.ROOM || 'default';
|
|
const apiKey = process.env.API_KEY;
|
|
const apiSecret = process.env.API_SECRET;
|
|
if (!apiKey || !apiSecret) {
|
|
console.error('missing API_KEY/API_SECRET in env');
|
|
process.exit(2);
|
|
}
|
|
const at = new AccessToken(apiKey, apiSecret, { identity: identity, name: identity });
|
|
if (VideoGrant) at.addGrant(new VideoGrant({ room: room }));
|
|
else if (typeof at.addGrant === 'function') at.addGrant({ room: room, roomJoin: true, canPublish: true, canSubscribe: true });
|
|
(async ()=>{ const t = (typeof at.toJwt === 'function') ? await at.toJwt() : at.jwt; console.log(t); })();
|
|
}catch(e){ console.error('ERRGEN', e && e.stack ? e.stack : e); process.exit(2); }
|
|
NODE
|
|
) || { echo "[error] token generation failed" >&2; exit 3; }
|
|
|
|
if [ -z "$TOKEN" ]; then
|
|
echo "[error] empty token" >&2; exit 4
|
|
fi
|
|
|
|
# Save token
|
|
echo "$TOKEN" > "$TOKEN_FILE"
|
|
chmod 600 "$TOKEN_FILE"
|
|
|
|
echo; echo "=== Token generated and saved to: $TOKEN_FILE ==="
|
|
echo "Token preview: ${TOKEN:0:140}..."
|
|
|
|
VALIDATE_URL="$SERVER_URL/rtc/validate"
|
|
|
|
echo; echo "=== CURL validate (strict TLS) -> $CURL_FILE ==="
|
|
# store headers and body
|
|
set +e
|
|
curl -i -sS --max-time 15 -H "Authorization: Bearer $TOKEN" "$VALIDATE_URL" > "$CURL_FILE" 2>&1
|
|
CURL_EXIT=$?
|
|
set -e
|
|
if [ $CURL_EXIT -ne 0 ]; then
|
|
echo "[warn] curl strict failed (exit $CURL_EXIT). See $CURL_FILE"
|
|
else
|
|
echo "[ok] curl strict completed. See $CURL_FILE"
|
|
fi
|
|
|
|
# insecure curl (diagnostic)
|
|
echo; echo "=== CURL validate (insecure -k) -> $CURLK_FILE ==="
|
|
set +e
|
|
curl -i -sS -k --max-time 15 -H "Authorization: Bearer $TOKEN" "$VALIDATE_URL" > "$CURLK_FILE" 2>&1
|
|
CURLK_EXIT=$?
|
|
set -e
|
|
if [ $CURLK_EXIT -ne 0 ]; then
|
|
echo "[warn] curl -k failed (exit $CURLK_EXIT). See $CURLK_FILE"
|
|
else
|
|
echo "[ok] curl -k completed. See $CURLK_FILE"
|
|
fi
|
|
|
|
# 2) WebSocket handshake attempt
|
|
WS_HOST=$(echo "$SERVER_URL" | sed -E 's#https?://##' | sed -E 's#/$##')
|
|
WS_URL="wss://$WS_HOST/rtc?access_token=$TOKEN"
|
|
|
|
echo; echo "=== WS handshake attempt to: $WS_URL (output -> $WS_FILE) ==="
|
|
if command -v wscat >/dev/null 2>&1; then
|
|
if command -v timeout >/dev/null 2>&1; then
|
|
timeout 10s wscat -c "$WS_URL" > "$WS_FILE" 2>&1 || true
|
|
else
|
|
wscat -c "$WS_URL" > "$WS_FILE" 2>&1 || true
|
|
fi
|
|
echo "[info] wscat output saved to $WS_FILE"
|
|
elif command -v websocat >/dev/null 2>&1; then
|
|
if command -v timeout >/dev/null 2>&1; then
|
|
timeout 10s websocat "$WS_URL" > "$WS_FILE" 2>&1 || true
|
|
else
|
|
websocat "$WS_URL" > "$WS_FILE" 2>&1 || true
|
|
fi
|
|
echo "[info] websocat output saved to $WS_FILE"
|
|
else
|
|
echo "[info] wscat/websocat not installed; skipping WS handshake test"
|
|
fi
|
|
|
|
# 3) decode payload (no signature verification)
|
|
echo "$TOKEN" | awk '{print $0}' > /dev/null
|
|
node -e 'try{const t=process.argv[1]; const p=t.split(".")[1]; const b=Buffer.from(p.replace(/-/g,"+").replace(/_/g,"/"),"base64").toString(); console.log(b);}catch(e){console.error("failed decode",e);} ' "$TOKEN" > "$PAYLOAD_FILE" 2>&1 || true
|
|
|
|
echo; echo "=== DECODED PAYLOAD SAVED TO: $PAYLOAD_FILE ==="
|
|
|
|
# Print short summary and file locations for user to copy
|
|
cat <<EOF
|
|
|
|
SUMMARY (files saved):
|
|
Token: $TOKEN_FILE
|
|
Curl (strict TLS): $CURL_FILE
|
|
Curl (insecure -k): $CURLK_FILE
|
|
WS attempt: $WS_FILE
|
|
Decoded payload: $PAYLOAD_FILE
|
|
|
|
Commands to view outputs:
|
|
cat $TOKEN_FILE
|
|
sed -n '1,200p' $CURL_FILE
|
|
sed -n '1,200p' $CURLK_FILE
|
|
sed -n '1,200p' $WS_FILE
|
|
sed -n '1,200p' $PAYLOAD_FILE
|
|
|
|
Paste the contents of those files here and I will interpret the results and guide next steps.
|
|
EOF
|
|
|
|
echo; echo "=== DONE ==="
|