Skip to main content

OpenBao

OpenBao is an open-source, Vault-compatible secrets manager. It stores secret material centrally and lets clients authenticate and read it on demand, instead of secrets living as plaintext files or long-lived credentials scattered across a cluster.

We recommend OpenBao as the backend for the External Secrets Operator rather than a cloud-specific secret manager (AWS Secrets Manager, Google Secret Manager, Azure Key Vault), since it's open-source and not tied to a single cloud provider. The reference implementation configures this by default: secrets are stored in a KV v2 engine, and each tenant's data is automatically path-prefixed under its own path (e.g. secret/<tenant>/*), with per-tenant policies enforcing that isolation.

Architecture

Workloads don't use a static token to talk to OpenBao. Instead, each tenant gets its own OpenBao role and policy, scoped to that tenant's own path prefix, and authenticates using Kubernetes auth:

  1. A client (in practice, the External Secrets Operator on behalf of a tenant) presents a Kubernetes ServiceAccount token to OpenBao's kubernetes auth method.
  2. OpenBao validates that token against the Kubernetes API, then checks it against the role's bound_service_account_names / bound_service_account_namespaces.
  3. On a match, OpenBao issues a short-lived token scoped to that tenant's policy: read/list access to that tenant's prefix only, nothing else.

No long-lived credential is stored anywhere for this flow; a token is minted and validated per login.

See the External Secrets Operator page for how a workload actually consumes a secret this way, or the secret management tutorial for a hands-on walkthrough with the bao CLI.

Deployment modes

Local

When starting a local HavenPlus cluster via task run-local, OpenBao runs in dev mode: a single instance that auto-initializes and auto-unseals on startup. Be aware that you should never run OpenBao on production this way.

Production-like (HA)

Runs OpenBao with multiple replicas with integrated Raft storage for high availability, and auto-unseal so pods can restart without manual intervention.

Auto-unseal currently uses a static seal key: a random key generated once and stored as a Kubernetes Secret in the same cluster. This is a known trade-off: anyone able to read that Secret can unseal OpenBao, so there's no separation between "the cluster is compromised" and "the vault is compromised". A production deployment should replace this with one of the other unseal methods backed by a KMS or HSM (e.g. AWS KMS, GCP Cloud KMS, Azure Key Vault, or a PKCS#11 HSM), which keeps the unseal key in a system genuinely separate from the cluster. See the OpenBao Unseal Mechanisms guide for more detail on these options and how to choose one.

Bringing up a fresh HA instance is automated as a chain of Flux Kustomizations, each wrapping a Kubernetes Job: openbao-config-bootstrap generates the seal key first, then openbao-config-init runs the one-time bao operator init once the leader pod is reachable (concurrently with the OpenBao chart install itself), and finally openbao-config-auth uses the resulting root token to enable Kubernetes auth and write per-tenant policies and roles. No manual step is required after the initial apply.