Skip to content

Annotations Reference

CloudTaser uses Kubernetes pod annotations under the cloudtaser.io/ prefix to control sidecar injection, secret fetching, eBPF enforcement, and S3 proxy behaviour. Annotations are evaluated by the mutating admission webhook at pod creation time.


Injection Control

cloudtaser.io/inject

Required Yes
Values "true" or "false"
Default Not set (no injection)

Enables or disables CloudTaser sidecar injection for the pod. The webhook only mutates pods where this annotation is explicitly set to "true".

metadata:
  annotations:
    cloudtaser.io/inject: "true"

Annotation values must be strings

Kubernetes annotation values are always strings. Use "true" (quoted) in YAML, not the bare boolean true.

cloudtaser.io/config

Required No
Values Name of a CloudTaserConfig CR in the same namespace
Default Not set

References a CloudTaserConfig custom resource by name. When set, the webhook reads vault address, role, secret paths, and env mappings from the CR instead of individual annotations. This is the recommended approach for production workloads.

metadata:
  annotations:
    cloudtaser.io/inject: "true"
    cloudtaser.io/config: "my-app-config"

Config reference vs inline annotations

When cloudtaser.io/config is set, individual vault/secret annotations on the pod are ignored. The CR is the single source of truth. This keeps your Deployment manifests clean and allows config changes without redeploying.

cloudtaser.io/containers

Required No
Values Comma-separated container names
Default All containers in the pod

Restricts which containers in the pod receive the injected wrapper. By default, the wrapper is injected into every container. Use this annotation to target specific containers when a pod runs multiple containers and only some need secrets.

metadata:
  annotations:
    cloudtaser.io/inject: "true"
    cloudtaser.io/containers: "api,worker"

Vault Configuration

cloudtaser.io/vault-address

Required Yes (unless using config reference)
Values URL (including scheme and port)
Default Not set

The address of the EU-hosted OpenBao or Vault instance. Must be reachable from the pod network. TLS is strongly recommended for production.

cloudtaser.io/vault-address: "https://vault.eu-west-1.example.com:8200"

cloudtaser.io/vault-role

Required Yes (unless using config reference)
Values Vault Kubernetes auth role name
Default Not set

The Vault role used for Kubernetes service account authentication. The role must be configured in Vault to accept the pod's service account token.

cloudtaser.io/vault-role: "my-app-role"

cloudtaser.io/vault-auth-method

Required No
Values "kubernetes", "token"
Default "kubernetes"

The authentication method used to obtain a Vault token. Kubernetes auth is the default and recommended method for pods. Token auth is available for testing or when integrating with external token providers.

cloudtaser.io/vault-auth-method: "kubernetes"

Token auth

When using "token", the wrapper expects a valid Vault token in the VAULT_TOKEN environment variable. This is primarily useful for local development and testing. In production, use Kubernetes auth.

cloudtaser.io/vault-tls-skip-verify

Required No
Values "true" or "false"
Default "false"

Disables TLS certificate verification when connecting to Vault. This should only be used in development or testing environments.

cloudtaser.io/vault-tls-skip-verify: "true"

Do not use in production

Skipping TLS verification defeats the purpose of EU data sovereignty. An attacker performing a man-in-the-middle attack could intercept secrets in transit. Always use properly signed certificates in production.


Secret Configuration

cloudtaser.io/secret-paths

Required Yes (unless using config reference)
Values Comma-separated Vault KV paths
Default Not set

One or more Vault KV secret paths to fetch. The wrapper retrieves all key-value pairs from each path and makes them available to the application process.

cloudtaser.io/secret-paths: "secret/data/myapp/db,secret/data/myapp/api-keys"

cloudtaser.io/env-map

Required No
Values Field-to-variable mappings (see format below)
Default Not set (all fields exposed with original names)

Maps individual Vault secret fields to specific environment variable names. Each path's mappings are separated by semicolons, and within a path, individual field mappings use the field=VAR format separated by commas.

Format: field1=VAR1,field2=VAR2;field3=VAR3,field4=VAR4

  • Commas separate field mappings within the same secret path
  • Semicolons separate mapping groups corresponding to each path in secret-paths
