Kubernetes Centralized External Secrets Management with HashiCorp Vault

Hands-on Tutorial

Segesta
Self-managed vs. HCP Vault cluster
  1. Install HashiCorp Vault CLI
brew tap hashicorp/tap
brew install hashicorp/tap/vault
vault server -dev -dev-root-token-id root -dev-listen-address 0.0.0.0:8200
export VAULT_ADDR=http://0.0.0.0:8200
vault login root
minikube start
EXTERNAL_VAULT_ADDR=$(minikube ssh "dig +short host.docker.internal" | tr -d '\r')
helm repo add hashicorp https://helm.releases.hashicorp.com
helm repo update
helm install vault hashicorp/vault --set "injector.externalVaultAddr=https://$EXTERNAL_VAULT_ADDR:8200" --set "tlsDisable=true"
VAULT_HELM_SECRET_NAME=$(kubectl get secrets --output=json | jq -r '.items[].metadata | select(.name|startswith("vault-token-")).name')
TOKEN_REVIEW_JWT=$(kubectl get secret $VAULT_HELM_SECRET_NAME --output='go-template={{ .data.token }}' | base64 --decode)
KUBE_CA_CERT=$(kubectl config view --raw --minify --flatten --output='jsonpath={.clusters[].cluster.certificate-authority-data}' | base64 --decode)
KUBE_HOST=$(kubectl config view --raw --minify --flatten --output='jsonpath={.clusters[].cluster.server}')
vault auth enable -path=<cluster-name> kubernetes
vault write auth/<cluster-name>/config \
token_reviewer_jwt="$TOKEN_REVIEW_JWT" \
kubernetes_host="$KUBE_HOST" \
kubernetes_ca_cert="$KUBE_CA_CERT" \
issuer="https://kubernetes.default.svc.cluster.local"
vault kv put secret/<cluster-name>/config username='admin' password='secret'

vault policy write <cluster-name>-policy - <<EOF
path "secret/data/<cluster-name>/config" {
capabilities = ["read"]
}
EOF
vault write auth/<cluster-name>/role/<cluster-name>-role \
bound_service_account_names=test-sa \
bound_service_account_namespaces=default \
policies=<cluster-name>-policy \
ttl=24h
kubectl create sa test-sa
kubectl apply -f sample.yaml
#sample.yaml
apiVersion: v1
kind: Pod
metadata:
name: sample
labels:
app: sample
annotations:
# This will ensure the initial secret injection (initContainer)
vault.hashicorp.com/agent-inject: 'true'
# Optional: Ensure real-time updating of secrets (sidecar will be running at all times)
vault.hashicorp.com/agent-inject-status: 'update'
# Vault Auth Path
vault.hashicorp.com/auth-path: 'auth/minikube'
# Namespace
vault.hashicorp.com/namespace: 'default'
# Bounds injection to Vault role defined above
vault.hashicorp.com/role: 'minikube-role'
# Mount secrets on the /vault/secrets/credentials.txt
vault.hashicorp.com/agent-inject-secret-credentials.txt: 'secret/data/minikube/config'
spec:
serviceAccountName: test-sa
containers:
- name: app
image: nginx:latest
ports:
- containerPort: 80
kubectl exec -it sample -c app -- cat /vault/secrets/credentials.txt
data: map[password:secret username:admin]
kubectl exec -it sample -c app -- cat /vault/secrets/credentials.txt
data: map[password:secret username:admin2]

--

--

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store