Commit Graph

13 Commits

Author SHA1 Message Date
c5ff1a3fca Upgrade OpenBAO 2.5.5 -> 2.6.2
Picks up 6 security fixes across 2.6.0/2.6.2, notably GHSA-xp3c-3jw3-4vcr
(LIST bypassing an explicit deny from a wildcard grant).

Checked the 2.6.x breaking changes against this deployment before upgrading:

- Identity-template hardening (+ * / , now rejected in template values):
  no {{ }} templating in any policy, and every pki/ssh role has
  *_template = false. Unaffected.
- Container default user changed root -> openbao (uid 100): the raft volume
  at /openbao/file is already uid 100 and the config bind-mount is
  world-readable :ro, so no chown fixup was needed. Both containers now run
  as uid=100(openbao). Unaffected.
- Cloud KMS + pkcs11 seals become external plugins in 2.7.0: this uses the
  transit seal, which stays built in. Unaffected.
- physical/file deprecated in 2.7.0: storage is raft. Unaffected.
- Pre-v2.5.0 corrupt identity groups purged on unseal: cluster was created
  on 2.5.5, and the `family` group survived. Unaffected.
- Arch-specific tags (2.6.x-arm64) no longer published: compose uses the
  plain multi-arch tag. Unaffected.

Upgrade order was unsealer first (recreate, manually unseal 1-of-1 shamir,
confirm the autounseal transit key is readable), then main, which
auto-unsealed via transit. Cluster IDs preserved on both.

Verified after: all 13 mounts, 4 auth methods and 14 policies intact; KV
read, PKI issue, SSH CA sign and transit encrypt all work through their
scoped tokens; backup token still 403s outside its scope; raft snapshots
succeed on 2.6.2; HTTPS via Traefik serves 2.6.2 with a trusted chain.

