[cloud]: Validate Cloud Namespaces - #147
Merged
Merged
Conversation
The canonical "Cloud" config derives its endpoint from the translated
`namespace: {{ .RemoteNamespace }}.tmprl.cloud:7233` with a
".$TEMPORAL_ACCOUNT" suffix. Config loading expands environment
variables with os.Expand, which substitutes empty for an unset one, so a
blank TEMPORAL_ACCOUNT silently leaves a bare-dot suffix and every
namespace translates to "<name>.". The proxy would then dial
"<name>..tmprl.cloud" and the operator saw nothing but a DNS failure.
More generally, the proxy had no notion of a Cloud upstream, so a
namespace Cloud would reject was indistinguishable from a valid one.
When an upstream is Temporal Cloud, namespaces (post-translation) are
now validated. For non-templated hosts, this is done at startup to
prevent mistakes. For dynamic ones, a DEBUG log is printed indicating
why the namespace is invalid. Requests are still forwarded upstream for
now.
> NOTE: Auto-detection means a config the proxy used to accept can now
fail to start, but only one that could never have worked against Cloud
anyways.
Codecov Report❌ Patch coverage is 📢 Thoughts on this report? Let us know! 🚀 New features to boost your workflow:
|
Vaughan-Temporal
added a commit
that referenced
this pull request
Sep 4, 2026
Method translation needed a cloudApi block naming Temporal Cloud's control plane, which restated something the proxy can already work out. #147 gave the upstream a notion of being Cloud - declared with `cloud: true`, or detected from a .tmprl.cloud address - and translating the methods Cloud does not serve on a frontend follows from exactly that. Enable it there instead, so a Cloud upstream needs no configuration for it at all. The control plane is now derived per upstream: cloud.APIHostPort, the upstream's own credentials (one Temporal Cloud API key authorizes both the frontend and the control plane), and a default outbound TLS configuration. TLS is not inherited, since the control plane is a different host and the upstream's server name or client certificate would not apply to it. Deriving per upstream rather than sharing one connection matters for pooling. A static resolver keys the pool by dial target, which is unique among upstreams but not among control planes: every Cloud upstream resolves to the same address, so a shared key would hand the second upstream whichever connection the first created, and with it the first's credentials. The pool key is the derived name instead. The connection is not opened eagerly. Translation is incidental to an upstream's normal traffic, so a control plane that is unreachable must not stop the proxy serving everything else. The cloudApi block survives as an override for a different Cloud environment, or for credentials or TLS the upstream does not carry. An address that is not a Cloud endpoint is reported at startup rather than rejected, since a test double or a private environment legitimately carries no Cloud domain and the proxy cannot tell that apart from a typo - the same treatment #147 gives a namespace it cannot validate on a templated upstream. Also moves the control-plane address to internal/cloud, next to the domain suffix it is built from, since it is a fact about Cloud rather than about configuration.
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 canonical "Cloud" config derives its endpoint from the translated
namespace: {{ .RemoteNamespace }}.tmprl.cloud:7233with a.$TEMPORAL_ACCOUNTsuffix. Config loading expands environment variables withos.Expand, which substitutes an empty value for an unset one, so a blank TEMPORAL_ACCOUNT silently leaves a bare-dot suffix, and every namespace translates to ".". The proxy would then dial "..tmprl.cloud" and the operator saw nothing but a DNS failure. More generally, the proxy had no notion of a Cloud upstream, so a namespace Cloud would reject was indistinguishable from a valid one.Now, when an upstream is Temporal Cloud, namespaces (post-translation) are validated. For non-templated hosts, this is done at startup to prevent mistakes. For dynamic ones, a DEBUG log is printed indicating why the namespace is invalid. Requests are still forwarded upstream for now.