hashicorp/vault
Auto-unseal
Auto-unseal replaces the human Shamir-share workflow with an external KMS that wraps Vault's keyring. After the first init, every subsequent start unseals automatically — there's no operator in the loop. Implementation: vault/seal_autoseal.go, vault/seal/, with vendor wrappers from hashicorp/go-kms-wrapping/v2.
Why operators want it
Shamir is a great property for "the human in the room owns this Vault." It's a poor fit for autoscaling clusters, container restarts, or multi-region deployments where you can't pre-stage humans for every unseal event. Auto-unseal trades the threshold ceremony for trust in a cloud KMS or HSM.
Supported seal types
The seal block in the server config selects the type. Each maps to a specific wrapper in go-kms-wrapping:
seal "..." block |
KMS / HSM | Notes |
|---|---|---|
awskms |
AWS KMS | IAM credentials or instance role. |
gcpckms |
Google Cloud KMS | service account or workload identity. |
azurekeyvault |
Azure Key Vault | service principal or managed identity. |
ocikms |
Oracle Cloud KMS | OCI principal config. |
transit |
Another Vault cluster's transit engine | Useful for "Vault unseals Vault" patterns. |
pkcs11 (Enterprise) |
HSM via PKCS#11 | Closed-source. |
aead |
Local AEAD | Test only. |
The wrappers themselves come from github.com/hashicorp/go-kms-wrapping/v2 and wrappers/<name>/v2 modules.
Configuration
storage "raft" {
path = "/vault/data"
node_id = "vault-1"
}
seal "awskms" {
region = "us-east-1"
kms_key_id = "alias/vault-seal"
}
listener "tcp" {
address = "0.0.0.0:8200"
tls_cert_file = "/etc/vault/tls/cert.pem"
tls_key_file = "/etc/vault/tls/key.pem"
}Multiple seal blocks are allowed (Enterprise) so the keyring is wrapped redundantly across vendors.
How it works
sequenceDiagram
participant V as Vault start
participant Seal as autoSeal
participant KMS as External KMS
participant Phys as Storage
V->>Phys: read core/seal-config and core/keyring
V->>Seal: Unseal with stored ciphertext
Seal->>KMS: Decrypt(ciphertext)
KMS-->>Seal: keyring plaintext
Seal->>V: keyring loaded
V->>V: PostUnseal: mount backends, start expiration, ...On first init, Vault generates the keyring, encrypts it with the configured KMS key, and stores the ciphertext at core/keyring. On subsequent starts, it reads the ciphertext and asks the KMS to decrypt — no Shamir shares are required.
Recovery key
Even with auto-unseal, some operations (operator generate-root, operator rekey-recovery-key) require human authorization. For those, Vault keeps a separate recovery key that is Shamir-split. vault operator init -recovery-shares=5 -recovery-threshold=3 is the equivalent of Shamir init for an auto-unsealed cluster.
vault/generate_root_recovery.go is the dedicated flow.
Migration
Switching from Shamir to KMS, or from one KMS to another, is supported in-place:
# new seal config
seal "shamir" { disabled = true }
seal "awskms" {
region = "us-east-1"
kms_key_id = "alias/vault-seal"
}Start the cluster, then run vault operator unseal -migrate <shamir share>. Vault rewraps the keyring with the new wrapper on every node before completing unseal.
Failure modes
- KMS unreachable at unseal time — Vault stays sealed and retries. The
auto_unsealmetric reports the consecutive failure count. - Wrong KMS key — Vault refuses to unseal; logs
recover from sealed configuration. - Multi-seal disagreement (Enterprise) — Vault unseals if at least one wrapper succeeds, but logs the lagging wrappers and surfaces them via
seal-status.
Integration points
- Configured in server config.
- Wraps the seal keyring.
- The recovery key flow takes the place of operator-level Shamir actions.
command/server.go::setSealbuilds the seal stack fromsealblocks and theentropyblock (for HSM-backed entropy augmentation).
Operator commands
vault operator init -recovery-shares=… -recovery-threshold=…— initialize an auto-unseal cluster.vault operator generate-root -recovery— start a root-token generation that requires the recovery key.vault operator rekey -target=recovery— rekey the recovery shares.vault operator unseal -migrate— migrate from Shamir to/from auto-unseal.
Entry points for modification
- New KMS vendor: implement a
wrapping.Wrapperingo-kms-wrapping, add theseal "<type>"parser tocommand/server.go::setSeal. - Tweak retry semantics on KMS failure:
vault/seal_autoseal.go. - Multi-seal redundancy logic:
vault/seal/seal.goandvault/seal/seal_wrapper.go.
Built by Factory AutoWiki from public repository content. It is a generated preview for codebase exploration, not source-maintained documentation.