Assistant: codex Assistant-Model: gpt-6-astra Assistant-Session: 01a13eab-1e6a-7b33-9c37-372e90ada3a2
78 lines
4.6 KiB
Markdown
78 lines
4.6 KiB
Markdown
# Bootstrap recovery transport check
|
|
|
|
Owner work: NK-WP-0049. Follow
|
|
[the exact recovery ceremony](../../docs/bootstrap-recovery-ceremony.md).
|
|
|
|
For an identity/custody outage, start with the
|
|
[Storage Share disaster recovery guide](../../docs/disaster-recovery-storage-share.md).
|
|
`retrieve-identity-offline.py` performs fixed-provider ciphertext retrieval from
|
|
privately entered independent provider access, without OpenBao/SSO. Its source
|
|
receipt pins the object, strong ETag, size and digest; failed downloads are removed.
|
|
`recovery-kit.py` builds an allowlisted standalone tools ZIP and can publish only
|
|
three new versioned guide/ZIP/checksum files beside the backups with exact
|
|
readback. `run-offline-recovery.sh` is the owner's private two-prompt handoff for
|
|
publication, outage-path retrieval and the existing archive recovery check.
|
|
Run secret prompts in the owner's own terminal, never an agent-captured PTY.
|
|
Actual owner publication/readback and outage-path archive recovery passed on
|
|
2026-10-16; see the [published location and receipts](../../docs/storage-share-recovery-publication.md).
|
|
Service restore admission remains in the
|
|
[isolated restore packet](../../docs/identity-service-restore-packet.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
|
|
```
|
|
|
|
|
|
`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.
|
|
|
|
```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
|
|
```
|
|
|
|
`identity-backup-profile.json` prepares missing full service coverage and names
|
|
the exact current workload/PVC/credential dependencies, proposed provider paths
|
|
and remaining implementation/admission gates. It is a proposal, not a new live
|
|
publisher grant. `prepare-identity-coverage.py --receipt NEW_PATH` verifies the
|
|
primary cluster and current deployment/PVC/reference bindings using metadata
|
|
only. It refuses replacement resources, unobserved/unready deployments and new
|
|
unreviewed references. It has no Secret-data, pod-exec, mutation or upload route.
|
|
Its receipt says `prepared_not_admitted`; it cannot prove a backup exists.
|