vault kubernetes with csi - juancamilocc/virtual_resources GitHub Wiki
In this guide, you will learn how to set up and deploy Vault step by step in a Kubernetes environment using the CSI plugin.
First, we need to execute the following commands.
helm repo add hashicorp https://helm.releases.hashicorp.com
helm repo update
helm install vault hashicorp/vault --namespace vault \
--set server.ha.enabled=false \
--set server.ha.raft.enabled=true \
--set server.ha.raft.storage.storageClass=standard \
--set server.ha.raft.storage.size=10Gi \
--set "injector.enabled=false" \
--set "csi.enabled=true"
kubectl -n vault get pods
# NAME READY STATUS RESTARTS AGE
# vault-0 0/1 Running 0 2m25s
# vault-csi-provider-69szd 2/2 Running 0 2m25s
Now, we have to get the unseal and root keys.
kubectl exec vault-0 -n vault -- vault operator init -key-shares=1 -key-threshold=1 -format=json > vault-cluster-keys.json
cat vault-cluster-keys.json
# {
# "unseal_keys_b64": [
# "<base64 unseal_key>"
# ],
# "unseal_keys_hex": [
# "<hex unseal key>"
# ],
# "unseal_shares": 1,
# "unseal_threshold": 1,
# "recovery_keys_b64": [],
# "recovery_keys_hex": [],
# "recovery_keys_shares": 0,
# "recovery_keys_threshold": 0,
# "root_token": "hvs.<token root>"
# }
NOTE:
You can generate more than one unseal key by modifying the value of -key-shares
, meanwhile the value of -key-threshold
specifies how many valid keys are required to unseal Vault. In this guide, for simplicity, we will use only one key.
Now, let's unseal Vault as follows.
kubectl exec vault-0 -n vault -- vault operator unseal <BASE64_UNSEAL_KEY>
# Key Value
# --- -----
# Seal Type shamir
# Initialized true
# Sealed false
# Total Shares 1
# Threshold 1
# Version 1.18.1
# Build Date 2024-10-29T14:21:31Z
# Storage Type raft
# Cluster Name vault-cluster-62b0352c
# Cluster ID 6d9984e4-7464-ce94-1b05-523918ca0c73
# HA Enabled true
# HA Cluster n/a
# HA Mode standby
# Active Node Address <none>
# Raft Committed Index 33
# Raft Applied Index 33
NOTE: If you generated more than one unseal key, you must repeat the command for each key you have.
Now, let's enable authentication with Kubernetes.
kubectl config view --raw --minify --flatten -o json | jq -r '.clusters[0].cluster.server'
# https://192.168.49.2:8443
kubectl -n vault exec vault-0 -- vault auth enable kubernetes
kubectl -n vault exec vault-0 -- vault write auth/kubernetes/config kubernetes_host=https://192.168.49.2:8443
Now, we need to install the CSI plugin in our Kubernetes cluster.
helm repo add secrets-store-csi-driver https://kubernetes-sigs.github.io/secrets-store-csi-driver/charts
helm install csi-secrets-store secrets-store-csi-driver/secrets-store-csi-driver --set syncSecret.enabled=true --namespace kube-system
kubectl --namespace=kube-system get pods -l "app=secrets-store-csi-driver"
# NAME READY STATUS RESTARTS AGE
# csi-secrets-store-secrets-store-csi-driver-fvhr8 3/3 Running 1 (6m1s ago) 7m6s
Finally, we will set up a port-forward to access its graphical interface.
kubectl -n vault port-forward svc/vault 8200:8200
Access it using the root token generated in our vault-cluster-key.json
file.
Let’s enable our secrets engine by navigating to Enable a secrets engine > KV > Enable Engine
. Here, we will create our first secrets.
As an example, we will create the following secrets, click on Create secret
, set a name and we assign keys and values.
As an example, we will create the following secrets. Click on Create secret, provide a name, and assign keys and values.
# Allow capabilities in path
path "kv/data/secrets-test/*" {
capabilities = ["read", "create", "update", "delete"]
}
# Block any action in sys and auth, to avoid administration operations
path "sys/*" {
capabilities = []
}
path "auth/*" {
capabilities = []
}
The previous policy allows us to create, read, update, and delete any secrets in the secrets-test
path. Additionally, it denies access to auth and sys capabilities.
We need to create a role. Go to Kubernetes > Create role
, and provide a name
, in Bound service account name
reference a service account that we will use to authenticate against Vault, which is secrets-test
. Select the namesppace where our application will be running, which is default
. Finally, in Generated Token's Policies
, select the policy we created previously, named secrets-test-policy
.
In our Kubernetes cluster, let's create a service account, as follows.
kubectl -n default create serviceaccount secrets-test
kubectl get sa
# NAME SECRETS AGE
# default 0 74d
# secrets-test 0 6s
Now, let's deploy the SecretProviderClass
making reference to our secrets.
apiVersion: secrets-store.csi.x-k8s.io/v1
kind: SecretProviderClass
metadata:
name: vault-test
namespace: default
spec:
provider: vault
secretObjects:
- data:
- objectName: key1
key: key1
- objectName: key2
key: key2
secretName: test-secrets
type: Opaque
parameters:
vaultAddress: "http://vault.vault.svc.cluster.local:8200"
roleName: "secrets-test-role"
objects: |
- objectName: "key1"
secretPath: "kv/data/secrets-test"
secretKey: "key1"
- objectName: "key2"
secretPath: "kv/data/secrets-test"
secretKey: "key2"
Verify the secret provider class had been created correctly.
kubectl apply -f secrets-vault.yaml
kubectl -n default get secretproviderclass
# NAME AGE
# vault-test 34s
Now, let's deploy an application referencing those secrets, as follows.
apiVersion: apps/v1
kind: Deployment
metadata:
name: test-deploy
namespace: default
spec:
replicas: 1
selector:
matchLabels:
app: debian
template:
metadata:
labels:
app: debian
spec:
serviceAccountName: secrets-test
containers:
- name: debian
image: debian:bullseye-slim
command: ["sleep", "infinity"]
env:
- name: key1
valueFrom:
secretKeyRef:
name: test-secrets
key: key1
- name: key2
valueFrom:
secretKeyRef:
name: test-secrets
key: key2
resources:
limits:
cpu: 15m
memory: 105M
requests:
cpu: 15m
memory: 105M
volumeMounts:
- name: test-secrets
mountPath: "/mnt/secrets-store"
volumes:
- name: test-secrets
csi:
driver: secrets-store.csi.k8s.io
readOnly: true
volumeAttributes:
secretProviderClass: "vault-test"
We can verify the environment variables in our pod, as follows.
kubectl get pods
# NAME READY STATUS RESTARTS AGE
# test-deploy-b9584967-n4xh7 1/1 Running 0 1m13s
kubectl exec -it test-deploy-b9584967-n4xh7 -- bash
# root@test-deploy-b9584967-n4xh7:/# cd mnt/secrets-store/
# root@test-deploy-b9584967-n4xh7:/mnt/secrets-store# ls
# key1 key2
root@test-deploy-b9584967-n4xh7:/# cd mnt/secrets-store# cat key1
# secret1
root@test-deploy-b9584967-n4xh7:/# cd mnt/secrets-store# cat key2
# secret2
root@test-deploy-b9584967-n4xh7:/# cd mnt/secrets-store# echo "$key1"
# secret1
root@test-deploy-b9584967-n4xh7:/# cd mnt/secrets-store# echo "$key2"
# secret2
This guide provides a comprehensive step-by-step procedure to install and configure Vault in a Kubernetes environment using the CSI plugin. It covers all the necessary steps, from installation and initialization to deploying an application that uses Vault-managed secrets.