Skip to content

SecretMapping CRD

The SecretMapping custom resource defines how existing Kubernetes Secrets map to Vault paths. It is typically auto-generated by the cloudtaser discover command during migration, but can also be created manually. When applied, the operator automatically injects matching workloads with the CloudTaser wrapper, replacing their dependency on Kubernetes Secrets with direct Vault access.


API Details

Field Value
API Group api.cloudtaser.io
API Version v1alpha1
Kind SecretMapping
Short Name sm
Scope Namespaced
# List all SecretMappings
kubectl get sm -A

# Describe a specific mapping
kubectl describe sm payment-service-secrets -n production

Purpose

SecretMapping bridges the gap between existing Kubernetes Secrets and Vault-based secret delivery. During a migration:

  1. Discovery -- The CLI scans workloads and identifies which Kubernetes Secrets they reference (via envFrom, env.valueFrom, and volume mounts).
  2. Mapping -- The CLI generates SecretMapping CRs that map each K8s Secret to a corresponding Vault path.
  3. Migration -- The operator reads the SecretMapping, injects the wrapper into matching pods, and (optionally) removes the original Secret references.

This allows teams to migrate incrementally, one workload at a time, without changing application code.


Spec Fields

selector

Type metav1.LabelSelector
Required Yes

Label selector that identifies which workloads this mapping applies to. All pods matching the selector in the same namespace will receive CloudTaser injection based on this mapping.

spec:
  selector:
    matchLabels:
      app: payment-service

vaultAddress

Type string
Required Yes

The URL of the EU-hosted OpenBao or Vault instance.

spec:
  vaultAddress: "https://vault.eu-west-1.example.com:8200"

vaultRole

Type string
Required Yes

The Vault Kubernetes auth role for authenticating the matched workloads.

spec:
  vaultRole: "payment-service"

vaultAuthPath

Type string
Required No
Default "auth/kubernetes"

The mount path of the Kubernetes auth method in Vault.

spec:
  vaultAuthPath: "auth/kubernetes"

sources

Type []Source
Required Yes

An array of secret sources describing the mapping from original Kubernetes Secrets to Vault paths. Each entry represents one Kubernetes Secret that has been migrated.

Source Fields

Field Type Required Description
originalType string Yes The type of original K8s secret reference: "Secret", "ConfigMap", or "ExternalSecret"
originalRef string Yes The name of the original Kubernetes Secret or ConfigMap
vaultPath string Yes The Vault KV path where the secret data has been migrated
envMapping map[string]string No Maps original secret keys to environment variable names
spec:
  sources:
    - originalType: "Secret"
      originalRef: "payment-db-credentials"
      vaultPath: "secret/data/payments/database"
      envMapping:
        username: PGUSER
        password: PGPASSWORD
    - originalType: "Secret"
      originalRef: "stripe-api-key"
      vaultPath: "secret/data/payments/stripe"
      envMapping:
        api_key: STRIPE_SECRET_KEY

stripOriginals

Type bool
Required No
Default false

When true, the operator removes the original Kubernetes Secret references (envFrom, env.valueFrom, volume mounts) from the pod spec during injection. This ensures the pod no longer depends on Kubernetes Secrets at all.

spec:
  stripOriginals: true

Use with caution

Setting stripOriginals: true modifies the pod spec to remove Secret references. Verify that all referenced secrets have been migrated to Vault before enabling this. If a secret is missing from Vault, the application will fail to start.

Incremental migration

During migration, keep stripOriginals: false (the default). Both the original K8s Secret and the Vault secret will be available. Once you have verified the application works with Vault secrets, set stripOriginals: true to complete the cutover.


Status Fields

The status subresource is managed by the operator and is read-only.

ready

Type bool

Indicates whether the mapping has been validated and is active.

message

Type string

A human-readable status message.

matchedWorkloads

Type int

The number of workloads (Deployments, StatefulSets, DaemonSets, Jobs) whose pods match the selector.

migratedSecrets

Type int

The number of source entries that have been validated as accessible in Vault.


Full Example

secretmapping-full.yaml
apiVersion: api.cloudtaser.io/v1alpha1
kind: SecretMapping
metadata:
  name: payment-service-secrets
  namespace: production
  labels:
    app.kubernetes.io/name: payment-service
    app.kubernetes.io/managed-by: cloudtaser-cli
  annotations:
    cloudtaser.io/discovered-at: "2026-03-21T09:00:00Z"
    cloudtaser.io/source-cluster: "gke-prod-eu-west1"
spec:
  selector:
    matchLabels:
      app: payment-service
  vaultAddress: "https://vault.eu-west-1.example.com:8200"
  vaultRole: "payment-service"
  vaultAuthPath: "auth/kubernetes"
  sources:
    - originalType: "Secret"
      originalRef: "payment-db-credentials"
      vaultPath: "secret/data/payments/database"
      envMapping:
        username: PGUSER
        password: PGPASSWORD
        host: PGHOST
        port: PGPORT
        dbname: PGDATABASE
    - originalType: "Secret"
      originalRef: "stripe-api-key"
      vaultPath: "secret/data/payments/stripe"
      envMapping:
        secret_key: STRIPE_SECRET_KEY
        webhook_secret: STRIPE_WEBHOOK_SECRET
    - originalType: "Secret"
      originalRef: "internal-api-token"
      vaultPath: "secret/data/payments/internal-api"
      envMapping:
        token: INTERNAL_API_TOKEN
  stripOriginals: false

Usage with the CLI

The typical workflow uses the CLI to generate SecretMappings automatically.

Discover existing secrets

cloudtaser discover --namespace production --output secretmappings/

This scans all workloads in the production namespace, identifies Kubernetes Secret references, and generates a SecretMapping YAML file for each workload.

Review and customize

Review the generated files and adjust envMapping or vaultPath values as needed. The CLI generates sensible defaults based on the original Secret keys.

Migrate secrets to Vault

cloudtaser migrate --mapping secretmappings/payment-service-secrets.yaml \
  --vault-addr https://vault.eu-west-1.example.com:8200

This copies the actual secret values from Kubernetes Secrets into the specified Vault paths.

Apply the mapping

kubectl apply -f secretmappings/payment-service-secrets.yaml

Verify

kubectl get sm -n production

Expected output:

NAME                       READY   MATCHED-WORKLOADS   MIGRATED-SECRETS   AGE
payment-service-secrets    True    1                   3                  30s

Complete the cutover

Once verified, enable stripOriginals to remove the original K8s Secret dependencies:

kubectl patch sm payment-service-secrets -n production \
  --type merge -p '{"spec":{"stripOriginals":true}}'

Restart the workload to apply the change:

kubectl rollout restart deployment/payment-service -n production

Relationship to CloudTaserConfig

SecretMapping and CloudTaserConfig serve complementary purposes:

CloudTaserConfig SecretMapping
Created by Platform team, manually CLI discover command
Use case New workloads built for Vault Migrating existing workloads from K8s Secrets
Selection Referenced by annotation Label selector (automatic matching)
Strips originals Not applicable Optional (stripOriginals)
Recommended for Greenfield deployments Brownfield migrations

Both can coexist in the same namespace. If a pod matches both a SecretMapping selector and has a cloudtaser.io/config annotation, the explicit annotation takes precedence.