> ## Documentation Index
> Fetch the complete documentation index at: https://docs.futurex.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Appendix: Rekey and rotate OpenBao

> Rekey the recovery keys and rotate the encryption key of an OpenBao deployment that uses HSM auto-unseal, including the prerequisite rotation operator token you create before revoking the root token.

When you deploy OpenBao with HSM auto-unseal, initialization generates a root key on the HSM and a set of **recovery keys** derived from an internal recovery key split by Shamir's Secret Sharing ([en.wikipedia.org/wiki/Shamir%27s\_secret\_sharing](https://en.wikipedia.org/wiki/Shamir%27s_secret_sharing)). Recovery keys replace the unseal keys used in a standard Shamir-only deployment. Because the HSM handles unsealing automatically, recovery keys are not used to unseal OpenBao. They exist solely for privileged operator operations, such as generating a new root token or rotating recovery keys.

You might want to regenerate the recovery keys in cases such as the following:

* Someone joins or leaves the organization.
* Security wants to change the number of shares or the threshold.
* Compliance mandates that you rotate the keys at regular intervals.

In addition to rekeying the recovery keys, you might need to rotate the underlying encryption key that OpenBao uses to encrypt data at rest. In OpenBao, rekeying and rotating are two separate operations:

* **Rekeying** generates a new set of recovery key shares.
* **Key rotation** generates a new encryption key for OpenBao.

> [!NOTE]
>
> Recent OpenBao releases disable the `sys/generate-root/*` and `sys/generate-recovery-token/*` endpoints by default, because they previously allowed unauthenticated access that could be exploited to disrupt rekey operations. The authenticated approach requires a token with `sudo` capabilities on the rotation paths. You must configure this token **before** you revoke the initial root token. Confirm the exact behavior against the release notes for your OpenBao version.

## Prerequisite: Create a rotation operator token

Before you revoke the initial root token after setup, create a dedicated **rotation operator token** with the permissions required to perform recovery key rotation. This token serves as a break-glass credential. Store it as securely as the recovery key shares.

**Step 1**

Using your root token, create a policy file that grants `sudo` access to the rotation paths.

If you have not set the root token as an environment variable, set it now.

```shell expandable lines wrap title="Shell" theme={null}
export BAO_TOKEN="<root-token>"
```

Then create the policy file.

> [!NOTE]
>
> This is an **example policy** file that creates an operator able to perform all the operations listed here. Adjust the paths and permissions to fit your organization's security structure.

The paths let the rotation operator perform the following:

* Rotation operations on the recovery and root keys (`sys/rotate/*`).
* Encryption keyring rotation through `bao operator rotate` (`sys/rotate`, `sys/key-status`).
* Recovery token generation for break-glass root token generation (`sys/generate-recovery-token/*`).
* Look up, renew, and revoke their own token (`auth/token/lookup-self`, `auth/token/renew-self`, `auth/token/revoke-self`).
* Check their own capabilities on any path (`sys/capabilities-self`).

```shell expandable lines wrap title="Shell" theme={null}
cat <<EOF > rotation-policy.hcl
# Recovery and root key rotation
path "sys/rotate/*" {
  capabilities = ["create", "read", "update", "delete", "sudo"]
}

# Bare rotate path for bao operator rotate
path "sys/rotate" {
  capabilities = ["update", "sudo"]
}

# Generate recovery token (break-glass root token generation)
path "sys/generate-recovery-token/*" {
  capabilities = ["create", "read", "update", "delete", "sudo"]
}

# Key status check (required by bao operator rotate)
path "sys/key-status" {
  capabilities = ["read"]
}

# Token self-management
path "auth/token/lookup-self" {
  capabilities = ["read"]
}

path "auth/token/renew-self" {
  capabilities = ["update"]
}

path "auth/token/revoke-self" {
  capabilities = ["update"]
}

# Capabilities self-check
path "sys/capabilities-self" {
  capabilities = ["update"]
}
EOF

bao policy write rotation-operator rotation-policy.hcl
```

