Auto-unseal using Azure Key Vault

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

» 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.


» Prerequisites

This guide assumes the following:

» Terraform Azure Provider Prerequisites

A service principal is an application within Azure Active Directory which can be used to authenticate. Service principals are preferable to running an app using your own credentials. Follow the instruction in the Terraform documentation to create a service principal.

The following Azure credentials will be needed to perform the steps in this guide:

» Download demo assets

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

» Steps

This guide demonstrates how to implement and use the Auto-unseal feature using Azure Key Vault. You are going to perform the following steps:

  1. Provision the Cloud Resources
  2. Test the Auto-unseal Feature
  3. Clean Up

» Step 1: Provision the Cloud Resources

Be sure to set your working directory to where the /operations/azure-keyvault-unseal folder is located.

The working directory should contain the provided Terraform files:


The main.tf generates a new resource group with:

  • Virtual machine with Vault already installed
  • Azure Vault Key (Test-vault-xxxx)
  • A key (generated-key)

Set your Azure credentials in the terraform.tfvars.example and save it as terraform.tfvars. Overwrite the default variable values (variables.tf) as needed.

Example terrafrom.tfvars:

public_key = "ssh-rsa AAAA..."

Now you are ready to provision the cloud resources using Terraform.

# Initialize the Azure provider plugins
$ terraform init

# Create an execution plan
$ terraform plan
Plan: 12 to add, 0 to change, 0 to destroy.

# Apply the changes
$ terraform apply -auto-approve

ip =
key_vault_name = Test-vault-1e5a88de
ssh-addr =
    Connect to your virtual machine via SSH:

    $ ssh azureuser@

» Step 2: Test the Auto-unseal Feature

Execute the following command to retrieve your virtual machine information:

$ terraform output ssh-addr

SSH to connect to your virtual machine with username, azureuser:

$ ssh azureuser@<IP_address>

Run vault status command to check current status:

$ vault status

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

Notice that Initialized is false.

Run the vault operator init command to initialize the Vault server so that you can unseal:

$ vault operator init

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    5
Threshold                3
Version                  1.1.0
Cluster Name             vault-cluster-092ba5de
Cluster ID               8b173565-7d74-fe5b-a199-a2b56b7019ee
HA Enabled               false

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

In the service log, you should find a trace where Azure Vault key is being fetched to unseal the Vault server.

$ sudo journalctl --no-pager -u vault

==> Vault server configuration:
        Azure Environment: AzurePublicCloud
           Azure Key Name: generated-key
         Azure Vault Name: Test-vault-a414d041
                Seal Type: azurekeyvault
                      Cgo: disabled
               Listener 1: tcp (addr: "", cluster address: "", max_request_duration: "1m30s", max_request_size: "33554432", tls: "disabled")
                Log Level: (not set)
                    Mlock: supported: true, enabled: false
                  Storage: file
                  Version: Vault v1.1.0
              Version Sha: 37a1dc9c477c1c68c022d2084550f25bf20cac33
 ==> Vault server started! Log data will stream in below:
 2019-01-22T19:43:29.114Z [WARN]  no `api_addr` value specified in config or in VAULT_API_ADDR; falling back to detection if possible, but this value should be manually set
 2019-01-22T19:43:29.121Z [INFO]  core: stored unseal keys supported, attempting fetch
 2019-01-22T19:43:29.162Z [INFO]  core: vault is unsealed

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

$ sudo systemctl restart vault

$ vault status

Explorer the systemd configuration for Vault server which is located at /lib/systemd/system/vault.service:

$ cat /lib/systemd/system/vault.service

Description=Vault Agent
ExecStartPre=/sbin/setcap 'cap_ipc_lock=+ep' /usr/local/bin/vault
ExecStart=/usr/local/bin/vault server -config /etc/vault.d
ExecReload=/bin/kill -HUP

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

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

storage "file" {
  path = "/opt/vault"
listener "tcp" {
  address     = ""
  tls_disable = 1
seal "azurekeyvault" {
  client_id      = "YOUR-APP-ID"
  client_secret  = "YOUR-APP-PASSWORD"
  tenant_id      = "YOUR-AZURE-TENANT-ID"
  vault_name     = "Test-vault-XXXXXX"
  key_name       = "generated-key"
disable_mlock = true

Notice the Vault configuration file defines the azurekeyvault stanza with all parameter values properly populated: client ID, client secret, tenant ID, vault name (generated by Terraform), and Azure Key Vault key name.

» Step 3: Clean Up

Once completed, execute the following commands to clean up:

$ terraform destroy -auto-approve

$ rm -rf .terraform terraform.tfstate*

» Help and Reference