DEMO LAB

See cloudtaser running.

EU/UK data sovereignty for US cloud workloads. You keep the keys. The provider never sees plaintext — not on request, not under the CLOUD Act, not under court order.

Demo options

LIVE DEMO · WATCH OR TRY · ONE RUN AT A TIME

Three live terminals stream real output from three real systems: a managed GKE cluster in the US (n2d nodes with AMD SEV, the install target) and two EU-hosted VMs running cloudtaser's P2P beacon relay (FRA) and OpenBao secret store (NL). Click through and you'll see the actual cryptographic work end-to-end — no mocks. When someone is running the demo, you watch their steps in real time. When they finish or step away, it is your turn.

Maintenance

Demo improvements in progress

We are upgrading the live demo environment. Check back shortly, or schedule a guided walkthrough with an engineer.

TARGET CLUSTER US · GKE n2d · AMD SEV no workload deployed
BEACON RELAY EU·FRA · TCP 443 · mTLS idle · awaiting bridge
SECRET STORE EU·NL · OpenBao no cluster bound
EU-hosted OpenBao · NL
Step 3 registers your cluster. Secrets never leave EU jurisdiction.
Session is registering this cluster…
Cluster registered

What you just saw: a live K8s cluster with an eBPF-enforced secret store. No secret ever touched etcd, a K8s Secret object, or disk. The cloud provider had no path to plaintext. If that landed, the engineering details are below — or talk to us now.

How this actually works (engineering deep dive)

Three official endpoints

browser (xterm.js fed by SSE streams)
https://demo.cloudtaser.io/api/demo/stream?channel=clusterSSE, cluster output https://demo.cloudtaser.io/api/demo/stream?channel=beaconSSE, beacon log https://demo.cloudtaser.io/api/demo/stream?channel=vaultSSE, OpenBao audit https://demo.cloudtaser.io/api/*orchestrator: state, next, probe
Cloudflare TLS · Turnstile · rate-limit · Access policy
Role What runs here Region & cost
US GKE Cluster zonal GKE (free control plane) · 1 × n2d-highcpu-2 · AMD SEV · 30 GB pd-balanced · cloudtaser operator + wrapper + eBPF + demo-app pod · reached from VM2 via kubectl (container.developer IAM) us-west1-a
~$30–46/mo
EU VM2 — Beacon + Orchestrator cloudtaser-beacon relay · orchestrator Go daemon · SSE stream endpoints for cluster and beacon channels europe-west3 (Frankfurt)
e2-micro ~$9/mo
EU VM3 — Secret Store OpenBao · cloudtaser-cli · SSE stream endpoint for vault channel europe-west4 (Netherlands)
e2-micro ~$9/mo
Total: real GKE + 2 EU VMs, ~$48–64/month. Public DNS via Cloudflare; nothing is directly reachable from the public internet except through the Cloudflare tunnels.
Honest disclosure: the GKE cluster and both VMs are on GCP. GCP is US-parented — per our own sovereign-deployment-guide, GCP EU regions do NOT establish sovereignty under CLOUD Act analysis. For production sovereignty the secret store would move to Hetzner / OVH / Scaleway / IONOS / Exoscale / UpCloud.

Production topology — what a customer deployment looks like. OpenBao secret store runs on an EU-owned provider (Hetzner / OVH / Scaleway / IONOS / Exoscale / UpCloud). Workload pods run on the US cloud of your choice (GKE, EKS, AKS) on confidential-compute node SKUs. The cloudtaser bridge sits next to OpenBao; an EU-hosted beacon relay carries outbound-only traffic from the cluster. Result: keys never leave EU jurisdiction, ciphertext sits on US infrastructure, the provider has no path to plaintext. This is the topology our Sovereign Deployment Decision Guide walks through.

What you're watching today — honest deviation. For the live demo all three machines (GKE node + beacon VM + OpenBao VM) run on GCP — europe-west3 / europe-west4 for the EU pieces, us-west1 for the cluster. GCP EU regions are real EU data centres but a US-parented operator, so they do NOT clear the sovereignty guide's first-leg test (the secret store wants an EU-owned provider). Posture-wise the demo proves every cloudtaser claim that doesn't depend on substrate jurisdiction (memfd_secret, eBPF enforcement, beacon framing, P2P transport, register/init flow). For the substrate claim itself, swap GCP-EU for Hetzner / OVH / etc — same chart, same code, same operator. Hetzner migration of the demo's own secret store is on our near-term roadmap.

