You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tinkerpop.apache.org by sp...@apache.org on 2016/04/27 19:58:57 UTC
[07/24] incubator-tinkerpop git commit: Added ability to pass an
SslContext to the driver.
Added ability to pass an SslContext to the driver.
This will be useful if the user needs more complex ssl configuration than the Cluster builder allows.
Project: http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/commit/99960661
Tree: http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/tree/99960661
Diff: http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/diff/99960661
Branch: refs/heads/TINKERPOP-1179
Commit: 9996066189686812befdeb69e33ef2e9a8a6b9b7
Parents: cfa95c8
Author: Stephen Mallette <sp...@genoprime.com>
Authored: Wed Apr 20 13:50:01 2016 -0400
Committer: Stephen Mallette <sp...@genoprime.com>
Committed: Wed Apr 20 15:07:15 2016 -0400
----------------------------------------------------------------------
.../tinkerpop/gremlin/driver/Channelizer.java | 29 +----
.../tinkerpop/gremlin/driver/Cluster.java | 121 +++++++++++++------
.../server/GremlinServerIntegrateTest.java | 23 ++++
.../GremlinServerSessionIntegrateTest.java | 1 +
4 files changed, 107 insertions(+), 67 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/99960661/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/Channelizer.java
----------------------------------------------------------------------
diff --git a/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/Channelizer.java b/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/Channelizer.java
index c850a11..40be11c 100644
--- a/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/Channelizer.java
+++ b/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/Channelizer.java
@@ -23,7 +23,6 @@ import io.netty.handler.codec.http.websocketx.CloseWebSocketFrame;
import io.netty.handler.ssl.SslContextBuilder;
import io.netty.handler.ssl.SslProvider;
import io.netty.handler.ssl.util.InsecureTrustManagerFactory;
-import io.netty.handler.ssl.util.SelfSignedCertificate;
import org.apache.tinkerpop.gremlin.driver.exception.ConnectionException;
import org.apache.tinkerpop.gremlin.driver.handler.NioGremlinRequestEncoder;
import org.apache.tinkerpop.gremlin.driver.handler.NioGremlinResponseDecoder;
@@ -43,9 +42,7 @@ import io.netty.handler.ssl.SslContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import javax.net.ssl.SSLException;
import java.io.File;
-import java.security.cert.CertificateException;
import java.util.Optional;
import java.util.UUID;
import java.util.concurrent.ConcurrentMap;
@@ -120,7 +117,7 @@ public interface Channelizer extends ChannelHandler {
final Optional<SslContext> sslCtx;
if (supportsSsl()) {
try {
- sslCtx = Optional.of(createSSLContext(cluster.connectionPoolSettings()));
+ sslCtx = Optional.of(cluster.createSSLContext());
} catch (Exception ex) {
throw new RuntimeException(ex);
}
@@ -136,30 +133,6 @@ public interface Channelizer extends ChannelHandler {
pipeline.addLast(PIPELINE_GREMLIN_SASL_HANDLER, new Handler.GremlinSaslAuthenticationHandler(cluster.authProperties()));
pipeline.addLast(PIPELINE_GREMLIN_HANDLER, new Handler.GremlinResponseHandler(pending));
}
-
- private SslContext createSSLContext(final Settings.ConnectionPoolSettings sslSettings) throws Exception {
- final SslProvider provider = SslProvider.JDK;
-
- final SslContextBuilder builder = SslContextBuilder.forClient();
- if (cluster.connectionPoolSettings().trustCertChainFile != null)
- builder.trustManager(new File(cluster.connectionPoolSettings().trustCertChainFile));
- else {
- logger.warn("SSL configured without a trustCertChainFile and thus trusts all certificates without verification (not suitable for production)");
- builder.trustManager(InsecureTrustManagerFactory.INSTANCE);
- }
-
- if (null != sslSettings.keyCertChainFile && null != sslSettings.keyFile) {
- final File keyCertChainFile = new File(sslSettings.keyCertChainFile);
- final File keyFile = new File(sslSettings.keyFile);
-
- // note that keyPassword may be null here if the keyFile is not password-protected.
- builder.keyManager(keyCertChainFile, keyFile, sslSettings.keyPassword);
- }
-
- builder.sslProvider(provider);
-
- return builder.build();
- }
}
/**
http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/99960661/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/Cluster.java
----------------------------------------------------------------------
diff --git a/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/Cluster.java b/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/Cluster.java
index 7ae898b..3fa11f7 100644
--- a/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/Cluster.java
+++ b/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/Cluster.java
@@ -20,11 +20,17 @@ package org.apache.tinkerpop.gremlin.driver;
import io.netty.buffer.PooledByteBufAllocator;
import io.netty.channel.ChannelOption;
+import io.netty.handler.ssl.SslContext;
+import io.netty.handler.ssl.SslContextBuilder;
+import io.netty.handler.ssl.SslProvider;
+import io.netty.handler.ssl.util.InsecureTrustManagerFactory;
import org.apache.tinkerpop.gremlin.driver.ser.Serializers;
import io.netty.bootstrap.Bootstrap;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import org.apache.commons.lang3.concurrent.BasicThreadFactory;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
import javax.net.ssl.TrustManager;
import java.io.File;
@@ -38,6 +44,7 @@ import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
+import java.util.Optional;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
@@ -52,15 +59,12 @@ import java.util.stream.Collectors;
* @author Stephen Mallette (http://stephen.genoprime.com)
*/
public final class Cluster {
+ private static final Logger logger = LoggerFactory.getLogger(Cluster.class);
private Manager manager;
- private Cluster(final List<InetSocketAddress> contactPoints, final MessageSerializer serializer,
- final int nioPoolSize, final int workerPoolSize,
- final Settings.ConnectionPoolSettings connectionPoolSettings,
- final LoadBalancingStrategy loadBalancingStrategy,
- final AuthProperties authProps) {
- this.manager = new Manager(contactPoints, serializer, nioPoolSize, workerPoolSize, connectionPoolSettings, loadBalancingStrategy, authProps);
+ private Cluster(final Builder builder) {
+ this.manager = new Manager(builder);
}
public synchronized void init() {
@@ -268,6 +272,34 @@ public final class Cluster {
return manager.allHosts();
}
+ SslContext createSSLContext() throws Exception {
+ // if the context is provided then just use that and ignore the other settings
+ if (manager.sslContextOptional.isPresent()) return manager.sslContextOptional.get();
+
+ final SslProvider provider = SslProvider.JDK;
+ final Settings.ConnectionPoolSettings connectionPoolSettings = connectionPoolSettings();
+ final SslContextBuilder builder = SslContextBuilder.forClient();
+
+ if (connectionPoolSettings.trustCertChainFile != null)
+ builder.trustManager(new File(connectionPoolSettings.trustCertChainFile));
+ else {
+ logger.warn("SSL configured without a trustCertChainFile and thus trusts all certificates without verification (not suitable for production)");
+ builder.trustManager(InsecureTrustManagerFactory.INSTANCE);
+ }
+
+ if (null != connectionPoolSettings.keyCertChainFile && null != connectionPoolSettings.keyFile) {
+ final File keyCertChainFile = new File(connectionPoolSettings.keyCertChainFile);
+ final File keyFile = new File(connectionPoolSettings.keyFile);
+
+ // note that keyPassword may be null here if the keyFile is not password-protected.
+ builder.keyManager(keyCertChainFile, keyFile, connectionPoolSettings.keyPassword);
+ }
+
+ builder.sslProvider(provider);
+
+ return builder.build();
+ }
+
public final static class Builder {
private List<InetAddress> addresses = new ArrayList<>();
private int port = 8182;
@@ -292,6 +324,7 @@ public final class Cluster {
private String keyCertChainFile = null;
private String keyFile = null;
private String keyPassword = null;
+ private SslContext sslContext = null;
private LoadBalancingStrategy loadBalancingStrategy = new LoadBalancingStrategy.RoundRobin();
private AuthProperties authProps = new AuthProperties();
@@ -359,6 +392,16 @@ public final class Cluster {
}
/**
+ * Explicitly set the {@code SslContext} for when more flexibility is required in the configuration than is
+ * allowed by the {@link Builder}. If this value is set to something other than {@code null} then all other
+ * related SSL settings are ignored.
+ */
+ public Builder sslContext(final SslContext sslContext) {
+ this.sslContext = sslContext;
+ return this;
+ }
+
+ /**
* File location for a SSL Certificate Chain to use when SSL is enabled. If this value is not provided and
* SSL is enabled, the {@link TrustManager} will be established with a self-signed certificate which is NOT
* suitable for production purposes.
@@ -596,33 +639,13 @@ public final class Cluster {
return this;
}
- private List<InetSocketAddress> getContactPoints() {
+ List<InetSocketAddress> getContactPoints() {
return addresses.stream().map(addy -> new InetSocketAddress(addy, port)).collect(Collectors.toList());
}
public Cluster create() {
if (addresses.size() == 0) addContactPoint("localhost");
- final Settings.ConnectionPoolSettings connectionPoolSettings = new Settings.ConnectionPoolSettings();
- connectionPoolSettings.maxInProcessPerConnection = this.maxInProcessPerConnection;
- connectionPoolSettings.minInProcessPerConnection = this.minInProcessPerConnection;
- connectionPoolSettings.maxSimultaneousUsagePerConnection = this.maxSimultaneousUsagePerConnection;
- connectionPoolSettings.minSimultaneousUsagePerConnection = this.minSimultaneousUsagePerConnection;
- connectionPoolSettings.maxSize = this.maxConnectionPoolSize;
- connectionPoolSettings.minSize = this.minConnectionPoolSize;
- connectionPoolSettings.maxWaitForConnection = this.maxWaitForConnection;
- connectionPoolSettings.maxWaitForSessionClose = this.maxWaitForSessionClose;
- connectionPoolSettings.maxContentLength = this.maxContentLength;
- connectionPoolSettings.reconnectInitialDelay = this.reconnectInitialDelay;
- connectionPoolSettings.reconnectInterval = this.reconnectInterval;
- connectionPoolSettings.resultIterationBatchSize = this.resultIterationBatchSize;
- connectionPoolSettings.enableSsl = this.enableSsl;
- connectionPoolSettings.trustCertChainFile = this.trustCertChainFile;
- connectionPoolSettings.keyCertChainFile = this.keyCertChainFile;
- connectionPoolSettings.keyFile = this.keyFile;
- connectionPoolSettings.keyPassword = this.keyPassword;
- connectionPoolSettings.channelizer = this.channelizer;
- return new Cluster(getContactPoints(), serializer, this.nioPoolSize, this.workerPoolSize,
- connectionPoolSettings, loadBalancingStrategy, authProps);
+ return new Cluster(this);
}
}
@@ -654,22 +677,42 @@ public final class Cluster {
private final Settings.ConnectionPoolSettings connectionPoolSettings;
private final LoadBalancingStrategy loadBalancingStrategy;
private final AuthProperties authProps;
+ private final Optional<SslContext> sslContextOptional;
private final ScheduledExecutorService executor;
private final AtomicReference<CompletableFuture<Void>> closeFuture = new AtomicReference<>();
- private Manager(final List<InetSocketAddress> contactPoints, final MessageSerializer serializer,
- final int nioPoolSize, final int workerPoolSize, final Settings.ConnectionPoolSettings connectionPoolSettings,
- final LoadBalancingStrategy loadBalancingStrategy,
- final AuthProperties authProps) {
- this.loadBalancingStrategy = loadBalancingStrategy;
- this.authProps = authProps;
- this.contactPoints = contactPoints;
- this.connectionPoolSettings = connectionPoolSettings;
- this.factory = new Factory(nioPoolSize);
- this.serializer = serializer;
- this.executor = Executors.newScheduledThreadPool(workerPoolSize,
+ private Manager(final Builder builder) {
+ this.loadBalancingStrategy = builder.loadBalancingStrategy;
+ this.authProps = builder.authProps;
+ this.contactPoints = builder.getContactPoints();
+
+ connectionPoolSettings = new Settings.ConnectionPoolSettings();
+ connectionPoolSettings.maxInProcessPerConnection = builder.maxInProcessPerConnection;
+ connectionPoolSettings.minInProcessPerConnection = builder.minInProcessPerConnection;
+ connectionPoolSettings.maxSimultaneousUsagePerConnection = builder.maxSimultaneousUsagePerConnection;
+ connectionPoolSettings.minSimultaneousUsagePerConnection = builder.minSimultaneousUsagePerConnection;
+ connectionPoolSettings.maxSize = builder.maxConnectionPoolSize;
+ connectionPoolSettings.minSize = builder.minConnectionPoolSize;
+ connectionPoolSettings.maxWaitForConnection = builder.maxWaitForConnection;
+ connectionPoolSettings.maxWaitForSessionClose = builder.maxWaitForSessionClose;
+ connectionPoolSettings.maxContentLength = builder.maxContentLength;
+ connectionPoolSettings.reconnectInitialDelay = builder.reconnectInitialDelay;
+ connectionPoolSettings.reconnectInterval = builder.reconnectInterval;
+ connectionPoolSettings.resultIterationBatchSize = builder.resultIterationBatchSize;
+ connectionPoolSettings.enableSsl = builder.enableSsl;
+ connectionPoolSettings.trustCertChainFile = builder.trustCertChainFile;
+ connectionPoolSettings.keyCertChainFile = builder.keyCertChainFile;
+ connectionPoolSettings.keyFile = builder.keyFile;
+ connectionPoolSettings.keyPassword = builder.keyPassword;
+ connectionPoolSettings.channelizer = builder.channelizer;
+
+ sslContextOptional = Optional.ofNullable(builder.sslContext);
+
+ this.factory = new Factory(builder.nioPoolSize);
+ this.serializer = builder.serializer;
+ this.executor = Executors.newScheduledThreadPool(builder.workerPoolSize,
new BasicThreadFactory.Builder().namingPattern("gremlin-driver-worker-%d").build());
}
http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/99960661/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/server/GremlinServerIntegrateTest.java
----------------------------------------------------------------------
diff --git a/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/server/GremlinServerIntegrateTest.java b/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/server/GremlinServerIntegrateTest.java
index fdcf358..ed42d53 100644
--- a/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/server/GremlinServerIntegrateTest.java
+++ b/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/server/GremlinServerIntegrateTest.java
@@ -19,6 +19,10 @@
package org.apache.tinkerpop.gremlin.server;
import java.io.File;
+
+import io.netty.handler.ssl.SslContextBuilder;
+import io.netty.handler.ssl.SslProvider;
+import io.netty.handler.ssl.util.InsecureTrustManagerFactory;
import org.apache.commons.lang.exception.ExceptionUtils;
import org.apache.log4j.Logger;
import org.apache.tinkerpop.gremlin.driver.Client;
@@ -122,6 +126,7 @@ public class GremlinServerIntegrateTest extends AbstractGremlinServerIntegration
break;
case "shouldEnableSsl":
case "shouldEnableSslButFailIfClientConnectsWithoutIt":
+ case "shouldEnableSslWithSslContextProgrammaticallySpecified":
settings.ssl = new Settings.SslSettings();
settings.ssl.enabled = true;
break;
@@ -272,6 +277,24 @@ public class GremlinServerIntegrateTest extends AbstractGremlinServerIntegration
}
@Test
+ public void shouldEnableSslWithSslContextProgrammaticallySpecified() throws Exception {
+ // just for testing - this is not good for production use
+ final SslContextBuilder builder = SslContextBuilder.forClient();
+ builder.trustManager(InsecureTrustManagerFactory.INSTANCE);
+ builder.sslProvider(SslProvider.JDK);
+
+ final Cluster cluster = Cluster.build().enableSsl(true).sslContext(builder.build()).create();
+ final Client client = cluster.connect();
+
+ try {
+ // this should return "nothing" - there should be no exception
+ assertEquals("test", client.submit("'test'").one().getString());
+ } finally {
+ cluster.close();
+ }
+ }
+
+ @Test
public void shouldEnableSslButFailIfClientConnectsWithoutIt() {
final Cluster cluster = Cluster.build().enableSsl(false).create();
final Client client = cluster.connect();
http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/99960661/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/server/GremlinServerSessionIntegrateTest.java
----------------------------------------------------------------------
diff --git a/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/server/GremlinServerSessionIntegrateTest.java b/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/server/GremlinServerSessionIntegrateTest.java
index 208aaef..15b2c4b 100644
--- a/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/server/GremlinServerSessionIntegrateTest.java
+++ b/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/server/GremlinServerSessionIntegrateTest.java
@@ -119,6 +119,7 @@ public class GremlinServerSessionIntegrateTest extends AbstractGremlinServerInt
fail("Should have tossed the manually generated exception");
} catch (Exception ex) {
final Throwable root = ExceptionUtils.getRootCause(ex);
+ ex.printStackTrace();
assertEquals("no worky", root.getMessage());
// just force a commit here of "something" in case there is something lingering