Skip to content

Add opt-in Cloud KMS auto-unseal support for OpenBao #458

@sehkone

Description

@sehkone

Background

bootroot currently operates OpenBao using a manual unseal method based on Shamir secret sharing (3 shares, threshold 2). This works fine in air-gapped environments, but when operating remotely over the internet, it becomes impractical because an operator must manually enter unseal keys every time OpenBao restarts.

Goal

Provide opt-in support for auto-unseal via Cloud KMS when the user chooses to use it. The default remains the existing Shamir method. This issue covers new installations only; migrating existing Shamir deployments to auto-unseal will be tracked in a separate issue.

Supported KMS Providers

  • AWS KMS
  • GCP Cloud KMS
  • Azure Key Vault

Korean cloud providers' KMS (NHN, Naver Cloud, Kakao Cloud, etc.) are excluded from the current scope because OpenBao does not officially support them. Expansion will be considered once OpenBao completes its Auto Unseal Plugin support.

Authentication Methods

Calling Cloud KMS APIs requires cloud authentication. Two methods are supported depending on the deployment environment.

1. Running on a Cloud VM

Authenticate automatically without credentials using each cloud's VM permission features. This works by obtaining temporary tokens from the metadata endpoint inside the VM.

Cloud Feature Name
AWS IAM Role (Instance Profile)
GCP Service Account
Azure Managed Identity
  • This is the recommended approach for security since there are no credentials to manage separately.
  • The metadata endpoint must be accessible from inside the Docker container (note AWS IMDSv2 hop limit, etc.).

2. Running outside a Cloud VM (on-premises, different cloud, etc.)

Authenticate by passing credentials via environment variables.

  • AWS: AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, AWS_REGION
  • GCP: GOOGLE_APPLICATION_CREDENTIALS (service account key file path — the JSON file must be volume-mounted into the container)
  • Azure: AZURE_TENANT_ID, AZURE_CLIENT_ID, AZURE_CLIENT_SECRET

While cloud-side controls (IP restrictions, audit logs, credential deactivation, periodic rotation) offer more safeguards than raw unseal keys, KMS credentials remain high-risk credentials as the seal trust root. They require the same level of protection as unseal keys.

Caveat: KMS Lifecycle Dependency

Auto-unseal provides operational convenience, but creates a strong dependency between OpenBao's data and the KMS key. If the KMS key is deleted or becomes inaccessible, OpenBao data may be unrecoverable even with backups. This risk must be documented in operational guides, along with KMS key protection policies (deletion protection, multi-region replication, etc.).

Scope of Changes

Seal configuration is read when OpenBao starts, so it must be configured before bootroot infra up. Therefore, this feature spans both the infra and init layers.

bootroot infra up (seal configuration)

  • Add seal type options (e.g., --seal-type=awskms, --kms-key-id=..., --kms-region=...)
  • Add credential configuration options depending on whether running on a Cloud VM
  • Conditionally insert a seal stanza into openbao.hcl before starting the OpenBao container
    • e.g., seal "awskms" { kms_key_id = "..." region = "..." }
    • Also consider injecting VAULT_SEAL_TYPE env var + provider-specific env vars into Compose
  • For non-Cloud VM + GCP environments, configure the volume mount path for the credential JSON file

Seal Configuration Persistence

Currently, openbao/openbao.hcl is a static file bind-mounted as read-only in Compose. The dynamically configured seal settings for auto-unseal must persist across subsequent infra up restarts. The source of truth for seal configuration is the rendered HCL or pre-infra up artifacts such as Compose overrides/.env. The following design decisions are needed:

  • Convert openbao.hcl to a rendered file and persist the output on disk
  • Or store seal-related environment variables in a Compose override file/.env

state.json is not the source of truth for seal configuration; it is used only as metadata so that post-init commands (rotate, etc.) can identify the current seal mode.

bootroot init (initialization flow)

  • When using auto-unseal, change the /sys/init request model:
    • Shamir: secret_shares, secret_threshold
    • Auto-unseal: stored_shares, recovery_shares, recovery_threshold
  • The meaning of keys in the response changes: process as recovery keys instead of unseal keys
  • Skip the unseal step and wait for auto-unseal completion instead
  • Branch terminology in CLI output and summary: use "recovery key" instead of "unseal key"

rotate openbao-recovery

  • In OpenBao 2.4, sys/rekey/* was deprecated, and in 2.5, unauthenticated rekey endpoints are disabled by default
  • Use new authenticated endpoints depending on seal type:
    • Shamir share rotation: /sys/rotate/root/*
    • Auto-unseal recovery key rotation: /sys/rotate/recovery/*
    • Root token issuance/rotation is a separate flow from the above endpoints and retains the existing approach
  • Note: This endpoint change also needs to be applied to the existing Shamir mode rotate openbao-recovery (handle in a separate issue or together with this one)

CLI Flag Terminology Transition

The current CLI flags for rotate openbao-recovery (--rotate-unseal-keys, --unseal-key, --unseal-key-file) and help text are written for Shamir. In auto-unseal mode:

  • --rotate-unseal-keys → change behavior to recovery key rotation (or add --rotate-recovery-keys)
  • --unseal-key / --unseal-key-file → change meaning to recovery key input (or add --recovery-key / --recovery-key-file)
  • Display correct terminology in help text based on seal type
  • Decide on backward compatibility during implementation (whether to keep existing flags as aliases)

Docker Compose

  • Configure a path to pass credential environment variables to the OpenBao container in non-Cloud VM environments
  • Add credential JSON file volume mount for GCP

state.json

  • Add a seal_type field so subsequent commands can identify the current seal mode (not the source of truth for seal configuration)
  • Track recovery key provisioning status

Out of Scope

  • Transit auto-unseal (using the Transit engine of a separate OpenBao instance)
  • Korean cloud KMS support (no official OpenBao support)
  • Migrating existing Shamir deployments to auto-unseal (tracked in a separate issue)

Metadata

Metadata

Assignees

Labels

enhancementNew feature or request

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions