HashiCorp Vault — Seal & Unseal
Vault’s seal/unseal mechanism is fundamental to its security model. When Vault starts, it’s in a sealed state — it knows where encrypted data is stored but cannot decrypt it. You must unseal Vault before it can serve requests.
Why Seal/Unseal Exists
The barrier encrypts all data using an encryption key, which itself is encrypted by the master key. When Vault is sealed:
- The master key is not in memory
- No data can be decrypted
- No operations can be performed (except unseal and status checks)
This means even if an attacker gains access to the Vault server, they cannot read secrets from a sealed instance.
Sealed State Unsealed State
┌──────────────┐ ┌──────────────┐
│ Vault │ │ Vault │
│ │ │ │
│ ❌ No master│ ── unseal ──▶ │ ✅ Master │
│ key in │ │ key in │
│ memory │ │ memory │
│ │ │ │
│ ❌ Cannot │ │ ✅ Can │
│ decrypt │ │ decrypt │
│ data │ │ data │
└──────────────┘ └──────────────┘
Shamir’s Secret Sharing
By default, Vault uses Shamir’s Secret Sharing algorithm to split the master key into multiple pieces called unseal keys (or key shares).
Master Key
│
Shamir Split
┌─────────┼─────────┐
│ │ │
▼ ▼ ▼
Share 1 Share 2 Share 3
(Alice) (Bob) (Carol)
Any 2 of 3 shares can reconstruct
the master key (threshold = 2)
How it works:
- During
vault operator init, you specify:- Key shares — How many pieces to split the master key into
- Key threshold — How many shares are needed to reconstruct it
- Each share is given to a different trusted person
- To unseal Vault, the threshold number of people must provide their shares
# Initialize Vault with 5 key shares and a threshold of 3
vault operator init -key-shares=5 -key-threshold=3
# Output:
# Unseal Key 1: 4jY/+qB1...
# Unseal Key 2: Gx1N7f0p...
# Unseal Key 3: kQY9h8Bz...
# Unseal Key 4: JlN2mXqR...
# Unseal Key 5: PwZ8vKsT...
#
# Initial Root Token: hvs.abc123xyz...
#
# Vault initialized with 5 key shares and a key threshold of 3.
⚠️ Critical: Store unseal keys securely and distribute them to different people. Never store all keys in the same location.
The Unseal Process
To unseal Vault, you must provide the threshold number of key shares:
# Check seal status
vault status
# Output (sealed):
# Key Value
# --- -----
# Seal Type shamir
# Initialized true
# Sealed true ← Vault is sealed
# Total Shares 5
# Threshold 3
# Unseal Progress 0/3 ← No shares provided yet
# Provide first share
vault operator unseal 4jY/+qB1...
# Unseal Progress 1/3
# Provide second share
vault operator unseal Gx1N7f0p...
# Unseal Progress 2/3
# Provide third share (reaches threshold)
vault operator unseal kQY9h8Bz...
# Sealed false ← Vault is now unsealed!
API equivalent:
# Unseal via API
curl --request PUT \
--data '{"key": "4jY/+qB1..."}' \
http://127.0.0.1:8200/v1/sys/unseal
Auto-Unseal
Manual unsealing is impractical for production. Auto-unseal delegates the unseal operation to a trusted external service:
┌─────────────┐ ┌──────────────────┐
│ Vault │────────▶│ KMS / HSM │
│ Server │ │ │
│ │◀────────│ • AWS KMS │
│ Auto-unseal│ │ • Azure Key Vault│
│ on startup │ │ • GCP Cloud KMS │
│ │ │ • HSM (PKCS#11) │
└─────────────┘ └──────────────────┘
With auto-unseal, the master key is encrypted by the external KMS. On startup, Vault contacts the KMS to decrypt the master key automatically.
AWS KMS auto-unseal configuration:
seal "awskms" {
region = "us-east-1"
kms_key_id = "alias/vault-unseal-key"
}
Azure Key Vault auto-unseal:
seal "azurekeyvault" {
tenant_id = "your-tenant-id"
vault_name = "vault-unseal-kv"
key_name = "vault-unseal-key"
}
GCP Cloud KMS auto-unseal:
seal "gcpckms" {
project = "my-project"
region = "global"
key_ring = "vault-keyring"
crypto_key = "vault-unseal-key"
}
💡 Tip: With auto-unseal, Vault still generates recovery keys (instead of unseal keys). Recovery keys cannot unseal Vault but are needed for certain operations like generating a new root token.
Seal Types Comparison
| Feature | Shamir | Auto-Unseal |
|---|---|---|
| Unseal method | Multiple key holders provide shares | External KMS/HSM decrypts automatically |
| Human intervention | Required on every restart | None after initial setup |
| Key distribution | Must securely distribute shares | KMS access managed via IAM |
| Recovery keys | N/A (unseal keys serve this role) | Generated for administrative operations |
| Best for | High-security, air-gapped environments | Production deployments, automated operations |
The Seal Operation
You can re-seal Vault at any time. This is useful if a security breach is suspected:
# Seal Vault immediately
vault operator seal
# Output:
# Vault is sealed.
After sealing:
- All in-memory encryption keys are discarded
- No requests can be served
- The unseal process must be repeated
API equivalent:
curl --header "X-Vault-Token: $VAULT_TOKEN" \
--request PUT \
http://127.0.0.1:8200/v1/sys/seal
Seal Wrap (Enterprise)
Vault Enterprise supports seal wrap, which adds an extra layer of encryption for specific secrets using the seal mechanism (KMS/HSM):
Standard Encryption: Seal Wrap:
┌──────────┐ ┌──────────────────────┐
│ Data │ │ Data │
│ ↓ │ │ ↓ │
│ Barrier │ │ Barrier Encryption │
│ (AES) │ │ ↓ │
│ ↓ │ │ KMS/HSM Encryption │
│ Storage │ │ ↓ │
└──────────┘ │ Storage │
└──────────────────────┘
Seal wrap provides FIPS 140-2 compliance for specific secret paths.
Best Practices
| Practice | Why |
|---|---|
| Use auto-unseal in production | Eliminates manual intervention on restarts |
| Distribute Shamir shares to different people | No single person can unseal alone |
| Store recovery keys in a secure vault (physical) | Needed for root token generation |
| Test the unseal process regularly | Ensure you can recover from restarts |
| Use PGP/GPG encryption for key shares during init | Protect shares in transit |
| Set up monitoring for seal events | Alert on unexpected seals |
Quick Reference
| Command | Description |
|---|---|
vault operator init |
Initialize Vault and generate unseal keys |
vault operator init -key-shares=5 -key-threshold=3 |
Custom Shamir parameters |
vault status |
Check seal status |
vault operator unseal <key> |
Provide an unseal key share |
vault operator seal |
Re-seal Vault |
vault operator init -recovery-shares=5 -recovery-threshold=3 |
For auto-unseal recovery keys |
Next: Dev vs Production Mode