Every cluster mutation the demo performs is a file at cloudtaser.io/demo-lab/manifests/ — read the YAML, don't trust the narration.

Want a sovereign-topology trial in your environment? Book a 30-min call → — we'll size a Hetzner / OVH / Scaleway pilot against one of your workloads and walk the substrate decisions with your security team.

Demo infrastructure internals (for the curious) — orchestrator state machine, probe whitelist, RBAC, GKE rationale

Watch / run state machine

orchestrator state {
    driver_session_id : string | null
    driver_claimed_at : timestamp
    driver_last_seen  : timestamp   // updated on each /api/demo/next or /api/demo/probe
    demo_step         : 0..7
    viewers           : set<session_id>
}

transitions:
  visitor arrives         -> registered as viewer; receives current state snapshot
  driver_session_id null  -> first viewer to POST /api/demo/claim wins (atomic compare-and-swap)
  session active          -> only host session can POST /next or /probe
  driver_last_seen > 5min -> server releases session; broadcasts state change
  session hits hard cap   -> server releases at 20min regardless of activity
  all viewers disconnect  -> demo idles; ttyd streams persist (cluster state intact)
  next viewer arrives     -> same session / viewer logic applies

broadcast via Server-Sent Events on /api/demo/events:
  {type:"claim",   viewer_id:"..."}
  {type:"step",    step:N, by:"..."}
  {type:"probe",   name:"...", exit_code:0|non-zero}
  {type:"release", reason:"idle"|"hard_cap"|"explicit"}
  {type:"reset",   new_state:{...}}

Probe whitelist (curated command palette)

Frontend sends {probe: "ptrace_attach"} as an opaque key. Orchestrator does a dict lookup against a fixed YAML. No user-supplied string ever reaches a shell. Command-injection surface is zero by construction.

