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:
- Discovery -- The CLI scans workloads and identifies which Kubernetes Secrets they reference (via
envFrom,env.valueFrom, and volume mounts). - Mapping -- The CLI generates SecretMapping CRs that map each K8s Secret to a corresponding Vault path.
- 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.
vaultAddress¶
| Type | string |
| Required | Yes |
The URL of the EU-hosted OpenBao or Vault instance.
vaultRole¶
| Type | string |
| Required | Yes |
The Vault Kubernetes auth role for authenticating the matched workloads.
vaultAuthPath¶
| Type | string |
| Required | No |
| Default | "auth/kubernetes" |
The mount path of the Kubernetes auth method in Vault.
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.
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¶
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¶
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¶
Verify¶
Expected output:
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:
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.