Skip to content

CRUD Operations for Secrets

This guide covers how to create, read, update, and delete secrets in OpenBao.

Prerequisites

  • OpenBao CLI installed and configured (Setup Guide)
  • Authenticated with appropriate permissions
  • Access to the secrets path you want to manage

Secrets Engine

We use the KV v2 (Key-Value version 2) secrets engine, which provides:

  • Versioned secrets
  • Soft delete and recovery
  • Metadata tracking
  • Check-and-set operations

Create Secrets

Create a Simple Secret

bao kv put clusters/hetzner-mgmt/myapp key="value"

Create a Secret with Multiple Key-Value Pairs

bao kv put clusters/hetzner-mgmt/myapp \
  username="admin" \
  password="supersecret" \
  api_key="abc123"

Create a Secret from a File

# From a JSON file
bao kv put clusters/hetzner-mgmt/myapp @secrets.json

# From stdin
echo '{"username":"admin","password":"secret"}' | bao kv put clusters/hetzner-mgmt/myapp -

Create a Secret in a Nested Path

# Creates the path automatically
bao kv put clusters/hetzner-mgmt/apps/frontend/config \
  api_url="https://api.example.com" \
  debug="false"

Read Secrets

Read All Key-Value Pairs

bao kv get clusters/hetzner-mgmt/myapp

Output:

========= Secret Path =========
clusters/data/hetzner-mgmt/myapp

======= Metadata =======
Key                Value
---                -----
created_time       2026-01-18T19:58:55.981062993Z
custom_metadata    <nil>
deletion_time      n/a
destroyed          false
version            1

===== Data =====
Key        Value
---        -----
username   admin
password   supersecret
api_key    abc123

Read a Specific Field

bao kv get -field=password clusters/hetzner-mgmt/myapp

Output:

supersecret

Read as JSON

bao kv get -format=json clusters/hetzner-mgmt/myapp

Read a Specific Version

bao kv get -version=1 clusters/hetzner-mgmt/myapp

List Secrets in a Path

bao kv list clusters/hetzner-mgmt/

Output:

Keys
----
myapp
apps/
config

Update Secrets

Update (Replace) All Values

# This REPLACES all existing keys
bao kv put clusters/hetzner-mgmt/myapp \
  username="newuser" \
  password="newpassword"

Full Replacement

bao kv put replaces all keys. If you only specify username, the password and api_key will be removed.

Patch (Update Specific Keys)

# Only updates specified keys, preserves others
bao kv patch clusters/hetzner-mgmt/myapp \
  password="updatedpassword"

Add a New Key to Existing Secret

bao kv patch clusters/hetzner-mgmt/myapp \
  new_key="new_value"

Delete Secrets

Soft Delete (Recoverable)

bao kv delete clusters/hetzner-mgmt/myapp

The secret is marked as deleted but can be recovered.

Delete a Specific Version

bao kv delete -versions=2 clusters/hetzner-mgmt/myapp

Recover a Deleted Secret

bao kv undelete -versions=1 clusters/hetzner-mgmt/myapp

Permanently Destroy a Version

# Cannot be recovered!
bao kv destroy -versions=1 clusters/hetzner-mgmt/myapp

Permanently Destroy All Versions

# Cannot be recovered!
bao kv metadata delete clusters/hetzner-mgmt/myapp

Version Management

View All Versions

bao kv metadata get clusters/hetzner-mgmt/myapp

Rollback to Previous Version

# Read the old version
bao kv get -version=1 clusters/hetzner-mgmt/myapp

# Re-create with the old values (creates a new version)
bao kv put clusters/hetzner-mgmt/myapp \
  username="olduser" \
  password="oldpassword"

Practical Examples

Store Database Credentials

bao kv put clusters/hetzner-mgmt/databases/postgresql \
  host="postgres.default.svc.cluster.local" \
  port="5432" \
  database="myapp" \
  username="myapp_user" \
  password="$(openssl rand -base64 32)"

Store API Keys

bao kv put clusters/hetzner-mgmt/external-services/stripe \
  publishable_key="pk_live_xxx" \
  secret_key="sk_live_xxx" \
  webhook_secret="whsec_xxx"

Store TLS Certificates

bao kv put clusters/hetzner-mgmt/tls/myapp \
  cert="$(cat cert.pem)" \
  key="$(cat key.pem)" \
  ca="$(cat ca.pem)"

Use in Scripts

#!/bin/bash
# Retrieve credentials and use them
DB_PASSWORD=$(bao kv get -field=password clusters/hetzner-mgmt/databases/postgresql)
export PGPASSWORD="$DB_PASSWORD"
psql -h localhost -U myapp_user -d myapp

Best Practices

  1. Use Descriptive Paths: Organize secrets logically (e.g., clusters/hetzner-mgmt/apps/frontend/)
  2. Don't Store in Git: Never commit secrets to version control
  3. Use Patch for Updates: Prefer bao kv patch over bao kv put when updating single fields
  4. Rotate Regularly: Update sensitive credentials periodically
  5. Use Versions: Leverage versioning for audit trails and rollbacks
  6. Least Privilege: Request only the permissions you need

Next Steps