Prepare native isolated directory recovery and offline service images

Assistant: codex
Assistant-Model: gpt-6-astra
Assistant-Session: 01a13eab-1e6a-7b33-9c37-372e90ada3a2
This commit is contained in:
tegwick 2026-10-16 20:33:57 +02:00
parent 31f483966c
commit d5484bb90a
9 changed files with 815 additions and 7 deletions

View file

@ -0,0 +1,57 @@
{
"schema": "netkingdom.isolated-lldap-preparation.v1",
"date": "2026-10-16",
"status": "native_synthetic_verified_owner_run_pending",
"sources": [
{
"path": "tools/bootstrap-recovery/isolated-lldap.py",
"sha256": "35bfa8411186ad936a199bd450c7e18c2ad51059301a6db9650e6bd055ab1b81"
},
{
"path": "tools/bootstrap-recovery/run-isolated-lldap.sh",
"sha256": "f0b9cecf92482b0af10a6e304c66677dc4390b6a4560826700a659723af5e2fc"
},
{
"path": "tests/test_isolated_lldap_recovery.py",
"sha256": "729791f7271da617969255e782351f134b807500394f3522db6ae00d4bd4dc77"
},
{
"path": "docs/identity-service-restore-packet.md",
"sha256": "2c30f87cbcd836d93177503932f82824a3bd9a0a6683aec07987d3e740353d44"
}
],
"target": {
"engine_id": "74f93783-6cef-43a8-a3c4-f62586cd3bc1",
"engine_name": "bnt-lap001",
"linux_local_unix_endpoint_only": true
},
"tests": {
"focused_command": "NK49_RUN_ISOLATED_LLDAP_TEST=1 python3 -m pytest -q tests/test_isolated_lldap_recovery.py",
"focused_passed": 6,
"failed": 0,
"broader_run_passed": 49,
"broader_run_skipped": 1,
"skip_reason": "separately opted-in PostgreSQL fixture; actual PostgreSQL archive recovery already accepted in T23",
"native_existing_user_and_invalid_credential_result": true,
"native_encrypted_bundle_to_directory_restore": true,
"original_key_missing_refused": true,
"network_none_and_before_import_isolation_guard_verified": true,
"directory_data_preserved_and_container_tmpfs_cleanup_verified": true,
"fixture_signing_secret_generated_per_run": true
},
"credential_route": {
"catalog_id": "net-kingdom-lldap-bind-credential",
"owner": "railiance-platform",
"resolvable_fetch_lane": false,
"use": "owner boundary discovery only; no service credential fetched; actual existing-user input remains private with operator"
},
"knowledge": {
"version": "0.2.6",
"digest": "8d1d6a9d4d07fec7b619618de7dfe2be2254c1790f85f4198c7fe19db9751c02",
"status": "withheld; current local security companion, task card and owner route reviewed directly; orientation only"
},
"actual_backup_native_lldap_authentication_proven": false,
"actual_private_key_or_user_password_received_by_agent": false,
"production_contacted": false,
"other_service_authentication_or_mfa_or_audit_proven": false
}

View file

@ -0,0 +1,51 @@
{
"schema": "netkingdom.identity-recovery-offline-images.v1",
"status": "saved_loaded_inspected",
"observed_at": "2026-10-16T18:19:11.824598+00:00",
"target": {
"engine_id": "74f93783-6cef-43a8-a3c4-f62586cd3bc1",
"engine_name": "bnt-lap001",
"images": [
{
"reference": "docker.io/lldap/lldap@sha256:9e605a66c02514bfcffd1b67cafb1e98d50992216bb2871d7ae44622047dd09d",
"image_id": "sha256:9e605a66c02514bfcffd1b67cafb1e98d50992216bb2871d7ae44622047dd09d"
},
{
"reference": "ghcr.io/gpappsoft/privacyidea-docker@sha256:af7841adad262f129e0c1d4f553af13f21cb2f4dc713533f316cfe43ed0b4473",
"image_id": "sha256:af7841adad262f129e0c1d4f553af13f21cb2f4dc713533f316cfe43ed0b4473"
}
],
"production_contacted": false,
"network_mode": "none",
"host_ports_published": false
},
"archive_path": "/tmp/nk49-service-image-cache-vxokyfoa/identity-images.tar",
"archive_bytes": 347521536,
"archive_sha256": "e61124c5b4473bf49671e254ad83a8829a046c72e8d46582dad6f6594fecd434",
"images": [
{
"reference": "docker.io/lldap/lldap@sha256:9e605a66c02514bfcffd1b67cafb1e98d50992216bb2871d7ae44622047dd09d",
"image_id": "sha256:9e605a66c02514bfcffd1b67cafb1e98d50992216bb2871d7ae44622047dd09d"
},
{
"reference": "ghcr.io/gpappsoft/privacyidea-docker@sha256:af7841adad262f129e0c1d4f553af13f21cb2f4dc713533f316cfe43ed0b4473",
"image_id": "sha256:af7841adad262f129e0c1d4f553af13f21cb2f4dc713533f316cfe43ed0b4473"
},
{
"reference": "postgres@sha256:ff23cdce56cac62ada6f66013e1a50864c0abbe79d132d40b6e05bd80f378a70",
"image_id": "sha256:ff23cdce56cac62ada6f66013e1a50864c0abbe79d132d40b6e05bd80f378a70"
},
{
"reference": "docker.io/authelia/authelia@sha256:bd97cff4fcbf715b5ff1f9ae286afbe6033afce385302520b0368122d43a6f54",
"image_id": "sha256:bd97cff4fcbf715b5ff1f9ae286afbe6033afce385302520b0368122d43a6f54"
},
{
"reference": "forgejo.coulomb.social/coulomb/key-cape@sha256:cdec9dd7c515f7e0a6169fc3fa560ee2cc47bf40d899755dec808c362f5ce010",
"image_id": "sha256:cdec9dd7c515f7e0a6169fc3fa560ee2cc47bf40d899755dec808c362f5ce010"
}
],
"production_registry_required_for_local_drill": false,
"offhost_image_escrow_proven": false,
"source_archive_image_lineage_proven": false,
"service_custody_or_age_key_supplied_to_image_cache": false
}

