Files
felhom.eu/scripts/iso/test/bootstrap-modes.sh
T
admin 36c5cd5fdf hub v0.62.0 + scripts v1.19.0 — R-21 slice C: the universal secret-free ISO
A generic ISO carries NO customer secret. The box registers itself at the hub
as an unclaimed appliance; the operator binds it to a customer; the hub delivers
the customer-id + retrieval passphrase ONCE; day-0 completes via the slice-A path.

Hub (v0.62.0):
- store/appliance.go: appliance_registrations keyed by (uuid, mac_set) — MAC set
  is the tiebreaker (duplicate SMBIOS UUIDs); token stored as sha256 only.
  Idempotent register (sticky-discard), atomic one-shot delivery, bind/discard.
- api/appliance.go: POST /appliance/register (the one unauth endpoint, per-IP
  rate-limited, 256-bit token); GET /appliance/poll (404 no-oracle / 204 unbound
  / 200 deliver-once / 410 delivered). Passphrase read live, never logged.
- web/appliances.go: Hosts-page "Unclaimed appliances" section + BIND (customer
  picker, host count display-only) + DISCARD; SSH host-key fingerprints; events.
- Red-proofs: one-shot delivery + register idempotency (both proven red);
  404-no-oracle, sticky-discard, bind staging, render. Green + confirm gate.

Scripts (v1.19.0):
- felhom-bootstrap.sh: ONE unit, TWO modes. Direct (env has customer/passphrase)
  = slice-A path, byte-identical, only branched around. Pairing (generic) =
  register + poll (RestartSec=30 is the poll timer); on delivery write the env
  0600 and fall through to direct. Secrets + token shredded on success.
- build-felhom-iso.sh --pairing: generic secret-free ISO, -generic filename,
  manifest mode=pairing. profiles/generic.profile (new).
- test/bootstrap-modes.sh: Scenario D (direct = zero appliance calls) + pairing
  register/poll + delivery handoff — all green in a debian container.
2026-07-17 15:07:31 +02:00

111 lines
4.8 KiB
Bash

