36c5cd5fdf
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.
111 lines
4.8 KiB
Bash
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
|