probes:
  # ── Positive-path probes (1–2): prove the secret landed correctly ───────

  app_sees_secret:
    label: "Postgres uses POSTGRES_PASSWORD (SELECT-as-ledger works)"
    target: pod
    cmd:   kubectl exec -n {{NAMESPACE}} deploy/postgres -- \
             psql -U ledger -d demo -tAc \
               "SELECT 'OK_DB:' || count(*) FROM messages"
    expected: "exit 0 + 'OK_DB:' in output (authenticated query proves
               the secret reached the app via memfd_secret, not K8s Secret)"

  no_k8s_secret:
    label: "Zero K8s Secrets -- DB_PASSWORD is nowhere in any Secret object"
    target: vm2-host
    cmd:   kubectl get secrets -A ... | grep DB_PASSWORD \
             || echo 'OK: no secret containing DB_PASSWORD'
    expected: "exit 0 + 'OK: no secret' sentinel — secret travelled via
               memfd_secret memory, not through etcd"

  # ── Adversarial probes (3–5): block-is-pass ─────────────────────────────

  ptrace_attach:
    label: "ATTACK - ptrace attach against the wrapped postgres"
    target: node-probe  # privileged DaemonSet; hostPID; strace installed
    cmd:   kubectl exec -n cloudtaser-demo ds/node-probe -- \
             sh -c "P=$(pgrep postgres | head -1); \
                    timeout 2 strace -p $P -e trace=none -c 2>&1; \
                    echo PID=$P"
    expected: "exit 0 + PID=<N> in output (attach succeeds today;
               eBPF sys_enter_ptrace tracepoint records PTRACE_DENIED
               audit event. Future LSM hook will return EPERM before
               attach. Run ebpf_audit probe after to see the event.)"

  read_environ:
    label: "ATTACK - cat /proc/1/environ inside the postgres pod"
    target: pod  # kubectl exec into {{NAMESPACE}} deploy/postgres
    cmd:   kubectl exec -n {{NAMESPACE}} deploy/postgres -- \
             sh -c "cat /proc/1/environ 2>&1; echo ---END---"
    expected: "non-zero exit + 'Permission denied' (eBPF kprobe_openat
               blocks the read; DB_PASSWORD absent from environ anyway —
               cloudtaser delivers via memfd_secret, not environ array)"

  read_mem:
    label: "ATTACK - dd if=/proc/1/mem inside the postgres pod"
    target: pod
    cmd:   kubectl exec -n {{NAMESPACE}} deploy/postgres -- \
             sh -c "dd if=/proc/1/mem bs=1 count=1 2>&1"
    expected: "non-zero exit + 'Permission denied' - eBPF kprobe on
               sys_openat blocks the open before any seekable FD exists"

  # ── Informational probes (6–9): surface the protection posture ──────────

  show_secretmem:
    label: "Secret memory protection active (memfd_secret OR mlock fallback)"
    target: pod
    strategy: |
      Two-stage approach (log greps first, FD inspection fallback):
        Stage 1: kubectl logs grep for "memfd_secret":true OR mlock-
                 fallback line — cheap, kernel-agnostic, covers GKE COS.
        Stage 2: iterate /proc/[PID]/fd looking for "secretmem" symlink.
      Failure of all paths = genuine protection regression.
    expected: "exit 0; wrapper-attested memfd_secret or mlock-fallback
               log line, or 'secretmem FD present in /proc/<pid>/fd'"

  ebpf_audit:
    label: "eBPF audit log (last 10 enforcement events)"
    target: vm2-host  # kubectl logs from orchestrator host
    cmd:   kubectl logs -n cloudtaser-system \
             -l app=cloudtaser-ebpf --tail=500 2>&1 | \
             { grep -iE 'block|deny|EPERM|enforce|kprobe' || \
               echo '(no enforcement events yet - run adversarial probes first)'; } | \
             tail -10
    expected: "exit 0; grep for block/deny/EPERM/enforce/kprobe events
               matching the ptrace_attach and read_mem probes run earlier"

  ls_fds:
    label: "ls -la /proc/<app-pid>/fd (memfd_secret FDs visible; not readable)"
    target: pod
    cmd:   kubectl exec -n {{NAMESPACE}} deploy/postgres -- \
             sh -c "P=$(pgrep postgres | head -1); \
                    echo PID=$P; ls -la /proc/$P/fd | head -15"
    expected: "exit 0; fd table of the wrapped postgres process (not
               PID 1). Entries backed by memfd_secret appear as
               anon-inode symlinks; reading them is blocked because
               the backing pages are not in the kernel direct map"

  kubectl_pods:
    label: "kubectl get pods -o wide (informational)"
    target: vm2-host
    cmd:   kubectl get pods -n {{NAMESPACE}} -o wide
    expected: "exit 0; live pod list for the per-session demo-XXXX-XXXX
               namespace; 'postgres' pod must be Running"

  # ── Confidential-compute probes (10–14): AMD SEV + protection score ─────

  cc_dmesg:
    label: "dmesg | grep SEV on the GKE CC node"
    target: node-probe  # hostPath-mounts / at /host
    cmd:   kubectl exec -n cloudtaser-demo ds/node-probe -- \
             sh -c "chroot /host dmesg 2>&1 | grep -iE 'sev|amd mem' | head -8 \
                    || echo '(no AMD encryption signatures in dmesg)'"
    expected: "exit 0 + 'SEV' in output (AMD Memory Encryption active)"

  cc_cpuinfo:
    label: "grep sev/sme in /proc/cpuinfo (CPU memory-encryption features)"
    target: node-probe
    cmd:   kubectl exec -n cloudtaser-demo ds/node-probe -- \
             sh -c "FLAGS=\$(grep -oE 'sev[_a-z]*|sme' /host/proc/cpuinfo ...); \
                    echo CC_FEATURES: \$FLAGS"
    expected: "exit 0 + 'CC_FEATURES:' sentinel with sev/sme flag list"

  cc_kernel_version:
    label: "uname -a + /proc/cmdline on the GKE CC node"
    target: node-probe
    cmd:   kubectl exec -n cloudtaser-demo ds/node-probe -- \
             sh -c "cat /host/proc/version; cat /host/proc/cmdline"
    expected: "exit 0 + 'Linux' in output (kernel version + boot params)"

  cc_node_metadata:
    label: "kubectl describe node (confidentialCompute label + machine type)"
    target: vm2-host
    cmd:   kubectl get nodes -o jsonpath='{range .items[0]}{.metadata.labels}...'
    expected: "exit 0 + 'gke-' in output (GKE node labels including
               cloud.google.com/gke-confidential-nodes)"

  cc_protection_summary:
    label: "Protection score -- secret delivery, runtime defence, hypervisor isolation, sovereign custody"
    target: vm2-host
    cmd:   |  # walks four protection legs; always exits 0
      EBPF_OK=... INJ=... MEMFD=... CC=...
      echo "CloudTaser protection: ebpf=\$EBPF inject-annotation=\$INJ \
            memfd_secret=\$MEMFD confidential-compute=\$CC"
    expected: "exit 0 + 'CloudTaser protection:' sentinel with four
               GREEN/MISSING/NA legs (eBPF, inject, memfd, CC)"

