generated from coulomb/repo-seed
- sso-mfa/bootstrap/gen-secrets.sh: generates all pre-cluster secrets (PI_SECRET_KEY, PI_PEPPER, DB passwords, Keycloak admin, break-glass) into a structured secrets/ directory; prints summary with truncated values. PI_ENCFILE deferred — must be generated inside the privacyIDEA container. - sso-mfa/bootstrap/pack-bundle.sh: age-encrypts the secrets directory into an offsite ops bundle. - sso-mfa/bootstrap/README.md: KeePassXC group/entry structure, full workflow (generate → KeePassXC → bundle → shred → PI_ENCFILE post-deploy). - .gitignore: add sso-mfa/bootstrap/secrets/, *.age, *.kdbx. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
118 lines
3.9 KiB
Markdown
118 lines
3.9 KiB
Markdown
# Phase 0a — Pre-cluster Secret Bootstrap
|
|
|
|
This directory contains tooling for the KeePassXC bootstrap phase (T01 Phase 0a).
|
|
No secrets are stored here — only scripts and documentation.
|
|
|
|
## Why KeePassXC first?
|
|
|
|
The single-credential bootstrap principle (Decision D1): one master password
|
|
unlocks the KeePassXC vault; all other credentials are generated inside it.
|
|
KeePassXC is the pre-cluster source of truth. After the K3s cluster is running,
|
|
secrets migrate into HashiCorp Vault (T01 Phase 0b) and KeePassXC becomes the
|
|
break-glass / dev-local backup.
|
|
|
|
## KeePassXC database structure
|
|
|
|
Create a new `.kdbx` database. Use a strong master password stored in your
|
|
personal password manager (Bitwarden, 1Password, etc.).
|
|
|
|
Recommended group structure:
|
|
|
|
```
|
|
net-kingdom/
|
|
├── privacyIDEA/
|
|
│ ├── pi-admin (username: pi-admin, password: PI_ADMIN_PASSWORD)
|
|
│ ├── database (username: privacyidea, password: PI_DB_PASSWORD)
|
|
│ ├── SECRET_KEY (password field only — PI_SECRET_KEY value)
|
|
│ ├── PI_PEPPER (password field only — PI_PEPPER value)
|
|
│ └── PI_ENCFILE (binary attachment: pi.enc — generate after deploy)
|
|
├── PostgreSQL/
|
|
│ ├── postgres root (username: postgres, password: PG_ROOT_PASSWORD)
|
|
│ ├── keycloak user (username: keycloak, password: PG_KEYCLOAK_PASSWORD)
|
|
│ └── privacyidea user (username: privacyidea — same password as PI_DB_PASSWORD)
|
|
├── Keycloak/
|
|
│ ├── admin (username: admin, password: KC_ADMIN_PASSWORD)
|
|
│ └── database (username: keycloak — same password as PG_KEYCLOAK_PASSWORD)
|
|
├── Break-glass/
|
|
│ ├── break-glass (username: break-glass, password: BREAKGLASS_PASSWORD)
|
|
│ └── recovery-otp (TOTP seed — enroll manually after Keycloak is up)
|
|
└── Vault/
|
|
└── (populated in Phase 0b after Vault is deployed)
|
|
```
|
|
|
|
## Workflow
|
|
|
|
### Step 1 — Generate secrets
|
|
|
|
```bash
|
|
chmod +x gen-secrets.sh
|
|
./gen-secrets.sh ./secrets
|
|
```
|
|
|
|
This writes `.env` files to `./secrets/` (gitignored). Inspect each file,
|
|
then copy each value into the appropriate KeePassXC entry.
|
|
|
|
### Step 2 — Create the age encryption key (one-time)
|
|
|
|
```bash
|
|
age-keygen -o ~/net-kingdom-ops-bundle.key
|
|
```
|
|
|
|
The public key prints to stdout. The private key is in the `.key` file.
|
|
Store the `.key` file somewhere safe (NOT in this repo; NOT in the secrets/ dir).
|
|
|
|
### Step 3 — Create the encrypted ops bundle
|
|
|
|
```bash
|
|
chmod +x pack-bundle.sh
|
|
./pack-bundle.sh ./secrets "age1..." ops-bundle.tar.age
|
|
```
|
|
|
|
Store `ops-bundle.tar.age` offsite (cloud storage, external drive, separate location).
|
|
|
|
### Step 4 — Shred the generated files
|
|
|
|
```bash
|
|
find ./secrets -type f -exec shred -u {} \;
|
|
rm -rf ./secrets
|
|
```
|
|
|
|
### Step 5 — PI_ENCFILE (after privacyIDEA container is running — T04)
|
|
|
|
```bash
|
|
# Generate the encryption key inside the running container:
|
|
kubectl exec -n mfa <pi-pod-name> -- pi-manage create_enckey
|
|
|
|
# Extract it:
|
|
kubectl cp -n mfa <pi-pod-name>:/etc/privacyidea/enckey ./pi.enc
|
|
|
|
# Store as a binary attachment in KeePassXC → net-kingdom/privacyIDEA/PI_ENCFILE
|
|
|
|
# Create the K8s Secret:
|
|
kubectl create secret generic privacyidea-enckey \
|
|
--from-file=PI_ENCFILE=./pi.enc \
|
|
--namespace mfa
|
|
|
|
# Shred the local copy:
|
|
shred -u ./pi.enc
|
|
```
|
|
|
|
## Notes on secret reuse
|
|
|
|
Some secrets appear in multiple components — this is intentional to avoid
|
|
drift. When adding to KeePassXC, note the cross-references rather than
|
|
duplicating the value:
|
|
|
|
- `PI_DB_PASSWORD` == PostgreSQL `privacyidea` user password
|
|
- `KC_DB_PASSWORD` == PostgreSQL `keycloak` user password
|
|
|
|
Use KeePassXC references (`{REF:P@T:UUID}`) to avoid maintaining two copies.
|
|
|
|
## Phase 0b — HashiCorp Vault (after T02, once K3s is running)
|
|
|
|
See `../vault/` (created in T01 Phase 0b) for:
|
|
- Vault Helm chart values
|
|
- ESO (External Secrets Operator) configuration
|
|
- Vault secret path layout
|
|
- Migration procedure: KeePassXC → Vault
|