This post looks at how an integration of the Secrets Store CSI Driver in Kubernetes with a cluster-external HashiCorp Vault server can be configured to use the Vault Kubernetes auth method.
- HashiCorp Vault: A popular open source secrets store.
-
Secrets Store CSI Driver: Integrates secrets stores with Kubernetes via a Container Storage Interface (CSI) volume.
Outline
In the Kubernetes cluster, a service account and service account token secret are created and linked to a ClusterRoleBinding granting access to the Token Review API.
In the Vault server, the details of the Kubernetes host and a token review JWT are configured in a Kubernetes authentication method.
Set up
See this post for setup of Secrets Store CSI Driver and HashiCorp Vault.
That post was agnostic about the location of the Vault server. It could be in-cluster or external. For the purpose of this post, the Vault server should be external to the Kubernetes cluster on which the CSI driver runs alongside your workloads. For example, you could run the server in dev mode on your workstation.
Kubernetes configuration
Creating Service Account, service account token Secret and ClusterRoleBinding.
vault-auth.yml
apiVersion: v1
kind: ServiceAccount
metadata:
name: vault-auth
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: role-tokenreview-binding
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: system:auth-delegator
subjects:
- kind: ServiceAccount
name: vault-auth
namespace: default
---
apiVersion: v1
kind: Secret
metadata:
name: vault-auth
annotations:
kubernetes.io/service-account.name: vault-auth
type: kubernetes.io/service-account-token
Everything above is standard/template apart from the name of the secret (here, 'vault-auth') and the namespace of the workload and service account (here, 'default').
kubectl apply -f ./vault-auth.yml
Vault configuration
Configuring an authentication method to use the Kubernetes cluster's JWT Verifier.
TOKEN_REVIEW_JWT=$(kubectl get secret vault-auth -o '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}')
KUBE_ISSUER=$(kubectl get --raw /.well-known/openid-configuration | jq -r .issuer)
vault write auth/kubernetes/config \
token_reviewer_jwt="$TOKEN_REVIEW_JWT" \
kubernetes_host="$KUBE_HOST" \
kubernetes_ca_cert="$KUBE_CA_CERT" \
issuer="$KUBE_ISSUER"
PS
Your Vault server can be configured to authenticate with multiple Kubernetes servers. You would write an authentication method configuration for each.
vault auth enable -path=kubernetes-mycluster kubernetes
vault write auth/kubernetes-mycluster/config ...
References