NET-WP-0020 finished: attended-ceremony + auto-unseal-transit profiles, greenfield init/unseal proof

T2: greenfield live proof against a fresh uninitialized OpenBao 2.5.5 —
caught and fixed 'bao operator unseal -' not reading stdin (now
'bao write sys/unseal key=-'); init and reseal-replay paths proven.
T3: attended-ceremony selectable — runbook, non-secret ceremony-record
template + validator, and a lab/production deployment profile that blocks
sops-held-automation in console selection, gates, and the init script.
T4: console gate + evidence flags for auto-unseal-transit (Helm seal stanza
prepared in railiance-platform).
Also: SCOPE.md refreshed to current repo state; adhoc fix for the broken
check-secrets Make target (unescaped $).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
2026-07-02 22:08:33 +02:00
parent 60b9d7037d
commit 85a781b7a4
10 changed files with 564 additions and 69 deletions

View File

@@ -78,8 +78,15 @@ PY
# Only sops-held-automation may be automated. attended-ceremony and
# auto-unseal-transit must never reach `bao operator init/unseal` from here.
MODEL=""
PROFILE=""
if [[ -f "$CONSOLE_METADATA" ]]; then
MODEL=$(python3 -c 'import json,sys; print(json.load(open(sys.argv[1])).get("openbao_unseal_custody_model") or "")' "$CONSOLE_METADATA")
PROFILE=$(python3 -c 'import json,sys; print(json.load(open(sys.argv[1])).get("deployment_profile") or "")' "$CONSOLE_METADATA")
fi
if [[ "$PROFILE" == "production" ]]; then
die "deployment profile is 'production' — sops-held automation is blocked.
Use the attended ceremony (docs/openbao-attended-ceremony-runbook.md) or
auto-unseal-transit, or reselect: select-deployment-profile --profile lab"
fi
if [[ "$MODEL" != "sops-held-automation" ]]; then
die "unseal custody model is '${MODEL:-unselected}' — automation requires 'sops-held-automation'.
@@ -145,8 +152,10 @@ if [[ "$SEALED" == "true" ]]; then
log "replaying unseal shares (have $SHARE_COUNT)..."
for idx in $(seq 0 $((SHARE_COUNT - 1))); do
# Share travels stdin→stdin; never argv, never logs.
# `bao operator unseal -` does not read stdin (needs a TTY or the
# share in argv), so use the sys/unseal API with key=- instead.
python3 -c 'import json,sys; print(json.load(open(sys.argv[1]))["unseal_keys_b64"][int(sys.argv[2])])' "$INIT_FILE" "$idx" \
| kubectl -n "$NAMESPACE" exec -i "$POD" -- bao operator unseal - >/dev/null
| kubectl -n "$NAMESPACE" exec -i "$POD" -- bao write sys/unseal key=- >/dev/null
STATUS_JSON="$(bao_status)"
SEALED=$(python3 -c 'import json,sys; print(str(json.loads(sys.stdin.read()).get("sealed", True)).lower())' <<<"$STATUS_JSON")
log "unseal share $((idx + 1)) applied (sealed=$SEALED)"