From c585409ef511fb813695c6343eb693f6b06e531d Mon Sep 17 00:00:00 2001 From: Shawn Hathaway Date: Tue, 19 May 2020 18:42:01 -0700 Subject: [PATCH 1/3] SSL/TLS Support --- .../internal/WorkflowServiceStubsImpl.java | 20 +++++-- .../WorkflowServiceStubsOptions.java | 60 +++++++++++++++++-- 2 files changed, 70 insertions(+), 10 deletions(-) diff --git a/src/main/java/io/temporal/internal/WorkflowServiceStubsImpl.java b/src/main/java/io/temporal/internal/WorkflowServiceStubsImpl.java index 45eb0a0718..f6b208a10f 100644 --- a/src/main/java/io/temporal/internal/WorkflowServiceStubsImpl.java +++ b/src/main/java/io/temporal/internal/WorkflowServiceStubsImpl.java @@ -28,6 +28,8 @@ import io.grpc.Server; import io.grpc.inprocess.InProcessChannelBuilder; import io.grpc.inprocess.InProcessServerBuilder; +import io.grpc.netty.shaded.io.grpc.netty.NettyChannelBuilder; +import io.grpc.netty.shaded.io.netty.handler.ssl.SslContext; import io.grpc.stub.MetadataUtils; import io.temporal.proto.workflowservice.WorkflowServiceGrpc; import io.temporal.serviceclient.WorkflowServiceStubs; @@ -103,11 +105,19 @@ public WorkflowServiceStubsImpl( // Do not shutdown a channel passed to the constructor from outside channelNeedsShutdown = serviceImpl != null; } else { - this.channel = - ManagedChannelBuilder.forTarget(options.getTarget()) - .defaultLoadBalancingPolicy("round_robin") - .usePlaintext() - .build(); + NettyChannelBuilder builder = + NettyChannelBuilder.forTarget(options.getTarget()) + .defaultLoadBalancingPolicy("round_robin"); + + if (options.getSslContext() == null && !options.getEnableHttps()) { + builder.usePlaintext(); + } else if (options.getSslContext() != null) { + builder.sslContext(options.getSslContext()); + } else { + builder.useTransportSecurity(); + } + + this.channel = builder.build(); channelNeedsShutdown = true; } GrpcMetricsInterceptor metricsInterceptor = diff --git a/src/main/java/io/temporal/serviceclient/WorkflowServiceStubsOptions.java b/src/main/java/io/temporal/serviceclient/WorkflowServiceStubsOptions.java index 49fd1bec4a..69577f7884 100644 --- a/src/main/java/io/temporal/serviceclient/WorkflowServiceStubsOptions.java +++ b/src/main/java/io/temporal/serviceclient/WorkflowServiceStubsOptions.java @@ -25,7 +25,9 @@ import io.grpc.ManagedChannel; import io.grpc.ManagedChannelBuilder; import io.grpc.NameResolver; +import io.grpc.netty.shaded.io.netty.handler.ssl.SslContext; import io.temporal.proto.workflowservice.WorkflowServiceGrpc; + import java.util.Map; import java.util.Optional; import java.util.function.Function; @@ -63,16 +65,22 @@ public static WorkflowServiceStubsOptions getDefaultInstance() { private final String target; - /** The tChannel timeout in milliseconds */ + /** The user provided context for SSL/TLS over gRPC **/ + private final SslContext sslContext; + + /** Indicates whether basic HTTPS/SSL/TLS should be enabled **/ + private final boolean enableHttps; + + /** The gRPC timeout in milliseconds */ private final long rpcTimeoutMillis; - /** The tChannel timeout for long poll calls in milliseconds */ + /** The gRPC timeout for long poll calls in milliseconds */ private final long rpcLongPollTimeoutMillis; - /** The tChannel timeout for query workflow call in milliseconds */ + /** The gRPC timeout for query workflow call in milliseconds */ private final long rpcQueryTimeoutMillis; - /** Optional TChannel headers */ + /** Optional gRPC headers */ private final Map headers; private final Scope metricsScope; @@ -89,6 +97,8 @@ public static WorkflowServiceStubsOptions getDefaultInstance() { private WorkflowServiceStubsOptions(Builder builder) { this.target = builder.target; + this.sslContext = builder.sslContext; + this.enableHttps = builder.enableHttps; this.channel = builder.channel; this.rpcLongPollTimeoutMillis = builder.rpcLongPollTimeoutMillis; this.rpcQueryTimeoutMillis = builder.rpcQueryTimeoutMillis; @@ -104,8 +114,21 @@ private WorkflowServiceStubsOptions(Builder builder, boolean ignore) { throw new IllegalStateException( "Only one of the target and channel options can be set at a time"); } + + if (builder.sslContext != null && builder.channel != null) { + throw new IllegalStateException( + "Only one of the sslContext and channel options can be set at a time"); + } + + if (builder.enableHttps && builder.channel != null) { + throw new IllegalStateException( + "Only one of the enableHttps and channel options can be set at a time"); + } + this.target = builder.target == null && builder.channel == null ? LOCAL_DOCKER_TARGET : builder.target; + this.sslContext = builder.sslContext; + this.enableHttps = builder.enableHttps; this.channel = builder.channel; this.rpcLongPollTimeoutMillis = builder.rpcLongPollTimeoutMillis; this.rpcQueryTimeoutMillis = builder.rpcQueryTimeoutMillis; @@ -125,6 +148,16 @@ public String getTarget() { return target; } + /** @return Returns the gRPC SSL Context to use. **/ + public SslContext getSslContext() { + return sslContext; + } + + /** @return Returns a boolean indicating whether gRPC should use SSL/TLS. **/ + public boolean getEnableHttps() { + return enableHttps; + } + /** @return Returns the rpc timeout value in millis. */ public long getRpcTimeoutMillis() { return rpcTimeoutMillis; @@ -171,6 +204,8 @@ public Scope getMetricsScope() { */ public static class Builder { private ManagedChannel channel; + private SslContext sslContext; + private boolean enableHttps; private String target; private long rpcTimeoutMillis = DEFAULT_RPC_TIMEOUT_MILLIS; private long rpcLongPollTimeoutMillis = DEFAULT_POLL_RPC_TIMEOUT_MILLIS; @@ -191,6 +226,7 @@ private Builder() {} private Builder(WorkflowServiceStubsOptions options) { this.target = options.target; this.channel = options.channel; + this.enableHttps = options.enableHttps; this.rpcLongPollTimeoutMillis = options.rpcLongPollTimeoutMillis; this.rpcQueryTimeoutMillis = options.rpcQueryTimeoutMillis; this.rpcTimeoutMillis = options.rpcTimeoutMillis; @@ -200,12 +236,26 @@ private Builder(WorkflowServiceStubsOptions options) { this.metricsScope = options.metricsScope; } - /** Sets gRPC channel to use. Exclusive with target. */ + /** Sets gRPC channel to use. Exclusive with target and sslContext. */ public Builder setChannel(ManagedChannel channel) { this.channel = channel; return this; } + /** Sets gRPC SSL Context to use, used for more advanced scenarios such as mTLS. + * Supercedes enableHttps; Exclusive with channel. */ + public Builder setSslContext(SslContext sslContext) { + this.sslContext = sslContext; + return this; + } + + /** Sets option to enable SSL/TLS/HTTPS for gRPC. + * Exclusive with channel; Ignored if SSLContext is specified */ + public Builder setEnableHttps(boolean enableHttps) { + this.enableHttps = enableHttps; + return this; + } + /** * Sets a target string, which can be either a valid {@link NameResolver}-compliant URI, or an * authority string. See {@link ManagedChannelBuilder#forTarget(String)} for more information From 50eb2e3de880097ad078dcef67ae20cb612542bc Mon Sep 17 00:00:00 2001 From: Shawn Hathaway Date: Wed, 20 May 2020 16:40:22 -0700 Subject: [PATCH 2/3] Formatting --- .../internal/WorkflowServiceStubsImpl.java | 2 -- .../WorkflowServiceStubsOptions.java | 25 +++++++++++-------- 2 files changed, 14 insertions(+), 13 deletions(-) diff --git a/src/main/java/io/temporal/internal/WorkflowServiceStubsImpl.java b/src/main/java/io/temporal/internal/WorkflowServiceStubsImpl.java index f6b208a10f..0f7b2b33ad 100644 --- a/src/main/java/io/temporal/internal/WorkflowServiceStubsImpl.java +++ b/src/main/java/io/temporal/internal/WorkflowServiceStubsImpl.java @@ -23,13 +23,11 @@ import io.grpc.ClientInterceptor; import io.grpc.ClientInterceptors; import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; import io.grpc.Metadata; import io.grpc.Server; import io.grpc.inprocess.InProcessChannelBuilder; import io.grpc.inprocess.InProcessServerBuilder; import io.grpc.netty.shaded.io.grpc.netty.NettyChannelBuilder; -import io.grpc.netty.shaded.io.netty.handler.ssl.SslContext; import io.grpc.stub.MetadataUtils; import io.temporal.proto.workflowservice.WorkflowServiceGrpc; import io.temporal.serviceclient.WorkflowServiceStubs; diff --git a/src/main/java/io/temporal/serviceclient/WorkflowServiceStubsOptions.java b/src/main/java/io/temporal/serviceclient/WorkflowServiceStubsOptions.java index 69577f7884..6fde7ad0ff 100644 --- a/src/main/java/io/temporal/serviceclient/WorkflowServiceStubsOptions.java +++ b/src/main/java/io/temporal/serviceclient/WorkflowServiceStubsOptions.java @@ -27,7 +27,6 @@ import io.grpc.NameResolver; import io.grpc.netty.shaded.io.netty.handler.ssl.SslContext; import io.temporal.proto.workflowservice.WorkflowServiceGrpc; - import java.util.Map; import java.util.Optional; import java.util.function.Function; @@ -65,10 +64,10 @@ public static WorkflowServiceStubsOptions getDefaultInstance() { private final String target; - /** The user provided context for SSL/TLS over gRPC **/ + /** The user provided context for SSL/TLS over gRPC * */ private final SslContext sslContext; - /** Indicates whether basic HTTPS/SSL/TLS should be enabled **/ + /** Indicates whether basic HTTPS/SSL/TLS should be enabled * */ private final boolean enableHttps; /** The gRPC timeout in milliseconds */ @@ -117,12 +116,12 @@ private WorkflowServiceStubsOptions(Builder builder, boolean ignore) { if (builder.sslContext != null && builder.channel != null) { throw new IllegalStateException( - "Only one of the sslContext and channel options can be set at a time"); + "Only one of the sslContext and channel options can be set at a time"); } if (builder.enableHttps && builder.channel != null) { throw new IllegalStateException( - "Only one of the enableHttps and channel options can be set at a time"); + "Only one of the enableHttps and channel options can be set at a time"); } this.target = @@ -148,12 +147,12 @@ public String getTarget() { return target; } - /** @return Returns the gRPC SSL Context to use. **/ + /** @return Returns the gRPC SSL Context to use. * */ public SslContext getSslContext() { return sslContext; } - /** @return Returns a boolean indicating whether gRPC should use SSL/TLS. **/ + /** @return Returns a boolean indicating whether gRPC should use SSL/TLS. * */ public boolean getEnableHttps() { return enableHttps; } @@ -242,15 +241,19 @@ public Builder setChannel(ManagedChannel channel) { return this; } - /** Sets gRPC SSL Context to use, used for more advanced scenarios such as mTLS. - * Supercedes enableHttps; Exclusive with channel. */ + /** + * Sets gRPC SSL Context to use, used for more advanced scenarios such as mTLS. Supercedes + * enableHttps; Exclusive with channel. + */ public Builder setSslContext(SslContext sslContext) { this.sslContext = sslContext; return this; } - /** Sets option to enable SSL/TLS/HTTPS for gRPC. - * Exclusive with channel; Ignored if SSLContext is specified */ + /** + * Sets option to enable SSL/TLS/HTTPS for gRPC. Exclusive with channel; Ignored if SSLContext + * is specified + */ public Builder setEnableHttps(boolean enableHttps) { this.enableHttps = enableHttps; return this; From 2d7048a12ea7b40a2bb77982ab111c5ab26f0e9f Mon Sep 17 00:00:00 2001 From: Shawn Hathaway Date: Thu, 21 May 2020 03:24:17 -0700 Subject: [PATCH 3/3] Missing builder assignment --- .../io/temporal/serviceclient/WorkflowServiceStubsOptions.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/java/io/temporal/serviceclient/WorkflowServiceStubsOptions.java b/src/main/java/io/temporal/serviceclient/WorkflowServiceStubsOptions.java index 6fde7ad0ff..5f8330d055 100644 --- a/src/main/java/io/temporal/serviceclient/WorkflowServiceStubsOptions.java +++ b/src/main/java/io/temporal/serviceclient/WorkflowServiceStubsOptions.java @@ -226,6 +226,7 @@ private Builder(WorkflowServiceStubsOptions options) { this.target = options.target; this.channel = options.channel; this.enableHttps = options.enableHttps; + this.sslContext = options.sslContext; this.rpcLongPollTimeoutMillis = options.rpcLongPollTimeoutMillis; this.rpcQueryTimeoutMillis = options.rpcQueryTimeoutMillis; this.rpcTimeoutMillis = options.rpcTimeoutMillis;