OpenBao: complete gids voor secrets management op Kubernetes
OpenBao is een open-source secrets management platform β een community-driven fork van HashiCorp Vault, beheerd door de Linux Foundation. Waar Vault in 2023 overstapte naar een commerciΓ«le licentie (BSL), bleef OpenBao volledig open-source onder de Mozilla Public License 2.0. Voor organisaties die secrets centraal willen beheren in Kubernetes en OpenShift-omgevingen, is OpenBao een krachtig alternatief dat actief wordt doorontwikkeld.
Wat is secrets management en waarom heb je het nodig?
In moderne cloud-native omgevingen heb je overal geheimen nodig: database-wachtwoorden, API-sleutels, TLS-certificaten, SSH-sleutels. De verkeerde aanpak is deze secrets hardcoded in configuratiebestanden of environment variables op te slaan β zeker niet in Git.
OpenBao lost dit op door een centrale, beveiligde opslag te bieden met:
- Versleutelde opslag β secrets worden versleuteld opgeslagen, nooit als plain tekst
- Dynamische secrets β tijdelijke, automatisch roterende credentials (bijv. database-wachtwoorden die na 1 uur verlopen)
- Fine-grained access control β elke applicatie krijgt alleen de secrets waar het recht op heeft
- Audit logging β volledig overzicht van wie welk secret heeft opgevraagd
- Lease management β secrets verlopen automatisch, geen lang-levende credentials
Architectuur en kernconcepten
De vier stappen van OpenBao
- Authenticatie β wie ben je? (Kubernetes ServiceAccount, LDAP, OIDC, AppRole)
- Validatie β wat mag je? (policies bepalen toegang tot paths)
- Autorisatie β toegang verlenen via een token met gekoppelde policies
- Secret ophalen β de applicatie leest het secret via de API
Secrets engines
- KV (Key-Value) β eenvoudige statische secrets opslag, versie 1 (geen history) of versie 2 (met history)
- PKI β dynamische TLS-certificaten genereren, fungeert als Certificate Authority
- Database β dynamische database-credentials genereren voor PostgreSQL, MySQL, MongoDB etc.
- SSH β tijdelijke SSH-sleutels of OTP’s genereren
- Transit β versleuteling als dienst (encrypt/decrypt zonder het secret zelf op te slaan)
- TOTP β time-based one-time passwords genereren
Auth methoden
- Kubernetes β ServiceAccount tokens, ideaal voor Kubernetes/OpenShift deployments
- AppRole β machine-to-machine authenticatie voor CI/CD pipelines
- OIDC β gebruikersauthenticatie via Keycloak, Azure AD, Okta
- LDAP β Active Directory of OpenLDAP integratie
- Token β directe token-authenticatie (voor beheer)
OpenBao installeren op Kubernetes met Helm
# Voeg de OpenBao Helm repository toe
helm repo add openbao https://openbao.github.io/openbao-helm
helm repo update
# Namespace aanmaken
kubectl create namespace openbao
# Installeren in dev-modus (niet voor productie)
helm install openbao openbao/openbao \
--namespace openbao \
--set "server.dev.enabled=true" \
--set "server.dev.devRootToken=root"
# Status controleren
kubectl get pods -n openbao
# Port-forward voor lokale toegang
kubectl port-forward svc/openbao 8200:8200 -n openbao
Productie-installatie met Raft storage (HA)
# values.yaml voor productie
server:
ha:
enabled: true
replicas: 3
raft:
enabled: true
setNodeId: true
affinity: |
podAntiAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchLabels:
app.kubernetes.io/name: openbao
topologyKey: kubernetes.io/hostname
resources:
requests:
memory: 256Mi
cpu: 250m
limits:
memory: 512Mi
cpu: 500m
ingress:
enabled: true
hosts:
- host: openbao.voorbeeld.nl
paths: ["/"]
tls:
- secretName: openbao-tls
hosts: ["openbao.voorbeeld.nl"]
ui:
enabled: true
injector:
enabled: true # Sidecar injector voor automatische secret-injectie
Initialiseren en unsealen
# OpenBao initialiseren (eenmalig)
kubectl exec -n openbao openbao-0 -- bao operator init \
-key-shares=5 \
-key-threshold=3
# Dit geeft 5 unseal keys en 1 root token
# Bewaar deze VEILIG en VERSPREID (bijv. in aparte kluis per beheerder)
# Unseal key 1: abc123...
# Unseal key 2: def456...
# Root token: hvs.xyz789...
# Unsealen (3 van de 5 keys nodig)
kubectl exec -n openbao openbao-0 -- bao operator unseal abc123...
kubectl exec -n openbao openbao-0 -- bao operator unseal def456...
kubectl exec -n openbao openbao-0 -- bao operator unseal ghi789...
# Status controleren
kubectl exec -n openbao openbao-0 -- bao status
Auto-unseal met een externe KMS (aanbevolen voor productie)
# values.yaml fragment voor auto-unseal met AWS KMS
server:
extraEnvironmentVars:
VAULT_SEAL_TYPE: awskms
AWS_REGION: eu-west-1
VAULT_AWSKMS_SEAL_KEY_ID: arn:aws:kms:eu-west-1:123456789:key/abc-def
# Of met Azure Key Vault
server:
extraEnvironmentVars:
VAULT_SEAL_TYPE: azurekeyvault
AZURE_TENANT_ID: tenant-id
AZURE_CLIENT_ID: client-id
AZURE_CLIENT_SECRET: client-secret
VAULT_AZUREKEYVAULT_VAULT_NAME: mijn-keyvault
VAULT_AZUREKEYVAULT_KEY_NAME: openbao-unseal-key
CLI-basiscommando’s
# Omgevingsvariabelen instellen
export BAO_ADDR=https://openbao.voorbeeld.nl
export BAO_TOKEN=hvs.roottoken123
# Inloggen
bao login hvs.roottoken123
# Status bekijken
bao status
# Secrets engine inschakelen
bao secrets enable -path=geheimen kv-v2
# Secret opslaan
bao kv put geheimen/database \
gebruikersnaam=admin \
wachtwoord=GeheimWachtwoord123
# Secret opvragen
bao kv get geheimen/database
# Specifiek veld opvragen
bao kv get -field=wachtwoord geheimen/database
# Versiegeschiedenis bekijken (KV v2)
bao kv metadata get geheimen/database
# Specifieke versie opvragen
bao kv get -version=2 geheimen/database
# Secret verwijderen (soft delete)
bao kv delete geheimen/database
# Secret permanent verwijderen
bao kv destroy -versions=1,2 geheimen/database
Kubernetes integratie β de juiste manier
Kubernetes auth methode configureren
# Kubernetes auth inschakelen
bao auth enable kubernetes
# Configureren (vanuit binnen het cluster)
bao write auth/kubernetes/config \
kubernetes_host="https://kubernetes.default.svc:443" \
kubernetes_ca_cert=@/var/run/secrets/kubernetes.io/serviceaccount/ca.crt \
token_reviewer_jwt=@/var/run/secrets/kubernetes.io/serviceaccount/token
# Policy aanmaken
bao policy write mijn-app-policy - <
Secrets via de sidecar injector (aanbevolen)
# Deployment met automatische secret-injectie
apiVersion: apps/v1
kind: Deployment
metadata:
name: mijn-app
namespace: productie
spec:
template:
metadata:
annotations:
# Injectie inschakelen
vault.hashicorp.com/agent-inject: "true"
vault.hashicorp.com/role: "mijn-app"
# Secret injecteren als bestand
vault.hashicorp.com/agent-inject-secret-database: "geheimen/data/mijn-app/database"
# Template voor de injectie (optioneel, voor specifiek formaat)
vault.hashicorp.com/agent-inject-template-database: |
{{- with secret "geheimen/data/mijn-app/database" -}}
export DB_USER="{{ .Data.data.gebruikersnaam }}"
export DB_PASS="{{ .Data.data.wachtwoord }}"
{{- end -}}
spec:
serviceAccountName: mijn-app-sa
containers:
- name: mijn-app
image: mijn-app:1.0.0
# Secret beschikbaar als /vault/secrets/database
Secrets via de Vault Secrets Operator (moderne aanpak)
# VaultStaticSecret resource
apiVersion: secrets.hashicorp.com/v1beta1
kind: VaultStaticSecret
metadata:
name: database-secret
namespace: productie
spec:
type: kv-v2
mount: geheimen
path: mijn-app/database
destination:
name: database-secret # Wordt een gewoon Kubernetes Secret
create: true
refreshAfter: 30s
vaultAuthRef: openbao-auth
PKI secrets engine β dynamische TLS-certificaten
# PKI engine inschakelen
bao secrets enable pki
# Maximum TTL instellen
bao secrets tune -max-lease-ttl=8760h pki
# Root CA genereren
bao write pki/root/generate/internal \
common_name="Voorbeeld Root CA" \
ttl=8760h
# Intermediate CA aanmaken
bao secrets enable -path=pki_int pki
bao secrets tune -max-lease-ttl=4380h pki_int
# CSR genereren voor intermediate
bao write pki_int/intermediate/generate/internal \
common_name="Voorbeeld Intermediate CA" \
| jq -r '.data.csr' > intermediate.csr
# Ondertekenen met root CA
bao write pki/root/sign-intermediate \
csr=@intermediate.csr \
format=pem_bundle \
ttl=4380h \
| jq -r '.data.certificate' > intermediate.cert.pem
# Ondertekend certificaat importeren
bao write pki_int/intermediate/set-signed \
certificate=@intermediate.cert.pem
# Rol aanmaken voor certificaatuitgifte
bao write pki_int/roles/server-cert \
allowed_domains="voorbeeld.nl" \
allow_subdomains=true \
max_ttl=720h
# Certificaat uitschrijven
bao write pki_int/issue/server-cert \
common_name="api.voorbeeld.nl" \
ttl=720h
Database secrets engine β dynamische credentials
# Database engine inschakelen
bao secrets enable database
# PostgreSQL configureren
bao write database/config/mijn-db \
plugin_name=postgresql-database-plugin \
allowed_roles="app-rol" \
connection_url="postgresql://{{username}}:{{password}}@postgres:5432/mijndb" \
username="openbao-beheer" \
password="BeheerWachtwoord"
# Rol aanmaken (dynamische gebruiker met TTL)
bao write database/roles/app-rol \
db_name=mijn-db \
creation_statements="CREATE ROLE \"{{name}}\" WITH LOGIN PASSWORD '{{password}}' VALID UNTIL '{{expiration}}'; GRANT SELECT, INSERT ON ALL TABLES IN SCHEMA public TO \"{{name}}\";" \
revocation_statements="DROP ROLE IF EXISTS \"{{name}}\";" \
default_ttl=1h \
max_ttl=24h
# Dynamische credentials opvragen
bao read database/creds/app-rol
# Output:
# Key Value
# --- -----
# username v-root-app-rol-AbCdEf
# password A1b2C3d4-tijdelijkeCredential
OpenBao op OpenShift deployen
# OpenShift vereist extra machtigingen voor de injector oc create namespace openbao oc adm policy add-scc-to-user anyuid -z openbao -n openbao oc adm policy add-scc-to-user anyuid -z openbao-agent-injector -n openbao # Helm installatie voor OpenShift helm install openbao openbao/openbao \ --namespace openbao \ --set "global.openshift=true" \ --set "server.route.enabled=true" \ --set "server.route.host=openbao.apps.cluster.voorbeeld.nl" # Route controleren oc get route -n openbao
Audit logging instellen
# File audit log inschakelen
bao audit enable file file_path=/bao/logs/audit.log
# Syslog audit inschakelen
bao audit enable syslog tag="openbao" facility="AUTH"
# Audit logs bekijken (elk request en response wordt gelogd)
kubectl exec -n openbao openbao-0 -- cat /bao/logs/audit.log | jq '.'
OpenBao vs HashiCorp Vault
| Eigenschap | OpenBao | HashiCorp Vault |
|---|---|---|
| Licentie | Mozilla Public License 2.0 (open-source) | Business Source License (commercieel) |
| Beheer | Linux Foundation community | HashiCorp / IBM |
| API-compatibiliteit | Volledig compatibel met Vault API | β |
| Kosten | Gratis | Gratis tot bepaalde schaal, daarna Enterprise |
| Enterprise features | Worden stapsgewijs open-source gemaakt | Achter betaalmuur |
| Migratie van Vault | Drop-in replacement, zelfde API | β |
Veelgestelde vragen
Is OpenBao een drop-in replacement voor Vault?
Ja β OpenBao gebruikt dezelfde API als HashiCorp Vault en is volledig achterwaarts compatibel. Bestaande Vault-clients, Terraform-providers en Kubernetes-integraties werken zonder aanpassingen op OpenBao. Alleen de CLI-commandonaam verschilt: vault is vervangen door bao.
Wat is het verschil tussen OpenBao en Kubernetes Secrets?
Kubernetes Secrets zijn base64-gecodeerde waarden opgeslagen in etcd β ze zijn standaard niet versleuteld en iedereen met cluster-admin rechten kan ze inzien. OpenBao versleutelt alles, biedt dynamische secrets, fine-grained toegangscontrole en audit logging. OpenBao vervangt Kubernetes Secrets niet volledig, maar is complementair: de meeste organisaties gebruiken OpenBao als de centrale bron en injecteren secrets dynamisch in Kubernetes workloads.
Hoe verhoudt OpenBao zich tot External Secrets Operator?
External Secrets Operator (ESO) is een Kubernetes-operator die secrets synchroniseert vanuit externe bronnen (AWS Secrets Manager, Azure Key Vault, Google Secret Manager) naar Kubernetes Secrets. OpenBao is zelf een secrets-store. ESO ondersteunt ook OpenBao/Vault als bron β je kunt beide combineren: OpenBao als centrale secrets-store, ESO om die secrets te synchroniseren naar Kubernetes Secrets.