Instructions inspired from auto unseal with transit guide
Prerequisites
- Docker
vault
CLI
# make persistent directories and set permissions
mkdir -p vault/config
mkdir -p vault/data
sudo chown 100:100 vault/data
# make initial config file
tee vault/config/config.hcl <<EOF
storage "file" {
path = "/vault/data"
}
listener "tcp" {
tls_disable = 1
address = "[::]:8200"
cluster_address = "[::]:8201"
}
EOF
# run vault server
docker run -d --name vault --cap-add=IPC_LOCK -p 8200:8200 -v $(pwd)/vault/config:/vault/config -v $(pwd)/vault/data:/vault/data vault server
# initialize vault & make note of root token and unseal key
VAULT_ADDR=http://127.0.0.1:8200 vault operator init -n 1 -t 1
# unseal the vault server
VAULT_ADDR=http://127.0.0.1:8200 vault operator unseal <unseal key from above>
# login to the vault server with the root token
VAULT_ADDR=http://127.0.0.1:8200 vault login <root token from above>
# Enable the transit secrets engine
VAULT_ADDR=http://127.0.0.1:8200 vault secrets enable transit
# Create a key named 'autounseal'
VAULT_ADDR=http://127.0.0.1:8200 vault write -f transit/keys/autounseal
# Create a policy file
tee autounseal.hcl <<EOF
path "transit/encrypt/autounseal" {
capabilities = [ "update" ]
}
path "transit/decrypt/autounseal" {
capabilities = [ "update" ]
}
EOF
# Create an 'autounseal' policy
VAULT_ADDR=http://127.0.0.1:8200 vault policy write autounseal autounseal.hcl
# Create a client token with autounseal policy attached and response wrap it with TTL of 600 seconds.
VAULT_ADDR=http://127.0.0.1:8200 vault token create -policy="autounseal" -wrap-ttl=600
# make note of the "wrapping_token" from the output above
# unwrap the autounseal token and capture the client token
VAULT_ADDR=http://127.0.0.1:8200 VAULT_TOKEN=<wrapping_token> vault unwrap
# make note of the "token" - this will be the client token used for vault instance #2
# make persistent directories and set permissions
mkdir -p vault2/config
mkdir -p vault2/data
sudo chown 100:100 vault2/data
# make initial config file
tee vault2/config/config.hcl <<EOF
storage "file" {
path = "/vault/data"
}
listener "tcp" {
tls_disable = 1
address = "[::]:8200"
cluster_address = "[::]:8201"
}
seal "transit" {
address = "http://<ip adress of the host where the first vault server is running>:8200"
disable_renewal = "false"
key_name = "autounseal"
mount_path = "transit/"
tls_skip_verify = "true"
}
EOF
# run vault server
docker run -d --name vault2 --cap-add=IPC_LOCK -p 8100:8200 -e VAULT_TOKEN="<client token obtained from vault server 1 above>" -v $(pwd)/vault2/config:/vault/config -v $(pwd)/vault2/data:/vault/data vault server
# initialize vault & make note of root token and unseal key
VAULT_ADDR=http://127.0.0.1:8100 vault operator init -recovery-shares=1 -recovery-threshold=1
# unseal the vault server
VAULT_ADDR=http://127.0.0.1:8100 vault operator unseal <unseal key from above>
# login to the second vault server with the root token
VAULT_ADDR=http://127.0.0.1:8100 vault login <root token from above>
# Enable the transit secrets engine
VAULT_ADDR=http://127.0.0.1:8100 vault secrets enable transit
# Create a key named 'autounseal'
VAULT_ADDR=http://127.0.0.1:8100 vault write -f transit/keys/autounseal
# Create a policy file
tee autounseal.hcl <<EOF
path "transit/encrypt/autounseal" {
capabilities = [ "update" ]
}
path "transit/decrypt/autounseal" {
capabilities = [ "update" ]
}
EOF
# Create an 'autounseal' policy
VAULT_ADDR=http://127.0.0.1:8100 vault policy write autounseal autounseal.hcl
# Create a client token with autounseal policy attached and response wrap it with TTL of 600 seconds.
VAULT_ADDR=http://127.0.0.1:8100 vault token create -policy="autounseal" -wrap-ttl=600
# make note of the "wrapping_token" from the output above
# unwrap the autounseal token and capture the client token
VAULT_ADDR=http://127.0.0.1:8100 VAULT_TOKEN=<wrapping_token> vault unwrap
# make note of the "token" - this will be the client token used for vault instance #2
# append transit seal type to first vault server config file
tee -a vault/config/config.hcl <<EOF
seal "transit" {
address = "http://<ip adress of the host where the second vault server is running>:8200"
disable_renewal = "false"
key_name = "autounseal"
mount_path = "transit/"
tls_skip_verify = "true"
}
EOF
# shut-down first vault server
docker rm -f vault
# restart first vault server with the client token obtained from the previous step
docker run -d --name vault --cap-add=IPC_LOCK -p 8200:8200 -e VAULT_TOKEN="<client token obtained from vault server 2 above>" -v $(pwd)/vault/config:/vault/config -v $(pwd)/vault/data:/vault/data vault server
# unseal the first vault server again
VAULT_ADDR=http://127.0.0.1:8200 vault operator unseal <unseal key for first vault server>
# login to the first vault server with the root token
VAULT_ADDR=http://127.0.0.1:8200 vault login <root token for first vault server>
# migrate the unseal type from shamir to the transit type this was just configured for
VAULT_ADDR=http://127.0.0.1:8200 vault operator unseal -migrate
Now the two vault servers will unseal each-other.
It is important to note that this approach has a big downside: If both vault instances are shut-down, the auto-unsealing approach described above will not work. It will be necessary to manually-unseal each vault instance before they can auto-unseal each other.