Note: sys/seal-status now reports `commit_date` instead of `build_date`.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NFtVLA7VVqXL5G2S18c4Jk
2026-08-22 09:12:14 +02:00
123e65ee46 Renew root-owned /etc infra tokens too (backups were dead 24 days)
renew-app-tokens.sh only walked ~/.config/openbao/*.token, so the three
root-owned tokens were never renewed and lapsed on 2026-07-29:

  /etc/openbao-backup.token           -> nightly raft snapshots failed (403)
  /etc/openbao-unsealer-backup.token  -> same, unsealer instance
  /etc/openbao-cert-renew.token       -> would have failed silently at <21d

Nightly backups had been failing for 24 days before this was noticed; the
last good snapshot was 2026-07-28. All three tokens have been re-issued as
periodic (30d) and the script now covers both sets.

The unsealer's token belongs to a separate instance with no published port,
so it renews via `docker compose exec` rather than curl -- renewing it
against main returns 403. Note `bao token renew` takes no -self flag; the
bare form is the renew-self call.

Service now runs as root to read /etc, and chowns the log back to lutz.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NFtVLA7VVqXL5G2S18c4Jk
2026-08-22 09:12:14 +02:00
f2919cf50a Add daily app-token renewal (script + systemd timer)
Periodic scoped tokens (~/.config/openbao/*.token) expired because nothing
renewed them within their period. renew-app-tokens.sh renews all of them via
auth/token/renew-self; openbao-token-renew.timer runs it daily (Persistent=true).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-08-01 10:20:12 +02:00
63f864b68b gitignore: cover *-credentials.txt (operator login creds)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-08-01 10:04:13 +02:00
f12034bab9 apply-policies: fix header always showing [dry-run]
${DRY:+...} expanded on DRY=0 (non-empty). Gate the label on DRY=1 instead;
the apply logic was already correct.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-08-01 10:03:12 +02:00
700e4ce15a Add smtp-healthcheck-ro policy (scoped read for ClaudeAdmin SMTP creds)
Read-only access to secret/data/smtp/healthcheck, consumed by the ClaudeAdmin
healthcheck email notifier via a periodic token.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-08-01 10:00:07 +02:00
af31208251 Add prepare-host.sh: one-command SSH host onboarding
Generalize the .26 rollout into a reusable template:
- authorize the host principal on ssh/roles/host (allowlist, merged)
- sign the host certificate (ssh/sign/host)
- emit a self-contained installer (user-CA TrustedUserCAKeys + HostCertificate)
  to artifacts/, additive and lockout-safe
- add @cert-authority for the host to the client's known_hosts
Needs no SSH access to the target (ssh-keyscan). README updated.

Also gitignore .claude/ (local harness settings).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-19 10:53:32 +02:00
5e5e7f779f Add governance blueprint: policy-as-code, operator/auditor, identity setup
Reviewable governance scaffolding — NOTHING applied to live OpenBAO yet:

- policies/: materialize all existing policies as code (faithfully fetched
  from live) + new `operator` (use engines, no admin) and `auditor`
  (read-only governance visibility, no secret material)
- scripts/apply-policies.sh: idempotent policy-as-code apply, with a
  read-only --dry-run that diffs files vs live (ignores comments)
- scripts/setup-identity.sh: identity-as-code — policy-bound groups
  (g-admins/operators/auditors/personal) + a human entity/alias; DEFAULT
  DRY-RUN, --apply to execute
- GOVERNANCE.md: the layered model, policy catalog, naming, apply order,
  and cross-cutting controls (audit device, root offline, AppRole migration)

Dry-runs verified read-only: apply-policies shows operator/auditor as NEW,
all others unchanged.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-30 21:05:38 +02:00
21929fa899 Add personal-backup playground (KV + transit) and AppRole demo
Two isolated personal-credential backup options to evaluate, both excluded
from the admin policy (root-only break-glass):
- Scenario A: personal/ KV v2 (versioned) + personal-{put,get,list}.sh
- Scenario B: transit-personal/ key personal-backup + secret-{encrypt,decrypt}.sh

Plus an AppRole example of how a system should consume a secret:
- demo-app role/policy (read-only secret/demo-app/*), short-lived tokens
- scripts/app-get-secret.sh: login (role_id+secret_id) -> token -> read

All tokens/credentials live under ~/.config/openbao (outside the repo).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-28 20:28:32 +02:00
5a111b7a20 Add SSH CA integration: signed user + host certs, ssh-login helper
Turn the ssh/ engine into an SSH CA for cert-based access:

- ssh/ roles: "user" (8h user certs, principal-restricted) and "host"
  (long-lived host certs); mount max-lease-ttl raised for host certs
- scripts/ssh-login.sh: sign a fresh user cert via a scoped ssh/sign/user
  token (API, no bao binary) and connect — no authorized_keys on targets
- ca/openbao-ssh-ca.pub: the SSH CA public key (for TrustedUserCAKeys and
  client @cert-authority trust)
- README: usage, host onboarding, client trust
- gitignore generated per-host artifacts/

First host wired + verified end-to-end: 192.168.0.26 (pifour) — lutz cert
login and host-cert verification both confirmed.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-28 14:55:01 +02:00
37a97cb0f4 Add OpenBAO-backed git credential helper for gitea pushes
Store the gitea PAT in OpenBAO KV (secret/gitea/push) and fetch it via a
git credential helper instead of keeping it in ~/.git-credentials:

- scripts/git-credential-openbao.sh: helper that reads the cred from the
  OpenBAO API using a scoped, read-only periodic token
- scripts/store-gitea-cred.sh: one-time hidden-input store of the PAT
- README: usage + rotation notes

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-28 14:37:39 +02:00
14f46e1082 Add unsealer, internal CA/TLS, auto-unseal, and automated cert+backup
Build out the home-lab OpenBAO deployment beyond the basic node:

- docker-compose: add openbao-unsealer sidecar; main node now transit
  auto-unseals against it (seal config kept in gitignored config/seal.hcl)
- policies/admin.hcl: non-root admin policy; per-engine rules for
  ssh/pki/pki_int/totp/transit
- Internal two-tier CA (pki/ root + pki_int/ intermediate) issues the
  openbao.famfi.home leaf Traefik serves; root CA published under ca/
- scripts/ + systemd/: daily cert renewal and Raft snapshot backups
  (both instances), with scoped tokens stored outside the repo
- README: full runbook (auto-unseal, PKI, renewal, backups, DR/restore)

Secrets (init/unsealer keys, tokens, seal stanza) stay gitignored.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-28 14:28:49 +02:00
95e1b676e2 Initial Commit 2026-06-28 13:41:17 +02:00