OpenBao is a **secret management tool** embedded into your application stack. It can handle the creation, storage, and management of secrets, ensuring they remain secure. For seamless integration across multiple Kubernetes applications, OpenBao works with the [Kubernetes External Secrets Operator](https://external-secrets.io/latest/), which converts OpenBao’s secrets into Kubernetes secrets.
OpenBao organizes your secrets in one encrypted location, reducing the risk of loss or accidental exposure, such as through a public code push. To dive deeper take a look [here 🤿](#secure-secrets-storage-1)
OpenBao allows you to define rules about who can access which secrets and under what conditions. To dive deeper take a look [here 🤿](#controlled-access-1)
Secrets with a lease are automatically revoked at the end of their lifespan. Revocation can also be done manually. To dive deeper take a look [here 🤿](#leasing-and-revocation-1)
OpenBao generates short-lived secrets on demand and revokes them automatically when they’re no longer needed. To dive deeper take a look [here 🤿](#dynamic-secrets-1)
OpenBao encrypts and decrypts data without storing it, offering cryptographic functions as a service. To dive deeper take a look [here 🤿](#encryption-as-a-service)
Detailed logs track who accessed which secrets and when, providing complete traceability in case of a breach. To dive deeper, take a look [here 🤿](#audit-devices-and-logs-1)
- **Authentication:** Before a human or machine can gain any access, an administrator must configure OpenBao with an auth method. When a client tries to log in to OpenBao, the system checks client’s data against an internal or external (see *Validation* below) system. Once authenticated, OpenBao generates an **access token** for the client. This token is then used for every action performed in OpenBao.
- **Authorization:** OpenBao applies policies based on the authentication method and rules set by the admin to the token that was generated during authentication. Policies provide a declarative way to grant or forbid access to certain **paths** and **operations** in OpenBao.
OpenBao uses policies to manage access to secrets. Policies are basically a **combination of paths and capabilities** (operations) that they allow on these path. Let’s consider this example:
This policy permits *creating*, *reading*, *listing*, and *deleting* the secrets at `database/postgres/`, but only allows *reading* and *listing***all** resources in `database/mysql/` and its subpaths.
[Here's a tutorial how to use it 🔨 ](#controlled-access-2)
For even deeper understanding, go to https://openbao.org/docs/concepts/policies/ 🔗
Dynamic secrets do not exist until read. These secrets are revoked automatically after use. Most of the OpenBao's *secrets engines* are *dynamic secret engines* (more on that later).
An application requests Kubernetes credentials from OpenBao, which generates a token with specific permissions. The token is automatically revoked after use or its lease end.
[Here's a tutorial how to use it 🔨 ](#dynamic-secrets-2)
To simplify key rolling processes, consumers using OpenBao should regularly verify their subscription status to either renew leases where permitted or request replacements for secrets that need updating.
In addition to that, a lease can be revoked manually. When this happens, it invalidates that secret immediately and prevents any further renewals. OpenBao can revoke not only single secrets, but a tree of secrets, for example all secrets read by a specific user, or all secrets of a particular type.
For example:
In the Kubernetes secrets engine, revoking a lease deletes associated Kubernetes service accounts, immeditally rendering their access keys invalid.
The transit secrets engine handles cryptographic operations on data in transit without storing it. It can encrypt, decrypt, sign, verify, and generate hashes or random bytes.
For example:
Your application sends data to OpenBao for encryption before saving it to a database. OpenBao can then decrypt the data on demand, ensuring security even if the database is compromised.
**Audit devices** are the tool for collecting detailed **logs** of all requests to OpenBao, and their responses. Because every operation with OpenBao is an API request/response, when using a single audit device, the audit log contains every interaction with the OpenBao API, including errors - except for a few paths which do not go via the audit system. **Audit log** telemetry on the other hand provides information on the health of your configured audit devices.
One of the core concepts of OpenBao are secret engines. Think of them as a set of path-based APIs, that can be provided with some set of data, after which they take some action on that data, and they return a result.
The External Secrets Operator needs a kubernetes secret containing the **OpenBao's initial token** (see above) to access its secrets. You can create it with:
To fetch it as a kubernetes secret you'll need to create an **external-secrets.yaml** file and apply it to the cluster with `kubectl apply -f external-secrets.yaml`
refreshInterval: "15s" #This specifies the time interval at which the ExternalSecret controller will refresh the secrets.
secretStoreRef: # This references the first file.
name: bao-backend
kind: SecretStore
target: #This specifies the target Kubernetes secret that the ExternalSecret will create.
name: postgres-secret
creationPolicy: Owner
data: # This is an array of secret key-value pairs that the ExternalSecret will retrieve from the Vault secret store and store in the Kubernetes secret.
- secretKey: POSTGRES_USER #Name of the k8 secret that is being created
remoteRef: #This is an object that contains the reference to the secret in the Vault secret store.
key: data/postgres # This specifies the path to the secret in the Vault secret store
property: POSTGRES_USER #This specifies the name of the secret property to retrieve from the Vault secret.
- secretKey: POSTGRES_PASSWORD
remoteRef:
key: data/postgres
property: POSTGRES_PASSWORD
```
After that just run `kubectl get externalsecrets -A` to check that there are no problems with synchronization. And to access the secret on your cluster run: `kubectl get secrets -n openbao`
When an OpenBao server starts, it begins in a sealed state. In this state, OpenBao is configured to know where and how to access the physical storage, but it cannot decrypt any of the stored data because it's lacking the **encryption key**. Unsealing is the process of solving this issue.
<bstyle="color:orange">Note: In the sealed state no operations are possible exept of unsealing the OpenBao and checking the status of the seal.</b>
This **encryption key** is stored together with the OpenBao's secrets, but encrypted with another encryption key, known as the **root key**. The **root key** however is also encrypted, this time by the **unseal key**. The **unseal key** can have the form of an algorith called **[Shamir Secret's Sharing](https://en.wikipedia.org/wiki/Shamir%27s_secret_sharing)** (multiple Key Shares) or might be stored in a **trusted device or service**.
- **Shamir's Secret Sharing:** The unseal key is split into multiple parts (e.g. five parts), and only a subset (e.g. three parts) is needed to reconstruct it.
- **Trusted Device or Service:** The unseal key can be stored securely in a trusted service, such as Cloud KMS or AWS KMS.
To learn more, visit: https://openbao.org/docs/concepts/seal/ 🔗
`In our stack unsealing happens automatically. To access the root token just run: ./getpassword.sh`
#### Secret Engines
<bstyle="color:orange">Note: OpenBao is a fork of [Hashicorp Vault](https://www.hashicorp.com/products/vault). The "bao" keyword is the equivalent of the "vault" keyword and they can be used interchangeably for OpenBao.</b>
To use OpenBao, you first need to log in using your root token.
`kubectl exec -ti openbao-0 -n openbao -- bao login <root_token_from_getpassword.sh>`
Let's enable the first secret engine — the **key-value (KV) secrets engine** without secret versioning - on the path **/database/**.
Now, let's add your first secret to the *postgres* and mysql folders in that KV engine path.
```
kubectl exec -ti openbao-0 -n openbao -- bao kv put database/postgres user=postgres password=123456
kubectl exec -ti openbao-0 -n openbao -- bao kv put database/mysql user=admin password=654321
```
This way, we've saved **two** secrets with each two key value pairs in the KV secret engine activated at path */database/*.
To retrieve this secret, use the *get* command with the specific path.
`kubectl exec -ti openbao-0 -n openbao -- bao kv get database/postgres`
or
`kubectl exec -ti openbao-0 -n openbao -- bao kv get database/mysql`
#### Controlled Access
OpenBao allows you to write with **entities**, **authentication method**, or **tokens**. Let's only consider the entities in detail for the understanding puprose and only take a brief look at the the auth methods and tokens.
Until now, we’ve been using the **static Key-Value (KV) Secret Engine** to store credentials. Let’s switch to a **dynamic** one—the **Database Secret Engine**.
creation_statements="CREATE ROLE \"{{name}}\" WITH LOGIN PASSWORD '{{password}}'; GRANT ALL PRIVILEGES ON DATABASE mydatabase TO \"{{name}}\";" \
default_ttl="1h" \
max_ttl="24h"
```
The `my-postgres-role`:
1. Tells OpenBao to create a user with a `{{name}}` and `{{password}}` from the `connection_url` of the [secret engine](#secret-engine) specification - in our example *postgres* and *password*.
2. Defines to `GRANT ALL PRIVILEGES ON DATABASE` to that user.
3. Sets the `default_ttl` to 1 hour and `max_ttl` to 24 hours.
4. As already mentioned - dynamic secrets do not exist until read. Only users with access to the path `database/roles/my-postgres-role` are allowed to get the above specified credentials.
Let's now generate a postgres database credentials with:
`kubectl exec -ti openbao-0 -n openbao -- bao read database/creds/readonly`
or
`kubectl exec -ti openbao-0 -n openbao -- bao read database/creds/my-postgres-role`
#### Leasing and Revocation
##### Leasing
To understand how leasing and revocation work we will need the [Dynamic Secrets Engine](#dynamic-secrets-2) we've set up before.
As we've seen the `bao read` command returns us the secrets lease ID.
To set the Lease Durations for a whole Secrets Engine use:
-`bao write transit/decrypt/my-key` - notice that this time we're using the `decrypt` part of the path
-`ciphertext` - this time the data we're providing is already encrypted
-`vault:` - indicates that the text has been encrypted by OpenBao
-`v1` - tells OpenBao which version of the key has been used to encrypt the data. This way OpenBao knows how to handle the ciphertext even after key rotation.
You should see `aGVsbG8td29ybGQ=` as the result. To convert it to a readable form, run:
`echo "aGVsbG8td29ybGQ=" | base64 --decode`
For more information visit https://openbao.org/docs/secrets/transit/#setup 🔗