generated from coulomb/repo-seed
Refine bootstrap actions and runbook templates
This commit is contained in:
@@ -1216,20 +1216,9 @@ def command_payloads(data: dict[str, Any]) -> list[dict[str, str]]:
|
||||
initial_config_applied = yes(data, "openbao_initial_config_applied")
|
||||
trial_exposed = yes(data, "openbao_trial_material_exposed")
|
||||
response_complete = yes(data, "openbao_compromise_response_complete")
|
||||
keys_rotated = yes(data, "openbao_unseal_keys_rotated")
|
||||
root_disposed = data.get("root_token_disposition") in {"revoked", "offline-sealed"}
|
||||
openbao_direct_taint = openbao_trial_taint(data, "direct")
|
||||
openbao_downstream_taint = openbao_trial_taint(data, "downstream")
|
||||
|
||||
status_state = "todo"
|
||||
status_reason = "Run any time to inspect the current OpenBao deployment state."
|
||||
if preflight_done:
|
||||
status_state = "done"
|
||||
status_reason = "Deployment and pre-init status were verified."
|
||||
if (init_output or initialized) and not root_disposed:
|
||||
status_state = "redo"
|
||||
status_reason = "OpenBao changed during init/unseal; rerun status before root-token disposition."
|
||||
|
||||
preflight_state = "done" if preflight_done else "todo"
|
||||
preflight_reason = "Safe preflight passed."
|
||||
if not preflight_done:
|
||||
@@ -1246,14 +1235,6 @@ def command_payloads(data: dict[str, Any]) -> list[dict[str, str]]:
|
||||
init_state = "blocked"
|
||||
init_reason = "OpenBao preflight must pass first."
|
||||
|
||||
unseal_state = "done" if initialized else "todo"
|
||||
unseal_reason = "OpenBao is recorded as initialized and unsealed."
|
||||
if not initialized:
|
||||
unseal_reason = "Provide threshold shares by prompt, not as command arguments."
|
||||
if not (init_output or initialized):
|
||||
unseal_state = "blocked"
|
||||
unseal_reason = "OpenBao init output must be produced first."
|
||||
|
||||
config_state = "done" if initial_config_applied else "todo"
|
||||
config_reason = "Initial configuration is recorded. Root-token disposition remains a separate gate."
|
||||
if not initial_config_applied:
|
||||
@@ -1276,13 +1257,6 @@ def command_payloads(data: dict[str, Any]) -> list[dict[str, str]]:
|
||||
verify_reason = "OpenBao must be initialized and unsealed first."
|
||||
|
||||
return [
|
||||
{
|
||||
"name": "OpenBao status",
|
||||
"description": "Show pod, service, PVC, and seal/init status.",
|
||||
"status": status_state,
|
||||
"status_reason": status_reason,
|
||||
"command": "make -C ../railiance-platform openbao-status",
|
||||
},
|
||||
{
|
||||
"name": "OpenBao preflight",
|
||||
"description": "Run safe status and verification checks. Does not initialize OpenBao.",
|
||||
@@ -1303,16 +1277,6 @@ def command_payloads(data: dict[str, Any]) -> list[dict[str, str]]:
|
||||
},
|
||||
openbao_direct_taint if init_output or initialized else {},
|
||||
),
|
||||
add_taint(
|
||||
{
|
||||
"name": "OpenBao unseal prompt",
|
||||
"description": "Enter unseal shares by interactive terminal prompt. Do not place shares on the command line.",
|
||||
"status": unseal_state,
|
||||
"status_reason": unseal_reason,
|
||||
"command": "kubectl exec -it -n openbao openbao-0 -- bao operator unseal",
|
||||
},
|
||||
openbao_direct_taint if initialized else {},
|
||||
),
|
||||
add_taint(
|
||||
{
|
||||
"name": "OpenBao initial configuration",
|
||||
@@ -1337,43 +1301,30 @@ 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")
|
||||
lockdown_drilled = yes(data, "openbao_emergency_lockdown_drilled")
|
||||
openbao_direct_taint = openbao_trial_taint(data, "direct")
|
||||
openbao_downstream_taint = openbao_trial_taint(data, "downstream")
|
||||
|
||||
key_compromise_status = "done" if response_complete else "todo"
|
||||
key_compromise_location = "Use for trial output exposure, screenshots, chat paste, shell history, or lost custody."
|
||||
if not trial_exposed:
|
||||
key_compromise_status = "blocked" if not init_output else "todo"
|
||||
key_compromise_location = "Mark trial key material exposed before running the response checklist."
|
||||
key_compromise_location = "Template: record the exposure, choose reset versus rotation, inspect affected paths, and record only the non-secret outcome."
|
||||
if trial_exposed and not response_complete:
|
||||
key_compromise_location = "Active template: trial material is marked exposed; choose reset versus rotation before production trust."
|
||||
elif response_complete:
|
||||
key_compromise_location = "Template retained for future incidents; the current non-secret compromise response is marked complete."
|
||||
|
||||
rotate_status = "done" if keys_rotated else "todo"
|
||||
rotate_location = "Run only after OpenBao is unsealed and existing exposed shares are available for quorum."
|
||||
rotate_location = "Template: unseal OpenBao, start rotate-keys, submit current shares by prompt, route new shares to custody holders, then record confirmation."
|
||||
if not initialized:
|
||||
rotate_status = "blocked"
|
||||
rotate_location = "Unseal OpenBao first; rotate-keys needs a quorum of current unseal shares."
|
||||
if not trial_exposed and not keys_rotated:
|
||||
rotate_status = "blocked"
|
||||
rotate_location = "Record the key-compromise condition or schedule a normal rotation first."
|
||||
rotate_location = "Template: prepare now; execution needs an unsealed OpenBao instance and a quorum of current shares."
|
||||
|
||||
lockdown_status = "done" if lockdown_drilled else "todo"
|
||||
lockdown_location = "Requires an unsealed OpenBao instance and a token with root or sudo on sys/seal."
|
||||
lockdown_location = "Template: use a root/sudo-capable token, run emergency seal, confirm Sealed true, then record the drill or incident outcome."
|
||||
if not initialized:
|
||||
lockdown_status = "blocked"
|
||||
lockdown_location = "OpenBao is not recorded as unsealed; sealing is only meaningful while it is serving requests."
|
||||
lockdown_location = "Template: prepare now; execution only changes availability while OpenBao is unsealed and 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."
|
||||
restore_location = "Template: prepare workspace, snapshot, encrypt to age recipient, restore in isolation, verify, destroy drill environment, then record evidence."
|
||||
if not initial_config_applied:
|
||||
restore_status = "blocked"
|
||||
restore_location = "Apply OpenBao initial configuration before proving backup and restore."
|
||||
restore_location = "Template: prepare now; execute after initial OpenBao configuration exists and before live secrets move in."
|
||||
|
||||
return [
|
||||
add_taint(
|
||||
@@ -1384,7 +1335,7 @@ def runbook_payloads(data: dict[str, Any]) -> list[dict[str, str]]:
|
||||
"responsibility": "openbao-ceremony-operator",
|
||||
"email": role_email(data, "role_openbao_operator_email"),
|
||||
"location": key_compromise_location,
|
||||
"state": key_compromise_status,
|
||||
"state": "template",
|
||||
},
|
||||
openbao_direct_taint if trial_exposed and not response_complete else {},
|
||||
),
|
||||
@@ -1396,7 +1347,7 @@ def runbook_payloads(data: dict[str, Any]) -> list[dict[str, str]]:
|
||||
"responsibility": "openbao-ceremony-operator",
|
||||
"email": role_email(data, "role_openbao_operator_email"),
|
||||
"location": rotate_location,
|
||||
"state": rotate_status,
|
||||
"state": "template",
|
||||
},
|
||||
openbao_downstream_taint if trial_exposed and not response_complete else {},
|
||||
),
|
||||
@@ -1408,7 +1359,7 @@ def runbook_payloads(data: dict[str, Any]) -> list[dict[str, str]]:
|
||||
"responsibility": "openbao-ceremony-operator",
|
||||
"email": role_email(data, "role_openbao_operator_email"),
|
||||
"location": lockdown_location,
|
||||
"state": lockdown_status,
|
||||
"state": "template",
|
||||
},
|
||||
openbao_downstream_taint if initialized else {},
|
||||
),
|
||||
@@ -1420,7 +1371,7 @@ def runbook_payloads(data: dict[str, Any]) -> list[dict[str, str]]:
|
||||
"responsibility": "openbao-ceremony-operator",
|
||||
"email": role_email(data, "role_openbao_operator_email"),
|
||||
"location": restore_location,
|
||||
"state": restore_status,
|
||||
"state": "template",
|
||||
},
|
||||
openbao_downstream_taint if initialized else {},
|
||||
),
|
||||
@@ -1428,61 +1379,40 @@ def runbook_payloads(data: dict[str, Any]) -> list[dict[str, str]]:
|
||||
|
||||
|
||||
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")
|
||||
lockdown_drilled = yes(data, "openbao_emergency_lockdown_drilled")
|
||||
openbao_direct_taint = openbao_trial_taint(data, "direct")
|
||||
openbao_downstream_taint = openbao_trial_taint(data, "downstream")
|
||||
|
||||
exposure_status = "done" if trial_exposed else "todo"
|
||||
exposure_reason = "Trial key-material exposure is recorded in non-secret metadata." if trial_exposed else "Record that the trial init output escaped custody before using affected material."
|
||||
def token_prompt_command(bao_command: str) -> str:
|
||||
return (
|
||||
"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 -- "
|
||||
f"sh -c 'read -r BAO_TOKEN; export BAO_TOKEN; {bao_command}'\n"
|
||||
"unset OPENBAO_TOKEN"
|
||||
)
|
||||
|
||||
response_status = "done" if response_complete else "todo"
|
||||
response_reason = "Compromise response was recorded." if response_complete else "Stop production use of exposed material, decide rotate-vs-reset, and record non-secret evidence."
|
||||
if not trial_exposed:
|
||||
response_status = "blocked"
|
||||
response_reason = "Record the key-material exposure first."
|
||||
def action(name: str, description: str, command: str, taint: dict[str, str] | None = None) -> dict[str, str]:
|
||||
return add_taint(
|
||||
{
|
||||
"name": name,
|
||||
"description": description,
|
||||
"command": command,
|
||||
},
|
||||
taint or {},
|
||||
)
|
||||
|
||||
unseal_status = "done" if initialized else "todo"
|
||||
unseal_reason = "OpenBao is unsealed." if initialized else "Unseal by hidden prompt before rotating unseal keys."
|
||||
if not init_output:
|
||||
unseal_status = "blocked"
|
||||
unseal_reason = "OpenBao init output must exist first."
|
||||
|
||||
rotate_status = "done" if keys_rotated else "todo"
|
||||
rotate_reason = "New unseal keys are recorded as generated." if keys_rotated else "Start rotation, then submit current shares by prompt until quorum completes."
|
||||
if not initialized:
|
||||
rotate_status = "blocked"
|
||||
rotate_reason = "OpenBao must be unsealed before rotate-keys can run."
|
||||
if not trial_exposed and not keys_rotated:
|
||||
rotate_status = "blocked"
|
||||
rotate_reason = "Record exposure or schedule a normal rotation before generating new shares."
|
||||
|
||||
lockdown_status = "done" if lockdown_drilled else "todo"
|
||||
lockdown_reason = "Emergency lock-down drill is recorded." if lockdown_drilled else "Seals OpenBao immediately. Use only during an emergency or scheduled drill."
|
||||
if not initialized:
|
||||
lockdown_status = "blocked"
|
||||
lockdown_reason = "OpenBao must be unsealed before emergency seal changes availability."
|
||||
seal_command = (
|
||||
"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 seal'\n"
|
||||
"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 {}
|
||||
seal_command = token_prompt_command("bao operator seal")
|
||||
audit_list_command = token_prompt_command("bao audit list")
|
||||
secrets_list_command = token_prompt_command("bao secrets list")
|
||||
auth_list_command = token_prompt_command("bao auth list")
|
||||
openbao_status_command = "kubectl exec -n openbao openbao-0 -- bao status"
|
||||
direct_taint = openbao_direct_taint if initialized else {}
|
||||
downstream_taint = openbao_downstream_taint if initialized else {}
|
||||
compromise_taint = openbao_downstream_taint if trial_exposed and not response_complete 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 = (
|
||||
@@ -1505,8 +1435,6 @@ def runbook_command_payloads(data: dict[str, Any]) -> list[dict[str, str]]:
|
||||
'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'
|
||||
@@ -1531,155 +1459,95 @@ def runbook_command_payloads(data: dict[str, Any]) -> list[dict[str, str]]:
|
||||
)
|
||||
|
||||
return [
|
||||
add_taint(
|
||||
{
|
||||
"name": "Record key exposure",
|
||||
"description": "Non-secret metadata checkbox in this UI; do not paste exposed values.",
|
||||
"status": exposure_status,
|
||||
"status_reason": exposure_reason,
|
||||
"command": "Use the checkbox: Trial key material exposed",
|
||||
},
|
||||
openbao_direct_taint if trial_exposed and not response_complete else {},
|
||||
action(
|
||||
"OpenBao status",
|
||||
"Show seal, initialization, storage, and HA state for the OpenBao pod. This command does not require a token.",
|
||||
openbao_status_command,
|
||||
downstream_taint,
|
||||
),
|
||||
add_taint(
|
||||
{
|
||||
"name": "Unseal by prompt",
|
||||
"description": "Provide threshold shares interactively. Never put shares on the command line.",
|
||||
"status": unseal_status,
|
||||
"status_reason": unseal_reason,
|
||||
"command": "kubectl exec -it -n openbao openbao-0 -- bao operator unseal",
|
||||
},
|
||||
openbao_direct_taint if initialized else {},
|
||||
action(
|
||||
"Unseal by prompt",
|
||||
"Provide threshold shares interactively. Never put shares on the command line.",
|
||||
"kubectl exec -it -n openbao openbao-0 -- bao operator unseal",
|
||||
direct_taint,
|
||||
),
|
||||
add_taint(
|
||||
{
|
||||
"name": "Start unseal-key rotation",
|
||||
"description": "Generate a new 3-share, threshold-2 Shamir split after compromise or planned migration.",
|
||||
"status": rotate_status,
|
||||
"status_reason": rotate_reason,
|
||||
"command": "kubectl exec -it -n openbao openbao-0 -- bao operator rotate-keys -init -key-shares=3 -key-threshold=2",
|
||||
},
|
||||
openbao_downstream_taint if trial_exposed and not response_complete else {},
|
||||
action(
|
||||
"bao audit list",
|
||||
"List OpenBao audit devices using a token entered by local hidden prompt.",
|
||||
audit_list_command,
|
||||
downstream_taint,
|
||||
),
|
||||
add_taint(
|
||||
{
|
||||
"name": "Submit current shares for rotation",
|
||||
"description": "Repeat by prompt until the required threshold completes. Use the nonce from rotation init.",
|
||||
"status": rotate_status,
|
||||
"status_reason": rotate_reason,
|
||||
"command": "kubectl exec -it -n openbao openbao-0 -- bao operator rotate-keys -nonce=<nonce-from-rotation-init>",
|
||||
},
|
||||
openbao_downstream_taint if trial_exposed and not response_complete else {},
|
||||
action(
|
||||
"bao secrets list",
|
||||
"List enabled OpenBao secrets engines using a token entered by local hidden prompt.",
|
||||
secrets_list_command,
|
||||
downstream_taint,
|
||||
),
|
||||
add_taint(
|
||||
{
|
||||
"name": "Cancel key rotation",
|
||||
"description": "Abort a started rotation if the nonce, share handling, or ceremony context is wrong.",
|
||||
"status": "todo" if initialized and not keys_rotated else "blocked",
|
||||
"status_reason": "Available while a rotation is in progress." if initialized and not keys_rotated else "No active rotation expected.",
|
||||
"command": "kubectl exec -it -n openbao openbao-0 -- bao operator rotate-keys -cancel",
|
||||
},
|
||||
openbao_downstream_taint if trial_exposed and not response_complete else {},
|
||||
action(
|
||||
"bao auth list",
|
||||
"List enabled OpenBao auth methods using a token entered by local hidden prompt.",
|
||||
auth_list_command,
|
||||
downstream_taint,
|
||||
),
|
||||
add_taint(
|
||||
{
|
||||
"name": "Record compromise response complete",
|
||||
"description": "Non-secret metadata checkbox after exposed material is rotated or the trial environment was reset.",
|
||||
"status": response_status,
|
||||
"status_reason": response_reason,
|
||||
"command": "Use the checkbox: Compromise response complete",
|
||||
},
|
||||
openbao_downstream_taint if trial_exposed and not response_complete else {},
|
||||
action(
|
||||
"Start unseal-key rotation",
|
||||
"Generate a new 3-share, threshold-2 Shamir split after compromise or planned migration.",
|
||||
"kubectl exec -it -n openbao openbao-0 -- bao operator rotate-keys -init -key-shares=3 -key-threshold=2",
|
||||
compromise_taint,
|
||||
),
|
||||
add_taint(
|
||||
{
|
||||
"name": "Emergency seal OpenBao",
|
||||
"description": "Prompt locally for an OpenBao token and seal Railiance OpenBao without placing the token on the command line.",
|
||||
"status": lockdown_status,
|
||||
"status_reason": lockdown_reason,
|
||||
"command": seal_command,
|
||||
},
|
||||
openbao_downstream_taint if initialized else {},
|
||||
action(
|
||||
"Submit current shares for rotation",
|
||||
"Repeat by prompt until the required threshold completes. Use the nonce from rotation init.",
|
||||
"kubectl exec -it -n openbao openbao-0 -- bao operator rotate-keys -nonce=<nonce-from-rotation-init>",
|
||||
compromise_taint,
|
||||
),
|
||||
add_taint(
|
||||
{
|
||||
"name": "Confirm sealed status",
|
||||
"description": "Check that Railiance OpenBao reports Sealed true after an emergency seal.",
|
||||
"status": "todo" if initialized else "blocked",
|
||||
"status_reason": "Run after emergency seal; expect Sealed true." if initialized else "OpenBao must be initialized before status confirms lock-down.",
|
||||
"command": "kubectl exec -n openbao openbao-0 -- bao status",
|
||||
},
|
||||
openbao_downstream_taint if initialized else {},
|
||||
action(
|
||||
"Cancel key rotation",
|
||||
"Abort a started rotation if the nonce, share handling, or ceremony context is wrong.",
|
||||
"kubectl exec -it -n openbao openbao-0 -- bao operator rotate-keys -cancel",
|
||||
compromise_taint,
|
||||
),
|
||||
add_taint(
|
||||
{
|
||||
"name": "Record emergency lock-down drill",
|
||||
"description": "Non-secret metadata checkbox after an emergency seal drill or real lock-down is confirmed.",
|
||||
"status": lockdown_status,
|
||||
"status_reason": lockdown_reason,
|
||||
"command": "Use the checkbox: Emergency lock-down drill recorded",
|
||||
},
|
||||
openbao_downstream_taint if initialized else {},
|
||||
action(
|
||||
"Emergency seal OpenBao",
|
||||
"Prompt locally for an OpenBao token and seal Railiance OpenBao without placing the token on the command line.",
|
||||
seal_command,
|
||||
downstream_taint,
|
||||
),
|
||||
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,
|
||||
action(
|
||||
"Confirm sealed status",
|
||||
"Check that Railiance OpenBao reports Sealed true after an emergency seal.",
|
||||
openbao_status_command,
|
||||
downstream_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,
|
||||
action(
|
||||
"Prepare restore drill workspace",
|
||||
"Create a local restricted directory for temporary snapshot evidence.",
|
||||
snapshot_workspace_command,
|
||||
downstream_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,
|
||||
action(
|
||||
"Create encrypted-restore snapshot source",
|
||||
"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.",
|
||||
snapshot_command,
|
||||
downstream_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,
|
||||
action(
|
||||
"Encrypt restore snapshot",
|
||||
"Encrypt the Raft snapshot to the custodian age recipient and remove the local plaintext snapshot. Replace <age-recipient> if no recipient is recorded.",
|
||||
encrypt_snapshot_command,
|
||||
downstream_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,
|
||||
action(
|
||||
"Run isolated restore proof",
|
||||
"Checklist for proving the snapshot can restore into an isolated OpenBao instance before live secrets move in.",
|
||||
isolated_restore_command,
|
||||
downstream_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,
|
||||
action(
|
||||
"Run post-restore readiness check",
|
||||
"Re-run the Railiance post-unseal checks after restore evidence has been captured.",
|
||||
"make -C ../railiance-platform openbao-verify-post-unseal",
|
||||
downstream_taint,
|
||||
),
|
||||
]
|
||||
|
||||
@@ -1689,7 +1557,6 @@ def section_gate_payloads(data: dict[str, Any]) -> list[dict[str, str]]:
|
||||
role_ok = all(row["state"] != "nil" for row in role_rows[:5])
|
||||
subsystem_rows = subsystem_payloads(data)
|
||||
integration_rows = integration_payloads(data)
|
||||
runbook_rows = runbook_payloads(data)
|
||||
artifact_rows = artifact_payloads(data)
|
||||
return [
|
||||
{
|
||||
@@ -1725,8 +1592,8 @@ def section_gate_payloads(data: dict[str, Any]) -> list[dict[str, str]]:
|
||||
{
|
||||
"key": "runbooks",
|
||||
"name": "Usecases & Runbooks",
|
||||
"status": "ok" if all(row["state"] in {"done", "blocked"} for row in runbook_rows) else "set",
|
||||
"reason": "Runbook states are recorded." if all(row["state"] in {"done", "blocked"} for row in runbook_rows) else "Review active runbooks and record non-secret outcomes.",
|
||||
"status": "ok",
|
||||
"reason": "Reusable actions and runbook templates are available; execution state is tracked by Integration & Tests and explicit confirmations.",
|
||||
},
|
||||
{
|
||||
"key": "terminology",
|
||||
@@ -2268,6 +2135,7 @@ def ui_html() -> str:
|
||||
.state.todo { background: var(--warn); }
|
||||
.state.err { background: var(--bad); }
|
||||
.state.blocked { background: var(--bad); }
|
||||
.state.template { background: #f1eee5; }
|
||||
.role-chip {
|
||||
display: inline-flex;
|
||||
max-width: 100%;
|
||||
@@ -2553,7 +2421,7 @@ def ui_html() -> str:
|
||||
<details class="panel workflow-section" data-section="integrations" open>
|
||||
<summary><span class="summary-title">4. Integration & Tests</span><span class="state nil" data-section-state="integrations">nil</span></summary>
|
||||
<div class="section-gate" data-section-gate="integrations">Loading integration gate.</div>
|
||||
<p class="notice">This section connects the subsystems and shows every console command as a copyable block. Commands still run outside this browser so secret output never enters the control surface.</p>
|
||||
<p class="notice">This section tracks stateful integration runbooks and gates. Status belongs to these tasks; reusable command-only actions live below in Usecases & Runbooks.</p>
|
||||
<div id="integrations-records" class="record-list"></div>
|
||||
<div class="inline-actions">
|
||||
<a class="button-link" href="/oidc/start" target="_blank" rel="noreferrer" title="Start the bootstrap-console OIDC authorization flow through KeyCape.">Start OIDC login check</a>
|
||||
@@ -2580,20 +2448,6 @@ def ui_html() -> str:
|
||||
<div id="command-list" class="command-list"></div>
|
||||
</details>
|
||||
|
||||
<details class="panel workflow-section" data-section="runbooks" open>
|
||||
<summary><span class="summary-title">6. Usecases & Runbooks</span><span class="state nil" data-section-state="runbooks">nil</span></summary>
|
||||
<div class="section-gate" data-section-gate="runbooks">Loading runbook gate.</div>
|
||||
<p class="notice">Use these routines when the ceremony path changes, trial secrets are exposed, or custody material must be regenerated. The UI records only non-secret outcomes.</p>
|
||||
<div id="runbooks-records" class="record-list"></div>
|
||||
<div class="choice-list">
|
||||
<label class="choice"><input id="openbao_trial_material_exposed" type="checkbox"><span><strong>Trial key material exposed</strong><span>Init output, unseal shares, or root-token material escaped the custody boundary during a trial.</span></span></label>
|
||||
<label class="choice"><input id="openbao_compromise_response_complete" type="checkbox"><span><strong>Compromise response complete</strong><span>Exposed material was rotated or the trial environment was reset. No secret values are recorded here.</span></span></label>
|
||||
<label class="choice"><input id="openbao_unseal_keys_rotated" type="checkbox"><span><strong>New unseal keys generated</strong><span>OpenBao generated replacement unseal shares under the current runbook.</span></span></label>
|
||||
<label class="choice"><input id="openbao_emergency_lockdown_drilled" type="checkbox"><span><strong>Emergency lock-down drill recorded</strong><span>Railiance OpenBao was sealed and status-confirmed during a drill or real lock-down. No token or share is recorded here.</span></span></label>
|
||||
</div>
|
||||
<div id="runbook-command-list" class="command-list"></div>
|
||||
</details>
|
||||
|
||||
<details class="panel workflow-section" data-section="artifacts" open>
|
||||
<summary><span class="summary-title">5. Artefacts & Locations</span><span class="state nil" data-section-state="artifacts">nil</span></summary>
|
||||
<div class="section-gate" data-section-gate="artifacts">Loading artefact gate.</div>
|
||||
@@ -2622,6 +2476,20 @@ def ui_html() -> str:
|
||||
</div>
|
||||
</details>
|
||||
|
||||
<details class="panel workflow-section" data-section="runbooks" open>
|
||||
<summary><span class="summary-title">6. Usecases & Runbooks</span><span class="state nil" data-section-state="runbooks">nil</span></summary>
|
||||
<div class="section-gate" data-section-gate="runbooks">Loading runbook gate.</div>
|
||||
<p class="notice">This section contains reusable actions and runbook templates. Action cards are copyable command references without task status; runbook task state belongs to Integration & Tests or to the explicit confirmation gates.</p>
|
||||
<div id="runbooks-records" class="record-list"></div>
|
||||
<div class="choice-list">
|
||||
<label class="choice"><input id="openbao_trial_material_exposed" type="checkbox"><span><strong>Trial key material exposed</strong><span>Init output, unseal shares, or root-token material escaped the custody boundary during a trial.</span></span></label>
|
||||
<label class="choice"><input id="openbao_compromise_response_complete" type="checkbox"><span><strong>Compromise response complete</strong><span>Exposed material was rotated or the trial environment was reset. No secret values are recorded here.</span></span></label>
|
||||
<label class="choice"><input id="openbao_unseal_keys_rotated" type="checkbox"><span><strong>New unseal keys generated</strong><span>OpenBao generated replacement unseal shares under the current runbook.</span></span></label>
|
||||
<label class="choice"><input id="openbao_emergency_lockdown_drilled" type="checkbox"><span><strong>Emergency lock-down drill recorded</strong><span>Railiance OpenBao was sealed and status-confirmed during a drill or real lock-down. No token or share is recorded here.</span></span></label>
|
||||
</div>
|
||||
<div id="runbook-command-list" class="command-list"></div>
|
||||
</details>
|
||||
|
||||
<details class="panel workflow-section" data-section="terminology" open>
|
||||
<summary><span class="summary-title">7. Terminology & Patterns</span><span class="state nil" data-section-state="terminology">nil</span></summary>
|
||||
<div class="section-gate" data-section-gate="terminology">Loading terminology gate.</div>
|
||||
@@ -2842,10 +2710,13 @@ def ui_html() -> str:
|
||||
const description = document.createElement("div");
|
||||
description.className = "record-description";
|
||||
description.textContent = item.description;
|
||||
const statusReason = document.createElement("div");
|
||||
statusReason.className = "record-description";
|
||||
statusReason.textContent = item.status_reason || "";
|
||||
title.append(name, description, statusReason);
|
||||
title.append(name, description);
|
||||
if (item.status_reason) {
|
||||
const statusReason = document.createElement("div");
|
||||
statusReason.className = "record-description";
|
||||
statusReason.textContent = item.status_reason;
|
||||
title.append(statusReason);
|
||||
}
|
||||
const taintNote = makeTaintNote(item);
|
||||
if (taintNote) title.append(taintNote);
|
||||
|
||||
@@ -2857,7 +2728,8 @@ def ui_html() -> str:
|
||||
button.dataset.command = item.command;
|
||||
const commandActions = document.createElement("div");
|
||||
commandActions.className = "inline-actions";
|
||||
commandActions.append(makeStateBadge(item.status), button);
|
||||
if (item.status) commandActions.append(makeStateBadge(item.status));
|
||||
commandActions.append(button);
|
||||
head.append(title, commandActions);
|
||||
|
||||
const code = document.createElement("code");
|
||||
|
||||
Reference in New Issue
Block a user