Files
net-kingdom/tools/security-bootstrap-console/README.md

9.1 KiB

Security Bootstrap Console

Local console and localhost web UI for the NetKingdom guided security bootstrap experience.

The console prints trust stage, gates, checklists, non-secret templates, and can write an explicit custody-mode approval record. It does not collect secret values and refuses live OpenBao initialization.

Run:

python3 tools/security-bootstrap-console/security_bootstrap_console.py status

Print the king credential kit checklist:

python3 tools/security-bootstrap-console/security_bootstrap_console.py king-kit

Validate non-secret kit metadata:

python3 tools/security-bootstrap-console/security_bootstrap_console.py \
  --metadata /tmp/security-bootstrap.json \
  validate-king-kit

Approve custody mode from the CLI:

python3 tools/security-bootstrap-console/security_bootstrap_console.py \
  --metadata /tmp/security-bootstrap.json \
  approve-custody-mode \
  --mode temporary-single-king \
  --mfa-enrolled-confirmed \
  --mfa-enrollment-source identity-provider \
  --recovery-confirmed \
  --custody-packet-prepared

The command asks for the phrase approve custody mode unless --yes is passed. two-of-three-planned can be recorded in metadata but cannot approve live OpenBao init.

For TOTP, use the QR code or setup key from the identity provider or other authority that will verify the login. This tool records only the non-secret enrollment confirmation and source.

Recovery material means the operator can regain control of the platform-root credential and encrypted bootstrap bundle without this UI storing any values: the platform-root password-safe entry, MFA recovery or re-enrollment path, custodian age private-key location, encrypted bootstrap bundle location, and notification/setup contact are all known.

The custody packet is separate. It is the offline OpenBao ceremony envelope: selected custody strategy, recovery-material references, init checklist, unseal-share assignment slots, root-token disposition plan, and signature/date. Select the custody strategy first, prepare recovery material and the custody packet for that strategy, then approve the strategy. Only after that approval should the OpenBao preflight/init sequence begin.

Secret capture is an architecture gate, not a user checkbox. The control surface must not request or store passwords, OTP seeds, recovery codes, private keys, OpenBao root tokens, or unseal shares. The UI reports this automatically from local metadata and plaintext bootstrap-secret presence.

Serve the local approval UI:

python3 tools/security-bootstrap-console/security_bootstrap_console.py \
  --metadata /tmp/security-bootstrap.json \
  web-ui

Open http://127.0.0.1:8765.

The web UI is structured as:

  1. Roles & Responsibilities - global bootstrap roles with designated operator emails.
  2. Subsystems & Scope - installation and initial access for LLDAP, privacyIDEA, KeyCape, the custodian age envelope, and Railiance OpenBao.
  3. Integration & Tests - OIDC and OpenBao preflight checks, with every operator command shown as a copyable console block.
  4. Usecases & Runbooks - guided routines for key-material compromise, trial-output exposure, and generating replacement unseal keys.
  5. Artefacts & Locations - final non-secret overview of established artefacts and where to find their custody references.

Role, subsystem, integration, and artefact records use the same fields: name, description, subsystem, responsibility, location, and state. States are nil, set, err, and ok. Role chips expose the designated email as hover text.

Responsibility assignments are edited through the Change responsibilities foldout. Editing enables local Save/Cancel actions; Save writes only non-secret role metadata and Cancel restores the last loaded values. Command cards use blocked, todo, redo, and done to show whether an operator command is available, needs to be run, should be repeated after a state change, or has already succeeded.

The Key material compromised runbook is also useful for trial ceremonies: mark the trial output as exposed, stop treating the generated unseal shares or root token as production material, then either rotate unseal keys after unseal or reset the trial environment before any live secrets are migrated.

