diff --git a/docs/openbao.md b/docs/openbao.md index 45945d5..680c344 100644 --- a/docs/openbao.md +++ b/docs/openbao.md @@ -272,8 +272,8 @@ Before any live application secrets move into OpenBao: custody. The drill must prove that a fresh OpenBao instance can restore the snapshot, unseal, and read a test secret. Record only non-secret evidence using - `docs/openbao-restore-drill-evidence.example.json` as a template, then - validate it with: + `docs/openbao-restore-drill-evidence.example.json` as a template, replace + every placeholder with real drill evidence, then validate it with: ```bash make openbao-validate-restore-evidence \ @@ -324,8 +324,8 @@ Audit Core archive exists. Emergency seal/unseal drills are disruptive and must only run in an attended window with threshold unseal shares available. Record non-secret drill evidence -using `docs/openbao-emergency-drill-evidence.example.json` as a template, then -validate it with: +using `docs/openbao-emergency-drill-evidence.example.json` as a template, +replace every placeholder with real drill evidence, then validate it with: ```bash make openbao-validate-emergency-evidence \ diff --git a/scripts/openbao-validate-emergency-drill-evidence.sh b/scripts/openbao-validate-emergency-drill-evidence.sh index be5fdfd..8b0c096 100755 --- a/scripts/openbao-validate-emergency-drill-evidence.sh +++ b/scripts/openbao-validate-emergency-drill-evidence.sh @@ -95,6 +95,16 @@ for marker in secret_markers: if marker in encoded: errors.append(f"secret-looking marker present: {marker}") +placeholder_markers = [ + "YYYY-MM-DD", + "example", + "Do not record", + "<", +] +for marker in placeholder_markers: + if marker in encoded: + errors.append(f"template placeholder present: {marker}") + if errors: for error in errors: print(f"[FAIL] {error}", file=sys.stderr) diff --git a/scripts/openbao-validate-restore-evidence.sh b/scripts/openbao-validate-restore-evidence.sh index eb102fc..bcac1b5 100755 --- a/scripts/openbao-validate-restore-evidence.sh +++ b/scripts/openbao-validate-restore-evidence.sh @@ -81,6 +81,9 @@ for key in ("snapshot_sha256", "encrypted_snapshot_sha256"): value = str(data.get(key, "")) if value and not sha_pattern.match(value): errors.append(f"{key} must be a sha256 hex digest, optionally prefixed with sha256:") + digest = value.removeprefix("sha256:").lower() + if digest and len(set(digest)) <= 1: + errors.append(f"{key} must not be a placeholder digest") for key in required_true: if data.get(key) is not True: @@ -100,6 +103,19 @@ for marker in secret_markers: if marker in encoded: errors.append(f"secret-looking marker present: {marker}") +placeholder_markers = [ + "YYYY-MM-DD", + "example", + "operator-local encrypted restore drill workspace", + "approved encrypted custody location", + "disposable cluster, VM, or namespace reference", + "Do not record", + "<", +] +for marker in placeholder_markers: + if marker in encoded: + errors.append(f"template placeholder present: {marker}") + if errors: for error in errors: print(f"[FAIL] {error}", file=sys.stderr) diff --git a/workplans/RAIL-PL-WP-0002-openbao-platform-secrets-service.md b/workplans/RAIL-PL-WP-0002-openbao-platform-secrets-service.md index 3b3b46f..b411029 100644 --- a/workplans/RAIL-PL-WP-0002-openbao-platform-secrets-service.md +++ b/workplans/RAIL-PL-WP-0002-openbao-platform-secrets-service.md @@ -309,6 +309,13 @@ duration, and `no_secret_material_recorded`. The validator does not run the disruptive drill; it only checks the evidence captured after the attended operation. +**2026-06-02:** Hardened both evidence validators so unchanged templates or +obvious placeholder values cannot accidentally satisfy NetKingdom T02. Restore +evidence now rejects placeholder digests and template wording, while emergency +drill evidence rejects template wording. Operators must copy the examples into +local evidence files and replace placeholders with real non-secret drill +evidence before validation can pass. + ### T07 - Cross-Repo Transition Tasks ```task