Skip to content

Commit 74d6b59

Browse files
authored
Add support for setting io.netty.handler.ssl.SslContext (#734)
This may be used as a convenient way to utilize OpenSSL as an alternative to the TLS/SSL protocol implementation in a JDK. See also https://netty.io/wiki/requirements-for-4.x.html#tls-with-openssl. JAVA-4177
1 parent 56e8e1b commit 74d6b59

File tree

17 files changed

+355
-70
lines changed

17 files changed

+355
-70
lines changed

.evergreen/.evg.yml

Lines changed: 24 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -333,7 +333,7 @@ functions:
333333
working_dir: "src"
334334
script: |
335335
${PREPARE_SHELL}
336-
STREAM_TYPE=netty AUTH="${AUTH}" SSL="${SSL}" MONGODB_URI="${MONGODB_URI}" TOPOLOGY="${TOPOLOGY}" COMPRESSOR="${COMPRESSOR}" JDK="${JDK}" .evergreen/run-tests.sh
336+
STREAM_TYPE="netty" AUTH="${AUTH}" SSL="${SSL}" NETTY_SSL_PROVIDER="${NETTY_SSL_PROVIDER}" MONGODB_URI="${MONGODB_URI}" TOPOLOGY="${TOPOLOGY}" COMPRESSOR="${COMPRESSOR}" JDK="${JDK}" .evergreen/run-tests.sh
337337
338338
"run plain auth test":
339339
- command: shell.exec
@@ -1224,6 +1224,8 @@ tasks:
12241224
name: "plain-auth-test"
12251225
- variant: ".test-scala-variant"
12261226
name: "scala-tests"
1227+
- variant: ".tests-netty-variant"
1228+
name: "netty-test"
12271229
commands:
12281230
- func: "publish snapshot"
12291231

@@ -1350,6 +1352,17 @@ axes:
13501352
display_name: NoSSL
13511353
variables:
13521354
SSL: "nossl"
1355+
- id: netty-ssl-provider
1356+
display_name: Netty TLS/SSL protocol provider
1357+
values:
1358+
- id: "jdk"
1359+
display_name: JDK
1360+
variables:
1361+
NETTY_SSL_PROVIDER: "JDK"
1362+
- id: "openssl"
1363+
display_name: OpenSSL
1364+
variables:
1365+
NETTY_SSL_PROVIDER: "OPENSSL"
13531366
- id: compressor
13541367
display_name: Compressor
13551368
values:
@@ -1489,10 +1502,17 @@ buildvariants:
14891502

14901503
- matrix_name: "tests-netty"
14911504
matrix_spec: { auth: "noauth", ssl: "*", jdk: "jdk8", version: ["4.2", "4.4"], topology: "replicaset", os: "linux" }
1492-
display_name: "Netty: ${version} ${topology} ${ssl} ${jdk} ${os} "
1493-
tags: ["tests-variant"]
1505+
display_name: "Netty: ${version} ${topology} ${ssl} ${auth} ${jdk} ${os} "
1506+
tags: ["tests-netty-variant"]
14941507
tasks:
1495-
- name: "test"
1508+
- name: "netty-test"
1509+
1510+
- matrix_name: "tests-netty-ssl-provider"
1511+
matrix_spec: { netty-ssl-provider: "*", auth: "auth", ssl: "ssl", jdk: "jdk8", version: ["5.0"], topology: "replicaset", os: "linux" }
1512+
display_name: "Netty SSL provider: ${version} ${topology} ${ssl} SslProvider.${netty-ssl-provider} ${auth} ${jdk} ${os} "
1513+
tags: ["tests-netty-variant"]
1514+
tasks:
1515+
- name: "netty-test"
14961516

14971517
- matrix_name: "tests-socket-snappy-compression"
14981518
matrix_spec: { compressor : "snappy", auth: "noauth", ssl: "nossl", jdk: "jdk8", version: ["4.2"], topology: "standalone", os: "linux" }

.evergreen/run-tests.sh

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ set -o errexit # Exit the script with error if any of the commands fail
66
# Supported/used environment variables:
77
# AUTH Set to enable authentication. Values are: "auth" / "noauth" (default)
88
# SSL Set to enable SSL. Values are "ssl" / "nossl" (default)
9+
# NETTY_SSL_PROVIDER The Netty TLS/SSL protocol provider. Ignored unless SSL is "ssl" and STREAM_TYPE is "netty". Values are "JDK", "OPENSSL", null (a.k.a. "" or '') (default).
910
# MONGODB_URI Set the suggested connection MONGODB_URI (including credentials and topology info)
1011
# TOPOLOGY Allows you to modify variables and the MONGODB_URI based on test topology
1112
# Supported values: "server", "replica_set", "sharded_cluster"
@@ -36,7 +37,9 @@ SLOW_TESTS_ONLY=${SLOW_TESTS_ONLY:-false}
3637
export ASYNC_TYPE="-Dorg.mongodb.test.async.type=${STREAM_TYPE}"
3738

3839
export JAVA_HOME="/opt/java/jdk11"
39-
40+
if [ "${SSL}" = "ssl" ] && [ "${STREAM_TYPE}" = "netty" ] && [ "${NETTY_SSL_PROVIDER}" != "" ]; then
41+
readonly JAVA_SYSPROP_NETTY_SSL_PROVIDER="-Dorg.mongodb.test.netty.ssl.provider=${NETTY_SSL_PROVIDER}"
42+
fi
4043

4144
############################################
4245
# Functions #
@@ -126,12 +129,16 @@ echo "Running tests with ${JDK}"
126129

127130
if [ "$SLOW_TESTS_ONLY" == "true" ]; then
128131
./gradlew -PjdkHome=/opt/java/${JDK} -Dorg.mongodb.test.uri=${MONGODB_URI} \
129-
${TRANSACTION_URI} ${GRADLE_EXTRA_VARS} ${ASYNC_TYPE} --stacktrace --info testSlowOnly
132+
${TRANSACTION_URI} ${GRADLE_EXTRA_VARS} ${ASYNC_TYPE} \
133+
${JAVA_SYSPROP_NETTY_SSL_PROVIDER} \
134+
--stacktrace --info testSlowOnly
130135
else
131136
./gradlew -PjdkHome=/opt/java/${JDK} -Dorg.mongodb.test.uri=${MONGODB_URI} \
132137
-Dorg.mongodb.test.awsAccessKeyId=${AWS_ACCESS_KEY_ID} -Dorg.mongodb.test.awsSecretAccessKey=${AWS_SECRET_ACCESS_KEY} \
133138
-Dorg.mongodb.test.tmpAwsAccessKeyId=${AWS_TEMP_ACCESS_KEY_ID} -Dorg.mongodb.test.tmpAwsSecretAccessKey=${AWS_TEMP_SECRET_ACCESS_KEY} -Dorg.mongodb.test.tmpAwsSessionToken=${AWS_TEMP_SESSION_TOKEN} \
134139
-Dorg.mongodb.test.azureTenantId=${AZURE_TENANT_ID} -Dorg.mongodb.test.azureClientId=${AZURE_CLIENT_ID} -Dorg.mongodb.test.azureClientSecret=${AZURE_CLIENT_SECRET} \
135140
-Dorg.mongodb.test.gcpEmail=${GCP_EMAIL} -Dorg.mongodb.test.gcpPrivateKey=${GCP_PRIVATE_KEY} \
136-
${TRANSACTION_URI} ${API_VERSION} ${GRADLE_EXTRA_VARS} ${ASYNC_TYPE} --stacktrace --info --continue test
141+
${TRANSACTION_URI} ${API_VERSION} ${GRADLE_EXTRA_VARS} ${ASYNC_TYPE} \
142+
${JAVA_SYSPROP_NETTY_SSL_PROVIDER} \
143+
--stacktrace --info --continue test
137144
fi

docs/reference/config.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ disableKinds = ["section", "taxonomy", "taxonomyTerm", "404"]
88

99
[params]
1010
javaSeDocsUri = "https://docs.oracle.com/javase/8/docs/"
11+
nettyApiUri = "https://netty.io/4.1/api/"
1112

1213
[blackfriday]
1314
plainIdAnchors = true

docs/reference/content/driver-reactive/tutorials/ssl.md

Lines changed: 47 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,9 @@ title = "TLS/SSL"
1010

1111
## TLS/SSL
1212

13-
The Java driver supports TLS/SSL connections to MongoDB servers using
14-
the underlying support for TLS/SSL provided by the JDK.
13+
By default the Java driver supports TLS/SSL connections to MongoDB servers using
14+
the underlying support for TLS/SSL provided by the JDK. This can be changed either by utilizing extensibility
15+
of the [Java SE API]({{< javaseref "api">}}), or via the [Netty API]({{< nettyapiref >}}).
1516
You can configure the driver to use TLS/SSL either with [`ConnectionString`]({{< apiref "mongodb-driver-core" "com/mongodb/ConnectionString" >}}) or with
1617
[`MongoClientSettings`]({{< apiref "mongodb-driver-core" "com/mongodb/MongoClientSettings" >}}).
1718

@@ -49,25 +50,56 @@ MongoClientSettings settings = MongoClientSettings.builder()
4950
MongoClient client = MongoClients.create(settings);
5051
```
5152

52-
### Specify `SSLContext` via `MongoClientSettings`
53+
### Specify Java SE `SSLContext` via `MongoClientSettings`
5354

5455
```java
5556
import javax.net.ssl.SSLContext;
5657
import com.mongodb.MongoClientSettings;
57-
import com.mongodb.reactivestreams.client.MongoClients;
58-
import com.mongodb.reactivestreams.client.MongoClient;
58+
import com.mongodb.MongoClient;
5959
```
6060

61-
To specify the [`javax.net.ssl.SSLContext`]({{< javaseref "api/javax/net/ssl/SSLContext.html" >}}) with
61+
To specify the [`javax.net.ssl.SSLContext`]({{< javaseref "api/javax/net/ssl/SSLContext.html" >}}) with
6262
[`MongoClientSettings`]({{< apiref "mongodb-driver-core" "com/mongodb/MongoClientSettings" >}}), set the `sslContext` property, as in:
6363

6464
```java
6565
SSLContext sslContext = ...
66+
MongoClientSettings settings = MongoClientSettings.builder()
67+
.applyToSslSettings(builder -> builder.enabled(true).context(sslContext))
68+
.build();
69+
MongoClient client = new MongoClient(settings);
70+
```
71+
72+
### Specify Netty `SslContext` via `NettyStreamFactoryFactory`
73+
74+
If you use the driver with [Netty](https://netty.io/) for network IO,
75+
you have an option to plug an alternative TLS/SSL protocol implementation provided by Netty.
76+
77+
```java
78+
import com.mongodb.MongoClientSettings;
79+
import com.mongodb.client.MongoClients;
80+
import com.mongodb.client.MongoClient;
81+
import com.mongodb.connection.netty.NettyStreamFactoryFactory;
82+
import io.netty.handler.ssl.SslContext;
83+
import io.netty.handler.ssl.SslContextBuilder;
84+
import io.netty.handler.ssl.SslProvider;
85+
```
86+
87+
To instruct the driver to use [`io.netty.handler.ssl.SslContext`]({{< nettyapiref "io/netty/handler/ssl/SslContext.html" >}}),
88+
use the method
89+
[`NettyStreamFactoryFactory.Builder.sslContext`]({{< apiref "mongodb-driver-core" "com/mongodb/connection/netty/NettyStreamFactoryFactory.Builder.html#sslContext(io.netty.handler.ssl.SslContext)" >}}).
90+
See the documentation of this method for details on which
91+
[`io.netty.handler.ssl.SslProvider`]({{< nettyapiref "io/netty/handler/ssl/SslProvider.html" >}})s are supported by the driver
92+
and implications of using them.
93+
94+
```java
95+
SslContext sslContext = SslContextBuilder.forClient()
96+
.sslProvider(SslProvider.OPENSSL)
97+
.build();
6698
MongoClientSettings settings = MongoClientSettings.builder()
67-
.applyToSslSettings(builder -> {
68-
builder.enabled(true);
69-
builder.context(sslContext);
70-
})
99+
.applyToSslSettings(builder -> builder.enabled(true))
100+
.streamFactoryFactory(NettyStreamFactoryFactory.builder()
101+
.sslContext(sslContext)
102+
.build())
71103
.build();
72104
MongoClient client = MongoClients.create(settings);
73105
```
@@ -91,7 +123,10 @@ MongoClientSettings settings = MongoClientSettings.builder()
91123
```
92124

93125
## Common TLS/SSL Configuration Tasks
94-
<p></p>
126+
127+
This section is based on the documentation for [Oracle JDK](https://www.oracle.com/java/technologies/javase-downloads.html#JDK8),
128+
so some parts may be inapplicable to your JDK or to the custom TLS/SSL implementation you use.
129+
95130
### Configure Trust Store and Key Store
96131
One may either configure trust stores and key stores specific to the client via
97132
[`javax.net.ssl.SSLContext.init(KeyManager[] km, TrustManager[] tm, SecureRandom random)`]
@@ -203,4 +238,4 @@ An application will need to set several JVM system properties to set up OCSP sta
203238
To configure an application to use OCSP stapling, the application must already be set up to connect to a server using TLS, and the server must be set up to staple an OCSP response to the certificate it returns as part of the the TLS handshake.
204239

205240
For more information on configuring a Java application to use OCSP, please
206-
refer to the [`Client-Driven OCSP and OCSP Stapling`]({{< javaseref "technotes/guides/security/jsse/ocsp.html" >}}).
241+
refer to the [`Client-Driven OCSP and OCSP Stapling`]({{< javaseref "technotes/guides/security/jsse/ocsp.html" >}}).

docs/reference/content/driver-scala/tutorials/ssl.md

Lines changed: 38 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,9 @@ title = "TLS/SSL"
1010

1111
## TLS/SSL
1212

13-
The Java driver supports TLS/SSL connections to MongoDB servers using
14-
the underlying support for TLS/SSL provided by the JDK.
13+
By default the Java driver supports TLS/SSL connections to MongoDB servers using
14+
the underlying support for TLS/SSL provided by the JDK. This can be changed either by utilizing extensibility
15+
of the [Java SE API]({{< javaseref "api">}}), or via the [Netty API]({{< nettyapiref >}}).
1516
You can configure the driver to use TLS/SSL either with [`ConnectionString`]({{< apiref "mongo-scala-driver" "org/mongodb/scala/package$$ConnectionString$.html" >}}) or with
1617
[`MongoClientSettings`]({{< apiref "mongo-scala-driver" "org/mongodb/scala/MongoClientSettings$.html" >}}).
1718

@@ -42,7 +43,7 @@ val settings = MongoClientSettings.builder()
4243
val client = MongoClient(settings)
4344
```
4445

45-
### Specify `SSLContext` via `MongoClientSettings`
46+
### Specify Java SE `SSLContext` via `MongoClientSettings`
4647

4748
```scala
4849
import javax.net.ssl.SSLContext
@@ -62,6 +63,36 @@ val settings = MongoClientSettings.builder()
6263
val client = MongoClient(settings)
6364
```
6465

66+
### Specify Netty `SslContext` via `NettyStreamFactoryFactory`
67+
68+
If you use the driver with [Netty](https://netty.io/) for network IO,
69+
you have an option to plug an alternative TLS/SSL protocol implementation provided by Netty.
70+
71+
```java
72+
import io.netty.handler.ssl.SslContextBuilder;
73+
import io.netty.handler.ssl.SslProvider;
74+
```
75+
76+
To instruct the driver to use [`io.netty.handler.ssl.SslContext`]({{< nettyapiref "io/netty/handler/ssl/SslContext.html" >}}),
77+
use the method
78+
[`NettyStreamFactoryFactory.Builder.sslContext`]({{< apiref "mongodb-driver-core" "com/mongodb/connection/netty/NettyStreamFactoryFactory.Builder.html#sslContext(io.netty.handler.ssl.SslContext)" >}}).
79+
See the documentation of this method for details on which
80+
[`io.netty.handler.ssl.SslProvider`]({{< nettyapiref "io/netty/handler/ssl/SslProvider.html" >}})s are supported by the driver
81+
and implications of using them.
82+
83+
```scala
84+
val sslContext = SslContextBuilder.forClient()
85+
.sslProvider(SslProvider.OPENSSL)
86+
.build();
87+
val settings = MongoClientSettings.builder()
88+
.applyToSslSettings((builder: SslSettings.Builder) => builder.enabled(true))
89+
.streamFactoryFactory(NettyStreamFactoryFactory.builder()
90+
.sslContext(sslContext)
91+
.build())
92+
.build()
93+
val client = MongoClient(settings)
94+
```
95+
6596
## Disable Hostname Verification
6697

6798
By default, the driver ensures that the hostname included in the
@@ -81,7 +112,10 @@ val settings = MongoClientSettings.builder()
81112
```
82113

83114
## Common TLS/SSL Configuration Tasks
84-
<p></p>
115+
116+
This section is based on the documentation for [Oracle JDK](https://www.oracle.com/java/technologies/javase-downloads.html#JDK8),
117+
so some parts may be inapplicable to your JDK or to the custom TLS/SSL implementation you use.
118+
85119
### Configure Trust Store and Key Store
86120
One may either configure trust stores and key stores specific to the client via
87121
[`javax.net.ssl.SSLContext.init(KeyManager[] km, TrustManager[] tm, SecureRandom random)`]

0 commit comments

Comments
 (0)