#!/usr/bin/env bash # Attended launcher: isolated original-OpenBao restore, phase A or T10 break-glass drill (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 [--break-glass-drill] ADMISSION ADMISSION_SIG ADMISSION_SHA256 CIPHERTEXT RECEIPT_DIR' MODE=phase-a if [[ "${1:-}" == --break-glass-drill ]]; then MODE=break-glass-drill; shift; fi [[ $# == 5 ]] || { printf '%s\n' "$usage"; exit 1; } [[ "$3" =~ ^sha256:[a-f0-9]{64}$ ]] || { printf '%s\n' 'ERROR: exact sha256: 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-${MODE}-$(date -u +%Y%m%dT%H%M%SZ).json" python3 scripts/openbao-isolated-restore/preflight.py --mode "$MODE" --admission "$1" --admission-sig "$2" \ --admission-sha256 "$3" --ciphertext "$4" --receipt "$RECEIPT" if [[ "$MODE" == break-glass-drill ]]; then printf '%s\n' 'Break-glass drill (RPF-WP-0064-T10) on an isolated, networkless restore. Never production.' printf '%s\n' 'Prompts: backup age identity, two unseal shares, the held initial root token (lookup-self only),' printf '%s\n' 'then two shares AGAIN for a fresh generate-root ceremony. Production root-token validity,' printf '%s\n' 'production generate-root availability and the SSO-down access path are not claimed.' else 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.' fi 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 --mode "$MODE" --admission "$1" --admission-sig "$2" \ --admission-sha256 "$3" --ciphertext "$4" --receipt "$RECEIPT" printf 'Safe receipt: %s\n' "$RECEIPT"