feat(docs): Explain AWS KMS auto-unseal

This commit is contained in:
hygienic-books 2025-02-04 03:04:39 +01:00
parent db1732d664
commit 6e0313a7b0

203
README.md
View File

@ -267,6 +267,209 @@ Output will for example look like:
Where the `accessor` ID (here `66IzIsoOpXycYqF33JmfIb8G`) is what you're going to want to use in your CLI command `vault token revoke`.
### Auto-unseal with AWS Key Management Service
So far we've unsealed Vault after every daemon start with multiple Shamir's Secret Sharing unseal keys or Shamir unseal keys for short. We can have a Vault instance auto-unseal itself by accessing Amazon Web Services (AWS) Key Management Service (KMS) for example via public Internet. Vault supports other providers, we're going with AWS KMS as an example.
> [!WARNING]
> Per [aws.amazon.com/kms/pricing](https://aws.amazon.com/kms/pricing) having one KMS key costs USD 1 per month pro-rated per hour of key existence. The following example assumes you're creating a symmetric encryption and decryption key with KMS as key material origin in a single region. As such API actions `kms:Encrypt`, `kms:Decrypt` and `kms:DescribeKey` (among others that we don't care about) are included in AWS KMS' Free Tier for up to 20,000 requests monthly. As long as Vault auto-unseals at most 20,000 times a month these operations won't cost you anything. A flat fee of USD 1 for the existence of a KMS key, however, applies.
#### Create resources
In AWS one way to get the necessary resources is to:
* In Key Management Service (KMS)
* Create one key
* Symmetric
* Encryption and decryption
* Key material origin KMS
* Single region
* Write down its Amazon Resource Name (ARN)
* In Identity and Access Management (IAM)
* Create an IAM policy in plain JSON, replace `<arn>` with ARN from above:
```
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "EnableKMSForVaultAutoUnseal",
"Effect": "Allow",
"Action": [
"kms:Encrypt",
"kms:Decrypt",
"kms:DescribeKey"
],
"Resource": "<arn>"
}
]
}
```
* Create a user group, attach above customer-managed policy to it
* Create a user
* Add it to the user group
* Create an access key and secret access key
#### Migrate Vault to auto-unseal with AWS KMS
The setup roughly goes like so:
* Configure Vault to use AWS KMS
* (Re-)Start Vault daemon
* Via CLI migrate unseal mechanism to AWS KMS
One way to configure Vault to do AWS KMS auto-unsealing is to specify the following environment variables. All but the fifth one (`VAULT_SEAL_TYPE=awskms`) depend on the KMS key you created so fill in the blanks with your specific key material. We're assuming that you have a Vault instance running with Docker Compose or a similar mechanism, we'll leave the implementation details to you for how to get these five environment variables into your Vault instance.
```
AWS_ACCESS_KEY_ID=
AWS_REGION=
AWS_SECRET_ACCESS_KEY=
VAULT_AWSKMS_SEAL_KEY_ID=
VAULT_SEAL_TYPE=awskms
```
(Re-)Start Vault to make the variables take effect. Vault (for example in its Docker log) will then indicate that it's entering seal migration mode:
```
core: entering seal migration mode; Vault will not automatically unseal even if using an autoseal: from_barrier_type=shamir to_barrier_type=awskms
```
At first glance when in this mode Vault will appear to behave like normal in that its web UI will be up and available. However, any attempt to unseal Vault with your previous unseal keys will do nothing.
Log in to Vault with the `vault` CLI client, see [Authenticate against Vault](#authenticate-against-vault) above. Issue the migration command as many times as you have your required Shamir unseal keys configured, enter them one at a time.
```
# vault operator unseal -migrate
# Which will prompt for:
Unseal Key (will be hidden):
```
After each `vault operator unseal -migrate` command the `vault` binary will print the current migration status like so (here after entering one of two Shamir unseal keys):
```
Key Value
--- -----
Seal Type awskms
Recovery Seal Type shamir
Initialized true
--> Sealed true
Total Recovery Shares 3
Threshold 2
--> Unseal Progress 1/2
Unseal Nonce dc..86
Seal Migration in Progress true
Version 1.18.3
Build Date 2024-12-16T14:00:53Z
Storage Type file
HA Enabled false
```
After entering the last unseal key vault will be unsealed and migrated. This will look like so:
```
# vault status
Key Value
--- -----
Seal Type awskms
Recovery Seal Type shamir
Initialized true
--> Sealed false
Total Recovery Shares 3
Threshold 2
Version 1.18.3
Build Date 2024-12-16T14:00:53Z
Storage Type file
Cluster Name vault-cluster
Cluster ID 9a..01
HA Enabled false
```
In its log output Vault will indicate that seal migration is complete. That's all there it to it: after every subsequent Vault daemon start it will attempt to access AWS KMS via public Internet and auto-unseal Vault.
#### Migrate back to Shamir unseal keys
Once a Vault instance is configured to auto-unseal with AWS KMS or any other key management provider Vault will not ever unseal via any other mechanism. If you lose Internet connectivity to AWS or the key gets deleted at AWS your Vault instance will remain locked. Your way out in this case is to migrate back to Shamir unseal keys. We'll assume that you're running Vault with Docker Compose and that you have environment variables set like so:
```
AWS_ACCESS_KEY_ID=
AWS_REGION=
AWS_SECRET_ACCESS_KEY=
VAULT_AWSKMS_SEAL_KEY_ID=
VAULT_SEAL_TYPE=awskms
```
Your container also has a bind-mounted HCL-formatted config file `/vault/config/vault.hcl`:
```
backend "file" {
path = "/vault/file"
}
listener "tcp" {
address = "0.0.0.0:8200"
tls_disable = 1
}
api_addr = "https://fully.qualified.domain.name"
disable_clustering = true
ui = true
```
Add this section to the file:
```
seal "awskms" {
disabled = true
}
```
So that the end result looks like so:
```
backend "file" {
path = "/vault/file"
}
listener "tcp" {
address = "0.0.0.0:8200"
tls_disable = 1
}
api_addr = "https://fully.qualified.domain.name"
disable_clustering = true
ui = true
seal "awskms" {
disabled = true
}
```
Also remove the environment variable `VAULT_SEAL_TYPE` from your container or at least change it to an empty string (`VAULT_SEAL_TYPE=`). Now (re-)start Vault and it'll report:
```
core: entering seal migration mode; Vault will not automatically unseal even if using an autoseal: from_barrier_type=awskms to_barrier_type=shamir
```
The rest is the reverse of [Migrate Vault to auto-unseal with AWS KMS](#migrate-vault-to-auto-unseal-with-aws-kms): log in to Vault via CLI `vault` binary and do a few incantations of `vault operator unseal -migrate`. Use your Shamir unseal keys. After successful migration `vault` binary will print:
```
Key Value
--- -----
--> Seal Type shamir
Initialized true
Sealed false
Total Shares 3
Threshold 2
Version 1.18.3
Build Date 2024-12-16T14:00:53Z
Storage Type file
Cluster Name vault-cluster
Cluster ID 9a..01
HA Enabled false
```
You now have decoupled Vault from AWS KMS and are back to using Shamir unseal keys. After every Vault daemon restart you'll have to manually unseal your instance again.
## Clean-up
If during any of the above steps you've used the Vault command-line client to authenticate against Vault with your `root` token make sure that client's `~/.vault-token` file is deleted. It contains the verbatim `root` token.