Skip to content

Instantly share code, notes, and snippets.

@atheiman
Last active April 5, 2023 13:29
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save atheiman/d177d839aaac9d7a7993e59df66532de to your computer and use it in GitHub Desktop.
Save atheiman/d177d839aaac9d7a7993e59df66532de to your computer and use it in GitHub Desktop.
Vault secret saved as file in app pod

These Kubernetes resource manifest yaml files demonstrate

  1. vault.yaml
  • setting up a test vault service
  • configuring the vault service with kubernetes auth and a role for a test app
  1. app.yaml
  • running an app with a vault-init initContainer to login to vault and obtain a token
  • a vault-secret-manager container to continuously interact with vault throughout the lifecycle of the app
  • an app container to use the secret saved by the vault-secret-manager container

Credit to https://medium.com/@gmaliar/dynamic-secrets-on-kubernetes-pods-using-vault-35d9094d169 for help on this.

---
apiVersion: v1
kind: ServiceAccount
metadata:
name: app
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: app
labels:
run: app
spec:
replicas: 1
selector:
matchLabels:
run: app
template:
metadata:
labels:
run: app
spec:
serviceAccountName: app
volumes:
- name: vault
emptyDir:
medium: Memory
- name: app-creds
emptyDir:
medium: Memory
initContainers:
# The init container is responsible for logging into vault and obtaining a
# token to share with the vault-secret-manager container. The token is
# shared via the volumeMount.
- name: vault-login
image: vault
command: [ "/bin/sh", "-c" ]
args:
- vault write -field=token auth/kubernetes/login role=app "jwt=$(cat /var/run/secrets/kubernetes.io/serviceaccount/token)" > /mnt/vault/.vault-token
env:
- name: VAULT_ADDR
value: http://vault
volumeMounts:
- name: vault
mountPath: /mnt/vault
containers:
- name: vault-secret-manager
image: vault
command: [ "/bin/sh", "-c" ]
args:
# This container continuously renews token and/or secret
# leases. The secret values are dropped into a file in the volume mount
# so the secret can be shared with the app container.
- |
set -ex
while true; do
vault token renew
vault kv get -format=json -field=data secret/app/db > /mnt/app-creds/db.json
sleep 300
done
env:
- name: VAULT_ADDR
value: http://vault
lifecycle:
preStop:
exec:
command: [ "vault", "token", "revoke", "-self" ]
volumeMounts:
# Mounted at the home directory because vault command finds token at
# ~/.vault-token by default.
- name: vault
mountPath: /root
- name: app-creds
mountPath: /mnt/app-creds
- name: app
# The app container can read secrets from the volumeMount at
# /mnt/app-creds which is continuously updated by the vault-secret-manager
# container.
image: busybox
command: [ "/bin/sh", "-c" ]
args:
- |
set -ex
while true; do
cat /mnt/app-creds/db.json
sleep 300
done
volumeMounts:
- name: app-creds
mountPath: /mnt/app-creds
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: vault
---
apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRoleBinding
metadata:
name: vault-auth-delegator
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: system:auth-delegator
subjects:
- kind: ServiceAccount
name: vault
namespace: default
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: vault
labels:
run: vault
spec:
replicas: 1
selector:
matchLabels:
run: vault
template:
metadata:
labels:
run: vault
spec:
serviceAccountName: vault
containers:
- name: vault
image: vault
args: [ "server", "-dev", "-dev-listen-address=0.0.0.0:8200", "-dev-root-token-id=$(VAULT_TOKEN)" ]
env:
- name: VAULT_ADDR
value: http://localhost:8200
- name: VAULT_TOKEN
value: root-token
ports:
- containerPort: 8200
name: vault
lifecycle:
postStart:
exec:
command:
- /bin/sh
- -c
- |
{
set -ex
# Wait for Vault server to start
until vault status; do
sleep 3
done
# Ensure that Vault token is valid
vault token lookup
# Enable Kubernetes auth
vault auth enable kubernetes
# Configure Kubernetes auth
vault write auth/kubernetes/config \
kubernetes_host=https://kubernetes \
kubernetes_ca_cert=@/run/secrets/kubernetes.io/serviceaccount/ca.crt \
token_reviewer_jwt=@/run/secrets/kubernetes.io/serviceaccount/token
# Read the new Kubernetes auth configuration
vault read auth/kubernetes/config
# Create a simple policy for the demo app to use
echo '{"path": {"secret/data/app/*": {"capabilities": ["read"]}}}' | vault policy write app -
# Create a role for the demo app to login with
vault write auth/kubernetes/role/app \
bound_service_account_names=app \
bound_service_account_namespaces=default \
policies=app \
ttl=4h
# Read the new role configuration
vault read auth/kubernetes/role/app
# Create an example static KV secret for the demo app to read
vault kv put secret/app/db username=app password=abc123
} 2>&1 | tee /postStart.log
---
apiVersion: v1
kind: Service
metadata:
name: vault
spec:
ports:
- port: 80
targetPort: vault
selector:
run: vault
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment