here's one way of doing it, which will set your secrets as environment variables in your k8s pods.
install and configure vault
install vault
helm repo add incubator http://storage.googleapis.com/kubernetes-charts-incubator
helm install incubator/vault --set vault.dev=false --set vault.config.storage.consul.address="myconsul-svc-name:8500",vault.config.storage.consul.path="vault"
this cluster role binding should be here
kubectl get clusterrolebinding vault -o yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: vault
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: system:auth-delegator
subjects:
- kind: ServiceAccount
name: vault
namespace: vault
enable and configure the kubernetes auth method
vault auth enable kubernetes
SECRET=$(kubectl get sa vault -n vault -o json | jq -r '.secrets[0].name')
TOKEN=$(kubectl get secret $SECRET -n vault -o json | jq -r '.data.token' | base64 -D)
kubectl get secret $SECRET -n vault -o json | jq -r '.data["ca.crt"]' | base64 -D > ca.crt
vault write auth/kubernetes/config \
token_reviewer_jwt="$TOKEN" \
kubernetes_host=https://KUBERNETES_API_ADDR:443 \
kubernetes_ca_cert=@ca.crt
rm ca.crt
hey! now we can store our secrets there!
add some secrets and set up some access policy
exec into the container
kubectl exec -it `kubectl get pods | awk '{print $1}' | grep vault | head -1` -- /bin/sh
add or edit your secrets
vault kv put kv2/MY_GROOVY_SERVICE MY_GROOVY_SECRET_NAME=MYGROOVYSECRET
vault kv patch kv2/MY_GROOVY_SERVICE ANOTHER_GROOVY_SECRET_NAME=ANOTHERGROOVYSECRET
remember, if your secret contains $
you may need to escape it like
vault kv put kv2/MY_GROOVY_SERVICE SECRET_CONTAINING_DOLLARS=thi\$_\$ecret_i\$_a_\$ecret
list existing secrets in the kv2 backend
vault kv list kv2
add an access policy for your secret
cat <<EOF | vault policy write MY_GROOVY_SERVICE -
path "/kv2/data/MY_GROOVY_SERVICE" {
capabilities = [ "read" ]
}
EOF
create a kubernetes auth role, and attach your policy to it
vault write auth/kubernetes/role/MY_GROOVY_SERVICE \
bound_service_account_names=MY_GROOVY_SERVICE \
bound_service_account_namespaces=MY_GROOVY_NAMESPACE \
policies=MY_GROOVY_SERVICE \
ttl=1h
setup the vault secrets webhook in k8s
this will let us access our secrets by popping them into our pods as environment variables
git clone https://github.com/innovia/kubernetes-mutation-webhook-vault-secrets.git
helm install helm-chart/
manually add the vault deployment's secret's ca cert as a secret to your deployment's desired namespace:
kubectl get secret $(kubectl get secret | grep vault-token | awk '{print $1}') -o json | jq -r '.data["ca.crt"]' | base64 -D > vault-consul-ca.crt
kubectl create secret generic vault-consul-ca --from-literal=ca.pem="$(cat vault-consul-ca.crt)" -n MY_GROOVY_NAMESPACE
where MY_GROOVY_NAMESPACE is the namespace where you want to deploy your app, not the namespace vault is running in.
now we can use it to read our secrets!
access your secrets from your helm deployment
making sure the name of the service account should match the name of the bound_service_account_names
you added above when creating a kubernetes auth role:
apiVersion: v1
kind: ServiceAccount
metadata:
name: MY_GROOVY_SERVICE <----------- HERE
labels:
app: ...
chart: ...
heritage: ...
release: ...
owner: ...
and in our deployment, make sure we include these annotations, serviceAccountName & envs.
apiVersion: apps/v1
kind: Deployment
metadata:
name: xxx
labels:
app: xxx
spec:
replicas: 1
template:
metadata:
labels:
app: xxx
annotations:
vault.security/enabled: "true" <------------------------------------------- So the vault secrets webhook knows to operate on pods in this deployment
vault.security/vault-addr: "http://VAULT_SERVICE_OR_INGRESS_ADDR:8200" <--- So it knows where to find vault
vault.security/vault-role: "MY_GROOVY_SERVICE" <--------------------------- So it knows which kubernetes vault auth role to use
vault.security/vault-path: "/kv2/data/MY_GROOVY_SERVICE" <----------------- So it knows where to find your secrets
vault.security/vault-tls-secret-name: "vault-consul-ca" <------------------ This is the name of the manually created secret, vault-consul-ca, we did earlier.
spec:
serviceAccountName: MY_GROOVY_SERVICE <-------------------------------------- The service account with kubernetes vault auth role permissions
containers:
- name: xxx
image: {{ $.Values.image.repository }}:{{ $.Values.image.tag }}
command:
- "java"
- "-jar"
- "/app/application.jar"
- "-Do=it"
env:
- name: "MY_GROOVY_SECRET" <---------------------------------------------- So it knows the name of the env var to store the secret in
value: "vault:MY_GROOVY_SECRET" <--------------------------------------- So it knows what this secret is named in vault. This is the most important bit!
et voilà. now you can read these secrets from you application, simply by reading the environment variable.