Kubernetes
Vault
Vaulthelm

Here’s the updated Vault + Kubernetes Auth Setup Documentation with detailed explanations in each section to help you understand what you're doing and why:


# 🛡️ HashiCorp Vault with Kubernetes Auth - Local Minikube Setup (Dev Mode)
 
This guide shows how to run Vault on Minikube using HA mode (with Raft storage) and enable Kubernetes-based authentication to securely inject secrets into workloads.
 
---
 
## 1. Install Vault via Helm
 
**Explanation**: Helm is the recommended way to deploy Vault in Kubernetes. This configuration enables:
- **HA mode**: Multiple Vault pods, using Raft as internal storage backend.
- **Vault UI**: So you can access Vault in the browser.
 
Create the custom values file:
 
```yaml
# vault-values.yml
server:
  ha:
    enabled: true
    raft:
      enabled: true
      setNodeId: true
  ui:
    enabled: true

Install with:

helm repo add hashicorp https://helm.releases.hashicorp.com
helm install vault hashicorp/vault -n vault --create-namespace -f vault-values.yml

2. Initialize and Unseal Vault

Explanation: Vault starts sealed for security. You need to initialize it to generate keys and then unseal it using one of them.

Initialize Vault and store keys:

kubectl exec -n vault vault-0 -- vault operator init -key-shares=1 -key-threshold=1 -format=json > keys.json

Extract and use the unseal key:

export UNSEAL=$(jq -r .unseal_keys_b64[0] keys.json)
kubectl exec -n vault vault-0 -- vault operator unseal $UNSEAL

Note: For HA, repeat unseal for vault-1, vault-2 as well.


3. Login to Vault (CLI)

Explanation: To configure Vault, you must authenticate. Here we use the root token generated during initialization.

Set the Vault address and login:

export VAULT_ADDR=http://localhost:8200
export VAULT_TOKEN=$(jq -r .root_token keys.json)
vault login $VAULT_TOKEN

You’re now authenticated as a root user in CLI.


4. Enable KV Secrets and Kubernetes Auth Methods

Explanation:

  • The kv (key-value) secrets engine stores arbitrary secrets.
  • The kubernetes auth method allows K8s pods to authenticate to Vault via service accounts.
vault secrets enable -path=secret kv-v2
vault auth enable kubernetes

5. Configure Kubernetes Auth Method

Explanation: Vault needs to connect to the Kubernetes API to validate ServiceAccount tokens. You supply:

  • Kubernetes Host URL
  • JWT: Vault uses this to verify tokens.
  • CA cert: Ensures HTTPS communication.

Extract credentials from Vault pod (recommended in Minikube):

kubectl exec -n vault -ti vault-0 -- sh
 
# Inside the pod
TOKEN_REVIEWER=$(cat /var/run/secrets/kubernetes.io/serviceaccount/token)
CA_CERT=$(cat /var/run/secrets/kubernetes.io/serviceaccount/ca.crt)
K8S_HOST=https://$KUBERNETES_PORT_443_TCP_ADDR:443
 
# Then configure Vault
vault write auth/kubernetes/config \
  kubernetes_host="$K8S_HOST" \
  token_reviewer_jwt="$TOKEN_REVIEWER" \
  kubernetes_ca_cert="$CA_CERT"

Why this matters: Vault now knows how to validate tokens from Kubernetes pods using its API.


6. Create Policy and Role

Explanation:

  • Policies define what a client (e.g., pod) can access.
  • Roles bind a Kubernetes service account to a Vault policy.

Define a webapp policy that allows reading one path:

vault policy write webapp - <<EOF
path "secret/data/webapp/config" {
  capabilities = ["read"]
}
EOF

Create a role to bind the policy to a service account:

vault write auth/kubernetes/role/webapp \
  bound_service_account_names=webapp-sa \
  bound_service_account_namespaces=default \
  policies=webapp \
  ttl=1h

Add a sample secret to test:

vault kv put secret/webapp/config username="demo" password="pwd123"

7. Create Kubernetes ServiceAccount

Explanation: A pod must use a specific service account (SA) to authenticate to Vault. Vault checks if the pod’s SA matches the role.

Create the SA in the default namespace:

kubectl create serviceaccount webapp-sa

Ensure this name matches the bound_service_account_names in the Vault role.

(Optional): Create vault-auth SA and bind it with permissions so Vault can verify tokens.

kubectl create serviceaccount vault-auth -n vault
kubectl create clusterrolebinding vault-auth-delegator \
  --clusterrole=system:auth-delegator \
  --serviceaccount=vault:vault-auth

8. Create a Test Pod Using That SA

Explanation: Now test if a pod using webapp-sa can authenticate to Vault and fetch secrets.

Use this manifest:

apiVersion: v1
kind: Pod
metadata:
  name: test-auth
spec:
  serviceAccountName: webapp-sa
  containers:
  - name: busybox
    image: busybox
    command: [ "/bin/sh", "-c", "sleep 3600" ]

Apply:

kubectl apply -f testpod.yaml

Access it:

kubectl exec -it test-auth -- sh

9. Authenticate to Vault from Inside the Pod

Explanation: The pod now has access to a ServiceAccount JWT. You use this JWT to login to Vault and receive a Vault token.

Inside the pod:

JWT=$(cat /var/run/secrets/kubernetes.io/serviceaccount/token)
 
curl -s --request POST \
  --data '{"jwt":"'"$JWT"'","role":"webapp"}' \
  http://vault.vault.svc.cluster.local:8200/v1/auth/kubernetes/login | jq

You’ll get a Vault client token in the response. Use it to access secrets:

curl \
  -H "X-Vault-Token: <vault_token>" \
  http://vault.vault.svc.cluster.local:8200/v1/secret/data/webapp/config | jq

✅ Summary

ComponentPurpose
Vault Helm ChartDeploys Vault into Kubernetes
Init & UnsealStarts and unlocks Vault
Auth MethodLets K8s pods authenticate to Vault
ServiceAccountIdentity that Vault binds to
Policy & RoleGrant and scope permissions
Pod TestValidate if secrets can be fetched

🔒 Next Steps (Optional)

  • Use Vault Agent Sidecar Injector for auto token and secret injection.
  • Setup TLS for Vault instead of dev HTTP.
  • Rotate secrets with dynamic secrets engines (e.g., DB, AWS).

---

Would you like me to export this as a `.md` file or add **Vault Agent Injector** setup next?

Pod Secret Injection Example


🛠️ Injecting Vault Secrets as Environment Variables in Kubernetes Pod

This guide explains how to inject secrets (e.g., DB credentials) stored in HashiCorp Vault into a Kubernetes Pod's environment variables, replacing traditional ConfigMap or Kubernetes Secret-based workflows.

We'll use:

  • Vault Agent Sidecar Injector (mutating webhook)
  • Vault Kubernetes Auth Method
  • A sample BusyBox pod that consumes the secrets

1. Prerequisites

  • Vault is installed via Helm in Minikube (HA mode with Raft)
  • Kubernetes Auth Method is enabled and configured
  • vault.kube.auth is set up and reachable

2. Enable Vault Agent Injector

Explanation: The Vault Agent Injector automatically injects a sidecar into your pods to authenticate and write secrets to memory or env.

Enable it:

helm upgrade --install vault hashicorp/vault \
  -n vault \
  -f vault-values.yml \
  --set injector.enabled=true

Verify:

kubectl get pods -n vault -l app.kubernetes.io/name=vault-agent-injector

3. Add DB Credentials in Vault

vault kv put secret/db-creds username=dbuser password=dbpass123

4. Define a Vault Policy

vault policy write dbapp - <<EOF
path "secret/data/db-creds" {
  capabilities = ["read"]
}
EOF

5. Create Vault Role for Pod

vault write auth/kubernetes/role/dbapp \
  bound_service_account_names=dbapp-sa \
  bound_service_account_namespaces=default \
  policies=dbapp \
  ttl=24h

6. Create a Kubernetes Service Account

kubectl create serviceaccount dbapp-sa

7. Annotate Pod with Vault Instructions

Here's a full manifest:

apiVersion: v1
kind: Pod
metadata:
  name: vault-env-busybox
  annotations:
    vault.hashicorp.com/agent-inject: "true"
    vault.hashicorp.com/role: "dbapp"
    vault.hashicorp.com/agent-inject-secret-DB_USER: "secret/data/db-creds"
    vault.hashicorp.com/agent-inject-template-DB_USER: |
      {{ with secret "secret/data/db-creds" }}
      export DB_USER={{ .Data.data.username }}
      export DB_PASS={{ .Data.data.password }}
      {{ end }}
    vault.hashicorp.com/agent-pre-populate-only: "true"
    vault.hashicorp.com/agent-inject-command: ["/bin/sh", "-c", "source /vault/secrets/DB_USER && env"]
    vault.hashicorp.com/log-level: debug
spec:
  serviceAccountName: dbapp-sa
  containers:
    - name: busybox
      image: busybox
      command: ["/bin/sh", "-c"]
      args:
        - |
          echo "Starting Busybox with Vault Secrets";
          source /vault/secrets/DB_USER;
          env;
          sleep 3600

8. Apply and Test

kubectl apply -f vault-env-busybox.yaml

Then check:

kubectl logs vault-env-busybox

You should see:

DB_USER=dbuser
DB_PASS=dbpass123

✅ Summary

  • No .env or Kubernetes Secrets used
  • Secrets dynamically pulled from Vault
  • Sidecar handles token auth and injection
  • Environment variables set via shell sourcing

🔒 Notes

  • The secrets are mounted at /vault/secrets/<NAME>
  • You can also mount as plain files or config using templates
  • Ideal for 12-factor apps, security-sensitive environments

🧙 AI Wizard - Instant Page Insights

Click the button below to analyze this page.
Get an AI-generated summary and key insights in seconds.
Powered by Perplexity AI!