Documentation
¶
Overview ¶
Package proxy serves every allowlisted service on a local unix socket, forwarding each request to an upstream Temporal Service over gRPC. The socket path is derived from the upstream host:port, so local workers connect without TLS while the upstream hop stays secured.
Index ¶
- func CloudNamespaceDialOptions(out func(string) string, log logger.Logger) []grpc.DialOption
- func CodecInterceptor(opts CodecOptions) (grpc.UnaryClientInterceptor, error)
- func ResolverFor(upstream *config.Upstream, opts []grpc.DialOption, log logger.Logger) (connect.Resolver, error)
- func TranslationDialOptions(t *protoutil.Translator, out, in func(string) string) []grpc.DialOption
- type CodecOptions
- type DynamicResolver
- type Forwarder
- type ForwarderOption
- type Option
- type Options
- type Reporter
- type ResolverOption
- type RouteData
- type Server
- type Vault
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func CloudNamespaceDialOptions ¶ added in v0.6.0
CloudNamespaceDialOptions returns the dial options that report a request whose translated namespace is not shaped like a Temporal Cloud namespace. out maps a local namespace to its remote name, and log may be nil, which reports nothing. Callers fold them into the dial options for the upstream connection, and only for an upstream that is Temporal Cloud.
This is diagnostic: nothing is rejected and the request travels unchanged.
func CodecInterceptor ¶ added in v0.5.1
func CodecInterceptor(opts CodecOptions) (grpc.UnaryClientInterceptor, error)
CodecInterceptor returns a unary client interceptor that runs payloads through the codecs opts select: outbound requests are encoded and inbound responses are decoded, each through a codec.Chain built for that request. A direction with no codecs is skipped entirely rather than walked for nothing.
Search attributes are never encoded, so they stay queryable upstream. The namespace a codec is given is the one the request carries, read via meta.NamespaceFrom.
func ResolverFor ¶ added in v0.5.0
func ResolverFor(upstream *config.Upstream, opts []grpc.DialOption, log logger.Logger) (connect.Resolver, error)
ResolverFor builds the connect.Resolver for an upstream. When neither the hostPort nor the TLS server name is templated it returns a static resolver, whose connection is constructed while the graph is built, opened on start, and reused for every request; otherwise it returns a DynamicResolver that renders the target and server name, and rebuilds credentials, per request. opts holds the request-independent dial options (namespace translation and outbound credentials). log, when non-nil, is threaded into the DynamicResolver for per-request debug entries.
func TranslationDialOptions ¶ added in v0.5.0
func TranslationDialOptions(t *protoutil.Translator, out, in func(string) string) []grpc.DialOption
TranslationDialOptions returns the dial options that install namespace translation on the outbound connection: t rewrites message bodies and typed error details, out maps local names to remote on the way out, and in maps remote names to local on the way back. Callers fold them into the dial options for the upstream connection.
Types ¶
type CodecOptions ¶ added in v0.5.1
type CodecOptions struct {
// Vault seals and opens payloads. With no Vault there is no encryption
// codec at all. Leave it nil rather than passing a nil concrete vault,
// which would read as present here and panic on first use.
Vault Vault
// Encrypt seals outbound payloads. Inbound payloads are opened whenever a
// Vault is present regardless, so payloads sealed earlier stay readable
// after sealing is turned off for new traffic.
Encrypt bool
// Reporter records the duration and result of each vault operation. It is
// required whenever a Vault is set.
Reporter *Reporter
}
CodecOptions selects the codecs a CodecInterceptor applies.
type DynamicResolver ¶
type DynamicResolver struct {
// contains filtered or unexported fields
}
DynamicResolver is a connect.Resolver that renders an upstream's dial target (and optional TLS server name) per request from the local namespace and request metadata. It always reports IsStatic as false, so a connect.Conn built from it resolves lazily on every call. A non-templated hostPort renders to itself, so a DynamicResolver also serves upstreams with a fixed address. Construct one with NewDynamicResolver.
func NewDynamicResolver ¶
func NewDynamicResolver(up *config.Upstream, opts ...ResolverOption) (*DynamicResolver, error)
NewDynamicResolver builds a DynamicResolver for up. It compiles the hostPort and TLS server-name templates (failing if either is malformed) and applies opts. By default the remote namespace equals the local one and no dial options are added; use WithRemoteNamespacer and WithOptionsFactory to change that.
func (*DynamicResolver) IsStatic ¶
func (r *DynamicResolver) IsStatic() bool
IsStatic reports that a DynamicResolver always resolves per request.
func (*DynamicResolver) Resolve ¶
func (r *DynamicResolver) Resolve(ctx context.Context) (string, string, []grpc.DialOption, error)
Resolve renders the dial target and server name from ctx and returns the pool cache key, the dial target, and the dial options. The cache key combines the target and rendered server name so that two requests to the same address with different server names get distinct pooled connections. It fails with codes.Internal (naming the upstream and template) when a template fails to render, the rendered address is empty or malformed, or the options factory errors; nothing is dialed in those cases.
type Forwarder ¶ added in v0.5.0
type Forwarder struct {
// contains filtered or unexported fields
}
Forwarder forwards any allowlisted method to a single upstream, typing each request and response from the proto registry rather than being generated per service. The typing is load-bearing: namespace translation and payload encryption are client interceptors on cc that operate on proto messages, so an opaque byte passthrough (as the router uses) would silently skip both. Resolved methods are cached, and a Forwarder is safe for concurrent use.
func NewForwarder ¶ added in v0.5.0
func NewForwarder(cc grpc.ClientConnInterface, a services.Allowlist, opts ...ForwarderOption) (*Forwarder, error)
NewForwarder builds a Forwarder that forwards over cc every method belonging to a service a admits. It fails when cc or a is nil. By default methods are typed against the global proto registry; use WithProtoTypes to override it.
func (*Forwarder) Handle ¶ added in v0.5.0
func (f *Forwarder) Handle(_ any, ss grpc.ServerStream) error
Handle forwards one stream to the upstream, and suits google.golang.org/grpc.UnknownServiceHandler. A method whose service the services.Allowlist does not admit is rejected with Unimplemented before any upstream work, so the proxy answers as a server that does not implement it rather than revealing that an upstream might. Only methods present in the compiled descriptors can be forwarded; anything else is Unimplemented too.
type ForwarderOption ¶ added in v0.5.0
type ForwarderOption func(*Forwarder)
ForwarderOption configures a Forwarder at construction time.
func WithProtoTypes ¶ added in v0.5.0
func WithProtoTypes(t protoutil.Types) ForwarderOption
WithProtoTypes sets the registry used to resolve a method's request and response message types. A nil registry leaves the default in place.
type Option ¶
type Option func(*Options)
Option configures a Server via New.
func WithLogger ¶
WithLogger sets the logger used by the proxy.
func WithSocketPath ¶ added in v0.5.0
WithSocketPath sets the unix socket path the proxy binds, overriding the one derived from hostPort. A caller that also dials this socket passes the same value to both sides so the two cannot disagree. New rejects a path that exceeds the platform's sun_path limit.
type Options ¶
type Options struct {
// contains filtered or unexported fields
}
Options configures a Server at construction time.
type Reporter ¶
type Reporter struct {
// contains filtered or unexported fields
}
Reporter records envelope-operation telemetry to Prometheus: each seal (encrypt) and open (decrypt) the encryption interceptor performs, timed end to end, including any KEK wrap or unwrap and any DEK cache lookup along the way. The AES-step duration alone is owned by internal/kms. The namespace label is unbounded, so handles are resolved per call via WithLabelValues rather than pre-computed. A Reporter is safe for concurrent use.
func NewReporter ¶
NewReporter builds the Prometheus-backed vault-operation Reporter. f must already be scoped to the "encryption" subsystem by the caller.
type ResolverOption ¶
type ResolverOption func(*DynamicResolver)
ResolverOption configures a DynamicResolver at construction.
func WithOptionsFactory ¶
func WithOptionsFactory(f func(RouteData) ([]grpc.DialOption, error)) ResolverOption
WithOptionsFactory sets the function that produces the dial options for a resolved request. It receives the rendered host and server name via RouteData.
func WithRemoteNamespacer ¶
func WithRemoteNamespacer(f func(string) string) ResolverOption
WithRemoteNamespacer sets the function that maps the local namespace to the remote one, making RemoteNamespace available to the templates.
func WithResolverLogger ¶ added in v0.5.0
func WithResolverLogger(l logger.Logger) ResolverOption
WithResolverLogger sets the logger used to emit a per-request debug entry after a successful resolve. Unset: no entry is emitted.
type RouteData ¶
type RouteData struct {
template.UpstreamContext
ResolvedServerName string
}
RouteData is passed to the options factory once a request has been resolved. It carries the template context used for rendering plus the resolved TLS server name, so the factory can build dial options (e.g. credentials whose SNI depends on the rendered server name).
type Server ¶
type Server struct {
// contains filtered or unexported fields
}
Server proxies the Temporal WorkflowService. It re-serves an upstream Temporal Service on a local unix socket, letting local workers connect without TLS while the upstream hop stays secured. The upstream connection(s) it forwards to are owned by the shared connect.Pool, not by this Server.
func New ¶
New constructs a Server that hands every inbound method to fw, which forwards it to the upstream fw was built against. The local listener is a unix socket whose path is derived from hostPort. The connection(s) fw forwards over are owned by the shared pool, not by this Server.
func (*Server) Listen ¶
Listen removes any socket left behind by a prior run and binds the proxy's local unix socket, returning the listener. Binding is separate from Start so callers can bind synchronously during startup (the socket is then listening, and the OS backlogs connections) before serving in the background, ensuring no request is routed to an unbound socket.