2026-10-15 22:57:14 +02:00
|
|
|
# Bootstrap recovery transport check
|
|
|
|
|
|
|
|
|
|
Owner work: NK-WP-0049. Follow
|
|
|
|
|
[the exact recovery ceremony](../../docs/bootstrap-recovery-ceremony.md).
|
|
|
|
|
|
|
|
|
|
`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:
|
|
|
|
|
|
|
|
|
|
```bash
|
|
|
|
|
python3 -m pytest -q tests/test_bootstrap_recovery_transport.py
|
|
|
|
|
```
|
2026-10-15 23:58:41 +02:00
|
|
|
|
|
|
|
|
|
|
|
|
|
`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.
|
2026-10-16 00:09:13 +02:00
|
|
|
|
|
|
|
|
`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.
|
|
|
|
|
|
|
|
|
|
```bash
|
|
|
|
|
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
|
|
|
|
|
```
|