-
Notifications
You must be signed in to change notification settings - Fork 181
💥 [BREAKING] enable TLS if api key provided #2740
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -418,7 +418,7 @@ public String toString() { | |
| public static class Builder<T extends Builder<T>> { | ||
| private ManagedChannel channel; | ||
| private SslContext sslContext; | ||
| private boolean enableHttps; | ||
| private Boolean enableHttps; | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Here's a contrived situation:
I don't mind if we break and/or don't-support this scenario, just wanted to mention it
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think we should at least document that scenario since it is confusing. Arguably if
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Hmm, maybe should revert the change: and make The semantics might be clearer this way tbh
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If we don't consider changing the return type of
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Hm I think changing the return type to a
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I didn't figure it'd be that common, but meh. This works for me, but what should be the return value of |
||
| private String target; | ||
| private Consumer<ManagedChannelBuilder<?>> channelInitializer; | ||
| private Duration healthCheckAttemptTimeout; | ||
|
|
@@ -435,6 +435,7 @@ public static class Builder<T extends Builder<T>> { | |
| private Collection<GrpcMetadataProvider> grpcMetadataProviders; | ||
| private Collection<ClientInterceptor> grpcClientInterceptors; | ||
| private Scope metricsScope; | ||
| private boolean apiKeyProvided; | ||
|
|
||
| protected Builder() {} | ||
|
|
||
|
|
@@ -613,6 +614,7 @@ public T addGrpcMetadataProvider(GrpcMetadataProvider grpcMetadataProvider) { | |
| * @return {@code this} | ||
| */ | ||
| public T addApiKey(AuthorizationTokenSupplier apiKey) { | ||
| this.apiKeyProvided = true; | ||
| addGrpcMetadataProvider( | ||
| new AuthorizationGrpcMetadataProvider(() -> "Bearer " + apiKey.supply())); | ||
| return self(); | ||
|
|
@@ -803,7 +805,7 @@ public ServiceStubsOptions build() { | |
| this.channel, | ||
| this.target, | ||
| this.channelInitializer, | ||
| this.enableHttps, | ||
| this.enableHttps != null ? this.enableHttps : false, | ||
| this.sslContext, | ||
| this.healthCheckAttemptTimeout, | ||
| this.healthCheckTimeout, | ||
|
|
@@ -837,7 +839,7 @@ public ServiceStubsOptions validateAndBuildWithDefaults() { | |
| "Only one of the 'sslContext' or 'channel' options can be set at a time"); | ||
| } | ||
|
|
||
| if (this.enableHttps && this.channel != null) { | ||
| if (Boolean.TRUE.equals(this.enableHttps) && this.channel != null) { | ||
| throw new IllegalStateException( | ||
| "Only one of the 'enableHttps' or 'channel' options can be set at a time"); | ||
| } | ||
|
|
@@ -851,6 +853,14 @@ public ServiceStubsOptions validateAndBuildWithDefaults() { | |
| Collection<ClientInterceptor> grpcClientInterceptors = | ||
| MoreObjects.firstNonNull(this.grpcClientInterceptors, Collections.emptyList()); | ||
|
|
||
| // Resolve enableHttps: explicit value, auto-enable with API key, or default false | ||
| boolean enableHttps = false; | ||
| if (this.enableHttps != null) { | ||
| enableHttps = this.enableHttps; | ||
| } else if (this.apiKeyProvided && this.sslContext == null && this.channel == null) { | ||
| enableHttps = true; | ||
| } | ||
|
|
||
| Scope metricsScope = this.metricsScope != null ? this.metricsScope : new NoopScope(); | ||
| Duration healthCheckAttemptTimeout = | ||
| this.healthCheckAttemptTimeout != null | ||
|
|
@@ -865,7 +875,7 @@ public ServiceStubsOptions validateAndBuildWithDefaults() { | |
| this.channel, | ||
| target, | ||
| this.channelInitializer, | ||
| this.enableHttps, | ||
| enableHttps, | ||
| this.sslContext, | ||
| healthCheckAttemptTimeout, | ||
| healthCheckTimeout, | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,100 @@ | ||
| package io.temporal.serviceclient; | ||
|
|
||
| import static org.junit.Assert.*; | ||
| import static org.mockito.Mockito.mock; | ||
|
|
||
| import io.grpc.ManagedChannel; | ||
| import io.grpc.netty.shaded.io.netty.handler.ssl.SslContext; | ||
| import org.junit.Test; | ||
|
|
||
| public class ServiceStubsOptionsTest { | ||
|
|
||
| @Test | ||
| public void testTLSEnabledByDefaultWhenAPIKeyProvided() { | ||
| ServiceStubsOptions options = | ||
| WorkflowServiceStubsOptions.newBuilder() | ||
| .setTarget("localhost:7233") | ||
| .addApiKey(() -> "test-api-key") | ||
| .validateAndBuildWithDefaults(); | ||
|
|
||
| assertTrue(options.getEnableHttps()); | ||
| } | ||
|
|
||
| @Test | ||
| public void testExplicitTLSDisableBeforeAPIKeyStillDisables() { | ||
| ServiceStubsOptions options = | ||
| WorkflowServiceStubsOptions.newBuilder() | ||
| .setTarget("localhost:7233") | ||
| .setEnableHttps(false) | ||
| .addApiKey(() -> "test-api-key") | ||
| .validateAndBuildWithDefaults(); | ||
|
|
||
| // Explicit TLS=false should take precedence regardless of order | ||
| assertFalse(options.getEnableHttps()); | ||
| } | ||
|
|
||
| @Test | ||
| public void testExplicitTLSDisableAfterAPIKeyStillDisables() { | ||
| ServiceStubsOptions options = | ||
| WorkflowServiceStubsOptions.newBuilder() | ||
| .setTarget("localhost:7233") | ||
| .addApiKey(() -> "test-api-key") | ||
| .setEnableHttps(false) | ||
| .validateAndBuildWithDefaults(); | ||
|
|
||
| // Explicit TLS=false should take precedence regardless of order | ||
| assertFalse(options.getEnableHttps()); | ||
| } | ||
|
|
||
| @Test | ||
| public void testTLSDisabledByDefaultWithoutAPIKey() { | ||
| ServiceStubsOptions options = | ||
| WorkflowServiceStubsOptions.newBuilder() | ||
| .setTarget("localhost:7233") | ||
| .validateAndBuildWithDefaults(); | ||
|
|
||
| assertFalse(options.getEnableHttps()); | ||
| } | ||
|
|
||
| @Test | ||
| public void testExplicitTLSEnableWithoutAPIKey() { | ||
| ServiceStubsOptions options = | ||
| WorkflowServiceStubsOptions.newBuilder() | ||
| .setTarget("localhost:7233") | ||
| .setEnableHttps(true) | ||
| .validateAndBuildWithDefaults(); | ||
|
|
||
| assertTrue(options.getEnableHttps()); | ||
| } | ||
|
|
||
| @Test | ||
| public void testTLSNotAutoEnabledWhenSslContextProvided() { | ||
| // When user provides custom sslContext, they're handling TLS themselves | ||
| // so enableHttps should not be auto-enabled | ||
| SslContext sslContext = mock(SslContext.class); | ||
| ServiceStubsOptions options = | ||
| WorkflowServiceStubsOptions.newBuilder() | ||
| .setTarget("localhost:7233") | ||
| .addApiKey(() -> "test-api-key") | ||
| .setSslContext(sslContext) | ||
| .validateAndBuildWithDefaults(); | ||
|
|
||
| // enableHttps stays false because sslContext handles TLS | ||
| assertFalse(options.getEnableHttps()); | ||
| assertNotNull(options.getSslContext()); | ||
| } | ||
|
|
||
| @Test | ||
| public void testTLSNotAutoEnabledWhenCustomChannelProvided() { | ||
| // When user provides custom channel, they're managing connection themselves | ||
| // so enableHttps should not be auto-enabled | ||
| ManagedChannel channel = mock(ManagedChannel.class); | ||
| ServiceStubsOptions options = | ||
| WorkflowServiceStubsOptions.newBuilder() | ||
| .setChannel(channel) | ||
| .addApiKey(() -> "test-api-key") | ||
| .validateAndBuildWithDefaults(); | ||
|
|
||
| assertFalse(options.getEnableHttps()); | ||
| } | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I assume we don't want to support a user calling
setEnableHttps(null)to restore to "default"? I don't mind, just want to confirm