#!/usr/bin/env bash # End-to-end local smoke test: dev-registry + pawletcache-server + a throwaway # HTTPS origin, wired together, verifying register -> signed token -> asset # fetch-through -> disk cache actually works. No real oxmc.me dependency. # # Requires: `npm install` already run in pawletcache-server/ (bonjour-service, # js-yaml, selfsigned). dev-registry/ has zero deps, nothing to install there. set -euo pipefail cd "$(dirname "$0")/.." # pawletcache-server/ ORIGIN_PORT=9443 REGISTRY_PORT=4100 CACHE_PORT=8543 ENROLLMENT_TOKEN=smoke-test-token # Path handling here is fussy on Windows+Git-Bash: native Windows node.exe # doesn't understand MSYS-style POSIX paths at all (not just /tmp — `pwd`'s # /c/Users/... gets misread as literal drive-root segments, e.g. resolves to # C:\c\Users\...). `pwd -W` gives the Windows-style form (C:/Users/...), # which both node.exe and Bash/`ls` resolve to the same real location — use # that for anything written into a file Node will read a path back out of. # (On real POSIX systems `pwd -W` doesn't exist; fall back to plain pwd.) WORKDIR="$(pwd -W 2>/dev/null || pwd)/.smoke-test-tmp-$$" mkdir -p "$WORKDIR" PIDS=() cleanup() { for pid in "${PIDS[@]:-}"; do kill "$pid" 2>/dev/null || true; done rm -rf "$WORKDIR" } trap cleanup EXIT pass() { echo "PASS: $1"; } fail() { echo "FAIL: $1"; cleanup; exit 1; } wait_for() { local url=$1 tries=${2:-30} for _ in $(seq 1 "$tries"); do curl -sk -o /dev/null "$url" && return 0 sleep 0.5 done return 1 } echo "== starting dummy HTTPS origin on :$ORIGIN_PORT ==" node scripts/dummy-origin.js "$ORIGIN_PORT" > "$WORKDIR/origin.log" 2>&1 & PIDS+=($!) wait_for "https://localhost:$ORIGIN_PORT/" || fail "dummy origin never came up" echo "== starting dev-registry on :$REGISTRY_PORT ==" DEV_REGISTRY_PORT=$REGISTRY_PORT \ DEV_REGISTRY_DATA_DIR="$WORKDIR/registry-data" \ DEV_ENROLLMENT_TOKENS=$ENROLLMENT_TOKEN \ DEV_TOKEN_TTL_MS=600000 \ node dev-registry/src/index.js > "$WORKDIR/registry.log" 2>&1 & PIDS+=($!) wait_for "http://localhost:$REGISTRY_PORT/health" || fail "dev-registry never came up" pass "dev-registry up" echo "== writing pawletcache-server config ==" cat > "$WORKDIR/config.yml" < "$WORKDIR/cache-server.log" 2>&1 & PIDS+=($!) wait_for "https://localhost:$CACHE_PORT/asset" || fail "pawletcache-server never came up" echo "== waiting for registration to land in dev-registry ==" registered=false for _ in $(seq 1 20); do lookup=$(curl -s "http://localhost:$REGISTRY_PORT/apis/aosp/cache/lookup") if echo "$lookup" | grep -q '"available":true'; then registered=true break fi sleep 0.5 done [ "$registered" = true ] || fail "pawletcache-server never registered with dev-registry (see $WORKDIR/cache-server.log, $WORKDIR/registry.log)" pass "pawletcache-server registered, dev-registry issued a signed token" echo "== verifying the CacheToken carries the right lanHost/port ==" token=$(node -e "console.log(JSON.parse(process.argv[1]).token)" "$lookup") node -e " const env = JSON.parse(Buffer.from(process.argv[1], 'base64').toString('utf8')); const p = env.payload; if (p.hostname !== 'localhost') throw new Error('hostname mismatch: ' + p.hostname); if (p.port !== String($CACHE_PORT)) throw new Error('port mismatch: ' + p.port); if (!p.tlsSpkiSha256) throw new Error('missing tlsSpkiSha256'); console.log('token payload OK:', JSON.stringify(p)); " "$token" || fail "CacheToken payload didn't look right" pass "CacheToken payload shape OK" echo "== fetching an asset through the cache (miss, then hit) ==" origin_url="https%3A%2F%2Flocalhost%3A${ORIGIN_PORT}%2Ffile" body1=$(curl -sk "https://localhost:$CACHE_PORT/asset?url=$origin_url") [ "$body1" = "hello from dummy origin" ] || fail "first fetch-through returned wrong body: '$body1'" pass "cache miss fetch-through returned correct content" body2=$(curl -sk "https://localhost:$CACHE_PORT/asset?url=$origin_url") [ "$body2" = "hello from dummy origin" ] || fail "second (cached) fetch returned wrong body: '$body2'" pass "cache hit returned correct content" [ -n "$(ls -A "$WORKDIR/assets" 2>/dev/null)" ] || fail "nothing landed in storageDir — cache didn't persist to disk" pass "asset persisted to disk cache" echo "== verifying the SSRF allowlist actually blocks non-allowlisted origins ==" status=$(curl -sk -o /dev/null -w '%{http_code}' "https://localhost:$CACHE_PORT/asset?url=https%3A%2F%2Fevil.example%2Ffile") [ "$status" = "403" ] || fail "expected 403 for a non-allowlisted origin, got $status" pass "non-allowlisted origin correctly rejected (403)" echo "" echo "ALL CHECKS PASSED"