Vault
Set up the Vault Secrets Operator CSI driver
Enterprise
Appropriate Vault Enterprise license required
Use the Vault Secrets Operator CSI driver with a CSISecrets
resource to
allow authorized Pods to mount ephemeral volumes containing secrets
from Vault as indexed files. Indexing starts at 0
and represents the
associated position in the associated vaultStaticSecrets
or
vaultAppRoleSecretIDs
list in the CSISecrets
resource. For example,
static_secret_0_secret
, static_secret_1_secret
, ... static_secret_N_secret
.
The CSI driver generates and syncs new AppRole secret IDs on container startup.
All other secrets sync when a requesting container starts or restarts, or when a user modifies a CSISecrets
resource.
Before you start
- Review the Vault Secrets Operator threat model. The simplified Kubernetes RBAC configuration examples below are not appropriate for production use.
- Review any applicable regulations or requirements to understand how your authentication choices may impact cluster security.
- Review the available Kubernetes integrations to confirm the Vault Secrets Operator CSI driver functionality meets your needs.
- Review your application deployments to determine how, if at all, they should handle Pod restarts for secrets updates.
Step 1: Install driver
Install the Vault Secrets Operator Helm chart with the csi.enabled
flag set to true
to deploy the CSI
driver as a DaemonSet running on every node:
$ helm install \
--version 1.0.0 \
--create-namespace \
--namespace vault-secrets-operator \
--set "csi.enabled=true" \
vault-secrets-operator \
hashicorp/vault-secrets-operator
Refer to the Helm chart documentation for additional configuration options.
Step 2: Create your Vault policies
You must create a Vault policy to allow the CSI driver to fetch secrets and/or generate AppRole secret IDs.
For example, the following policy lets the CSI driver fetch secrets from the Key/Value plugin:
path "example-kv/password" {
capabilities = ["read"]
}
path "example-kv-v2/data/api-key" {
capabilities = ["read"]
}
path "sys/license/status" {
capabilities = ["read"]
}
To generate AppRole secret IDs with the CSI driver so application Pods can log into Vault and fetch secrets independently, your Vault policy must grant the CSI driver permissions for the associated role.
For example, the following policy lets the CSI driver generate secret IDs using the AppRole plugin:
path "auth/approle/role/example-role/secret-id" {
capabilities = ["update"]
}
path "auth/approle/role/example-role/role-id" {
capabilities = ["read"]
}
Once you write the policy to Vault, you can create a role that uses that policy in any auth method supported by Vault Secrets Operator.
For example, to use the policy with the Kubernetes auth method:
$ vault write auth/kubernetes/role/example-auth-role \
bound_service_account_names=default \
bound_service_account_namespaces=default,vault-secrets-operator-system \
token_period=120 \
token_policies=csi-driver-policy \
audience=vault
Step 3: Create your auth custom resources
To authenticate the CSI driver to Vault, you must create VaultAuth
and
VaultConnection
resources,
as defined in the Custom Resource Definitions (CRDs) of the Vault Secrets Operator Helm chart and apply it to your cluster.
You can reference existing auth resources from Vault Secrets Operator or create entirely new resources. For example:
apiVersion: secrets.hashicorp.com/v1beta1
kind: VaultAuth
metadata:
name: default
namespace: vault-secrets-operator-system
spec:
vaultAuthGlobalRef:
name: default
---
apiVersion: secrets.hashicorp.com/v1beta1
kind: VaultAuthGlobal
metadata:
name: default
namespace: vault-secrets-operator-system
spec:
defaultAuthMethod: kubernetes
kubernetes:
audiences:
- vault
mount: kubernetes
role: example-auth-role
serviceAccount: example-service-account
tokenExpirationSeconds: 600
---
apiVersion: secrets.hashicorp.com/v1beta1
kind: VaultConnection
metadata:
name: default
namespace: vault-secrets-operator-system
spec:
address: http://vault.vault.svc.cluster.local:8200
skipTLSVerify: false
For more detailed resource examples, refer to the Vault Secrets Operator guide for Vault authentication.
Step 4: Create the CSISecrets resource
To securely sync secrets between Vault and your application Pods, you
must create a custom resource called CSISecrets
that lists information
available to the CSI driver Pods.
For example, the following resource definition creates a single CSISecrets
resource that can:
- Generate secret IDs from an
approle
auth method mounted atauth/approle
for a role configured with the namemy-app
. - Limit which Pods can use the associated
CSISecrets
resource based on regular expression patterns in theaccessControl
field. - Fetch secrets from a
kv
v1 secrets engine mounted atkv1
. - Fetch secrets from a
kv
v2 secrets engine mounted atkv2
.
apiVersion: secrets.hashicorp.com/v1beta1
kind: CSISecrets
metadata:
name: my-app-secrets
namespace: vault-secrets-operator-system
spec:
vaultAuthRef:
name: default
secrets:
vaultStaticSecrets:
- mount: kv1
path: app-api-key
type: kv-v1
- mount: kv2
path: app-api-key
type: kv-v2
version: 1 # The version of the KV secret -- if not specified, defaults to the latest version
vaultAppRoleSecretIDs:
- role: my-app
mount: approle
wrapTTL: "30m"
ttl: "1h"
numUses: 2
accessControl:
serviceAccountPattern: "default"
namespacePatterns:
- "default"
podNamePatterns:
- "^my-app-"
syncConfig:
containerState:
namePattern: "^(app|sidecar)$"
Refer to the full CSISecrets
API reference for additional configuration options.
Step 5: Mount the volume to your containers
Update the deployment spec for your application:
- Add the new
CSISecrets
resource to thevolumeMounts
field. - Define a regular expression in the
accessControl
stanza of yourCSISecrets
resource that specifies which Pods can access the secret data.
For example:
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-app
namespace: default
labels:
app.kubernetes.io/component: my-app
spec:
selector:
matchLabels:
app.kubernetes.io/component: my-app
replicas: 2
template:
metadata:
labels:
app.kubernetes.io/component: my-app
spec:
serviceAccountName: default
containers:
- name: app
image: my-app-image:latest
volumeMounts:
- name: csi-secrets
mountPath: /var/run/csi-secrets
- name: sidecar
image: my-app-sidecar-image:latest
volumeMounts:
- name: csi-secrets
mountPath: /var/run/csi-secrets
volumes:
- name: csi-secrets
csi:
driver: csi.vso.hashicorp.com
volumeAttributes:
csiSecretsName: my-app-secrets
csiSecretsNamespace: vault-secrets-operator-system
Tip
You can also use the Kubernetes
subPath
field and the associated file index to limit which secret files a container can
access. For example, the following subPath
limits access to the first approle
secret (app_role_0_wrap_info.json
):
volumeMounts:
- name: csi-secrets
mountPath: /var/run/app_role_0_wrap_info.json
subPath: app_role_0_wrap_info.json
Next, push the new configuration so the CSI driver Pod on your application Pod
node responds to the request. If the update succeeds, the kubelet
publishes
a volume containing all the secrets from the CSISecrets
resource.
Step 6: Verify Pods can access secrets appropriately
Once a Pod starts, you can verify whether it does, or does not, have access to the relevant CSISecrets
resource
by inspecting files on the configured mount.
For example, /var/run/csi-secrets
.