Operations

Auto-unseal using AWS KMS

When a Vault server is started, it starts in a sealed state and it does not know how to decrypt data. Before any operation can be performed on the Vault, it must be unsealed. Unsealing is the process of constructing the master key necessary to decrypt the data encryption key.

Unseal with Shamir's Secret Sharing

This guide demonstrates an example of how to use Terraform to provision an instance that can utilize an encryption key from AWS Key Management Services (KMS) to unseal Vault.

Challenge

Vault unseal operation requires a quorum of existing unseal keys split by Shamir's Secret sharing algorithm. This is done so that the "keys to the kingdom" won't fall into one person's hand. However, this process is manual and can become painful when you have many Vault clusters as there are now many different key holders with many different keys.

Solution

Vault supports opt-in automatic unsealing via cloud technologies: AliCloud KMS, Amazon KMS, Azure Key Vault, and Google Cloud KMS. This feature enables operators to delegate the unsealing process to trusted cloud providers to ease operations in the event of partial failure and to aid in the creation of new or ephemeral clusters.

Unseal with AWS KMS

Prerequisites

This guide assumes the following:

  • AWS account for provisioning cloud resources
  • Terraform installed and basic understanding of its usage

Download demo assets

Clone or download the demo assets from the hashicorp/vault-guides GitHub repository to perform the steps described in this guide.

Step 1: Provision the Cloud Resources

Be sure to set your working directory to where the /operations/aws-kms-unseal/terraform-aws folder is located.

The working directory should contain the provided Terraform files:

$ cd vault-guides/operations/aws-kms-unseal/terraform-aws

$ tree
.
├── README.md
├── instance-profile.tf
├── instance.tf
├── main.tf
├── private.key
├── ssh-key.tf
├── terraform.tfvars.example
├── userdata.tpl
├── variables.tf
└── versions.tf

0 directories, 10 files

Set your AWS credentials as environment variables:

$ export AWS_ACCESS_KEY_ID = "<YOUR_AWS_ACCESS_KEY_ID>"

$ export AWS_SECRET_ACCESS_KEY = "<YOUR_AWS_SECRET_ACCESS_KEY>"

By default, AWS resources will be provisioned in the us-east-1 region. If you wish to use another AWS region, create a file named terraform.tfvars and set the appropriate aws_region and aws_zone. (Reference the provided terraform.tfvars.example.)

Example:

aws_region = "us-west-1"
aws_zone = "us-west-1a"

Perform a terraform init to pull down the necessary provider resources. Then terraform plan to verify your changes and the resources that will be created. If all looks good, then perform a terraform apply to provision the resources.

$ terraform init
Initializing provider plugins...
...
Terraform has been successfully initialized!


$ terraform plan
...
Plan: 15 to add, 0 to change, 0 to destroy.


$ terraform apply -auto-approve
...
Apply complete! Resources: 15 added, 0 changed, 0 destroyed.

Outputs:

connections = Connect to Vault via SSH   ssh ubuntu@192.0.2.1 -i private.key
Vault web interface  http://192.0.2.1:8200/ui

Step 2: Test the Auto-unseal Feature

SSH into the provisioned EC2 instance.

$ ssh ubuntu@192.0.2.1 -i private.key
...
Are you sure you want to continue connecting (yes/no)? yes

When you are prompted, enter "yes" to continue.

To verify that Vault has been installed, run vault status command and notice that Initialized is false.

# First, set the VAULT_ADDR environment variable
$ export VAULT_ADDR=http://127.0.0.1:8200

# Check Vault server status
$ vault status

Key                      Value
---                      -----
Recovery Seal Type       awskms
Initialized              false
Sealed                   true
Total Recovery Shares    0
Threshold                0
Unseal Progress          0/0
Unseal Nonce             n/a
Version                  n/a
HA Enabled               false

Run the vault operator init command to initialize the Vault server by setting its key share to be 1 as follow:

$ vault operator init -recovery-shares=1 -recovery-threshold=1
Recovery Key 1: SbtJYhWnOaRlM3xrydq5J2lmUOXyxmK5qWixAdnUEPk=

Initial Root Token: s.20JnHBY66EKTj9zyR6SjTMNq

Success! Vault is initialized

Recovery key initialized with 1 key shares and a key threshold of 1. Please
securely distribute the key shares printed above.

Check the Vault status to verify that it has been initialized and unsealed.

$ vault status

Key                      Value
---                      -----
Recovery Seal Type       shamir
Initialized              true
Sealed                   false
Total Recovery Shares    1
Threshold                1
Version                  1.3.0
Cluster Name             vault-cluster-a06dedd4
Cluster ID               a88c09e4-fbfe-9ddd-e424-b1b46cb81254
HA Enabled               false

Notice that the Vault server is already unsealed (Sealed is false).

Restart the Vault server to ensure that Vault server gets automatically unsealed:

$ sudo systemctl restart vault

$ vault status

Log into Vault using the generated initial root token:

$ vault login s.20JnHBY66EKTj9zyR6SjTMNq

Success! You are now authenticated. The token information displayed below
is already stored in the token helper. You do NOT need to run "vault login"
again. Future Vault requests will automatically use this token.

Key                  Value
---                  -----
token                s.20JnHBY66EKTj9zyR6SjTMNq
token_accessor       5mRVTsVHR8zx2ajUDWhYyxmQ
token_duration       ∞
token_renewable      false
token_policies       ["root"]
identity_policies    []
policies             ["root"]

Review the Vault configuration file (/etc/vault.d/vault.hcl).

$ cat /etc/vault.d/vault.hcl

storage "file" {
  path = "/opt/vault"
}
listener "tcp" {
  address     = "0.0.0.0:8200"
  tls_disable = 1
}
seal "awskms" {
  region = "us-east-1"
  kms_key_id = "d7c1ffd9-8cce-45e7-be4a-bb38dd205966"
}
ui=true

Notice the Vault configuration file defines the awskms stanza which sets the AWS KMS key ID to use for encryption and decryption.

At this point, you should be able to launch the Vault Enterprise UI by entering the address provided in the terraform apply outputs (e.g. http://192.0.2.1:8200/ui) and log in with your initial root token.

Vault Enterprise UI Login

Step 3: Clean Up

Once completed, execute the following commands to clean up:

$ terraform destroy -force

$ rm -rf .terraform terraform.tfstate* private.key

Help and Reference