CloudTaserConfig CRD¶
The CloudTaserConfig custom resource provides a reusable, namespace-scoped configuration object for cloudtaser wrapper injection. Instead of specifying OpenBao addresses, secret paths, and environment mappings as individual pod annotations, you define them once in a CR and reference it from your workloads.
CloudTaserConfig centralizes secret injection configuration into a single Kubernetes resource per workload. This separation means platform teams can manage OpenBao paths and access policies independently of application deployment manifests. Changes to secret configuration do not require application redeployment, and the operator validates OpenBao connectivity and permissions automatically.
API Details¶
| Field | Value |
|---|---|
| API Group | api.cloudtaser.io |
| API Version | v1alpha1 |
| Kind | CloudTaserConfig |
| Short Name | ctc |
| Scope | Namespaced |
# List all CloudTaserConfig resources
kubectl get ctc -A
# Describe a specific config
kubectl describe ctc my-app-config -n production
Spec Fields¶
secretBackend¶
| Type | string |
| Required | No |
| Default | "auto" |
| Enum | vault, broker, auto |
Selects the secret delivery backend: "broker" (reverse-connect via beacon -- the default when a beacon address is configured), "vault" (legacy direct Secretstore HTTP), or "auto" (detect based on operator config).
secretStore¶
| Type | object |
| Required | No |
Groups the canonical connection settings for the CloudTaser Secretstore. Prefer this over the top-level vaultAddress / vaultRole / vaultAuthPath fields in new manifests; the top-level fields remain accepted as a deprecated alias and will be removed in CloudTaser v0.9.0.
| Sub-field | Type | Default | Description |
|---|---|---|---|
address |
string |
-- | Secretstore endpoint. Only required in vault (legacy direct) mode |
role |
string |
-- | Secretstore role for Kubernetes auth. Only required in vault mode |
authPath |
string |
auth/kubernetes |
Kubernetes auth method path |
caCertConfigMap |
string |
-- | ConfigMap in the workload's namespace holding the PEM CA bundle for Secretstore TLS |
caCertConfigMapKey |
string |
ca.crt |
Key within the ConfigMap |
spec:
secretStore:
address: "https://vault.eu-west-1.example.com:8200"
role: "my-app-role"
authPath: "auth/kubernetes"
vaultAddress (deprecated)¶
| Type | string |
| Required | No |
Deprecated Secretstore endpoint. Use spec.secretStore.address instead. Retained for back-compat with manifests authored before cloudtaser-operator v0.8.0; will be removed in CloudTaser v0.9.0.
vaultRole (deprecated)¶
| Type | string |
| Required | No |
Deprecated Secretstore role. Use spec.secretStore.role instead. Retained for back-compat and removed in CloudTaser v0.9.0.
vaultAuthPath (deprecated)¶
| Type | string |
| Required | No |
| Default | "auth/kubernetes" |
Deprecated Kubernetes auth method path. Use spec.secretStore.authPath instead.
secretPaths¶
| Type | []string |
| Required | Yes |
A list of OpenBao KV secret paths to fetch at pod startup. Each path is read in order, and all key-value pairs from each path are made available to the wrapped application process.
spec:
secretPaths:
- "secret/data/myapp/database"
- "secret/data/myapp/api-keys"
- "secret/data/shared/tls-certs"
envMap¶
| Type | string |
| Required | No |
Maps OpenBao secret fields to specific environment variable names, in the same format as the secretstore.cloudtaser.io/env-map annotation: field=ENV_VAR pairs separated by commas, one group per secretPaths entry, and the groups separated by semicolons in secretPaths order.
spec:
secretPaths:
- "secret/data/myapp/database"
- "secret/data/myapp/api-keys"
envMap: "username=DB_USER,password=DB_PASS,host=DB_HOST;stripe_key=STRIPE_SECRET_KEY,sendgrid_key=SENDGRID_API_KEY"
Unmapped fields
Fields not listed in envMap are still injected into the process environment using their original OpenBao field names. The map provides renaming, not filtering.
wrapperImage¶
| Type | string |
| Required | No |
| Default | Uses the image configured in the operator |
Overrides the wrapper container image. Useful when pinning specific wrapper versions per workload or using a private registry mirror.
wrapperResources¶
| Type | corev1.ResourceRequirements |
| Required | No |
| Default | requests: {cpu: 10m, memory: 32Mi}, limits: {cpu: 100m, memory: 64Mi} |
Resource requests and limits for the injected wrapper init container and sidecar.
workloadImageVerification¶
| Type | object |
| Required | No |
Configures cosign signature verification for user workload container images at admission time. When enabled, the webhook verifies cosign signatures on all container and init-container images using per-registry public key policies before admitting the pod.
| Sub-field | Type | Default | Description |
|---|---|---|---|
enabled |
boolean |
false |
Turns workload image verification on or off |
mode |
string |
warn |
Admission behaviour on verification failure: enforce (deny) or warn (admit with annotation) |
defaultAction |
string |
allow |
Behaviour for images matching no policy: allow, deny, or warn |
policies |
[]object |
-- | Per-registry cosign public key policies |
policies[].registryPrefix |
string |
-- | Image reference prefix to match |
policies[].cosignPublicKey |
string |
-- | PEM-encoded public key for signature verification |
spec:
workloadImageVerification:
enabled: true
mode: enforce
defaultAction: deny
policies:
- registryPrefix: "europe-west4-docker.pkg.dev/myproject/"
cosignPublicKey: |
-----BEGIN PUBLIC KEY-----
MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE...
-----END PUBLIC KEY-----
Status Fields¶
The status subresource is managed by the operator and is read-only.
ready¶
| Type | bool |
Indicates whether the config has been validated and is ready for use. The operator validates OpenBao connectivity and auth configuration.
message¶
| Type | string |
A human-readable message describing the current state, especially useful when ready is false.
injectedPods¶
| Type | int |
The number of pods currently running with this config applied.
lastValidated¶
| Type | metav1.Time |
Timestamp of the last successful validation of the OpenBao connection and auth configuration.
conditions¶
| Type | []metav1.Condition |
Standard Kubernetes conditions providing detailed status information.
| Condition Type | Description |
|---|---|
VaultReachable |
The operator can reach the configured OpenBao address. |
AuthConfigured |
The Kubernetes auth role is valid and accepts tokens from the target namespace. |
SecretsAccessible |
The configured secret paths are readable with the given role. |
Ready |
All validation checks have passed. |
Full Example¶
apiVersion: api.cloudtaser.io/v1alpha1
kind: CloudTaserConfig
metadata:
name: payment-service
namespace: production
labels:
app.kubernetes.io/name: payment-service
app.kubernetes.io/part-of: payments
spec:
vaultAddress: "https://vault.eu-west-1.example.com:8200"
vaultRole: "payment-service"
vaultAuthPath: "auth/kubernetes"
secretPaths:
- "secret/data/payments/database"
- "secret/data/payments/stripe"
- "secret/data/payments/internal-api"
envMap: "username=PGUSER,password=PGPASSWORD,host=PGHOST,port=PGPORT,dbname=PGDATABASE;secret_key=STRIPE_SECRET_KEY,webhook_secret=STRIPE_WEBHOOK_SECRET;token=INTERNAL_API_TOKEN"
wrapperImage: "europe-west4-docker.pkg.dev/skipopsmain/cloudtaser/cloudtaser-wrapper:v0.2.207"
wrapperResources:
requests:
cpu: "10m"
memory: "32Mi"
limits:
cpu: "100m"
memory: "64Mi"
Usage Pattern¶
Step 1: Create the CloudTaserConfig in your target namespace.
Step 2: Verify the config is ready.
Expected output:
Step 3: Reference the config from your Deployment annotations.
apiVersion: apps/v1
kind: Deployment
metadata:
name: payment-service
namespace: production
spec:
replicas: 3
selector:
matchLabels:
app: payment-service
template:
metadata:
labels:
app: payment-service
annotations:
secretstore.cloudtaser.io/inject: "true"
cloudtaser.io/config: "payment-service"
cloudtaser.io/rotation: "sighup"
cloudtaser.io/ebpf: "true"
spec:
serviceAccountName: payment-service
containers:
- name: api
image: eu.gcr.io/myproject/payment-service:v2.1.0
ports:
- containerPort: 8080
Step 4: Confirm injection after pod creation.
kubectl get pods -n production -l app=payment-service -o jsonpath='{.items[0].metadata.annotations.cloudtaser\.io/status}'
Expected output: injected
Troubleshooting¶
Config not found
If the webhook cannot find the referenced CloudTaserConfig in the pod's namespace, the pod will be admitted without injection and cloudtaser.io/status will be set to "error". Check that the CR name matches exactly and exists in the same namespace as the pod.
Config not ready
If the CloudTaserConfig exists but its ready status is false, the webhook will still inject the sidecar, but the wrapper may fail to authenticate at runtime. Always verify kubectl get ctc shows READY: True before deploying workloads.
Check operator logs for detailed validation errors: