Ultimate DevSecOps Bootcamp by School of Devops: Secrets Management with Vault
Делаю:
2026.01.04
Устанавливаю vault
// Connect to the vault-0 which has the vault manager configured
$ kubectl exec -it -n vault vault-0 -- sh
// Explore vault using some simple commands
$ vault
$ vault status
$ vault secrets list
// Adding Secret to the Vault
$ vault kv put secret/dso-demo/database username=devops password=mysupersecret
// Retrieve information that you just added and verify
$ vault kv list secret/
$ vault kv list secret/dso-demo
$ vault kv get secret/dso-demo/database
======== Secret Path ========
secret/data/dso-demo/database
======= Metadata =======
Key Value
--- -----
created_time 2026-01-04T05:26:07.408297829Z
custom_metadata <nil>
deletion_time n/a
destroyed false
version 1
====== Data ======
Key Value
--- -----
password mysupersecret
username devops
Setting up Vault Access Policies
$ vault policy
$ vault policy list
$ vault policy write dso-demo - <<EOF
path "secret/data/dso-demo/database" {
capabilities = ["read"]
}
EOF
$ vault policy read dso-demo
path "secret/data/dso-demo/database" {
capabilities = ["read"]
Writing Policy and Kubernetes RBAC
$ vault auth
$ vault auth list
$ vault auth enable kubernetes
$ vault auth list
$ env | grep -i kube
KUBERNETES_SERVICE_PORT=443
KUBERNETES_PORT=tcp://10.96.0.1:443
KUBERNETES_PORT_443_TCP_ADDR=10.96.0.1
KUBERNETES_PORT_443_TCP_PORT=443
KUBERNETES_PORT_443_TCP_PROTO=tcp
KUBERNETES_SERVICE_PORT_HTTPS=443
KUBERNETES_PORT_443_TCP=tcp://10.96.0.1:443
KUBERNETES_SERVICE_HOST=10.96.0.1
$ ls /var/run/secrets/kubernetes.io/serviceaccount/
ca.crt namespace token
$ ls /var/run/secrets/kubernetes.io/serviceaccount/
ca.crt namespace token
$ vault write auth/kubernetes/config \
kubernetes_host="https://$KUBERNETES_PORT_443_TCP_ADDR:443" \
token_reviewer_jwt="$(cat /var/run/secrets/kubernetes.io/serviceaccount/token)" \
kubernetes_ca_cert=@/var/run/secrets/kubernetes.io/serviceaccount/ca.crt \
issuer="https://kubernetes.default.svc.cluster.local"
$ vault auth list
Path Type Accessor Description Version
---- ---- -------- ----------- -------
kubernetes/ kubernetes auth_kubernetes_6ca9cb88 n/a n/a
token/ token auth_token_1081d226 token based credentials n/a
// map the vault policy with the service
account dso-demo
$ vault write auth/kubernetes/role/dso-demo \
bound_service_account_names=dso-demo \
bound_service_account_namespaces=default \
policies=dso-demo \
audience="" \
ttl=30h
Injecting a Secret into the Pod
Нужно добавить serviceAccountName: dso-demo и:
annotations:
vault.hashicorp.com/agent-inject: 'true'
vault.hashicorp.com/role: 'dso-demo'
vault.hashicorp.com/agent-inject-secret-database: 'secret/dso-demo/database'
В файл:
https://github.com/wildmakaka/dso-demo/blob/main/deploy/dso-demo-deploy.yaml
$ cat << 'EOF' | kubectl apply -f -
apiVersion: v1
kind: ServiceAccount
metadata:
name: dso-demo
EOF
$ cat << 'EOF' | kubectl create -f -
apiVersion: apps/v1
kind: Deployment
metadata:
creationTimestamp: null
labels:
app: dso-demo
name: dso-demo
spec:
replicas: 1
selector:
matchLabels:
app: dso-demo
strategy: {}
template:
metadata:
creationTimestamp: null
labels:
app: dso-demo
annotations:
vault.hashicorp.com/agent-inject: 'true'
vault.hashicorp.com/role: 'dso-demo'
vault.hashicorp.com/agent-inject-secret-database: 'secret/dso-demo/database'
spec:
serviceAccountName: dso-demo
containers:
- image: webmakaka/dso-demo
name: dso-demo
ports:
- containerPort: 8080
resources: {}
status: {}
EOF
$ kubectl get pods
NAME READY STATUS RESTARTS AGE
dso-demo-6768c4d85f-chrwk 0/2 Init:0/1 0 2m4s
Пошли траблшутить!
Troubleshooting the Vault Policy
$ vault policy read dso-demo
path "secret/data/dso-demo/database" {
capabilities = ["read"]
$ vault kv get secret/dso-demo/database
======== Secret Path ========
secret/data/dso-demo/database
======= Metadata =======
Key Value
--- -----
created_time 2026-01-04T05:26:07.408297829Z
custom_metadata <nil>
deletion_time n/a
destroyed false
version 1
====== Data ======
Key Value
--- -----
password mysupersecret
username devops
$ vault policy write dso-demo - <<EOF
path "secret/data/dso-demo/*" {
capabilities = ["read"]
}
EOF
$ vault policy read dso-demo
path "secret/data/dso-demo/*" {
capabilities = ["read"]
}
Не помогло!
$ vault policy write dso-demo - <<EOF
path "*" {
capabilities = ["read"]
}
EOF
$ kubectl exec -it dso-demo-xxxx -- sh
# ls /vault/secrets/
database
# cat /vault/secrets/database
data: map[password:mysupersecret username:devops]
metadata: map[created_time:2026-01-04T05:26:07.408297829Z custom_metadata:<nil> deletion_time: destroyed:false version:1]
$ vault policy write dso-demo - <<EOF
path "secret/data/dso-demo/database" {
capabilities = ["read"]
}
EOF
Customizing Secrets using Templates
$ cat << 'EOF' | kubectl apply -f -
apiVersion: apps/v1
kind: Deployment
metadata:
creationTimestamp: null
labels:
app: dso-demo
name: dso-demo
spec:
replicas: 1
selector:
matchLabels:
app: dso-demo
strategy: {}
template:
metadata:
creationTimestamp: null
labels:
app: dso-demo
annotations:
vault.hashicorp.com/agent-inject: 'true'
vault.hashicorp.com/role: 'dso-demo'
vault.hashicorp.com/agent-inject-secret-database: 'secret/dso-demo/database'
vault.hashicorp.com/agent-inject-template-database: |mysql -u -p -h database:3306 mydbspec:
serviceAccountName: dso-demo
containers:
- image: webmakaka/dso-demo
name: dso-demo
ports:
- containerPort: 8080
resources: {}
status: {}
EOF
$ kubectl exec -it dso-demo-xxxx -- sh
# cat /vault/secrets/database
mysql -u devops -p mysupersecret -h database:3306 mydb
Rotating Secrets
$ vault kv put secret/dso-demo/database user=devops password=superdupersecretnow
Ждем сколько-то времени.
# cat /vault/secrets/database
mysql -u <no value> -p superdupersecretnow -h database:3306 mydb