**Step 2**

Create a token attached to that policy. Replace `<DURATION>` with the desired token period, such as `768h` for 32 days. Your OpenBao configuration may already have a TTL cap that limits this value.

```shell expandable lines wrap title="Shell" theme={null}
bao token create \
  -policy=rotation-operator \
  -display-name="rotation-operator" \
  -no-default-policy \
  -orphan \
  -period=<DURATION>
```

> [!TIP]
>
> The output is similar to the following.
>
> ```text theme={null}
> Key                  Value
> ---                  -----
> token                s.OAZmOzcGb04tseVHVaHvhoZq
> token_accessor       xjsOyIYYrYwpqZzx8Rw3EQJr
> token_duration       768h
> token_renewable      true
> token_policies       ["rotation-operator"]
> identity_policies    []
> policies             ["rotation-operator"]
> ```

Save this token securely. Treat it with the same care as the recovery key shares.

**Step 3**

Revoke the root token to complete the initial setup, following best practice. Once revoked, the rotation operator token authorizes all future rotation operations.

```shell expandable lines wrap title="Shell" theme={null}
bao token revoke $BAO_TOKEN
unset BAO_TOKEN
```

Confirm that the root token is no longer active.

```shell expandable lines wrap title="Shell" theme={null}
bao token lookup
```

> [!TIP]
>
> With no token set, this returns a permission-denied error, which confirms that the root token was successfully revoked.
>
> ```text theme={null}
> Error looking up token: Error making API request.
>
> URL: GET http://127.0.0.1:8200/v1/auth/token/lookup-self
> Code: 403. Errors:
>
> * permission denied
> ```

## Rekey the OpenBao recovery keys

To rekey the recovery keys when HSM auto-unseal is configured, use the `bao operator rotate-keys` command with the `-target=recovery` flag. This generates a new set of recovery keys and invalidates all existing shares. It does not generate a new root key on the HSM. The process can optionally modify the total number of recovery key shares or the recovery key threshold. Recovery keys cannot decrypt the root key; they exist purely for authorization.

> [!NOTE]
>
> You cannot replace a single recovery key share. Rekeying invalidates **all** existing shares and generates a completely new set. Every keyholder receives a new share after the operation completes.

**Step 1**

Export the rotation operator token to authenticate the operation.

```shell expandable lines wrap title="Shell" theme={null}
export BAO_TOKEN="<rotation-operator-token>"
```

**Step 2**

Initialize the rekeying operation, modifying the key shares and key threshold values as needed.

```shell expandable lines wrap title="Shell" theme={null}
bao operator rotate-keys \
  -init \
  -target=recovery \
  -key-shares=5 \
  -key-threshold=3
```

> [!TIP]
>
> This command generates a nonce value and starts the rekeying process. All recovery key holders must provide this nonce value when they submit their share. The nonce is not a secret and is safe to distribute over insecure channels such as chat or email.
>
> ```text theme={null}
> Key                      Value
> ---                      -----
> Nonce                    52bd8754-07f8-7ec9-811c-3bc23bbaee6b
> Started                  true
> Rekey Progress           0/3
> New Shares               5
> New Threshold            3
> Verification Required    false
> ```

**Step 3**

Each key holder runs the following command, entering their recovery key share when prompted. Replace `<NONCE>` with the nonce value from the previous step.

```shell expandable lines wrap title="Shell" theme={null}
bao operator rotate-keys -target=recovery -nonce="<NONCE>"
```

OpenBao prompts for the share.

```text theme={null}
Recovery Key (will be hidden):
```

The output after each submission is similar to the following.

```text theme={null}
Key                      Value
---                      -----
Nonce                    52bd8754-07f8-7ec9-811c-3bc23bbaee6b
Started                  true
Rekey Progress           1/3
New Shares               5
New Threshold            3
Verification Required    false
```