cloudtaser.io/secret-paths: "secret/data/myapp/db,secret/data/myapp/stripe"
cloudtaser.io/env-map: "username=DB_USER,password=DB_PASS;api_key=STRIPE_KEY"

In this example:

  • From secret/data/myapp/db: field username becomes DB_USER, field password becomes DB_PASS
  • From secret/data/myapp/stripe: field api_key becomes STRIPE_KEY

Unmapped fields

Fields not listed in the env-map are still available to the application under their original Vault field names. The env-map provides renaming, not filtering.


Rotation

cloudtaser.io/rotation

Required No
Values "restart", "sighup", "none"
Default "none"

Controls how the wrapper handles secret rotation when Vault secrets are updated.

Value Behaviour
"restart" The wrapper terminates the application process and re-launches it with the new secrets. Suitable for applications that only read environment variables at startup.
"sighup" The wrapper sends SIGHUP to the application process after updating secrets in memory. The application must handle SIGHUP to re-read its configuration.
"none" Secrets are fetched once at startup. No automatic rotation. The pod must be restarted to pick up new secrets.
cloudtaser.io/rotation: "sighup"

eBPF Enforcement

cloudtaser.io/ebpf

Required No
Values "true" or "false"
Default "false"

Enables eBPF runtime enforcement for the pod. When enabled, the wrapper registers with the eBPF agent running on the node to activate kernel-level secret protection. Requires the eBPF daemonset to be deployed on the cluster.

cloudtaser.io/ebpf: "true"

See the eBPF agent configuration for details on enforcement modes and detected event types.


S3 Proxy

cloudtaser.io/s3-proxy

Required No
Values "true" or "false"
Default "false"

Injects the CloudTaser S3 encryption proxy as an additional sidecar container. The proxy transparently encrypts objects before they reach cloud storage using keys held in your EU vault.

cloudtaser.io/s3-proxy: "true"

cloudtaser.io/s3-proxy-endpoint

Required No (when using s3-proxy: "true")
Values S3-compatible endpoint URL
Default AWS S3 default endpoint

The upstream S3-compatible endpoint the proxy forwards requests to after encryption.

cloudtaser.io/s3-proxy-endpoint: "https://s3.eu-west-1.amazonaws.com"

cloudtaser.io/s3-proxy-region

Required No
Values AWS region string
Default "eu-west-1"

The AWS region for S3 requests.

cloudtaser.io/s3-proxy-region: "eu-central-1"

cloudtaser.io/s3-proxy-transit-key

Required Yes (when using s3-proxy: "true")
Values Vault Transit key name
Default Not set

The name of the Transit encryption key in Vault used to wrap per-object data encryption keys.

cloudtaser.io/s3-proxy-transit-key: "s3-dek-wrapper"

cloudtaser.io/s3-proxy-transit-mount

Required No
Values Vault Transit mount path
Default "transit"

The Vault mount path for the Transit secrets engine.

cloudtaser.io/s3-proxy-transit-mount: "transit"

Status (Read-Only)

cloudtaser.io/status

Set by Webhook (read-only)
Values "injected", "skipped", "error"

Set by the mutating admission webhook after processing the pod. Do not set this annotation manually.

Value Meaning
"injected" Sidecar injection was successful.
"skipped" The pod was evaluated but injection was not performed (e.g., inject: "false" or namespace excluded).
"error" Injection was attempted but failed. Check operator logs for details.

Complete Annotation Reference Table

Annotation Required Default Description
cloudtaser.io/inject Yes -- Enable sidecar injection
cloudtaser.io/config No -- Reference a CloudTaserConfig CR
cloudtaser.io/vault-address Conditional -- Vault endpoint URL
cloudtaser.io/vault-role Conditional -- Kubernetes auth role
cloudtaser.io/vault-auth-method No kubernetes Auth method
cloudtaser.io/vault-tls-skip-verify No false Skip TLS verification
cloudtaser.io/secret-paths Conditional -- Vault KV paths
cloudtaser.io/env-map No -- Field-to-env mappings
cloudtaser.io/rotation No none Rotation strategy
cloudtaser.io/containers No All Target containers
cloudtaser.io/ebpf No false Enable eBPF enforcement
cloudtaser.io/s3-proxy No false Inject S3 proxy sidecar
cloudtaser.io/s3-proxy-endpoint No AWS default S3 upstream endpoint
cloudtaser.io/s3-proxy-region No eu-west-1 S3 region
cloudtaser.io/s3-proxy-transit-key Conditional -- Transit encryption key name
cloudtaser.io/s3-proxy-transit-mount No transit Transit mount path
cloudtaser.io/status -- -- Read-only, set by webhook

