๐ Secret Management on HashiCorp Vault
Intro: Secret managers exist because CI variables, repo files, and host-level config files stop scaling safely once environments and teams multiply.
What Vault does
Vault is a secret-management control plane that supports:
- static secrets through KV engines
- dynamic secrets on demand
- transit encryption and signing workflows
- PKI issuance
- policy-based access and audit logging
How it works
- a client authenticates through token, AppRole, Kubernetes auth, OIDC/JWT, or cloud auth
- Vault maps identity to policies
- Vault returns a secret, a lease, or performs a crypto action
- audit devices record the action
- credentials can expire and be revoked
Basic lab install
curl -fsSL https://apt.releases.hashicorp.com/gpg | sudo gpg --dearmor -o /usr/share/keyrings/hashicorp-archive-keyring.gpg
echo "deb [signed-by=/usr/share/keyrings/hashicorp-archive-keyring.gpg] https://apt.releases.hashicorp.com $(lsb_release -cs) main" | sudo tee /etc/apt/sources.list.d/hashicorp.list
sudo apt-get update && sudo apt-get install -y vault
ui = true
listener "tcp" {
address = "0.0.0.0:8200"
tls_disable = 1
}
storage "file" {
path = "/opt/vault/data"
}
api_addr = "http://127.0.0.1:8200"
disable_mlock = true
Basic init and KV v2 use
export VAULT_ADDR='http://127.0.0.1:8200'
vault operator init
vault operator unseal
vault login
vault secrets enable -path=secret kv-v2
vault kv put secret/payments/api username="svc-payments" password="REPLACE_ME"
vault kv patch secret/payments/api password="ROTATED_VALUE"
Kubernetes auth example
vault auth enable kubernetes
vault write auth/kubernetes/config kubernetes_host="https://$KUBERNETES_SERVICE_HOST:$KUBERNETES_SERVICE_PORT"
vault write auth/kubernetes/role/payments-api bound_service_account_names=payments-api bound_service_account_namespaces=payments policies=payments-app ttl=1h
HA with Raft
storage "raft" {
path = "/vault/data"
node_id = "vault-1"
retry_join { leader_api_addr = "https://vault-0.internal:8200" }
retry_join { leader_api_addr = "https://vault-1.internal:8200" }
retry_join { leader_api_addr = "https://vault-2.internal:8200" }
}
api_addr = "https://vault-1.internal:8200"
cluster_addr = "https://vault-1.internal:8201"
disable_mlock = true
Common mistakes
- using dev mode outside local experimentation
- no TLS in production paths
- one shared root token for operators
- no audit devices
- static secrets only where dynamic leases would help
- no restore testing for snapshots
Cross-links
- โ๏ธ Vault Installation, HA, and Automation Pack
- ๐ก๏ธ Security as Policy for Terraform and Infrastructure as Code