Repeat this step for each keyholder until the threshold is met. You only need the threshold number of current keyholders to participate, for example, 3 of 5 existing holders.

**Step 4**

When the final required key share is submitted, OpenBao outputs the new recovery keys.

```text theme={null}
Key 1: 0e9TjZQOiVQp7mk0nK0y564oLyB3GbtqrObhSOQ4h54b
Key 2: GQc6jEVQoAslc5l9/Z6ErIfuV6l6TaOrHzuXBj/6H3rp
Key 3: /hF1PBAmFs0k3o3DRVHkaTFzXQfLt6ELOW/nheaR9G2G
Key 4: Y0zb5pWRTH962+VnEvOQQ6cTZJIypCP1cS3UK9DsUYjL
Key 5: ALRCSaTMd6FfkMYBaXxpeIKlyUiE+u2oxJL1MrmStWHB

Operation nonce: 52bd8754-07f8-7ec9-811c-3bc23bbaee6b

OpenBao recovery keys rekeyed with 5 key shares and a key threshold of 3.
Please securely distribute the key shares printed above.
```

All previous recovery key shares are now cryptographically invalid. Distribute the new shares immediately and confirm receipt from each keyholder.

**Step 5**

Clear the rotation operator token from the environment when the operation is complete.

```shell expandable lines wrap title="Shell" theme={null}
unset BAO_TOKEN
```

> [!WARNING]
>
> If something goes wrong before the operation completes, cancel the rotation to preserve the existing keys.
>
> ```shell expandable lines wrap title="Shell" theme={null}
> bao operator rotate-keys -cancel -target=recovery
> ```

## Generate a new root token

If the root token was revoked and a privileged operation requires one, such as mounting a new secrets engine or modifying policies, you can generate a new root token by using a quorum of recovery key shares.

> [!WARNING]
>
> Recent OpenBao releases disable the root token generation endpoints by default. To temporarily re-enable them, add the following line to the `listener` stanza in `/etc/openbao/openbao.hcl`.
>
> ```hcl expandable lines wrap title="/etc/openbao/openbao.hcl" theme={null}
> disable_unauthed_generate_root_endpoints = false
> ```
>
> Set this parameter to `false` only for the short period required to generate a new root token. Remove it and restart OpenBao as soon as the operation is complete.

**Step 1**

After you add the parameter to `/etc/openbao/openbao.hcl`, restart OpenBao.

```shell expandable lines wrap title="Shell" theme={null}
sudo systemctl restart openbao
```

**Step 2**

Generate a one-time password (OTP) to encode the resulting root token.

```shell expandable lines wrap title="Shell" theme={null}
bao operator generate-root -generate-otp
```

> [!TIP]
>
> Save the `OTP` value. You need it to decode the final root token.
>
> ```text theme={null}
> A One-Time-Password has been generated for you and is shown in the OTP field.
> Nonce         n/a
> Started       false
> Progress      0/3
> Complete      false
> OTP           IxQpFbSVJaRnPccBMgDxaBkJoU
> OTP Length    26
> ```

**Step 3**

Initialize the root token generation. Replace `<OTP>` with the value from the previous step.

```shell expandable lines wrap title="Shell" theme={null}
bao operator generate-root -init -otp="<OTP>"
```

> [!TIP]
>
> Save the `Nonce` value for the next step.
>
> ```text theme={null}
> Nonce         04211924-6d23-159a-13a8-f99fd6eb6ca7
> Started       true
> Progress      0/3
> Complete      false
> OTP Length    26
> ```

**Step 4**

Each keyholder submits their recovery key share. Replace `<NONCE>` with the value from the previous step. Repeat until the threshold is met.

```shell expandable lines wrap title="Shell" theme={null}
bao operator generate-root -nonce="<NONCE>"
```

