Instal Vault di Kubernetes

Vault adalah tools yang digunakan untuk mengelola secrets seperti password, API key, token, dan sertifikat secara tersentralisasi, aman, dan dinamis. Dengan integrasi Vault dan Kubernetes, pod di Kubernetes dapat mengakses secrets tanpa harus menyimpannya langsung di konfigurasi atau environment variable, yang biasanya menjadi celah untuk dimanfaatkan attacker, karena mudah diakses.
Contoh penggunaan
Menyediakan kredensial database sementara ke pod.
Menyimpan dan mengelola sertifikat TLS untuk aplikasi.
Menghasilkan secrets sementara (dynamic secrets) yang otomatis kedaluwarsa.
Tutorial
Diuji di Kubernetes v1.32.3 dan OS Ubuntu Jammy
Tambahkan helm repo Vault
helm repo add hashicorp https://helm.releases.hashicorp.com
Buat temporary directory untuk menyimpan certificate
mkdir ~/vault
Generate private key
export VAULT_K8S_NAMESPACE="vault" \
export VAULT_HELM_RELEASE_NAME="vault" \
export VAULT_SERVICE_NAME="vault-internal" \
export K8S_CLUSTER_NAME="cluster.local" \
export WORKDIR=~/vault/
openssl genrsa -out ${WORKDIR}/vault.key 2048
Buat file konfigurasi CSR (Certificate Signing Request)
cat > ${WORKDIR}/vault-csr.conf <<EOF
[req]
default_bits = 2048
prompt = no
encrypt_key = yes
default_md = sha256
distinguished_name = kubelet_serving
req_extensions = v3_req
[ kubelet_serving ]
O = system:nodes
CN = system:node:*.${VAULT_K8S_NAMESPACE}.svc.${K8S_CLUSTER_NAME}
[ v3_req ]
basicConstraints = CA:FALSE
keyUsage = nonRepudiation, digitalSignature, keyEncipherment, dataEncipherment
extendedKeyUsage = serverAuth, clientAuth
subjectAltName = @alt_names
[alt_names]
DNS.1 = *.${VAULT_SERVICE_NAME}
DNS.2 = *.${VAULT_SERVICE_NAME}.${VAULT_K8S_NAMESPACE}.svc.${K8S_CLUSTER_NAME}
DNS.3 = *.${VAULT_K8S_NAMESPACE}
IP.1 = 127.0.0.1
EOF
Generate CSR
openssl req -new -key ${WORKDIR}/vault.key -out ${WORKDIR}/vault.csr -config ${WORKDIR}/vault-csr.conf
Buat CSR Yaml untuk Kubernetes
cat > ${WORKDIR}/csr.yaml <<EOF
apiVersion: certificates.k8s.io/v1
kind: CertificateSigningRequest
metadata:
name: vault.svc
spec:
signerName: kubernetes.io/kubelet-serving
expirationSeconds: 8640000
request: $(cat ${WORKDIR}/vault.csr|base64|tr -d '\n')
usages:
- digital signature
- key encipherment
- server auth
EOF
kubectl create -f ${WORKDIR}/csr.yaml
Approve CSR
kubectl certificate approve vault.svc
Pastikan certificate sudah issued
kubectl get csr vault.svc
Buat certificate CRT
kubectl get csr vault.svc -o jsonpath='{.status.certificate}' | openssl base64 -d -A -out ${WORKDIR}/vault.crt
Buat certificate CA
kubectl config view \
--raw \
--minify \
--flatten \
-o jsonpath='{.clusters[].cluster.certificate-authority-data}' \
| base64 -d > ${WORKDIR}/vault.ca
Buat namespace
kubectl create namespace $VAULT_K8S_NAMESPACE
Buat TLS secret
kubectl create secret generic vault-ha-tls \
-n $VAULT_K8S_NAMESPACE \
--from-file=vault.key=${WORKDIR}/vault.key \
--from-file=vault.crt=${WORKDIR}/vault.crt \
--from-file=vault.ca=${WORKDIR}/vault.ca
Deploy Vault
cat > ${WORKDIR}/overrides.yaml <<EOF
global:
enabled: true
tlsDisable: false
injector:
enabled: true
server:
extraEnvironmentVars:
VAULT_CACERT: /vault/userconfig/vault-ha-tls/vault.ca
VAULT_TLSCERT: /vault/userconfig/vault-ha-tls/vault.crt
VAULT_TLSKEY: /vault/userconfig/vault-ha-tls/vault.key
volumes:
- name: userconfig-vault-ha-tls
secret:
defaultMode: 420
secretName: vault-ha-tls
volumeMounts:
- mountPath: /vault/userconfig/vault-ha-tls
name: userconfig-vault-ha-tls
readOnly: true
standalone:
enabled: false
affinity: ""
ha:
enabled: true
replicas: 2
raft:
enabled: true
setNodeId: true
config: |
cluster_name = "vault-integrated-storage"
ui = true
listener "tcp" {
tls_disable = 0
address = "[::]:8200"
cluster_address = "[::]:8201"
tls_cert_file = "/vault/userconfig/vault-ha-tls/vault.crt"
tls_key_file = "/vault/userconfig/vault-ha-tls/vault.key"
tls_client_ca_file = "/vault/userconfig/vault-ha-tls/vault.ca"
}
storage "raft" {
path = "/vault/data"
}
disable_mlock = true
service_registration "kubernetes" {}
ui:
enabled: true
serviceType: "NodePort"
serviceNodePort: null
externalPort: 8200
EOF
helm install -n $VAULT_K8S_NAMESPACE $VAULT_HELM_RELEASE_NAME hashicorp/vault -f ${WORKDIR}/overrides.yaml
Inisialisasi vault-0
dengan satu key dan satu key threshold, artinya kita membuat satu key dan butuh satu key untuk membuka Vault.
kubectl exec -n $VAULT_K8S_NAMESPACE vault-0 -- vault operator init \
-key-shares=1 \
-key-threshold=1 \
-format=json > ${WORKDIR}/cluster-keys.json
Untuk melihat unseal key
jq -r ".unseal_keys_b64[]" ${WORKDIR}/cluster-keys.json
Buat variable untuk capture unseal key
VAULT_UNSEAL_KEY=$(jq -r ".unseal_keys_b64[]" ${WORKDIR}/cluster-keys.json)
Unseal vault-0
kubectl exec -n $VAULT_K8S_NAMESPACE vault-0 -- vault operator unseal $VAULT_UNSEAL_KEY
Joinkan vault-1 ke raft cluster
kubectl exec -n $VAULT_K8S_NAMESPACE -it vault-1 -- /bin/sh
vault operator raft join -address=https://vault-1.vault-internal:8200 -leader-ca-cert="$(cat /vault/userconfig/vault-ha-tls/vault.ca)" -leader-client-cert="$(cat /vault/userconfig/vault-ha-tls/vault.crt)" -leader-client-key="$(cat /vault/userconfig/vault-ha-tls/vault.key)" https://vault-0.vault-internal:8200
exit
Unseal vault-1
kubectl exec -n $VAULT_K8S_NAMESPACE -ti vault-1 -- vault operator unseal $VAULT_UNSEAL_KEY
Export cluster root token
export CLUSTER_ROOT_TOKEN=$(cat ${WORKDIR}/cluster-keys.json | jq -r ".root_token")
Login ke vault-0
kubectl exec -n $VAULT_K8S_NAMESPACE vault-0 -- vault login $CLUSTER_ROOT_TOKEN
...
Success! You are now authenticated. The token information displayed below
is already stored in the token helper. You do NOT need to run "vault login"
again. Future Vault requests will automatically use this token.
Key Value
--- -----
token hvs.NcFnpImyX3GHFrKCvqTaWyvB
token_accessor HFdFIRYZojPRiTPgDLRldkic
token_duration ∞
token_renewable false
token_policies ["root"]
identity_policies []
policies ["root"]
...
List raft peers
kubectl exec -n $VAULT_K8S_NAMESPACE vault-0 -- vault operator raft list-peers
...
Node Address State Voter
---- ------- ----- -----
vault-0 vault-0.vault-internal:8201 leader true
vault-1 vault-1.vault-internal:8201 follower true
...
Access Vault UI, login dengan root token.
cat ${WORKDIR}/cluster-keys.json | jq -r ".root_token"
kubectl -n $VAULT_K8S_NAMESPACE get svc | grep vault-ui
...
vault-ui NodePort 10.101.40.205 <none> 8200:30826/TCP 20h
...
Referensi
Subscribe to my newsletter
Read articles from Rivaldy Ahmad Azhar directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by