The UI is a guide and approval surface, not the identity provider. Current lightweight-mode credential placement is:

  • bootstrap bundle encryption: custodian age public key;
  • user record: LLDAP (https://lldap.coulomb.social);
  • MFA enrollment and QR/setup key: privacyIDEA self-service (https://pink-account.coulomb.social);
  • privacyIDEA setup/admin repair: pi-admin at https://pink.coulomb.social;
  • OIDC/IAM Profile token issuer: KeyCape (https://kc.coulomb.social);
  • secret custody and OpenBao admin policies: OpenBao, after the attended ceremony.

The UI opens the external authority in a new browser tab and records only non-secret progress. It does not embed or prefill secret-bearing forms unless a future audited integration is built for that authority.

The custodian age public key is safe to store here and is used as the recipient for encrypted bootstrap bundles. The private age key is not stored here. Record only a non-secret private-key custody reference, such as a password-safe entry label or offline packet label. See docs/security-bootstrap-age-custody.md for the trust model.

LLDAP has no public registration flow. The first user path is:

  1. Log in to https://lldap.coulomb.social as admin.
  2. Retrieve LLDAP_LDAP_USER_PASS from the password safe entry net-kingdom/LLDAP/admin.
  3. Create the dedicated platform-root or king account.
  4. Add it to net-kingdom-admins for the current lightweight path.
  5. Store the new account password only in the password safe/offline custody packet, not in this metadata file.

For OTP enrollment, do not create a separate shadow identity in privacyIDEA if the LLDAP resolver is working. Use pi-admin to verify or repair the privacyIDEA realm, resolver, and self-enrollment policy. Then use platform-root in the self-service portal to generate the QR code or setup key and verify the factor. Admin-assisted token assignment is a fallback only; record it as the MFA enrollment source, but never record the seed, QR code, or recovery codes in this UI.

After doing that, return to the control surface, set account reference platform-root@lldap, check Account created, Admin group assigned, and Password stored, then save progress.

KeyCape does not have a dashboard at its root URL; https://kc.coulomb.social returning 404 is expected. Use https://kc.coulomb.social/.well-known/openid-configuration for issuer discovery or a registered OIDC client to test real login. The bootstrap UI acts as the local netkingdom-bootstrap-console callback at http://127.0.0.1:8876/oidc/callback. Treat that as a login-path check only: it should force LLDAP password auth and privacyIDEA MFA, then return to the local callback page. The callback exchanges the code and shows non-secret claims only; it does not store tokens, OTP values, or passwords. Mark OIDC login verified only for the same identity recorded in the credential section.

If the login-check flow redirects to https://kc.coulomb.social/api/oidc/authorization... and lands on a 404, the KeyCape service is reachable but its browser-facing Authelia redirect config is not yet rolled out. Regenerate keycape-config with sso-mfa/k8s/keycape/create-secrets.sh and restart the KeyCape deployment after confirming authelia.browserBaseURL is https://auth.coulomb.social.

After Authelia password login, KeyCape should show a compact OTP challenge if privacyIDEA reports that MFA is required. Only then should it issue the final OIDC authorization code back to the local callback.

Print a blank offline custody packet template:

python3 tools/security-bootstrap-console/security_bootstrap_console.py custody-packet

Show safe OpenBao preflight commands:

python3 tools/security-bootstrap-console/security_bootstrap_console.py openbao-preflight \
  --railiance-path ../railiance-platform

Run safe OpenBao preflight targets:

python3 tools/security-bootstrap-console/security_bootstrap_console.py openbao-preflight \
  --railiance-path ../railiance-platform \
  --run

This still does not run bao operator init.

OpenBao itself is operated from the Railiance runbook. Public ingress is disabled, so the live ceremony uses Railiance make targets, kubectl exec, or an operator port-forward. The local UI can record non-secret milestones such as preflight passed, initialized/unsealed, root-token disposition, and restore drill passed; it must never record root tokens or unseal shares.

Optional non-secret metadata can be supplied:

python3 tools/security-bootstrap-console/security_bootstrap_console.py metadata-template \
  > /tmp/security-bootstrap.json

python3 tools/security-bootstrap-console/security_bootstrap_console.py \
  --metadata /tmp/security-bootstrap.json \
  status

Do not put passwords, OTP seeds, OpenBao root tokens, unseal shares, recovery codes, private keys, or screenshots of secret output into the metadata file.