View file

@ -1,6 +1,7 @@
# Isolated identity service restore packet
NK-WP-0049-T15. Prepared 2026-10-16; **draft, not admitted or executed**.
NK-WP-0049-T15. Prepared 2026-10-16. **LLDAP stage ready for the private
operator run; remaining service stages are draft and unexecuted.**
Accountable preparer: codex. Execution/acceptance: Railiance Platform and the
LLDAP, Authelia, KeyCape and privacyIDEA service owners.
@ -15,7 +16,15 @@ needs equivalent provenance and archive checks before replacing this input.
## Targets and image admission still required
No execution target has been admitted. Select a disposable host/context and
The bounded LLDAP stage below selects the local Linux Docker engine
`bnt-lap001`, ID `74f93783-6cef-43a8-a3c4-f62586cd3bc1`; the executor refuses a
different engine or a remote Docker endpoint. All five exact image references
have been saved, loaded and inspected on that workstation; receipt:
`docs/evidence/2026-10-16-identity-outage-recovery/offline-service-images.json`.
This establishes local image availability without production registry access,
not an off-host image escrow or exact historical mutable-tag provenance.
No broader execution target has been admitted. Select a disposable host/context and
record its immutable identity, operator, private endpoints, maximum lifetime,
resource limits and exact owned cleanup inventory. Never select the production
context or reuse live PVCs. Use fresh private storage; no production host mounts,
@ -66,6 +75,51 @@ export literal environment values, Secret payloads or arbitrary configs.
plaintext/key files. Confirm absence and production resources unchanged;
retain sanitized receipts, original ciphertext and independently held keys.
## Ready owner step: isolated LLDAP recovery
Execute in your own terminal, using an existing account and the password valid
at the backup's capture time. No password belongs in the arguments:
```bash
bash tools/bootstrap-recovery/run-isolated-lldap.sh EXISTING_USER \
/tmp/nk49-offline-handoff-1X660a5t/transfer.json
```
Replace `EXISTING_USER` with the selected existing username. The command asks
privately for the independently held `railiance-backup` age key and then the
account password. It rechecks ciphertext size/hash, recipient and every archive
file before importing anything. Decrypted staging is in a private Linux tmpfs;
the key helper removes its temporary file at exit.
The executor creates only uniquely named `nk49-lldap-*` containers on the fixed
local engine. LLDAP has `--network none`, no published ports, read-only root,
all capabilities dropped, no added privileges, user1000, 256 MiB memory/one CPU
and private tmpfs for data/config. The client shares only that loopback network
namespace and verifies there is no external interface or route. Container
isolation is inspected before private import. No Kubernetes/OpenBao/SSO API,
production directory endpoint or provider grant is used. Containers have a
30-minute holding lifetime and are removed on exit; plaintext and containers
are checked for cleanup. A forced host/process termination can still require
owner reconciliation of the named resources.
The original server key/seed, JWT secret and directory data are preserved.
Admin-password reset, private-key replacement, SMTP and LDAPS listeners are
disabled. The private account password travels only through memory/stdin; it is
not placed in Docker arguments, environment values, logs or evidence. A native
LDAP bind must pass, and an explicit LDAP invalid-credentials result must reject
the wrong password. After a graceful stop, users/groups/memberships and available
attribute tables are compared with the original snapshot. Only equality and
aggregate counts leave the process.
The actual-image tests use disposable synthetic accounts, a real encrypted
bundle and the same restore executor. They cover positive and wrong-credential
paths, isolation, original-key refusal, directory preservation and cleanup.
They are not the real-backup proof: T16 remains waiting for the owner's private
run and safe receipt. Return only the outcome and evidence directory.
This step does not restore Authelia, KeyCape or privacyIDEA, and does not prove
current production password validity, MFA or audit continuity.
## Acceptance matrix
| Task / owner lane | Positive check | Negative check | Safe evidence |