Skip to content

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).

spec:
  secretBackend: broker

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.

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

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.

spec:
  vaultRole: "my-app-role"

vaultAuthPath (deprecated)

Type string
Required No
Default "auth/kubernetes"

Deprecated Kubernetes auth method path. Use spec.secretStore.authPath instead.

spec:
  vaultAuthPath: "auth/kubernetes-production"

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.

spec:
  wrapperImage: "europe-docker.pkg.dev/myproject/cloudtaser/wrapper:v0.2.207"

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.

spec:
  wrapperResources:
    requests:
      cpu: "20m"
      memory: "48Mi"
    limits:
      cpu: "200m"
      memory: "128Mi"

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

cloudtaserconfig-full.yaml
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.

kubectl apply -f cloudtaserconfig-full.yaml

Step 2: Verify the config is ready.

kubectl get ctc payment-service -n production

Expected output:

NAME              READY   INJECTED-PODS   LAST-VALIDATED         AGE
payment-service   True    0               2026-03-21T10:00:00Z   5s

Step 3: Reference the config from your Deployment annotations.

deployment.yaml
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:

kubectl logs -n cloudtaser-system deployment/cloudtaser-operator -f