"Conditional" means the annotation is required when not using a cloudtaser.io/config reference, or (for S3 fields) when s3-proxy is enabled.


Full Examples

Inline Annotations

All configuration specified directly on the Deployment:

deployment-inline.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:
        cloudtaser.io/inject: "true"
        cloudtaser.io/vault-address: "https://vault.eu-west-1.example.com:8200"
        cloudtaser.io/vault-role: "payment-service"
        cloudtaser.io/secret-paths: "secret/data/payments/db,secret/data/payments/stripe"
        cloudtaser.io/env-map: "username=DB_USER,password=DB_PASS;api_key=STRIPE_SECRET_KEY"
        cloudtaser.io/rotation: "sighup"
        cloudtaser.io/ebpf: "true"
        cloudtaser.io/containers: "api"
    spec:
      serviceAccountName: payment-service
      containers:
        - name: api
          image: eu.gcr.io/myproject/payment-service:v2.1.0
          ports:
            - containerPort: 8080
        - name: metrics
          image: eu.gcr.io/myproject/metrics-exporter:v1.0.0
          ports:
            - containerPort: 9090

In this example, only the api container receives secret injection. The metrics container is left untouched.

CloudTaserConfig Reference

Configuration managed through a CR, keeping the Deployment clean:

cloudtaserconfig.yaml
apiVersion: api.cloudtaser.io/v1alpha1
kind: CloudTaserConfig
metadata:
  name: payment-service
  namespace: production
spec:
  vaultAddress: "https://vault.eu-west-1.example.com:8200"
  vaultRole: "payment-service"
  secretPaths:
    - "secret/data/payments/db"
    - "secret/data/payments/stripe"
  envMap:
    "secret/data/payments/db":
      username: DB_USER
      password: DB_PASS
    "secret/data/payments/stripe":
      api_key: STRIPE_SECRET_KEY
deployment-with-config-ref.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:
        cloudtaser.io/inject: "true"
        cloudtaser.io/config: "payment-service"
        cloudtaser.io/rotation: "sighup"
        cloudtaser.io/ebpf: "true"
        cloudtaser.io/containers: "api"
    spec:
      serviceAccountName: payment-service
      containers:
        - name: api
          image: eu.gcr.io/myproject/payment-service:v2.1.0
          ports:
            - containerPort: 8080
        - name: metrics
          image: eu.gcr.io/myproject/metrics-exporter:v1.0.0
          ports:
            - containerPort: 9090

Recommended for production

Using a CloudTaserConfig reference separates secret configuration from workload deployment. Platform teams can manage vault paths and mappings independently of application deployment manifests.

S3 Proxy Injection

Adding client-side encryption to an application that uses S3:

deployment-s3-proxy.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: document-store
  namespace: production
spec:
  replicas: 2
  selector:
    matchLabels:
      app: document-store
  template:
    metadata:
      labels:
        app: document-store
      annotations:
        cloudtaser.io/inject: "true"
        cloudtaser.io/vault-address: "https://vault.eu-west-1.example.com:8200"
        cloudtaser.io/vault-role: "document-store"
        cloudtaser.io/secret-paths: "secret/data/docstore/db"
        cloudtaser.io/s3-proxy: "true"
        cloudtaser.io/s3-proxy-endpoint: "https://s3.eu-west-1.amazonaws.com"
        cloudtaser.io/s3-proxy-region: "eu-west-1"
        cloudtaser.io/s3-proxy-transit-key: "docstore-dek"
        cloudtaser.io/ebpf: "true"
    spec:
      serviceAccountName: document-store
      containers:
        - name: app
          image: eu.gcr.io/myproject/document-store:v1.3.0
          env:
            - name: AWS_ENDPOINT_URL
              value: "http://localhost:8099"
          ports:
            - containerPort: 8080

The application points its S3 client at localhost:8099 (the injected proxy), and the proxy handles encryption transparently before forwarding to the real S3 endpoint.