#!/bin/bash
# bootstrap-modes.sh — R-21 slice C regression harness for felhom-bootstrap.sh's two modes. Runs as
# root inside a throwaway debian container (writes /etc/felhom etc.); fakes curl + host-install +
# systemctl on PATH. Asserts:
# D (regression): a DIRECT env (customer-id + passphrase) enters run_direct and makes ZERO calls to
# /api/v1/appliance/* — the pairing code path is provably not entered.
# pairing: an env WITHOUT customer-id/passphrase enters run_pairing, POSTs /appliance/register,
# persists the token, and GETs /appliance/poll.
# delivery: a poll that returns 200 writes the direct env (0600) and invokes host-install.
set -uo pipefail
BSTRAP=/work/felhom-bootstrap.sh
FAKE=/work/fakebin; rm -rf "$FAKE"; mkdir -p "$FAKE"
CALLS=/work/curl.log
export PATH="$FAKE:$PATH"
fail=0
say() { echo "TEST: $*"; }
check() { if eval "$2"; then echo " ok: $1"; else echo " FAIL: $1"; fail=1; fi; }
# --- fake curl: logs every invocation's URL; emulates -o (fetch), --data (register), -w code (poll) --
cat > "$FAKE/curl" <<'CURL'
#!/bin/bash
url=""; ofile=""; wfmt=""
prev=""
for a in "$@"; do
case "$a" in http*|https*) url="$a";; esac
case "$prev" in -o) ofile="$a";; -w) wfmt="$a";; esac
prev="$a"
done
echo "$url" >> /work/curl.log
mode=$(cat /work/poll-mode 2>/dev/null || echo 204)
case "$url" in
*"/felhom-host-install.sh")
# write a stub host-install to the -o target
cat > "$ofile" <<'HI'
#!/bin/bash
echo "fake host-install ran: $*" >> /work/hostinstall.log
exit 0
HI
exit 0 ;;
*"/appliance/register")
echo '{"appliance_token":"TESTTOKEN123456","poll_interval_sec":30}'
exit 0 ;;
*"/appliance/poll")
if [ "$mode" = "200" ]; then
# body then, if -w set, a newline + code (matches the bootstrap's -w '\n%{http_code}')
printf '%s' '{"customer_id":"drill","retrieval_passphrase":"SEKRET-PASS","mode":"appliance","extra_args":"--cores 2"}'
[ -n "$wfmt" ] && printf '\n200'
else
[ -n "$wfmt" ] && printf '\n204'
fi
exit 0 ;;
esac
exit 0
CURL
chmod +x "$FAKE/curl"
# fake systemctl (disable is a no-op)
printf '#!/bin/bash\nexit 0\n' > "$FAKE/systemctl"; chmod +x "$FAKE/systemctl"
reset_state() {
rm -rf /etc/felhom /run/felhom-bootstrap-pass /var/lib/felhom-install "$CALLS" /work/hostinstall.log /work/poll-mode
mkdir -p /etc/felhom
}
# ============================ Scenario D — direct mode, zero appliance calls =========================
say "D: direct env -> run_direct, NO appliance calls"
reset_state
cat > /etc/felhom/bootstrap.env <<'ENV'
FELHOM_CUSTOMER_ID=acme
FELHOM_MODE=appliance
FELHOM_RETRIEVAL_PASSPHRASE=direct-pass
FELHOM_HUB_URL=https://hub.example
ENV
chmod 0600 /etc/felhom/bootstrap.env
bash "$BSTRAP"; rc=$?
check "run_direct exited 0 (host-install stub succeeded)" "[ $rc -eq 0 ]"
check "host-install was invoked" "[ -f /work/hostinstall.log ]"
check "ZERO /appliance/register calls" "! grep -q '/appliance/register' $CALLS"
check "ZERO /appliance/poll calls" "! grep -q '/appliance/poll' $CALLS"
check "done-flag written" "[ -f /etc/felhom/.bootstrap-done ]"
check "env shredded on success" "[ ! -f /etc/felhom/bootstrap.env ]"
# ============================ pairing mode — registers, then polls ==================================
say "pairing: no customer/passphrase -> register + poll (unbound=204)"
reset_state
cat > /etc/felhom/bootstrap.env <<'ENV'
FELHOM_HUB_URL=https://hub.example
ENV
echo 204 > /work/poll-mode
bash "$BSTRAP"; rc=$?
check "unbound poll -> exit non-zero (systemd retries)" "[ $rc -ne 0 ]"
check "POSTed /appliance/register" "grep -q '/appliance/register' $CALLS"
check "appliance token persisted 0600" "[ -f /etc/felhom/appliance-token ] && [ \"\$(stat -c %a /etc/felhom/appliance-token)\" = 600 ]"
check "GET /appliance/poll" "grep -q '/appliance/poll' $CALLS"
check "no direct env written yet" "! grep -q FELHOM_CUSTOMER_ID /etc/felhom/bootstrap.env"
check "host-install NOT run (unbound)" "[ ! -f /work/hostinstall.log ]"
# ============================ delivery — poll 200 writes env + runs host-install =====================
say "delivery: bound poll (200) -> write direct env + run host-install"
# keep the token from the previous step; flip the poll to 200
echo 200 > /work/poll-mode
bash "$BSTRAP"; rc=$?
check "delivery run exited 0" "[ $rc -eq 0 ]"
check "direct env written with customer-id" "grep -q 'FELHOM_CUSTOMER_ID=drill' /etc/felhom/bootstrap.env || [ -f /etc/felhom/.bootstrap-done ]"
check "host-install invoked after delivery" "[ -f /work/hostinstall.log ]"
check "done-flag written" "[ -f /etc/felhom/.bootstrap-done ]"
echo "=================================================="
if [ $fail -eq 0 ]; then echo "ALL BOOTSTRAP-MODE TESTS PASSED"; else echo "SOME TESTS FAILED"; fi
exit $fail