[examples]: Add a KMS extension server example - #105
Merged
Conversation
Codecov Report✅ All modified and coverable lines are covered by tests. 📢 Thoughts on this report? Let us know! 🚀 New features to boost your workflow:
|
There was a problem hiding this comment.
Pull request overview
Adds a new runnable KMS extension-server example to demonstrate the proxy’s api.kms.v1.EncryptionService contract end-to-end (DEK wrap/unwrap over authenticated TLS, payload encryption handled by the proxy), alongside starter/worker utilities and documentation. It also consolidates example modules under a single examples/ Go module.
Changes:
- Add
examples/kmswith an extension server (TLS + bearer auth), key derivation/framing logic, and starter/worker programs. - Add
examples/kms/config.yamland docs describing how to run the dev server, proxy, extension server, and verify ciphertext vs cleartext reads. - Introduce
examples/go.mod(and updateexamples/go.sum), removing the per-exampleexamples/cloud/go.mod.
Reviewed changes
Copilot reviewed 14 out of 15 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| README.md | Adds a top-level pointer to the new KMS example. |
| examples/kms/README.md | Full walkthrough explaining the KMS extension-server flow and how to observe ciphertext vs cleartext. |
| examples/kms/config.yaml | Proxy config wiring an extension server over TLS + static bearer credentials. |
| examples/kms/.gitignore | Ignores generated cert material (certs/). |
| examples/kms/greeting.go | Shared workflow/activity/task-queue constants for the example. |
| examples/kms/starter/main.go | Starts a fixed-ID workflow through the proxy and prints the result. |
| examples/kms/worker/main.go | Runs a worker against the proxy using cleartext SDK payloads. |
| examples/kms/gencerts/main.go | Generates a throwaway CA + server cert/key for the extension server. |
| examples/kms/server/main.go | Runs the TLS-enabled gRPC extension server and enforces required env secrets. |
| examples/kms/server/service.go | Implements EncryptionService Encrypt/Decrypt RPCs over the keyring. |
| examples/kms/server/keyring.go | Derives per-namespace AES-256-GCM keys via HKDF and frames ciphertext to be self-describing. |
| examples/kms/server/interceptor.go | Unary interceptor enforcing authorization: Bearer <token>. |
| examples/go.mod | New single Go module for all examples, with replace back to the working tree proxy. |
| examples/go.sum | Dependency checksum updates for the unified examples module. |
| examples/cloud/go.mod | Removed (cloud example now builds under the unified examples module). |
The proxy can wrap DEKs through an operator-run gRPC service implementing api.kms.v1.EncryptionService, but nothing in the repository showed how to build one, so the whole contract was left for a reader to infer from proto comments. This adds examples/kms: a runnable extension server, a proxy config pointing at it over authenticated TLS, and a greeting workflow driven through the proxy against a local dev server. The server derives one AES-256-GCM key per namespace from a master secret and frames its ciphertext so it is self-describing, which is what the contract requires: DecryptRequest carries no namespace, so the ciphertext has to carry its own key selector. The README walks through reading one execution twice, against the Temporal Service to see ciphertext and through the proxy to see it in the clear. The extension hop uses a private CA and a bearer token rather than plaintext, since credentials require TLS both by config validation and because gRPC refuses to put a per-RPC credential on an insecure connection. `go run ./gencerts` mints the throwaway CA; nothing is installed in a system trust store and no key material is committed.
pseudomuto
force-pushed
the
kms-extension-example
branch
from
July 30, 2026 10:39
601d9e5 to
da1ce9b
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The proxy can wrap DEKs through an operator-run gRPC service implementing api.kms.v1.EncryptionService, but nothing in the repository showed how to build one, so the whole contract was left for a reader to infer from proto comments.
This adds examples/kms: a runnable extension server, a proxy config pointing at it over authenticated TLS, and a greeting workflow driven through the proxy against a local dev server. The server derives one AES-256-GCM key per namespace from a master secret and frames its ciphertext so it is self-describing, which is what the contract requires: DecryptRequest carries no namespace, so the ciphertext has to carry its own key selector. The README walks through reading one execution twice, against the Temporal Service to see ciphertext and through the proxy to see it in the clear.
The extension hop uses a private CA and a bearer token rather than plaintext, since credentials require TLS both by config validation and because gRPC refuses to put a per-RPC credential on an insecure connection.
go run ./gencertsmints the throwaway CA; nothing is installed in a system trust store and no key material is committed.