diff --git a/bin/railiance b/bin/railiance index 1fabd75..a6daf9b 100755 --- a/bin/railiance +++ b/bin/railiance @@ -30,6 +30,7 @@ Commands: seed-local Run the seed script on this machine checklist Pre-VM checklist backup Backup postgres + config to Nextcloud (age-encrypted) + identity-recovery Verify an independently retrieved NetKingdom identity bundle preflight Pre-migration safety gate (must pass before cluster work) help Show this help EOF @@ -74,6 +75,7 @@ Rent-a-VM Checklist CK ;; next) cat "$ROOT/QUICKSTART.md" ;; + identity-recovery) exec bash "$ROOT/tools/cmd/railiance-identity-recovery" "$@" ;; backup) exec railiance-backup "$@" ;; preflight) exec railiance-preflight "$@" ;; *) echo "Unknown command: $cmd" >&2; usage; exit 2 ;; diff --git a/docs/backup-restore.md b/docs/backup-restore.md index 2c2c24d..132bfb7 100644 --- a/docs/backup-restore.md +++ b/docs/backup-restore.md @@ -1,5 +1,9 @@ # Backup & Restore +For NetKingdom identity keys, directory data and the linked MFA database, use +[Bootstrap from an identity backup](identity-recovery.md). The workstation +backup procedure below covers a different asset set. + Covers the current single-server development environment. This is the safety net that must be operational before any infrastructure migration work begins. diff --git a/docs/identity-recovery.md b/docs/identity-recovery.md new file mode 100644 index 0000000..456a561 --- /dev/null +++ b/docs/identity-recovery.md @@ -0,0 +1,23 @@ +# Bootstrap from an identity backup + +Use this handoff when recovering an existing Railiance identity, before introducing new issuer or MFA keys. `railiance-bootstrap` sequences recovery; NetKingdom owns identity capture and acceptance, S1/S2 own the replacement host/cluster and S3 owns database/custody service recovery. There is no automatic bare-VM production restore. + +1. Independently obtain the reviewed repositories/toolchain and the `railiance-backup` age key from offline/password-safe custody. Do not depend on the failed SSO or OpenBao instance to obtain these. The key stays in the operator's hidden terminal. +2. Retrieve the exact encrypted `net-kingdom-identity-*.tar.age` generation and safe transfer receipt from Storage Share `Backup/railiance-backups/net-kingdom-identity/`. The initial implementation is pending owner admission and first full bundle; existing privacyIDEA database-only dumps do not include service keys. Runtime publisher/retention shares are not recovery authority. During a healthy attended drill, NetKingdom `retrieve-identity.py` binds an independent Backup-account download by strong ETag/size/SHA256. That helper currently uses a healthy OpenBao custody path: during total custody loss, use independently held provider access to download and obtain an owner-reviewed transfer receipt before verification. That offline provider adapter is not implemented here. +3. Follow the exact NetKingdom [recovery ceremony](../../net-kingdom/docs/bootstrap-recovery-ceremony.md). On a healthy workstation with age and Docker, invoke the bootstrap handoff through the hidden-key wrapper: + +```bash +../net-kingdom/sso-mfa/bootstrap/sops-custody-unlock.sh \ + --expected-recipient age1zvryunvjhvpkmasskauga2heeg0ztnte9ymgppvjge36ekumk50syr3tsz \ + --prompt -- bash bin/railiance identity-recovery \ + --transfer-receipt /PRIVATE/independent-transfer.json \ + --receipt /PRIVATE/new-recovery-result.json +``` + +Paths are operator-selected private files; never paste keys or restored values into chat/logs. The command delegates to the reviewed sibling NetKingdom verifier. `NETKINGDOM_RECOVERY_ROOT` selects an explicitly reviewed alternate checkout. Verification decrypts privately, rejects a wrong key, checks the encrypted manifest/SQLite integrity/original RSA pairs, restores PostgreSQL in a pinned networkless disposable container and verifies cleanup. Its safe receipt does not contain restored credentials. A successful archive receipt is not full-service recovery. + +4. Provision an isolated replacement through S1 → S2 → S3, with outbound notification/provider writes disabled and fresh host/volume bindings reviewed by the owners. Production-target UIDs in the backup capture profile deliberately prevent capture tools from silently operating on a replacement cluster. Do not rebind them merely to make a check pass. +5. Have NetKingdom/service owners restore original directory/storage/encryption/signing/audit material into the isolated environment through a separately reviewed restore procedure. Prove existing-user authentication, issuer/JWKS/policy/client continuity, existing-token decryption/MFA, historical/new audit signatures and negative cases. The archive verifier deletes its plaintext; it is not a production restore/import command. Keep restored identities and outbound effects isolated until owner acceptance, then hand operation to the ordinary layers. +6. Retain the known-good independently recovered generation, record the exact artifact/hash and owner acceptance, retire temporary custody and verify cleanup. New backup grants and daily timer activation are separate owner-reviewed steps in the NetKingdom ceremony. + +Discovery: `capability.security.bootstrap-recovery` in the owning NetKingdom registry, related to `capability.railiance.bootstrap-sequencing`. Search reuse-surface for `identity backup`, `restore`, `privacyidea` or `disaster-recovery`. Neither a registry entry nor this dispatcher grants credentials or certifies an unattended disaster rebuild. diff --git a/registry/capabilities/capability.railiance.bootstrap-sequencing.md b/registry/capabilities/capability.railiance.bootstrap-sequencing.md index cb34eeb..e21095b 100644 --- a/registry/capabilities/capability.railiance.bootstrap-sequencing.md +++ b/registry/capabilities/capability.railiance.bootstrap-sequencing.md @@ -49,14 +49,18 @@ availability: target_level: A0 current_artifacts: - SCOPE.md + - docs/identity-recovery.md + - tools/cmd/railiance-identity-recovery consumption_modes: - informational relations: related_to: - capability.security.iam-tooling-suite + - capability.security.bootstrap-recovery evidence: documentation: - SCOPE.md + - docs/identity-recovery.md consumer_guidance: recommended_for: - Operator recovers identity, custody or data with independently held recovery material @@ -68,6 +72,9 @@ consumer_guidance: - End-to-end unattended rebuild is not established - 2026-10-14 architecture review estimates operational maturity separately; a registry entry does not authorize execution or establish deployment. + - Identity recovery handoff delegates isolated verification to NetKingdom; offline + provider retrieval and production import remain owner-run recovery steps, not + automated bare-VM restore. --- # Bootstrap sequencing contracts @@ -88,3 +95,5 @@ End-to-end unattended rebuild is not established. - [SCOPE.md](../../SCOPE.md) Assessment: CUST-WP-0081, 2026-10-14. Relations identify interfaces to compose; they do not certify native integration. Existing external evidence levels are retained where present. New entries use conservative C1/R0 until consumer assessment exists. + +Identity recovery handoff: [docs/identity-recovery.md](../../docs/identity-recovery.md). The source dispatcher adds verification only; availability/maturity are not promoted to assert a deployed recovery service. diff --git a/registry/indexes/capabilities.yaml b/registry/indexes/capabilities.yaml index 1034975..d50ec10 100644 --- a/registry/indexes/capabilities.yaml +++ b/registry/indexes/capabilities.yaml @@ -1,10 +1,10 @@ version: 1 -updated: '2026-10-14' +updated: '2026-10-16' domain: helix_forge capabilities: - id: capability.railiance.bootstrap-sequencing name: Bootstrap sequencing contracts - summary: Bare-VM to estate sequence and handoff contract. + summary: Bare-VM sequencing with NetKingdom identity backup recovery handoff. domain: infotech status: draft owner: railiance-bootstrap @@ -12,6 +12,9 @@ capabilities: - security - netkingdom - framework-reuse + - backup + - restore + - disaster-recovery vector: D3 / A0 / C1 / R0 path: registry/capabilities/capability.railiance.bootstrap-sequencing.md consumption_modes: diff --git a/tools/cmd/railiance-identity-recovery b/tools/cmd/railiance-identity-recovery new file mode 100644 index 0000000..4ae3292 --- /dev/null +++ b/tools/cmd/railiance-identity-recovery @@ -0,0 +1,28 @@ +#!/usr/bin/env bash +# Bootstrap handoff to the identity owner's isolated archive verifier. +set -euo pipefail +ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)" +if [[ $# == 0 || "${1:-}" == "--help" || "${1:-}" == "-h" ]]; then + cat <<'EOF' +Usage: bin/railiance identity-recovery --transfer-receipt PATH --receipt NEW_PATH + +Run through net-kingdom/sso-mfa/bootstrap/sops-custody-unlock.sh --prompt +with the independently held railiance-backup age key. Requires an independently +retrieved ciphertext and its safe transfer receipt, age, Docker and the pinned +PostgreSQL image. Default owner checkout: sibling net-kingdom; set +NETKINGDOM_RECOVERY_ROOT to an explicitly reviewed alternative checkout. + +This decrypts only into disposable local storage and verifies the full manifest, +SQLite/key pairs and native PostgreSQL restore. It does not restore production, +contact SSO or prove full identity authentication/audit continuity. +See docs/identity-recovery.md for the bootstrap ordering and custody handoff. +EOF + exit 0 +fi +OWNER="${NETKINGDOM_RECOVERY_ROOT:-${ROOT}/../net-kingdom}" +CHECKER="${OWNER}/tools/bootstrap-recovery/verify-identity.py" +if [[ ! -f "$CHECKER" || ! -f "${OWNER}/tools/bootstrap-recovery/identity-backup-profile.json" ]]; then + echo 'Missing reviewed NetKingdom recovery checkout; see docs/identity-recovery.md.' >&2 + exit 1 +fi +exec python3 "$CHECKER" "$@"