Skip to content

Commit aed6bd6

Browse files
committed
accommodating review comments
1 parent 7e1d9d8 commit aed6bd6

File tree

3 files changed

+436
-2
lines changed

3 files changed

+436
-2
lines changed

CONTRIBUTING.md

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,6 @@ This doc is intended for contributors to `cadence-java-client` (hopefully that's
44

55
📚 **New to contributing to Cadence?** Check out our [Contributing Guide](https://cadenceworkflow.io/community/how-to-contribute/getting-started) for an overview of the contribution process across all Cadence repositories. This document contains cadence-java-client specific setup and development instructions.
66

7-
**Note:** All contributors also need to fill out the [Uber Contributor License Agreement](http://t.uber.com/cla) before we can merge in any of your changes.
8-
97
Join our community on the CNCF Slack workspace at [cloud-native.slack.com](https://communityinviter.com/apps/cloud-native/cncf) in the **#cadence-users** channel to reach out and discuss issues with the team.
108

119
## Development Environment
Lines changed: 280 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,280 @@
1+
/*
2+
* Modifications Copyright (c) 2017-2020 Uber Technologies Inc.
3+
* Portions of the Software are attributed to Copyright (c) 2020 Temporal Technologies Inc.
4+
* Copyright 2012-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved.
5+
*
6+
* Licensed under the Apache License, Version 2.0 (the "License"). You may not
7+
* use this file except in compliance with the License. A copy of the License is
8+
* located at
9+
*
10+
* http://aws.amazon.com/apache2.0
11+
*
12+
* or in the "license" file accompanying this file. This file is distributed on
13+
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
14+
* express or implied. See the License for the specific language governing
15+
* permissions and limitations under the License.
16+
*/
17+
18+
package com.uber.cadence.serviceclient;
19+
20+
import io.grpc.netty.shaded.io.netty.handler.ssl.SslContext;
21+
import java.io.File;
22+
import java.io.InputStream;
23+
24+
/**
25+
* TLSOptions encapsulates TLS/SSL configuration for gRPC connections.
26+
*
27+
* <p>This class provides options for configuring secure connections to Cadence servers, including
28+
* support for custom CA certificates, mutual TLS (mTLS) with client certificates, and custom SSL
29+
* contexts.
30+
*
31+
* <p>Example usage:
32+
*
33+
* <pre>{@code
34+
* // Simple TLS with custom CA certificate
35+
* TLSOptions tlsOptions = TLSOptions.newBuilder()
36+
* .setTrustManagerCertFile(new File("path/to/ca.crt"))
37+
* .build();
38+
*
39+
* // Mutual TLS with client certificate
40+
* TLSOptions tlsOptions = TLSOptions.newBuilder()
41+
* .setTrustManagerCertFile(new File("path/to/ca.crt"))
42+
* .setClientCertFile(new File("path/to/client.crt"))
43+
* .setClientKeyFile(new File("path/to/client.key"))
44+
* .build();
45+
*
46+
* // Use with ClientOptions
47+
* ClientOptions options = ClientOptions.newBuilder()
48+
* .setHost("cadence.example.com")
49+
* .setPort(443)
50+
* .setTLSOptions(tlsOptions)
51+
* .build();
52+
* }</pre>
53+
*/
54+
public class TLSOptions {
55+
56+
private final File trustManagerCertFile;
57+
private final InputStream trustManagerCertInputStream;
58+
private final File clientCertFile;
59+
private final InputStream clientCertInputStream;
60+
private final File clientKeyFile;
61+
private final InputStream clientKeyInputStream;
62+
private final String clientKeyPassword;
63+
private final SslContext customSslContext;
64+
private final boolean disableHostVerification;
65+
66+
private TLSOptions(Builder builder) {
67+
this.trustManagerCertFile = builder.trustManagerCertFile;
68+
this.trustManagerCertInputStream = builder.trustManagerCertInputStream;
69+
this.clientCertFile = builder.clientCertFile;
70+
this.clientCertInputStream = builder.clientCertInputStream;
71+
this.clientKeyFile = builder.clientKeyFile;
72+
this.clientKeyInputStream = builder.clientKeyInputStream;
73+
this.clientKeyPassword = builder.clientKeyPassword;
74+
this.customSslContext = builder.customSslContext;
75+
this.disableHostVerification = builder.disableHostVerification;
76+
}
77+
78+
public static Builder newBuilder() {
79+
return new Builder();
80+
}
81+
82+
/** @return The trust manager certificate file (CA certificate) */
83+
public File getTrustManagerCertFile() {
84+
return trustManagerCertFile;
85+
}
86+
87+
/** @return The trust manager certificate input stream (CA certificate) */
88+
public InputStream getTrustManagerCertInputStream() {
89+
return trustManagerCertInputStream;
90+
}
91+
92+
/** @return The client certificate file for mutual TLS */
93+
public File getClientCertFile() {
94+
return clientCertFile;
95+
}
96+
97+
/** @return The client certificate input stream for mutual TLS */
98+
public InputStream getClientCertInputStream() {
99+
return clientCertInputStream;
100+
}
101+
102+
/** @return The client private key file for mutual TLS */
103+
public File getClientKeyFile() {
104+
return clientKeyFile;
105+
}
106+
107+
/** @return The client private key input stream for mutual TLS */
108+
public InputStream getClientKeyInputStream() {
109+
return clientKeyInputStream;
110+
}
111+
112+
/** @return The password for the client private key, if encrypted */
113+
public String getClientKeyPassword() {
114+
return clientKeyPassword;
115+
}
116+
117+
/** @return A custom SSL context, if provided */
118+
public SslContext getCustomSslContext() {
119+
return customSslContext;
120+
}
121+
122+
/** @return Whether to disable host verification */
123+
public boolean isDisableHostVerification() {
124+
return disableHostVerification;
125+
}
126+
127+
/** Builder for TLSOptions */
128+
public static class Builder {
129+
130+
private File trustManagerCertFile;
131+
private InputStream trustManagerCertInputStream;
132+
private File clientCertFile;
133+
private InputStream clientCertInputStream;
134+
private File clientKeyFile;
135+
private InputStream clientKeyInputStream;
136+
private String clientKeyPassword;
137+
private SslContext customSslContext;
138+
private boolean disableHostVerification;
139+
140+
private Builder() {}
141+
142+
/**
143+
* Sets the trust manager certificate file (CA certificate) to verify the server's certificate.
144+
*
145+
* @param trustManagerCertFile File containing the CA certificate in PEM format
146+
* @return this Builder
147+
*/
148+
public Builder setTrustManagerCertFile(File trustManagerCertFile) {
149+
this.trustManagerCertFile = trustManagerCertFile;
150+
return this;
151+
}
152+
153+
/**
154+
* Sets the trust manager certificate input stream (CA certificate) to verify the server's
155+
* certificate.
156+
*
157+
* @param trustManagerCertInputStream InputStream containing the CA certificate in PEM format
158+
* @return this Builder
159+
*/
160+
public Builder setTrustManagerCertInputStream(InputStream trustManagerCertInputStream) {
161+
this.trustManagerCertInputStream = trustManagerCertInputStream;
162+
return this;
163+
}
164+
165+
/**
166+
* Sets the client certificate file for mutual TLS authentication.
167+
*
168+
* @param clientCertFile File containing the client certificate in PEM format
169+
* @return this Builder
170+
*/
171+
public Builder setClientCertFile(File clientCertFile) {
172+
this.clientCertFile = clientCertFile;
173+
return this;
174+
}
175+
176+
/**
177+
* Sets the client certificate input stream for mutual TLS authentication.
178+
*
179+
* @param clientCertInputStream InputStream containing the client certificate in PEM format
180+
* @return this Builder
181+
*/
182+
public Builder setClientCertInputStream(InputStream clientCertInputStream) {
183+
this.clientCertInputStream = clientCertInputStream;
184+
return this;
185+
}
186+
187+
/**
188+
* Sets the client private key file for mutual TLS authentication.
189+
*
190+
* @param clientKeyFile File containing the client private key in PEM format
191+
* @return this Builder
192+
*/
193+
public Builder setClientKeyFile(File clientKeyFile) {
194+
this.clientKeyFile = clientKeyFile;
195+
return this;
196+
}
197+
198+
/**
199+
* Sets the client private key input stream for mutual TLS authentication.
200+
*
201+
* @param clientKeyInputStream InputStream containing the client private key in PEM format
202+
* @return this Builder
203+
*/
204+
public Builder setClientKeyInputStream(InputStream clientKeyInputStream) {
205+
this.clientKeyInputStream = clientKeyInputStream;
206+
return this;
207+
}
208+
209+
/**
210+
* Sets the password for the client private key if it is encrypted.
211+
*
212+
* @param clientKeyPassword Password for the encrypted private key
213+
* @return this Builder
214+
*/
215+
public Builder setClientKeyPassword(String clientKeyPassword) {
216+
this.clientKeyPassword = clientKeyPassword;
217+
return this;
218+
}
219+
220+
/**
221+
* Sets a custom SSL context. If provided, this will be used instead of building one from
222+
* certificate files.
223+
*
224+
* @param customSslContext Custom SSL context
225+
* @return this Builder
226+
*/
227+
public Builder setCustomSslContext(SslContext customSslContext) {
228+
this.customSslContext = customSslContext;
229+
return this;
230+
}
231+
232+
/**
233+
* Disables host verification. Use with caution - this reduces security by not verifying the
234+
* server's hostname matches its certificate.
235+
*
236+
* @param disableHostVerification true to disable host verification
237+
* @return this Builder
238+
*/
239+
public Builder setDisableHostVerification(boolean disableHostVerification) {
240+
this.disableHostVerification = disableHostVerification;
241+
return this;
242+
}
243+
244+
/**
245+
* Builds the TLSOptions.
246+
*
247+
* @return TLSOptions instance
248+
* @throws IllegalStateException if the configuration is invalid
249+
*/
250+
public TLSOptions build() {
251+
// Validate configuration
252+
if (customSslContext == null) {
253+
if (trustManagerCertFile == null && trustManagerCertInputStream == null) {
254+
throw new IllegalStateException(
255+
"Either trustManagerCertFile, trustManagerCertInputStream, or customSslContext must be set");
256+
}
257+
if (trustManagerCertFile != null && trustManagerCertInputStream != null) {
258+
throw new IllegalStateException(
259+
"Cannot set both trustManagerCertFile and trustManagerCertInputStream");
260+
}
261+
// Validate mutual TLS configuration
262+
boolean hasClientCert = clientCertFile != null || clientCertInputStream != null;
263+
boolean hasClientKey = clientKeyFile != null || clientKeyInputStream != null;
264+
if (hasClientCert != hasClientKey) {
265+
throw new IllegalStateException(
266+
"Both client certificate and client key must be provided for mutual TLS");
267+
}
268+
if (clientCertFile != null && clientCertInputStream != null) {
269+
throw new IllegalStateException(
270+
"Cannot set both clientCertFile and clientCertInputStream");
271+
}
272+
if (clientKeyFile != null && clientKeyInputStream != null) {
273+
throw new IllegalStateException("Cannot set both clientKeyFile and clientKeyInputStream");
274+
}
275+
}
276+
277+
return new TLSOptions(this);
278+
}
279+
}
280+
}

0 commit comments

Comments
 (0)