[Security][Infra] OpenBao Phase 3: PKI — internal CA, replace CI cert generation, mTLS for the stateful tier (epic #543) #547

Closed
opened 2026-07-13 21:07:25 +00:00 by spikerj · 2 comments
Owner

Enable the PKI secrets engine as the internal CA: replace SpikerSoft.Api/certs/generate-internal-certs.sh CI step with short-lived issued certs; then mTLS where it matters (MinIO, RabbitMQ, Mongo, Redis) service-by-service, dual-run per the house pattern. This is the 'certificate enforced' half of the epic.

Enable the PKI secrets engine as the internal CA: replace SpikerSoft.Api/certs/generate-internal-certs.sh CI step with short-lived issued certs; then mTLS where it matters (MinIO, RabbitMQ, Mongo, Redis) service-by-service, dual-run per the house pattern. This is the 'certificate enforced' half of the epic.
Author
Owner

Audited against origin/master — NOT DONE. No implementing artifact of any kind.

git grep -rniE "pki|internal ca|mtls" across openbao/* and docs/*.md returns nothing outside the secrets-management doc's own prose. The openbao/ tree contains bootstrap and provisioning scripts (bootstrap-*-secrets.sh, provision-*.sh, policies/admin.hcl) and the stack file — no PKI secrets-engine enablement, no CA role, no issuance path, no mTLS configuration on the stateful tier.

Notes are accurate as written; nothing has moved since filing.

One sequencing observation, since this is Phase 3 of #543. The epic's Phase 2 seam is genuinely live fleet-wide — that part worked. But the "retire scattered passwords" half hasn't landed: six sets of committed plaintext credentials remain (four in backend appsettings*.json, five literals in mailserver/docker-stack.yml), tracked on #633. And two things currently amplify that exposure:

  • #857 — I re-ran its reproduction today: the registry still issues anonymous pull tokens over the public internet, so every spikerj/* image is freely downloadable by anyone.
  • #643 — SonarQube's secret detection is switched off on three appsettings.json files (sonar-scan.yml:75-79), file-scoped rather than value-scoped, so future secrets there go unflagged too.

PKI is the right architectural direction, and the CI-cert-generation replacement in particular would remove a real class of manual work. But it doesn't reduce today's exposure, whereas #633's rotation and #857's visibility flip both do — and #857 is a single setting change. Worth taking those first unless there's a reason to sequence otherwise.

No dependency issue with doing this later: nothing in the epic blocks on Phase 3, and #610 (LE cert centralization, also unstarted) is the natural pair to do alongside it since both are cert-distribution work on the same vault.

Audited against `origin/master` — **NOT DONE. No implementing artifact of any kind.** `git grep -rniE "pki|internal ca|mtls"` across `openbao/*` and `docs/*.md` returns nothing outside the secrets-management doc's own prose. The `openbao/` tree contains bootstrap and provisioning scripts (`bootstrap-*-secrets.sh`, `provision-*.sh`, `policies/admin.hcl`) and the stack file — no PKI secrets-engine enablement, no CA role, no issuance path, no mTLS configuration on the stateful tier. Notes are accurate as written; nothing has moved since filing. **One sequencing observation, since this is Phase 3 of #543.** The epic's Phase 2 seam is genuinely live fleet-wide — that part worked. But the "retire scattered passwords" half hasn't landed: **six sets of committed plaintext credentials remain** (four in backend `appsettings*.json`, five literals in `mailserver/docker-stack.yml`), tracked on **#633**. And two things currently amplify that exposure: - **#857** — I re-ran its reproduction today: the registry **still issues anonymous pull tokens over the public internet**, so every `spikerj/*` image is freely downloadable by anyone. - **#643** — SonarQube's secret detection is switched off on three `appsettings.json` files (`sonar-scan.yml:75-79`), file-scoped rather than value-scoped, so future secrets there go unflagged too. PKI is the right architectural direction, and the CI-cert-generation replacement in particular would remove a real class of manual work. But it doesn't reduce today's exposure, whereas #633's rotation and #857's visibility flip both do — and #857 is a single setting change. Worth taking those first unless there's a reason to sequence otherwise. No dependency issue with doing this later: nothing in the epic blocks on Phase 3, and #610 (LE cert centralization, also unstarted) is the natural pair to do alongside it since both are cert-distribution work on the same vault.
Author
Owner

Migrated to spikerj/spikersoft-infrastructure#171 as part of the umbrella-tracker breakup.

Verified 2026-08-07 against spikersoft-infrastructure@86d03ff6: not started. git grep -rniE "pki|internal ca|mtls" -- openbao docs matches only the three anticipatory prose lines in openbao/docker-stack.yml's header comment — no PKI secrets-engine enablement, no CA role, no issuance path, no mTLS configuration on the stateful tier, and SpikerSoft.Api/certs/generate-internal-certs.sh is still the cert source. Live: bao.spikersoft.com/v1/sys/health → initialized: true, sealed: false (3-node raft healthy), so nothing blocks enabling the engine.

Status: not started.

Closing here. Work now lives in the repo that holds the fix, so fixes #171 in a PR will auto-close it on merge. The umbrella tracker keeps cross-repo epics only.

— Opus 5 Agent

Migrated to **spikerj/spikersoft-infrastructure#171** as part of the umbrella-tracker breakup. Verified 2026-08-07 against `spikersoft-infrastructure@86d03ff6`: **not started.** `git grep -rniE "pki|internal ca|mtls" -- openbao docs` matches only the three anticipatory prose lines in `openbao/docker-stack.yml`'s header comment — no PKI secrets-engine enablement, no CA role, no issuance path, no mTLS configuration on the stateful tier, and `SpikerSoft.Api/certs/generate-internal-certs.sh` is still the cert source. Live: `bao.spikersoft.com/v1/sys/health` → `initialized: true, sealed: false` (3-node raft healthy), so nothing blocks enabling the engine. Status: not started. Closing here. Work now lives in the repo that holds the fix, so `fixes #171` in a PR will auto-close it on merge. The umbrella tracker keeps cross-repo epics only. — Opus 5 Agent
Sign in to join this conversation.