How to Configure AWS KMS for Vault Auto-Unseal
Rather than manually unsealing Vault in the homelab every time updates are applied, it'd be preferable to have it auto-unseal using an AWS Key Management Server. This is how to setup the AWS part.
When I started using HashiCorp Vault in anger in my lab last year, I did what a lot of people probably did:
- Start with a single Vault host using file-based storage
- Create a Consul cluster for storage, still using a single Vault host
- Add another Vault host and stick a load-balancer in front of them
What I never changed throughout all of those steps was the mechanism used to seal and unseal Vault. By default, when you first initialise Vault a series of 5 unseal keys are created. These should be given to 5 different people and any 3 of those keys can be used to unseal Vault (think of it like undoing the deadbolts on your door).
Until it's unsealed, no-one can read or write any secrets and load-balancer health checks will fail. Yes it's secure, but if you path a Vault server or restart the service then it comes back up sealed. Manual intervention is required to unseal it.
In my lab it's not a huge problem, and probably why I did nothing about it for so long. I have all 5 unseal keys in my password safe and I'm the one who uses Vault. But, if I create a process to automate host patching that relies on being able to get credentials out of Vault then I've got myself a bit of a conundrum.
Luckily there are some options to configure auto-unsealing using an AWS Key Management Server that works very nicely with Vault. I decided to get it setup. Here's how...
Instructions
This guide assumes that you have an AWS account and have the AWS CLI tool installed. You'll also need access / secret keys for an AWS account that has sufficient privileges to perform the actions below.
Planning
The first step is to do a little planning. I selected the values for the following configuration items ahead of time:
Item | Value | Purpose |
---|---|---|
AWS region | eu-west-2 | The region within AWS where the KMS will be created |
IAM Path | /v12n/production/vault/ | A path within AWS IAM to create users and group objects in (optional) |
IAM Group Name | VaultKMSUnsealGroup | Name for the new group that will be created in AWS |
IAM Policy Name | VaultKMSUnsealPolicy | Name for the new policy that will be created in AWS - this policy controls the operations that group members can execute |
IAM User Name | VaultKMSUnsealUser | Name of the new user that will be created in AWS |
KMS Key Alias | VaultKMSUnsealKey | Alias / friendly name of the KMS key |
Create a new IAM group
- Open a new terminal
- Execute the following command to create a new IAM group:
aws iam create-group --group-name {{IAM Group Name}} --path {{IAM Path}}
- Verify that a success response is received that includes the ARN of the group created
Create a new IAM policy
- In the same terminal from before, create a JSON file with the following content (adjust the region in the Resource line to match the table above):
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": ["kms:Encrypt", "kms:Decrypt", "kms:DescribeKey"], "Resource": "arn:aws:kms:eu-west-2::key/*" } ] }
- Optionally, the resource used can be refined or opened up to limit access to specific resources.
- Execute the following command to create a new IAM policy:
aws iam create-policy --policy-name {{IAM Policy Name}} --path {{IAM Path}} --policy-document file://policy.json
- Verify that a success response is received that includes the ARN of the policy created
Attach the IAM policy to the group
- Copy the policy ARN from the output of the previous command
- Paste it in to the following command to attach the policy to the group (replace the example ARN shown):
aws iam attach-group-policy --group-name {{IAM Group Name}} --policy-arn arn:aws:iam::nnnn:policy/v12n/production/vault/VaultKMSUnsealPolicy
- The above command doesnt provide any output but success can be verified using the following:
aws iam list-attached-group-policies --group-name {{IAM Group Name}}
Create a new IAM user and access keys
- Execute the following command to create a new IAM user:
aws iam create-user --user-name {{IAM User Name}} --path {{IAM Path}}
- Verify that a success response is received that includes the ARN of the user created
- Execute the following command to create an access key for the user:
aws iam create-access-key --user-name {{IAM User Name}}
- If successful, make sure that the AccessKeyId and SecretAccessKey are copied and stored in a secure place!
Add the IAM user to the group
- Execute the following command to add the user created above to the group created earlier:
aws iam add-user-to-group --user-name {{IAM User Name}} --group-name {{IAM Group Name}}
- The above command doesnt provide any output but success can be verified using the following:
aws iam list-groups-for-user --user-name {{IAM User Name}}
Create a KMS key for Vault
- Execute the following command to create new Symmetric Key:
aws kms create-key --description "v12n Production Vault Unseal Key"
- Verify that a success response is received that includes the ARN and KeyId of the key created
- Record the KeyId in a secure place!
- (Optional) Create an alias for the key using the following command:
aws kms create-alias --alias-name alias/{{KMS Key Alias}} --target-key-id {{KMS KeyId}}
Next Steps
All of the above can be completed through the AWS console as well, but who doesn't love a command line?
In my next post I'll cover migration of my Vault server across to use AWS auto-unseal.