generated from coulomb/repo-seed
238 lines
10 KiB
Markdown
238 lines
10 KiB
Markdown
# 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:
|
|
|
|
```bash
|
|
python3 tools/security-bootstrap-console/security_bootstrap_console.py status
|
|
```
|
|
|
|
Print the king credential kit checklist:
|
|
|
|
```bash
|
|
python3 tools/security-bootstrap-console/security_bootstrap_console.py king-kit
|
|
```
|
|
|
|
Validate non-secret kit metadata:
|
|
|
|
```bash
|
|
python3 tools/security-bootstrap-console/security_bootstrap_console.py \
|
|
--metadata .local/security-bootstrap.json \
|
|
validate-king-kit
|
|
```
|
|
|
|
Approve custody mode from the CLI:
|
|
|
|
```bash
|
|
python3 tools/security-bootstrap-console/security_bootstrap_console.py \
|
|
--metadata .local/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:
|
|
|
|
```bash
|
|
make security-bootstrap-ui
|
|
```
|
|
|
|
Open `http://127.0.0.1:8876`.
|
|
|
|
The Make target stores non-secret progress in `.local/security-bootstrap.json`.
|
|
That directory is intentionally ignored by Git so local setup state survives
|
|
UI/server restarts without being committed.
|
|
|
|
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, replacement unseal keys, and OpenBao token
|
|
revocation.
|
|
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 **OpenBao token revocation** runbook includes a self-revoke action for the
|
|
token currently stored in the OpenBao pod token helper and an accessor-based
|
|
revocation action for accidentally disclosed tokens. The accessor path prompts
|
|
inside the pod for a root/sudo-capable OpenBao token and avoids placing token
|
|
values on the local command line.
|
|
|
|
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.
|
|
|
|
If the live privacyIDEA instance has lost the `coulomb` realm, LLDAP resolver,
|
|
or self-service policies, open **Usecases & Runbooks** and copy **Repair
|
|
privacyIDEA realm and self-service**. The action is attended: it prompts for
|
|
the `pi-admin` password and the LLDAP bind/admin password, writes them only to a
|
|
private temporary directory, runs
|
|
`sso-mfa/k8s/privacyidea/repair-realm-live.sh`, removes the temporary files on
|
|
exit, and then runs `sso-mfa/k8s/verify-t06.sh`. The UI does not store either
|
|
password, and TOTP enrollment or re-enrollment remains a human step in
|
|
`https://pink-account.coulomb.social`.
|
|
|
|
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:
|
|
|
|
```bash
|
|
python3 tools/security-bootstrap-console/security_bootstrap_console.py custody-packet
|
|
```
|
|
|
|
Show safe OpenBao preflight commands:
|
|
|
|
```bash
|
|
python3 tools/security-bootstrap-console/security_bootstrap_console.py openbao-preflight \
|
|
--railiance-path ../railiance-platform
|
|
```
|
|
|
|
Run safe OpenBao preflight targets:
|
|
|
|
```bash
|
|
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:
|
|
|
|
```bash
|
|
python3 tools/security-bootstrap-console/security_bootstrap_console.py metadata-template \
|
|
> .local/security-bootstrap.json
|
|
|
|
python3 tools/security-bootstrap-console/security_bootstrap_console.py \
|
|
--metadata .local/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.
|