Prerequisites
Start Vault
Use this script to create a external vault server on a linux hosts.
vault server -dev -dev-root-token-id password -dev-listen-address 0.0.0.0:8200 > vault.log 2>&1 &
export VAULT_ADDR=http://0.0.0.0:8200
vault login password
vault kv put secret/devwebapp/config username='giraffe' password='salsa'
Install the vault helm chart
- Add Vault helm repo
helm repo add hashicorp https://helm.releases.hashicorp.com
- Install the latest version of the Vault agent running in external mode.
helm install vault hashicorp/vault \
--create-namespace --namespace vault
--set "global.externalVaultAddr=${VAULT_ADDR}"
- Create a long-lived token for vault serviceaccount.
cat <<EOF | kubectl apply -f -
apiVersion: v1
kind: Secret
metadata:
name: vault-token-g955r
namespace: vault
annotations:
kubernetes.io/service-account.name: vault
type: kubernetes.io/service-account-token
EOF
Configure kubernetes auth method
- Create ServiceAccount in default namespace
cat <<EOF | kubectl apply -f -
apiVersion: v1
kind: ServiceAccount
metadata:
name: internal-app
namespace: default
EOF
cat <<EOF | kubectl apply -f -
apiVersion: v1
kind: ServiceAccount
metadata:
name: internal-app2
namespace: default
EOF
- Create new kubernetes auth method
export VAULT_ADDR=http://0.0.0.0:8200
vault auth enable kubernetes
# token name of vault serviceaccount
VAULT_SECRET_NAME=$(kubectl get secrets -n vault --output=json | jq -r '.items[].metadata | select(.name|startswith("vault-token-")).name')
# token of vault serviceaccount
TOKEN_REVIEW_JWT=$(kubectl get secret $VAULT_SECRET_NAME -n vault --output='go-template=' | base64 --decode)
# ca cert of kubernetes cluster
KUBE_CA_CERT=$(kubectl config view --raw --minify --flatten --output='jsonpath={.clusters[].cluster.certificate-authority-data}' | base64 --decode)
# URL of kubernetes cluster
KUBE_HOST=$(kubectl config view --raw --minify --flatten --output='jsonpath={.clusters[].cluster.server}')
# Configure the Kubernetes authentication method to use the service account token and kubernetes host, etc.
vault write auth/kubernetes/config \
token_reviewer_jwt="$TOKEN_REVIEW_JWT" \
kubernetes_host="$KUBE_HOST" \
kubernetes_ca_cert="$KUBE_CA_CERT" \
issuer="https://kubernetes.default.svc.cluster.local"
# Create a vault policy
vault policy write devwebapp - <<EOF
path "secret/data/devwebapp/config" {
capabilities = ["read"]
}
EOF
# Create two kubernetes authentication role.
vault write auth/kubernetes/role/devweb-app \
bound_service_account_names=internal-app \
bound_service_account_namespaces=default \
policies=devwebapp \
ttl=24h
vault write auth/kubernetes/role/devweb-app2 \
bound_service_account_names=internal-app2 \
bound_service_account_namespaces=default \
policies=devwebapp \
ttl=24h
Create two exmaple applications
After we setup the auth method for Vault server with two different roles that bind to kubernetes service accout, we can create two pods that use different service account to retrieve vault secrets.
apiVersion: v1
kind: Pod
metadata:
name: devwebapp-with-annotations
labels:
app: devwebapp-with-annotations
annotations:
vault.hashicorp.com/agent-inject: 'true'
vault.hashicorp.com/role: 'devweb-app'
vault.hashicorp.com/agent-inject-secret-credentials.txt: 'secret/data/devwebapp/config'
vault.hashicorp.com/secret-volume-path-credentials.txt: '/tmp'
spec:
serviceAccountName: internal-app
containers:
- name: app
image: burtlo/devwebapp-ruby:k8s
---
apiVersion: v1
kind: Pod
metadata:
name: devwebapp2-with-annotations
labels:
app: devwebapp2-with-annotations
annotations:
vault.hashicorp.com/agent-inject: 'true'
vault.hashicorp.com/role: 'devweb-app2'
vault.hashicorp.com/agent-inject-secret-credentials.txt: 'secret/data/devwebapp/config'
vault.hashicorp.com/secret-volume-path-credentials.txt: '/tmp'
spec:
serviceAccountName: internal-app2
containers:
- name: app
image: burtlo/devwebapp-ruby:k8s