net-kingdom/tools/bootstrap-recovery
tegwick a1939a7d06
All checks were successful
CI Smoke / host-smoke (push) Successful in 0s
CI Smoke / container-smoke (push) Successful in 1s
Prepare bounded off-host privacyIDEA recovery drill
Assistant: codex
Assistant-Model: gpt-6-astra
Assistant-Session: 01a13eab-1e6a-7b33-9c37-372e90ada3a2
2026-10-16 00:09:13 +02:00
..
check-privacyidea-database.py Prepare bounded off-host privacyIDEA recovery drill 2026-10-16 00:09:13 +02:00
fetch-privacyidea-backup.py Prepare bounded off-host privacyIDEA recovery drill 2026-10-16 00:09:13 +02:00
inventory-scaleway.py Inventory off-host recovery assets through existing bounded backup routes 2026-10-15 23:58:41 +02:00
inventory-storage-share.py Prepare bounded off-host privacyIDEA recovery drill 2026-10-16 00:09:13 +02:00
README.md Prepare bounded off-host privacyIDEA recovery drill 2026-10-16 00:09:13 +02:00
verify-bundle.py Harden remaining bootstrap custody callers and prepare isolated recovery 2026-10-15 22:57:14 +02:00

Bootstrap recovery transport check

Owner work: NK-WP-0049. Follow the exact recovery ceremony.

verify-bundle.py validates a digest-bound age-encrypted secrets/ tar archive using an explicit private temporary key and registered keys/age.pub. It checks an exact required-file list, unrelated wrong-key refusal, safe isolated file publication/readback and staging removal. No service or cluster is contacted.

It refuses links, special/duplicate/unreviewed entries, oversized content, private age keys in the bundle, wrong digest/recipient and existing receipt destinations. Only a closed metadata receipt leaves the process. Current service credentials, independent/off-host custody, production acceptance and revocation remain separate owner evidence. Same-UID/process-memory isolation and forensic secure erasure are not provided by this local checker.

Tests use real age encryption/decryption with disposable keys and malicious archive fixtures, never production credentials:

python3 -m pytest -q tests/test_bootstrap_recovery_transport.py

inventory-storage-share.py is a silent read-only child of the existing attended Platform Backup-account procedure. It checks the caller's OIDC/admin scope, reuses the owner custody accessor, and exports only bounded DAV names and sizes. Warden revokes and cleans up the session. It never reads an age key or object content and contains provider errors/redirects/proxies.

inventory-scaleway.py lists bounded metadata in the fixed backup bucket/prefix using the existing scoped runtime delivery and pinned primary cluster. It uses neither the bootstrap API key nor object GET/write/delete operations. Run through the already admitted caller with cached boto3 1.40.18; it emits only its safe receipt. Both inventories explicitly state their bounds and cannot prove asset absence outside them, ciphertext integrity, decryption or native recovery.

fetch-privacyidea-backup.py retrieves only the fixed reviewed PI ciphertext under the same attended Platform Backup-account procedure. Strong ETag binding, exact length, digest and private no-overwrite output are required. It reads no age key. check-privacyidea-database.py then runs through temporary human custody, checks the transfer lineage/digest and recipient, tests wrong-key refusal and restores the decrypted custom-format dump into pinned local PostgreSQL with no network, ports or host data mounts. Only three fixed table counts are exported. It removes the disposable database and plaintext and records cleanup. It does not prove token decryption, audit signing continuity or full identity recovery. See the exact prepared command in the ceremony, rather than inventing new inputs.

NK49_RUN_DISPOSABLE_POSTGRES_TEST=1 python3 -m pytest -q \
  tests/test_privacyidea_offhost_recovery.py \
  tests/test_storage_share_inventory.py tests/test_scaleway_backup_inventory.py