generated from coulomb/repo-seed
Add OpenBao restore drill actions
This commit is contained in:
@@ -13,6 +13,7 @@ import base64
|
||||
import hashlib
|
||||
import html
|
||||
import json
|
||||
import shlex
|
||||
import subprocess
|
||||
import sys
|
||||
import urllib.error
|
||||
@@ -1338,6 +1339,8 @@ def command_payloads(data: dict[str, Any]) -> list[dict[str, str]]:
|
||||
def runbook_payloads(data: dict[str, Any]) -> list[dict[str, str]]:
|
||||
init_output = yes(data, "openbao_init_output_produced")
|
||||
initialized = yes(data, "openbao_initialized")
|
||||
initial_config_applied = yes(data, "openbao_initial_config_applied")
|
||||
restore_done = yes(data, "restore_drill_passed")
|
||||
trial_exposed = yes(data, "openbao_trial_material_exposed")
|
||||
response_complete = yes(data, "openbao_compromise_response_complete")
|
||||
keys_rotated = yes(data, "openbao_unseal_keys_rotated")
|
||||
@@ -1366,6 +1369,12 @@ def runbook_payloads(data: dict[str, Any]) -> list[dict[str, str]]:
|
||||
lockdown_status = "blocked"
|
||||
lockdown_location = "OpenBao is not recorded as unsealed; sealing is only meaningful while it is serving requests."
|
||||
|
||||
restore_status = "done" if restore_done else "todo"
|
||||
restore_location = "Create, encrypt, and isolated-restore a Railiance OpenBao Raft snapshot before live secrets move in."
|
||||
if not initial_config_applied:
|
||||
restore_status = "blocked"
|
||||
restore_location = "Apply OpenBao initial configuration before proving backup and restore."
|
||||
|
||||
return [
|
||||
add_taint(
|
||||
{
|
||||
@@ -1403,12 +1412,26 @@ def runbook_payloads(data: dict[str, Any]) -> list[dict[str, str]]:
|
||||
},
|
||||
openbao_downstream_taint if initialized else {},
|
||||
),
|
||||
add_taint(
|
||||
{
|
||||
"name": "Restore drill",
|
||||
"description": "Prove that Railiance OpenBao can be snapshotted, restored into isolation, unsealed, and verified before production trust.",
|
||||
"subsystem": "Railiance OpenBao",
|
||||
"responsibility": "openbao-ceremony-operator",
|
||||
"email": role_email(data, "role_openbao_operator_email"),
|
||||
"location": restore_location,
|
||||
"state": restore_status,
|
||||
},
|
||||
openbao_downstream_taint if initialized else {},
|
||||
),
|
||||
]
|
||||
|
||||
|
||||
def runbook_command_payloads(data: dict[str, Any]) -> list[dict[str, str]]:
|
||||
init_output = yes(data, "openbao_init_output_produced")
|
||||
initialized = yes(data, "openbao_initialized")
|
||||
initial_config_applied = yes(data, "openbao_initial_config_applied")
|
||||
restore_done = yes(data, "restore_drill_passed")
|
||||
trial_exposed = yes(data, "openbao_trial_material_exposed")
|
||||
response_complete = yes(data, "openbao_compromise_response_complete")
|
||||
keys_rotated = yes(data, "openbao_unseal_keys_rotated")
|
||||
@@ -1454,6 +1477,59 @@ def runbook_command_payloads(data: dict[str, Any]) -> list[dict[str, str]]:
|
||||
"unset OPENBAO_TOKEN"
|
||||
)
|
||||
|
||||
restore_status = "done" if restore_done else "todo"
|
||||
restore_reason = "Restore drill is recorded." if restore_done else "Create encrypted snapshot evidence and complete an isolated restore proof."
|
||||
if not initial_config_applied:
|
||||
restore_status = "blocked"
|
||||
restore_reason = "OpenBao initial configuration must be applied before the restore drill."
|
||||
restore_taint = openbao_downstream_taint if initialized else {}
|
||||
public_key = extract_age_public_key(data.get("custodian_age_public_key"))
|
||||
quoted_public_key = shlex.quote(public_key if public_key else "<age-recipient>")
|
||||
snapshot_workspace_command = (
|
||||
'export RESTORE_DRILL_DIR="${RESTORE_DRILL_DIR:-/tmp/netkingdom-openbao-restore-drill}"\n'
|
||||
'mkdir -p "$RESTORE_DRILL_DIR"\n'
|
||||
'chmod 700 "$RESTORE_DRILL_DIR"\n'
|
||||
'printf "Restore drill workspace: %s\\n" "$RESTORE_DRILL_DIR"'
|
||||
)
|
||||
snapshot_command = (
|
||||
'export RESTORE_DRILL_DIR="${RESTORE_DRILL_DIR:-/tmp/netkingdom-openbao-restore-drill}"\n'
|
||||
'mkdir -p "$RESTORE_DRILL_DIR"\n'
|
||||
'chmod 700 "$RESTORE_DRILL_DIR"\n'
|
||||
"printf 'OpenBao token: ' >&2\n"
|
||||
"read -rs OPENBAO_TOKEN\n"
|
||||
"printf '\\n' >&2\n"
|
||||
'printf \'%s\\n\' "$OPENBAO_TOKEN" | kubectl exec -i -n openbao openbao-0 -- '
|
||||
"sh -c 'read -r BAO_TOKEN; export BAO_TOKEN; bao operator raft snapshot save /tmp/openbao-raft.snap'\n"
|
||||
"unset OPENBAO_TOKEN\n"
|
||||
'kubectl cp openbao/openbao-0:/tmp/openbao-raft.snap "$RESTORE_DRILL_DIR/openbao-raft.snap"\n'
|
||||
'kubectl exec -n openbao openbao-0 -- rm -f /tmp/openbao-raft.snap\n'
|
||||
'sha256sum "$RESTORE_DRILL_DIR/openbao-raft.snap" | tee "$RESTORE_DRILL_DIR/openbao-raft.snap.sha256"'
|
||||
)
|
||||
encrypt_snapshot_status = restore_status if public_key else "blocked"
|
||||
encrypt_snapshot_reason = restore_reason if public_key else "Record the custodian public age recipient before encrypting snapshot custody material."
|
||||
encrypt_snapshot_command = (
|
||||
'export RESTORE_DRILL_DIR="${RESTORE_DRILL_DIR:-/tmp/netkingdom-openbao-restore-drill}"\n'
|
||||
f'age -r {quoted_public_key} -o "$RESTORE_DRILL_DIR/openbao-raft.snap.age" "$RESTORE_DRILL_DIR/openbao-raft.snap"\n'
|
||||
'sha256sum "$RESTORE_DRILL_DIR/openbao-raft.snap.age" | tee "$RESTORE_DRILL_DIR/openbao-raft.snap.age.sha256"\n'
|
||||
'if command -v shred >/dev/null 2>&1; then\n'
|
||||
' shred -u "$RESTORE_DRILL_DIR/openbao-raft.snap"\n'
|
||||
"else\n"
|
||||
' rm -f "$RESTORE_DRILL_DIR/openbao-raft.snap"\n'
|
||||
"fi"
|
||||
)
|
||||
isolated_restore_command = (
|
||||
"cat <<'RESTORE_DRILL'\n"
|
||||
"Isolated Railiance OpenBao restore drill evidence required:\n"
|
||||
"1. Use a disposable cluster, VM, or namespace. Do not restore into namespace=openbao.\n"
|
||||
"2. Deploy a fresh OpenBao instance with empty storage.\n"
|
||||
"3. Decrypt the encrypted snapshot only inside the isolated drill workspace.\n"
|
||||
"4. Restore with: bao operator raft snapshot restore -force /tmp/openbao-raft.snap\n"
|
||||
"5. Unseal the isolated instance with the current trial/drill shares.\n"
|
||||
"6. Verify status, mounts, auth methods, policies, and a non-production test secret read.\n"
|
||||
"7. Destroy the isolated environment and record only non-secret evidence in this UI.\n"
|
||||
"RESTORE_DRILL"
|
||||
)
|
||||
|
||||
return [
|
||||
add_taint(
|
||||
{
|
||||
@@ -1545,6 +1621,66 @@ def runbook_command_payloads(data: dict[str, Any]) -> list[dict[str, str]]:
|
||||
},
|
||||
openbao_downstream_taint if initialized else {},
|
||||
),
|
||||
add_taint(
|
||||
{
|
||||
"name": "Prepare restore drill workspace",
|
||||
"description": "Create a local restricted directory for temporary snapshot evidence.",
|
||||
"status": restore_status,
|
||||
"status_reason": restore_reason,
|
||||
"command": snapshot_workspace_command,
|
||||
},
|
||||
restore_taint,
|
||||
),
|
||||
add_taint(
|
||||
{
|
||||
"name": "Create encrypted-restore snapshot source",
|
||||
"description": "Prompt locally for an OpenBao token, create a Raft snapshot in the pod, copy it out, remove the pod copy, and record a plaintext hash before encryption.",
|
||||
"status": restore_status,
|
||||
"status_reason": restore_reason,
|
||||
"command": snapshot_command,
|
||||
},
|
||||
restore_taint,
|
||||
),
|
||||
add_taint(
|
||||
{
|
||||
"name": "Encrypt restore snapshot",
|
||||
"description": "Encrypt the Raft snapshot to the custodian age recipient and remove the local plaintext snapshot.",
|
||||
"status": encrypt_snapshot_status,
|
||||
"status_reason": encrypt_snapshot_reason,
|
||||
"command": encrypt_snapshot_command,
|
||||
},
|
||||
restore_taint,
|
||||
),
|
||||
add_taint(
|
||||
{
|
||||
"name": "Run isolated restore proof",
|
||||
"description": "Checklist for proving the snapshot can restore into an isolated OpenBao instance before live secrets move in.",
|
||||
"status": restore_status,
|
||||
"status_reason": restore_reason,
|
||||
"command": isolated_restore_command,
|
||||
},
|
||||
restore_taint,
|
||||
),
|
||||
add_taint(
|
||||
{
|
||||
"name": "Run post-restore readiness check",
|
||||
"description": "Re-run the Railiance post-unseal checks after restore evidence has been captured.",
|
||||
"status": restore_status,
|
||||
"status_reason": restore_reason,
|
||||
"command": "make -C ../railiance-platform openbao-verify-post-unseal",
|
||||
},
|
||||
restore_taint,
|
||||
),
|
||||
add_taint(
|
||||
{
|
||||
"name": "Record restore drill passed",
|
||||
"description": "Non-secret metadata checkbox after encrypted snapshot evidence and isolated restore proof are complete.",
|
||||
"status": restore_status,
|
||||
"status_reason": restore_reason,
|
||||
"command": "Use the checkbox: Restore drill passed",
|
||||
},
|
||||
restore_taint,
|
||||
),
|
||||
]
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user