Unlocking the Secrets of Vault Auto Unseal: A Star Wars Journey
Written on
Chapter 1: Embarking on a Galactic Adventure
Prepare to journey through the galaxy as we set up Rebel bases, wield the lightsaber of transit auto unseal, navigate the Galactic Senate of policies, and infuse our adventure with the essence of Star Wars.
Today, we will delve into the capabilities of the auto unseal feature provided by Vault. In our first episode, we examined the default unsealing mechanism that employs Shamir’s secret sharing algorithm; today, we will focus on the transit key method. Why this shift? As Hashicorp pointed out, the manual process can become cumbersome when managing multiple Vault clusters, each with its own set of key holders and keys.
Table of Contents:
- Deploying the Rebel Alliances: Vault Instances
- Transit Auto Unseal: The Jedi Code for Vault-2
- Initial Vault Configuration
- The Epic Journey: Auto Unsealing in Action
- Conclusion: May the Vault Be with You!
Section 1.1: Deploying the Rebel Alliances: Vault Instances
In our previous episodes, we established a Vault instance managed through Terraform. While this setup serves its purpose, it is not ideal for production environments. For this episode, we will deploy an additional Vault instance within our Minikube cluster, housed in a separate namespace. This new instance will have the transit secret engine activated, and we will configure the original cluster to utilize the auto unseal process.
In a production-grade environment, the architecture depicted below illustrates a straightforward approach for implementing an effective unsealing mechanism.
Section 1.2: HA Auto Unseal Process
If you've been following along, you should know how to deploy Vault using Terraform. Now, we will introduce a new module for our second Vault instance, using a new file named vault-2.tf.
module "vault_2" {
source = "./modules/helmCharts"
release_name = "vault-2"
chart = "vault"
release_version = "0.27.0"
namespace = "vault-2"
initiate_namespace = true
purge_process = true
set = [
{
name = "ui.enabled"
value = "true"
},
{
name = "ui.serviceType"
value = "NodePort"
},
{
name = "injector.injector.enabled"
value = "true"
},
{
name = "server.dataStorage.storageClass"
value = "openebs-hostpath"
},
{
name = "server.dataStorage.size"
value = "10Gi"
},
{
name = "server.auditStorage.enabled"
value = "false"
},
{
name = "server.auditStorage.enabled"
value = "true"
},
{
name = "server.auditStorage.size"
value = "2Gi"
},
{
name = "server.auditStorage.storageClass"
value = "openebs-hostpath"
},
]
depends_on = [module.openebs]
}
Deploy this new instance and follow the steps from earlier episodes to unseal the new cluster. We’ve enabled auditing for this instance to maintain a comprehensive log of all requests to Vault. Now, you will have two namespaces: vault and vault-2, each with its own pods operating on persistent volumes.
Chapter 2: Transit Auto Unseal: The Jedi Code for Vault-2
As we govern our galaxy with Terraform, we will enable the transit key in the new Vault cluster while establishing the necessary policies and configurations.
The first step involves configuring the provider for the second Vault. Add the following snippet to the provider.tf file:
provider "vault" {
alias = "vault-2"
address = "http://127.0.0.1:42699"
token = "hvs.MVcqMb3VPxi8UBYyyM1EMt9d"
}
Using an alias allows the Vault provider to differentiate where to provision resources. Next, update all Terraform code to utilize either the first or the second provider accordingly.
Let's create our transit key engine and a policy in the second Vault. Add the following snippet to the vault-2.tf file:
module "transit_policy" {
providers = {
vault = vault.vault-2}
source = "./modules/policies"
policy_name = "transit"
file_name = file("policies/transit.hcl")
}
resource "vault_mount" "transit" {
provider = vault.vault-2
path = "transit"
type = "transit"
description = "Example description"
default_lease_ttl_seconds = 3600
max_lease_ttl_seconds = 86400
}
resource "vault_transit_secret_backend_key" "key" {
backend = vault_mount.transit.path
name = "transit"
provider = vault.vault-2
}
The policy should be crafted in the policies directory, named transit.hcl:
path "transit/encrypt/autounseal" {
capabilities = [ "update" ]
}
path "transit/decrypt/autounseal" {
capabilities = [ "update" ]
}
Upon applying the Terraform configuration, you should observe the transit secret engine enabled and the policy established in the second Vault. Now, let's create our Jedi token utilizing the policy:
vault token create -orphan -policy=transit -period=24h
In Vault, behold the periodic orphan token we've conjured for the sacred task of auto-unsealing. The term "orphan" indicates that this newly minted token stands alone, without a parent to be revoked alongside. It’s a solitary defender, prepared to tackle the challenges of auto-unsealing. Notably, the transit auto-unseal token is designed for automatic renewal by default.
Discover why this Star Wars saga is surprising fans again in this YouTube video.
Section 2.1: Initial Vault Configuration
Next, we must configure the first Vault to support the unseal process. All aspects of Vault can be set up using a configuration file. Since we manage Vault through Helm, we will update the first Vault by adding a values.yaml file to integrate the existing configuration with the new settings.
Create a file named values.yaml in the policies folder and include this snippet:
server:
standalone:
enabled: true
config: |
disable_mlock = true
ui=true
storage "file" {
path = "/vault/data"}
listener "tcp" {
tls_disable = 1
address = "[::]:8200"
cluster_address = "[::]:8201"
}
seal "transit" {
address = "http://vault-2-internal.vault-2.svc.cluster.local:8200"
token = "hvs.CAESIH2TmACLHT8Z5NxDhQGsXVPAr4dopwMOimlbi9x5TVzMGh4KHGh2cy43ZFdkbUI3OElVTVJQZVBEVkI3U2w2MEg"
disable_renewal = "false"
key_name = "transit"
mount_path = "transit/"
tls_skip_verify = "true"
}
The added seal section references the second Vault's address. The token corresponds to the one we previously created using the policy, while key_name and mount_path align with the defaults.
Update the Helm chart module as follows:
resource "helm_release" "helm_chart" {
version = var.release_version
name = var.release_name
repository = var.repository
chart = var.chart
namespace = var.namespace
create_namespace = var.initiate_namespace
atomic = var.purge_process
dynamic "set" {
for_each = var.set
content {
name = set.value.name
value = set.value.value
}
}
values = var.values
}
We’ve introduced a values resource attribute to accommodate the file we wish to merge. Add the following variable to the variables.tf file:
variable "values" {
type = list(string)
default = [ ]
}
Now, update the main module file:
module "vault" {
source = "./modules/helmCharts"
release_name = "vault"
values = [ "${file("./policies/values.yaml")}" ]
chart = "vault"
release_version = "0.27.0"
namespace = "vault"
initiate_namespace = true
purge_process = true
set = [
{
name = "ui.enabled"
value = "true"
},
{
name = "ui.serviceType"
value = "NodePort"
},
{
name = "injector.injector.enabled"
value = "true"
},
{
name = "server.dataStorage.storageClass"
value = "openebs-hostpath"
},
{
name = "server.dataStorage.size"
value = "10Gi"
},
{
name = "server.auditStorage.enabled"
value = "false"
}
]
depends_on = [module.openebs]
}
Deploy this configuration with Terraform.
Now, access the Vault that has the unseal configuration and instruct Vault to transition from the default unseal process to the transit unseal:
vault operator unseal -migrate
In a production environment, the auto unseal migration differs from what we've executed. Production setups employ a multi-node Vault with a leader and standby nodes.
Here are the steps for unseal migration in a multi-node cluster:
- Unseal migration on standby node 1
- Unseal migration on standby node x
- vault operator step-down on the leader node
- Unseal migration on the leader
Chapter 3: The Epic Journey: Auto Unsealing in Action
After deploying the new configuration, delete the pod of the first instance. Once it restarts, it will be unsealed.
With each initiation of Vault featuring the Auto-Unseal configuration, a fresh set of Recovery keys appears, distinct from the traditional Unseal Keys. It’s vital to understand that these Recovery keys serve a specialized purpose—they aren’t intended for the primary act of unsealing Vault. Instead, they are linked to authorization functions, enabling actions like generating a new root token. In the complex dance of Vault security, these keys have a specific choreography that ensures a delicate balance between access and safeguarding the sanctity of Vault’s secrets.
Watch this detailed breakdown of BAD BATCH Season 3 Episode 5, uncovering every Star Wars Easter egg you might have missed!
Conclusion: May the Vault Be with You!
Thus, our expedition through the intricate universe of Transit Auto Unseal in Vault reaches its final destination. As we bid farewell to the cosmic choreography of cryptographic keys and the orchestration of access control, let the insights gained from this transit auto unseal process resonate throughout the digital realms.
In the world of Vault, Transit Auto Unseal stands as the unsung champion, wielding the power to seamlessly recover and unveil the mysteries within. The automatic renewal of our periodic orphan token, standing strong without a parent, adds an element of intrigue to this cryptographic ballet.
May the force be with your Vault!
Connect
Connect with me on LinkedIn: ebenamor
GitHub: Profile