HashiCorp Vault Secrets Management
Dynamic credentials and K8s auth.
HashiCorp Vault: Secrets Management Guide
HashiCorp Vault provides centralized secrets management with dynamic credentials, encryption as a service, and fine-grained access control. For Kubernetes environments, Vault eliminates the need to store secrets in environment variables, config files, or even Kubernetes Secrets.
Why Vault over Kubernetes Secrets?
- Dynamic secrets — Generate short-lived database credentials on demand
- Automatic rotation — Credentials rotate without application changes
- Audit logging — Every secret access is logged
- Encryption as a service — Encrypt/decrypt data without managing keys in your application
- Multi-platform — Works across Kubernetes, VMs, serverless, and CI/CD
Vault Architecture on Kubernetes
helm repo add hashicorp https://helm.releases.hashicorp.com
helm install vault hashicorp/vault \
--namespace vault \
--create-namespace \
--set server.ha.enabled=true \
--set server.ha.replicas=3 \
--set server.ha.raft.enabled=true \
--set injector.enabled=trueKubernetes Authentication
Configure Vault to trust Kubernetes service accounts:
# Enable Kubernetes auth method
vault auth enable kubernetes
# Configure the auth method
vault write auth/kubernetes/config \
kubernetes_host="https://kubernetes.default.svc:443"
# Create a role for your application
vault write auth/kubernetes/role/api-service \
bound_service_account_names=api-service-sa \
bound_service_account_namespaces=production \
policies=api-secrets \
ttl=1hStatic Secrets
# Store a secret
vault kv put secret/production/api-service \
database_url="postgresql://user:pass@db:5432/app" \
api_key="sk_live_xxxxx"
# Vault policy for the application
path "secret/data/production/api-service" {
capabilities = ["read"]
}Dynamic Database Credentials
Vault generates unique, short-lived database credentials for each request:
# Configure database secrets engine
vault secrets enable database
vault write database/config/postgres \
plugin_name=postgresql-database-plugin \
connection_url="postgresql://{{username}}:{{password}}@postgres:5432/app" \
allowed_roles="api-role" \
username="vault_admin" \
password="admin_password"
# Create a role that generates credentials
vault write database/roles/api-role \
db_name=postgres \
creation_statements="CREATE ROLE \"{{name}}\" WITH LOGIN PASSWORD '{{password}}' VALID UNTIL '{{expiration}}'; GRANT SELECT, INSERT, UPDATE ON ALL TABLES IN SCHEMA public TO \"{{name}}\";" \
default_ttl=1h \
max_ttl=24hVault Agent Sidecar Injection
Automatically inject secrets into pods:
apiVersion: apps/v1
kind: Deployment
metadata:
name: api-service
spec:
template:
metadata:
annotations:
vault.hashicorp.com/agent-inject: "true"
vault.hashicorp.com/role: "api-service"
vault.hashicorp.com/agent-inject-secret-config: "secret/data/production/api-service"
vault.hashicorp.com/agent-inject-template-config: |
{{- with secret "secret/data/production/api-service" -}}
DATABASE_URL={{ .Data.data.database_url }}
API_KEY={{ .Data.data.api_key }}
{{- end -}}
spec:
serviceAccountName: api-service-sa
containers:
- name: api
image: api:latest
# Secrets are available at /vault/secrets/configSecret Rotation
- Dynamic secrets — Automatically expire and regenerate (no rotation needed)
- Static secrets — Use Vault's rotation API or external triggers
- PKI certificates — Vault can issue and auto-renew TLS certificates
Eazy SaaS Tip: We deploy Vault with dynamic database credentials as standard for production environments. Each application request gets unique, time-limited credentials — if a credential is compromised, it expires within an hour. This is a game-changer for database security.