OpenBao prompts for the recovery key share. The output after each submission is similar to the following.

```text theme={null}
Nonce         04211924-6d23-159a-13a8-f99fd6eb6ca7
Started       true
Progress      1/3
Complete      false
```

**Step 5**

When the threshold is reached, OpenBao outputs an encoded token.

> [!TIP]
>
> ```text theme={null}
> Nonce            04211924-6d23-159a-13a8-f99fd6eb6ca7
> Started          true
> Progress         3/3
> Complete         true
> Encoded Token    JW8yOykrKG54YQB3GicDLR4QBkETEH0qIww
> ```

Decode it with the following command. Replace `<ENCODED-TOKEN>` and `<OTP>` with the values from the previous steps.

```shell expandable lines wrap title="Shell" theme={null}
bao operator generate-root -decode="<ENCODED-TOKEN>" -otp="<OTP>"
```

> [!TIP]
>
> This outputs the decoded root token.
>
> ```text theme={null}
> s.fpyiRVHXk3soiNsREwAx6aBK
> ```

**Step 6**

Export the decoded root token and perform the required privileged operations.

```shell expandable lines wrap title="Shell" theme={null}
export BAO_TOKEN="<DECODED-ROOT-TOKEN>"
```

**Step 7**

Revoke the root token when all operations are complete.

```shell expandable lines wrap title="Shell" theme={null}
bao token revoke $BAO_TOKEN
unset BAO_TOKEN
```

**Step 8**

Remove `disable_unauthed_generate_root_endpoints = false` from the `listener` stanza in `/etc/openbao/openbao.hcl` to re-disable the unauthenticated root generation endpoints, then restart OpenBao.

```shell expandable lines wrap title="Shell" theme={null}
sudo systemctl restart openbao
```

## Rotate the encryption key

Unlike rekeying the recovery keys, rotating the OpenBao encryption key does not require a quorum of recovery keys. Any token with the proper permissions can perform encryption key rotation. You can rotate keys automatically or manually.

> [!NOTE]
>
> OpenBao automatically rotates the backend encryption key before it reaches 2^32 encryption operations, in adherence with NIST SP 800-38D guidelines.

### Adjust automatic key rotation

**Step 1**

Export the rotation operator token to authenticate the operation.

```shell expandable lines wrap title="Shell" theme={null}
export BAO_TOKEN="<rotation-operator-token>"
```

**Step 2**

View the current automatic rotation policy.

```shell expandable lines wrap title="Shell" theme={null}
bao read sys/rotate/config
```

> [!TIP]
>
> This returns the current status and configuration of automatic encryption key rotation.
>
> ```text theme={null}
> Key               Value
> ---               -----
> enabled           true
> interval          0
> max_operations    3865470566
> ```

**Step 3**

Configure a time interval for automatic key rotation.

```shell expandable lines wrap title="Shell" theme={null}
bao write sys/rotate/config interval=2160h
```

> [!TIP]
>
> ```text theme={null}
> Success! Data written to: sys/rotate/config
> ```

**Step 4**

Configure the maximum number of encryption operations per key.

```shell expandable lines wrap title="Shell" theme={null}
bao write sys/rotate/config max_operations=123456789
```

> [!TIP]
>
> ```text theme={null}
> Success! Data written to: sys/rotate/config
> ```

### Perform manual key rotation

Trigger a key rotation.

```shell expandable lines wrap title="Shell" theme={null}
bao operator rotate
```

> [!TIP]
>
> This adds a new key to the keyring. The new key encrypts all new values written to the storage backend.
>
> ```text theme={null}
> Success! Rotated key
>
> Key Term            2
> Install Time        14 Nov 23 21:47 UTC
> Encryption Count    1
> ```

## Continuity of operations

As with Shamir's Secret Sharing, both rekeying and rotating operations with HSM auto-unseal are fully online operations. OpenBao continues to service requests uninterrupted during these processes.
