Networkless disposable Docker target (--network none, read-only, tmpfs only, no volumes/ports/kubeconfig), metadata-only preflight before any prompt, SSH-signed admission in namespace railiance-openbao-restore-attempt, hidden custody prompts with sealed memfds, throwaway init + forced Raft restore from stdin, original-share unseal, generate-root readback credential (revoked), metadata-only readback against committed sources, reaper for parent loss and hard deadline. Original material refuses until T06 sets the image digest pin. Fix stale v2.5.3 app version in docs/openbao.md. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Assistant: claude-code Assistant-Model: opus Assistant-Process: 4384@bnt-lap001 Assistant-Session: 80d1f3da-7a91-4519-9737-9ba128b4da64
31 lines
2 KiB
Bash
31 lines
2 KiB
Bash
#!/usr/bin/env bash
|
|
# Attended launcher: isolated original-OpenBao restore, phase A (RPF-WP-0064).
|
|
# Founder workstation only. Never railiance01, never a kubeconfig, no network.
|
|
set +x
|
|
set -euo pipefail
|
|
ROOT="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")/../.." && pwd)"
|
|
cd -- "$ROOT"
|
|
umask 077
|
|
unset KUBECONFIG BAO_TOKEN VAULT_TOKEN BAO_ADDR VAULT_ADDR
|
|
usage='Usage: run-isolated-restore.sh ADMISSION ADMISSION_SIG ADMISSION_SHA256 CIPHERTEXT RECEIPT_DIR'
|
|
[[ $# == 5 ]] || { printf '%s\n' "$usage"; exit 1; }
|
|
[[ "$3" =~ ^sha256:[a-f0-9]{64}$ ]] || { printf '%s\n' 'ERROR: exact sha256:<hex> admission digest required.'; exit 1; }
|
|
for index in 1 2 4; do
|
|
[[ -f "${!index}" && ! -L "${!index}" ]] || { printf '%s\n' 'ERROR: provide regular owner-controlled input files.'; exit 1; }
|
|
done
|
|
[[ -d "$5" && ! -L "$5" && "$5" == /* ]] || { printf '%s\n' 'ERROR: RECEIPT_DIR must be an existing absolute directory.'; exit 1; }
|
|
[[ -t 0 && -t 1 && -t 2 ]] || { printf '%s\n' 'ERROR: run in your own interactive terminal.'; exit 1; }
|
|
[[ "$(hostname -s)" != railiance01* ]] || { printf '%s\n' 'ERROR: never on railiance01.'; exit 1; }
|
|
for tool in python3 age age-keygen docker ssh-keygen git; do
|
|
command -v "$tool" >/dev/null || { printf 'ERROR: required tool unavailable: %s\n' "$tool"; exit 1; }
|
|
done
|
|
RECEIPT="$5/rpf64-restore-$(date -u +%Y%m%dT%H%M%SZ).json"
|
|
python3 scripts/openbao-isolated-restore/preflight.py --admission "$1" --admission-sig "$2" \
|
|
--admission-sha256 "$3" --ciphertext "$4" --receipt "$RECEIPT"
|
|
printf '%s\n' 'Phase A only: networkless restore and metadata readback. No consumer continuity,'
|
|
printf '%s\n' 'live JWT login, phase B network or owner acceptance is claimed.'
|
|
printf '%s\n' 'You will be asked for the backup age identity, then two original unseal shares.'
|
|
printf '%s\n' 'Press Ctrl-C at any time to abort; the container is removed and an aborted receipt written.'
|
|
python3 scripts/openbao-isolated-restore/restore_adapter.py --admission "$1" --admission-sig "$2" \
|
|
--admission-sha256 "$3" --ciphertext "$4" --receipt "$RECEIPT"
|
|
printf 'Safe receipt: %s\n' "$RECEIPT"
|