#!/usr/bin/env bash
# Real demos for P052 "Why Passkeys Can't Be Phished Like Passwords". Made on the Mac with Docker Desktop.
# Defensive only (owner rule: no live attack demos): no look-alike page, nothing captured, nothing relayed.
# Three containers on their own network, with names from the reserved .test domain (RFC 6761):
#   shop        shop.test, Ana's Tea Shop: HTTPS, a password sign-in and passkeys (lab/site.py, py_webauthn)
#   other-site  other-site.test, any other web site: its sign-in page asks the browser for a passkey
#   laptop      Ana's laptop: a real Chromium (Playwright's build) with a software passkey store (lab/browser)
# The lab's own certificate authority is made fresh on every run and trusted only inside the laptop.
# Every command shown is typed into a real interactive bash in a pty (demo_driver.py).
set -euo pipefail
cd "$(dirname "$0")"
P=ce-p052
cleanup() { docker rm -f $P-shop $P-other $P-laptop >/dev/null 2>&1 || true; docker network rm $P-net >/dev/null 2>&1 || true; }
cleanup
[ -n "${KEEP:-}" ] || trap cleanup EXIT
T=$(mktemp -d)
# the lab's certificate authority and one certificate per site
openssl req -x509 -newkey ec -pkeyopt ec_paramgen_curve:P-256 -nodes -days 2 -subj "/CN=Lab CA" \
  -keyout "$T/ca.key" -out "$T/ca.crt" 2>/dev/null
for s in shop.test other-site.test; do
  mkdir -p "$T/$s"
  openssl req -newkey ec -pkeyopt ec_paramgen_curve:P-256 -nodes -subj "/CN=$s" \
    -keyout "$T/$s/site.key" -out "$T/$s/site.csr" 2>/dev/null
  printf "subjectAltName=DNS:%s\n" "$s" > "$T/$s/ext"
  openssl x509 -req -in "$T/$s/site.csr" -CA "$T/ca.crt" -CAkey "$T/ca.key" -CAcreateserial -days 2 \
    -extfile "$T/$s/ext" -out "$T/$s/site.crt" 2>/dev/null
done
docker build -q -t $P-site -f lab/Dockerfile.site lab >/dev/null
docker build -q -t $P-laptop -f lab/Dockerfile.laptop lab >/dev/null
docker network create $P-net >/dev/null
docker create --name $P-shop --hostname shop --network $P-net --network-alias shop.test \
  -e SITE=shop.test -e ANA_PW=tea-for-two $P-site >/dev/null
docker create --name $P-other --hostname other-site --network $P-net --network-alias other-site.test \
  -e SITE=other-site.test $P-site >/dev/null
docker cp "$T/shop.test" $P-shop:/srv/tls
docker cp "$T/other-site.test" $P-other:/srv/tls
docker start $P-shop $P-other >/dev/null
rm -rf "$T"/*.key "$T"/*/site.key
docker run -d --name $P-laptop --hostname laptop --network $P-net --ipc=host $P-laptop sleep infinity >/dev/null
docker cp "$T/ca.crt" $P-laptop:/tmp/lab-ca.crt
docker exec -u ana $P-laptop sh -c 'mkdir -p ~/.pki/nssdb && certutil -d sql:$HOME/.pki/nssdb -N --empty-password \
  && certutil -d sql:$HOME/.pki/nssdb -A -t "C,," -n "Lab CA" -i /tmp/lab-ca.crt'
# the laptop's curl trusts the lab CA too (the system store)
docker exec $P-laptop sh -c 'cp /tmp/lab-ca.crt /usr/local/share/ca-certificates/lab-ca.crt && update-ca-certificates >/dev/null 2>&1'
for i in $(seq 30); do docker logs $P-shop 2>&1 | grep -q listening && docker logs $P-other 2>&1 | grep -q listening && break; sleep 1; done
[ -n "${SETUP_ONLY:-}" ] && { echo "lab up"; trap - EXIT; exit 0; }
python3 - "$P" < demo_driver.py