Security analysis for the probe palette

  • Whitelist, not freeform. Frontend sends {probe: "ptrace_attach"}. Orchestrator looks up by key. User-supplied text never reaches a shell, eval, or command assembly.
  • Commands target the demo pod only. All kubectl exec calls are hardcoded to a per-session demo-XXXX-XXXX namespace targeting deploy/postgres or the privileged cloudtaser-demo/node-probe DaemonSet. The orchestrator's K8s service account has RBAC limited to create on pods/exec in namespaces demo-app and cloudtaser-demo, get on pods/log in cloudtaser-system, and get on nodes. It cannot reach other namespaces, the host, or outside the cluster.
  • Demo pod is sacrificial. postgres runs with no host-network access and mounts only synthetic secrets injected via cloudtaser. No customer material ever touches this stack.
  • All probes are read-only with bounded output. Each command has a timeout wrapper; output is head'd to ~8 KB. No writes, no curl, no network egress from the pod.
  • Rate-limited. 1 probe / 2 seconds per active session; hard cap 30 probes / session; session itself hard-capped at 20 minutes. Abuse doesn't compound; reset returns to baseline.
  • Probes can demonstrate bugs, not exploit them. If a probe that should block somehow succeeds, that IS a finding - valuable signal, feeds directly into the pentest engagement. Watcher count sees it in real time.
  • Probe output doesn't leak. Output streams into the cluster terminal pane (same place as the per-step command output). All viewers see the same stream. Nothing private is produced because nothing private exists on these VMs.

Why a real GKE cluster (not docker-compose on one box)

  • Architectural authenticity. Procurement teams ask "what am I actually seeing here?" A demo on one box invites every conceivable doubt. A real zonal GKE cluster with a confidential-compute node pool + two separate EU VMs + real beacon protocol over the Atlantic = exactly the topology a customer would run in production.
  • Confidential-compute target is a real one. The GKE node runs n2d-highcpu-2 with confidential_nodes.enabled = true. AMD SEV is active; /proc/cpuinfo shows sev; dmesg shows "AMD Memory Encryption Features active". The cc_* probes in the palette surface this live for all viewers. (SEV, not SEV-SNP: GKE's confidential_nodes API defaults to SEV on n2d; SEV-SNP on GKE requires preview flags not worth the complexity for MVP.)
  • Honest EU framing. The two EU VMs are in europe-west3 (Frankfurt) and europe-west4 (Netherlands). Real EU data-centre regions. Still GCP - US-parented - which does NOT clear the sovereign deployment decision guide's first-leg test. For real sovereignty: Hetzner / OVH / Scaleway / IONOS / Exoscale / UpCloud. Migration to a real EU-owned provider for the secret store is planned as a follow-up.
  • Beacon authenticity. GKE node in US, VM3 (secret store) in EU, VM2 (beacon) between them in EU. Bridge<>broker traffic actually crosses the Atlantic. Latency is real, not simulated. TLS terminates at the bridge (VM3) and the broker (GKE-side wrapper), not the relay.
  • Cost reality. ~$48-64/month. GKE zonal control plane is free inside GCP's monthly credit; only the 1 CC node + 2 small EU VMs cost anything.