From 9e035b0d958a04950002013852640a715ce65c84 Mon Sep 17 00:00:00 2001 From: "David Muto (pseudomuto)" Date: Fri, 24 Jul 2026 15:35:28 -0400 Subject: [PATCH] [docs]: Document payload encryption The proxy now supports payload encryption (envelope encryption with a KMS-wrapped DEK, plus per-Namespace overrides), but the docs never mentioned it, so a reader had no way to discover the feature or turn it on. Add it to the top-level README feature list, and give the Cloud example an opt-in path: a commented-out encryption: block in config.yaml plus a README section explaining what it does. --- README.md | 9 ++++++--- examples/cloud/README.md | 11 +++++++++++ examples/cloud/config.yaml | 19 +++++++++++++++++++ 3 files changed, 36 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index f531522..45cdcdd 100644 --- a/README.md +++ b/README.md @@ -6,9 +6,9 @@ [![license](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE) A gRPC proxy that sits between Temporal SDK Clients, Workers, and the Temporal UI on one side and one or more upstream -Temporal Services on the other. It handles Namespace translation and TLS termination so applications can target a single -local endpoint while the proxy fans requests out to the right upstream (a local dev Temporal Service, a self-hosted -deployment, Temporal Cloud, or some mix). +Temporal Services on the other. It handles Namespace translation, TLS termination, and payload encryption so +applications can target a single local endpoint while the proxy fans requests out to the right upstream (a local dev +Temporal Service, a self-hosted deployment, Temporal Cloud, or some mix). > [!NOTE] > @@ -61,6 +61,9 @@ flowchart LR overrides) in both requests and responses. - **TLS termination and outbound credentials.** Terminate inbound TLS/mTLS and attach the upstream's own TLS and credentials (API key or mTLS), so client code carries none of it. +- **Payload encryption.** Optionally seal payloads with envelope encryption on the hop to an upstream and open them on + responses, so the upstream only ever sees ciphertext while local Workers keep exchanging cleartext. DEKs are wrapped + by a KMS key (AWS KMS, Azure Key Vault, or GCP KMS), rotate automatically, and can be overridden per Namespace. - **Inbound authentication.** Optional static-token or JWKS validation on the gateway; off by default. - **Codec-transparent.** The gateway never parses payloads. It peeks the Namespace, picks an upstream, and relays raw frames in both directions. diff --git a/examples/cloud/README.md b/examples/cloud/README.md index 9ed5b8c..2079533 100644 --- a/examples/cloud/README.md +++ b/examples/cloud/README.md @@ -90,3 +90,14 @@ namespace name `quickstart`. For each request the proxy: > [!NOTE] > > With a single namespace both upstreams resolve to the same host; the split is what lets the same config scale to many. + +## Optional: encrypt payloads to Cloud + +`config.yaml` ends with a commented-out `encryption:` block. Uncomment it and restart the proxy to encrypt workflow and +activity payloads on the hop to Cloud: the worker and starter keep exchanging cleartext, the proxy seals payloads before +they leave and opens them on the way back, and Cloud only ever stores ciphertext (workflow inputs and results show as +encrypted bytes in the Cloud UI). + +The block uses a `testing://` key, which holds its key material in the config itself with no cloud KMS. That is fine for +this toy but never for real data; in production point the key at `awskms://`, `azurekeyvault://`, or `gcpkms://` +instead. diff --git a/examples/cloud/config.yaml b/examples/cloud/config.yaml index 1588ad3..99dd588 100644 --- a/examples/cloud/config.yaml +++ b/examples/cloud/config.yaml @@ -46,3 +46,22 @@ upstreams: credentials: static: apiKey: ${TEMPORAL_API_KEY} + +# Optional: encrypt payloads on the hop to Cloud. Uncomment to seal workflow and +# activity payloads before they leave the proxy and open them on the way back; +# the worker and starter keep exchanging cleartext, and Cloud only ever stores +# ciphertext (workflow inputs and results show as encrypted bytes in the Cloud +# UI). Restart the proxy after changing this. +# +# The key below is a throwaway local test key: the "testing://" scheme holds the +# key material in the config itself with no cloud KMS, which is fine for a toy but +# never for real data. In production, point uri at a KMS key instead (awskms://, +# azurekeyvault://, or gcpkms://). +# +# encryption: +# enabled: true +# cacheSize: 200 +# default: +# uri: testing://KioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKio= +# duration: 1h +# renewBefore: 15m