Quickstart: Protect a Workload in 5 Minutes¶
This guide takes you from zero to a running CloudTaser-protected workload. You will install the operator, store a secret in OpenBao, annotate a deployment, and verify that the secret exists only in process memory.
What you will have at the end: a pod where PGPASSWORD is injected directly from an EU-hosted vault into process memory. It never touches etcd, Kubernetes Secrets, or disk.
Prerequisites¶
| Tool | Purpose |
|---|---|
kubectl |
Kubernetes cluster access (1.28+) |
helm v3 |
Operator deployment |
| A running OpenBao or Vault instance | Secret storage (must be reachable from the cluster) |
bao or vault CLI |
Creating test secrets |
You also need the CloudTaser CLI installed.
# macOS (Apple Silicon)
curl -sL https://releases.cloudtaser.io/cli/v0.4.4/cloudtaser-cli-darwin-arm64 \
-o /usr/local/bin/cloudtaser && chmod +x /usr/local/bin/cloudtaser
# Linux (x86_64)
curl -sL https://releases.cloudtaser.io/cli/v0.4.4/cloudtaser-cli-linux-amd64 \
-o /usr/local/bin/cloudtaser && chmod +x /usr/local/bin/cloudtaser
Available platforms: darwin-amd64, darwin-arm64, linux-amd64, linux-arm64
Step 1: Install CloudTaser¶
Install the operator, mutating webhook, and eBPF agent from the OCI Helm chart:
helm install cloudtaser oci://ghcr.io/cloudtaser/cloudtaser-helm/cloudtaser \
--namespace cloudtaser-system \
--create-namespace \
--set operator.vaultAddress=https://vault.eu.example.com
Replace https://vault.eu.example.com with your actual vault address.
Verify the pods are running:
Expected output:
NAME READY STATUS RESTARTS AGE
cloudtaser-operator-6f8b9c7d4-x2k9m 1/1 Running 0 30s
cloudtaser-ebpf-xxxxx 1/1 Running 0 30s
Step 2: Connect the Cluster to Vault¶
Use the CLI to configure Kubernetes auth in your vault instance. This creates a ServiceAccount for vault token review, enables the Kubernetes auth backend, and creates a cloudtaser role:
cloudtaser connect \
--vault-address https://vault.eu.example.com \
--vault-token hvs.YOUR_ADMIN_TOKEN
Preview first
Add --dry-run to see what will be created without making changes.
Step 3: Create a Test Secret¶
Store a secret in your vault instance using the bao or vault CLI:
export BAO_ADDR=https://vault.eu.example.com
export BAO_TOKEN=hvs.YOUR_ADMIN_TOKEN
bao kv put secret/quickstart/db \
password="s3cret-from-eu-vault" \
username="app_user"
Step 4: Deploy a Protected Workload¶
Create a deployment with CloudTaser annotations that tell the operator where to find the secret and how to map it to environment variables:
apiVersion: apps/v1
kind: Deployment
metadata:
name: quickstart-app
namespace: default
spec:
replicas: 1
selector:
matchLabels:
app: quickstart-app
template:
metadata:
labels:
app: quickstart-app
annotations:
cloudtaser.io/inject: "true"
cloudtaser.io/vault-address: "https://vault.eu.example.com"
cloudtaser.io/vault-role: "cloudtaser"
cloudtaser.io/secret-paths: "secret/data/quickstart/db"
cloudtaser.io/env-map: "password=PGPASSWORD,username=PGUSER"
spec:
containers:
- name: app
image: busybox:latest
command: ["sh", "-c", "echo 'PGPASSWORD is set (value hidden)' && sleep 3600"]
Apply it:
Step 5: Verify the Secret is in Memory Only¶
Wait for the pod to be running:
Once READY 1/1, confirm the wrapper injected the secret:
# Check wrapper logs -- should show "secrets loaded, starting child process"
kubectl logs -l app=quickstart-app -c app | head -20
Verify the secret is NOT in the pod's environment (the wrapper scrubs it from /proc/1/environ):
This should return nothing -- the secret is only in the child process's memory, not in the wrapper's /proc/1/environ.
Verify the init container and volume injection happened:
Expected: cloudtaser-init
Step 6: Check Protection Score¶
Use the CLI to see the protection status of your cluster:
For a full validation:
For a compliance audit report:
What Just Happened¶
When the pod was created, the CloudTaser operator:
- Intercepted the pod creation via the mutating admission webhook
- Injected an init container (
cloudtaser-init) that copied the wrapper binary to a memory-backed emptyDir at/cloudtaser/ - Rewrote the container entrypoint to
/cloudtaser/wrapper - Set environment variables (
VAULT_ADDR,CLOUDTASER_SECRET_PATHS,CLOUDTASER_ENV_MAP, etc.) so the wrapper knows what to fetch - Added
CAP_IPC_LOCKso secrets can be locked in memory (no swap)
At runtime, the wrapper:
- Authenticated to vault using the pod's Kubernetes service account
- Fetched
passwordandusernamefromsecret/data/quickstart/db - Mapped them to
PGPASSWORDandPGUSER - Stored them in protected memory (memfd_secret + mlock)
- Fork+exec'd the original command (
sh -c ...) with secrets in the child's environment - Scrubbed secrets from its own
/proc/1/environ - Continues running as PID 1 for lease renewal and signal forwarding
Result: secrets travel directly from the EU vault to process memory. They never pass through etcd, Kubernetes Secrets, or any US-controlled storage layer.
Next Steps¶
- Getting Started (full guide) -- detailed walkthrough including OpenBao deployment
- Annotations Reference -- all available pod annotations
- CLI Reference -- full command documentation
- Security Model -- trust boundaries and threat model
- Installation Guide -- production Helm configuration