Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Sovereign, high-performance data protection

Secrets Store CSI Driver Provider

The Eviden KMS CSI provider (cosmian-kms-csi-provider) implements the Kubernetes Secrets Store CSI Driver provider interface. It allows pods to mount KMS-managed secrets as files in their filesystem without ever storing those secrets in a Kubernetes Secret object.

Worker-node DaemonSet

Unlike the KMS Provider Plugin, this component runs as a gRPC server on worker nodes (as a DaemonSet), not on control-plane nodes. It is called by the CSI driver whenever a pod is scheduled that references a SecretProviderClass.

sequenceDiagram
    participant K as kubelet
    participant D as secrets-store-csi-driver<br/>(DaemonSet)
    participant P as cosmian-kms-csi-provider<br/>(DaemonSet, Unix socket)
    participant M as Eviden KMS

    Note over K,M: Pod scheduled with CSI volume
    K->>D: MountRequest (SecretProviderClass)
    D->>P: gRPC Mount (objects list)
    P->>M: KMIP Get (object UID)
    M-->>P: plaintext secret value
    P-->>D: MountResponse (files + metadata)
    D-->>K: tmpfs volume mounted at /mnt/secrets-store/
    Note over K,M: Secret available as a file inside the pod

Prerequisites

RequirementDetails
Eviden KMS ≥ 5.26.0Running and reachable from every worker node
Kubernetes ≥ 1.25Secrets Store CSI Driver stable API
Helm ≥ 3.8Used to install the CSI driver and the provider
Secrets Store CSI DriverInstalled via Helm (see below)

Install the Secrets Store CSI Driver

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 \
  --namespace kube-system \
  --set syncSecret.enabled=false \
  --set enableSecretRotation=true \
  --set rotationPollInterval=1m

Enable enableSecretRotation if you want in-place file updates when a secret is rotated in the KMS.


Installation

The CSI provider is packaged together with the Eviden KMS Helm chart. Install the provider DaemonSet alongside the KMS server:

helm repo add cosmian https://cosmian.github.io/kms
helm repo update

helm install cosmian-kms cosmian/kms \
  --namespace cosmian-kms --create-namespace \
  --set csiProvider.enabled=true

To install only the provider (KMS server is deployed elsewhere):

helm install cosmian-kms-csi cosmian/kms \
  --namespace cosmian-kms --create-namespace \
  --set server.enabled=false \
  --set csiProvider.enabled=true \
  --set csiProvider.kmsUrl=https://kms.example.com:9998

Configuration

Create the configuration file at /etc/cosmian-kms-csi/config.yaml on every worker node (or mount it via a ConfigMap in the DaemonSet):

cosmian_kms:
  # URL of the Eviden KMS server
  server_url: "https://kms.example.com:9998"

  # Optional: API key authentication
  # api_key: "YOUR_API_KEY"

  # Optional: mutual TLS
  # tls_cert: "/etc/cosmian-kms-csi/client.crt"
  # tls_key:  "/etc/cosmian-kms-csi/client.key"
  # ca_cert:  "/etc/cosmian-kms-csi/ca.crt"

  # Unix socket path (must match the DaemonSet hostPath)
  socket_path: "/var/run/cosmian-kms-provider.sock"

Only server_url is required. socket_path defaults to /var/run/cosmian-kms-provider.sock.


Usage

1. Pre-create a secret in the KMS

# Create a symmetric key (or any KMS object)
ckms sym keys create \
  --algorithm aes \
  --number-of-bits 256 \
  --tag db-password
# Note the UID returned — e.g. "5f3a1b2c-4d56-..."

You can also create arbitrary secret data (e.g. passwords, API keys) using the ckms CLI or the KMS web UI.

2. Create a SecretProviderClass

apiVersion: secrets-store.csi.x-k8s.io/v1
kind: SecretProviderClass
metadata:
  name: db-password
  namespace: default
spec:
  provider: cosmian-kms
  parameters:
    objects: |
      - objectName: "db-password"
        kmsUID: "5f3a1b2c-4d56-..."   # UID of the KMS object

The objects list can reference multiple KMS objects. Each produces a separate file inside the pod at <mountPath>/<objectName>.

Pinning an object version

Each object entry accepts an optional objectVersion. When it is empty or absent, the provider always serves the current content of the KMS object. When it is set, it must be the version of the object's current content, that is the lower-case hexadecimal SHA-256 digest of the bytes the provider returns; otherwise the mount fails with a FailedPrecondition error (object '<uid>' has version <actual> but the SecretProviderClass pins objectVersion <expected>).

    objects: |
      - objectName: "db-password"
        kmsUID: "5f3a1b2c-4d56-..."
        objectVersion: "9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08"

A pinned objectVersion makes pods refuse to start (or to re-mount on rotation) when the secret was changed in the KMS, so only pin versions you intend to freeze. Releases before this behavior ignored the field: any objectVersion value that is not a content digest must be removed (or emptied) before upgrading.

3. Mount the SecretProviderClass in a Pod

apiVersion: v1
kind: Pod
metadata:
  name: app
  namespace: default
spec:
  containers:
    - name: app
      image: nginx
      volumeMounts:
        - name: secrets
          mountPath: /mnt/secrets
          readOnly: true
  volumes:
    - name: secrets
      csi:
        driver: secrets-store.csi.k8s.io
        readOnly: true
        volumeAttributes:
          secretProviderClass: db-password

The secret value is available inside the container at /mnt/secrets/db-password.


Secret rotation

When enableSecretRotation=true is set on the CSI driver, it re-calls the provider at the configured rotationPollInterval. If the KMS object value has changed (the provider detects this via a SHA-256 hash of the returned bytes), the CSI driver updates the in-memory tmpfs mount atomically. The pod sees the new file content without a restart.

To rotate a secret:

  1. In the KMS, update the object (e.g. replace the key material or secret value).
  2. Wait for rotationPollInterval — the file inside the running pod will be updated automatically.

Security considerations

  • The Unix socket (/var/run/cosmian-kms-provider.sock) must only be accessible by the CSI driver. Kubernetes hostPath volumes enforce this via file permissions.
  • The configuration file containing the api_key or TLS key must be mode 0600 and owned by the provider process user.
  • Secret data is held in a tmpfs (in-memory) volume in the pod — it is never written to the node's disk.
  • Use mutual TLS (tls_cert, tls_key, ca_cert) in production to authenticate the provider to the KMS server.

Troubleshooting

SymptomLikely causeFix
pod has unbound immediate PersistentVolumeClaimsCSI driver not installedInstall secrets-store-csi-driver via Helm
provider not found: cosmian-kmsProvider DaemonSet not running on the nodeCheck kubectl get pods -n kube-system -l app=cosmian-kms-csi-provider
connection refused to KMSWrong server_url or KMS unreachableVerify server_url from inside the node
object not found in mountWrong kmsUID in SecretProviderClassVerify the UID with ckms objects get <uid>
File not updating on rotationenableSecretRotation not enabledReinstall CSI driver with --set enableSecretRotation=true

Inspect provider logs

# Find the provider pod on the same node as your failing pod
kubectl get pods -n kube-system -l app=cosmian-kms-csi-provider -o wide

# Tail provider logs
kubectl logs -n kube-system <provider-pod> -f