Repository: cassandra
Updated Branches:
  refs/heads/trunk f109f200a -> 11496039f


Correct and clarify SSLFactory.getSslContext method and call sites

patch by Dinesh Joshi; reviewed by jasobrown for CASSANDRA-14314


Project: http://git-wip-us.apache.org/repos/asf/cassandra/repo
Commit: http://git-wip-us.apache.org/repos/asf/cassandra/commit/11496039
Tree: http://git-wip-us.apache.org/repos/asf/cassandra/tree/11496039
Diff: http://git-wip-us.apache.org/repos/asf/cassandra/diff/11496039

Branch: refs/heads/trunk
Commit: 11496039fb18bb45407246602e31740c56d28157
Parents: f109f20
Author: Dinesh A. Joshi <dinesh.jo...@apple.com>
Authored: Sat Mar 17 17:17:42 2018 -0700
Committer: Jason Brown <jasedbr...@gmail.com>
Committed: Thu Mar 22 06:38:56 2018 -0700

----------------------------------------------------------------------
 CHANGES.txt                                     |   1 +
 .../cassandra/config/DatabaseDescriptor.java    |   6 +-
 .../cassandra/config/EncryptionOptions.java     |  35 +++++
 .../apache/cassandra/net/MessagingService.java  |   6 +-
 .../cassandra/net/async/NettyFactory.java       |   6 +-
 .../cassandra/net/async/OptionalSslHandler.java |   2 +-
 .../apache/cassandra/security/SSLFactory.java   | 154 +++++++++++--------
 .../service/NativeTransportService.java         |   3 +-
 .../streaming/DefaultConnectionFactory.java     |   2 +-
 .../org/apache/cassandra/transport/Server.java  |   7 +-
 .../cassandra/transport/SimpleClient.java       |   5 +-
 .../cassandra/net/MessagingServiceTest.java     |   8 +-
 .../async/OutboundMessagingConnectionTest.java  |   7 +-
 .../cassandra/security/SSLFactoryTest.java      |  46 +++++-
 .../service/NativeTransportServiceTest.java     |  13 +-
 15 files changed, 194 insertions(+), 107 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cassandra/blob/11496039/CHANGES.txt
----------------------------------------------------------------------
diff --git a/CHANGES.txt b/CHANGES.txt
index c092a9f..f86a380 100644
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@ -1,4 +1,5 @@
 4.0
+ * Correct and clarify SSLFactory.getSslContext method and call sites 
(CASSANDRA-14314)
  * Use zero as default score in DynamicEndpointSnitch (CASSANDRA-14252)
  * Handle static and partition deletion properly on 
ThrottledUnfilteredIterator (CASSANDRA-14315)
  * NodeTool clientstats should show SSL Cipher (CASSANDRA-14322)

http://git-wip-us.apache.org/repos/asf/cassandra/blob/11496039/src/java/org/apache/cassandra/config/DatabaseDescriptor.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/config/DatabaseDescriptor.java 
b/src/java/org/apache/cassandra/config/DatabaseDescriptor.java
index 2e772c5..bf00d40 100644
--- a/src/java/org/apache/cassandra/config/DatabaseDescriptor.java
+++ b/src/java/org/apache/cassandra/config/DatabaseDescriptor.java
@@ -2005,17 +2005,17 @@ public class DatabaseDescriptor
         conf.dynamic_snitch_badness_threshold = dynamicBadnessThreshold;
     }
 
-    public static EncryptionOptions.ServerEncryptionOptions 
getServerEncryptionOptions()
+    public static EncryptionOptions.ServerEncryptionOptions 
getInternodeMessagingEncyptionOptions()
     {
         return conf.server_encryption_options;
     }
 
-    public static void 
setServerEncryptionOptions(EncryptionOptions.ServerEncryptionOptions 
encryptionOptions)
+    public static void 
setInternodeMessagingEncyptionOptions(EncryptionOptions.ServerEncryptionOptions 
encryptionOptions)
     {
         conf.server_encryption_options = encryptionOptions;
     }
 
-    public static EncryptionOptions getClientEncryptionOptions()
+    public static EncryptionOptions getNativeProtocolEncryptionOptions()
     {
         return conf.client_encryption_options;
     }

http://git-wip-us.apache.org/repos/asf/cassandra/blob/11496039/src/java/org/apache/cassandra/config/EncryptionOptions.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/config/EncryptionOptions.java 
b/src/java/org/apache/cassandra/config/EncryptionOptions.java
index 5260dff..45579fb 100644
--- a/src/java/org/apache/cassandra/config/EncryptionOptions.java
+++ b/src/java/org/apache/cassandra/config/EncryptionOptions.java
@@ -17,6 +17,9 @@
  */
 package org.apache.cassandra.config;
 
+import java.util.Arrays;
+import java.util.Objects;
+
 public class EncryptionOptions
 {
     public String keystore = "conf/.keystore";
@@ -54,6 +57,38 @@ public class EncryptionOptions
         optional = options.optional;
     }
 
+    @Override
+    public boolean equals(Object o)
+    {
+        if (o == this)
+            return true;
+        if (o == null || getClass() != o.getClass())
+            return false;
+
+        EncryptionOptions opt = (EncryptionOptions)o;
+        return Objects.equals(keystore, opt.keystore) &&
+               Objects.equals(truststore, opt.truststore) &&
+               Objects.equals(algorithm, opt.algorithm) &&
+               Objects.equals(protocol, opt.protocol) &&
+               Arrays.equals(cipher_suites, opt.cipher_suites) &&
+               require_client_auth == opt.require_client_auth &&
+               require_endpoint_verification == 
opt.require_endpoint_verification;
+    }
+
+    @Override
+    public int hashCode()
+    {
+        int result = 0;
+        result += 31 * (keystore == null ? 0 : keystore.hashCode());
+        result += 31 * (truststore == null ? 0 : truststore.hashCode());
+        result += 31 * (algorithm == null ? 0 : algorithm.hashCode());
+        result += 31 * (protocol == null ? 0 : protocol.hashCode());
+        result += 31 * Arrays.hashCode(cipher_suites);
+        result += 31 * Boolean.hashCode(require_client_auth);
+        result += 31 * Boolean.hashCode(require_endpoint_verification);
+        return result;
+    }
+
     public static class ServerEncryptionOptions extends EncryptionOptions
     {
         public enum InternodeEncryption

http://git-wip-us.apache.org/repos/asf/cassandra/blob/11496039/src/java/org/apache/cassandra/net/MessagingService.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/net/MessagingService.java 
b/src/java/org/apache/cassandra/net/MessagingService.java
index 573cf7d..c6ef986 100644
--- a/src/java/org/apache/cassandra/net/MessagingService.java
+++ b/src/java/org/apache/cassandra/net/MessagingService.java
@@ -737,7 +737,7 @@ public final class MessagingService implements 
MessagingServiceMBean
 
     public void listen()
     {
-        listen(DatabaseDescriptor.getServerEncryptionOptions());
+        listen(DatabaseDescriptor.getInternodeMessagingEncyptionOptions());
     }
 
     public void listen(ServerEncryptionOptions serverEncryptionOptions)
@@ -1606,7 +1606,7 @@ public final class MessagingService implements 
MessagingServiceMBean
 
             InetAddressAndPort preferredRemote = 
SystemKeyspace.getPreferredIP(to);
             InetAddressAndPort local = FBUtilities.getLocalAddressAndPort();
-            ServerEncryptionOptions encryptionOptions = secure ? 
DatabaseDescriptor.getServerEncryptionOptions() : null;
+            ServerEncryptionOptions encryptionOptions = secure ? 
DatabaseDescriptor.getInternodeMessagingEncyptionOptions() : null;
             IInternodeAuthenticator authenticator = 
DatabaseDescriptor.getInternodeAuthenticator();
 
             pool = new OutboundMessagingPool(preferredRemote, local, 
encryptionOptions, backPressure.newState(to), authenticator);
@@ -1656,7 +1656,7 @@ public final class MessagingService implements 
MessagingServiceMBean
     public static boolean isEncryptedConnection(InetAddressAndPort address)
     {
         IEndpointSnitch snitch = DatabaseDescriptor.getEndpointSnitch();
-        switch 
(DatabaseDescriptor.getServerEncryptionOptions().internode_encryption)
+        switch 
(DatabaseDescriptor.getInternodeMessagingEncyptionOptions().internode_encryption)
         {
             case none:
                 return false; // if nothing needs to be encrypted then return 
immediately.

http://git-wip-us.apache.org/repos/asf/cassandra/blob/11496039/src/java/org/apache/cassandra/net/async/NettyFactory.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/net/async/NettyFactory.java 
b/src/java/org/apache/cassandra/net/async/NettyFactory.java
index d891043..86ed4e7 100644
--- a/src/java/org/apache/cassandra/net/async/NettyFactory.java
+++ b/src/java/org/apache/cassandra/net/async/NettyFactory.java
@@ -122,7 +122,7 @@ public final class NettyFactory
     NettyFactory(boolean useEpoll)
     {
         this.useEpoll = useEpoll;
-        acceptGroup = getEventLoopGroup(useEpoll, 
determineAcceptGroupSize(DatabaseDescriptor.getServerEncryptionOptions()),
+        acceptGroup = getEventLoopGroup(useEpoll, 
determineAcceptGroupSize(DatabaseDescriptor.getInternodeMessagingEncyptionOptions()),
                                         
"MessagingService-NettyAcceptor-Thread", false);
         inboundGroup = getEventLoopGroup(useEpoll, 
FBUtilities.getAvailableProcessors(), "MessagingService-NettyInbound-Thread", 
false);
         outboundGroup = getEventLoopGroup(useEpoll, 
FBUtilities.getAvailableProcessors(), "MessagingService-NettyOutbound-Thread", 
true);
@@ -287,7 +287,7 @@ public final class NettyFactory
                 }
                 else
                 {
-                    SslContext sslContext = 
SSLFactory.getSslContext(encryptionOptions, true, true);
+                    SslContext sslContext = 
SSLFactory.getSslContext(encryptionOptions, true, 
SSLFactory.ConnectionType.INTERNODE_MESSAGING, SSLFactory.SocketType.SERVER);
                     InetSocketAddress peer = 
encryptionOptions.require_endpoint_verification ? channel.remoteAddress() : 
null;
                     SslHandler sslHandler = newSslHandler(channel, sslContext, 
peer);
                     logger.trace("creating inbound netty SslContext: 
context={}, engine={}", sslContext.getClass().getName(), 
sslHandler.engine().getClass().getName());
@@ -362,7 +362,7 @@ public final class NettyFactory
             // order of handlers: ssl -> logger -> handshakeHandler
             if (params.encryptionOptions != null)
             {
-                SslContext sslContext = 
SSLFactory.getSslContext(params.encryptionOptions, true, false);
+                SslContext sslContext = 
SSLFactory.getSslContext(params.encryptionOptions, true, 
SSLFactory.ConnectionType.INTERNODE_MESSAGING, SSLFactory.SocketType.CLIENT);
                 // for some reason channel.remoteAddress() will return null
                 InetAddressAndPort address = params.connectionId.remote();
                 InetSocketAddress peer = 
params.encryptionOptions.require_endpoint_verification ? new 
InetSocketAddress(address.address, address.port) : null;

http://git-wip-us.apache.org/repos/asf/cassandra/blob/11496039/src/java/org/apache/cassandra/net/async/OptionalSslHandler.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/net/async/OptionalSslHandler.java 
b/src/java/org/apache/cassandra/net/async/OptionalSslHandler.java
index b60ae13..d57518c 100644
--- a/src/java/org/apache/cassandra/net/async/OptionalSslHandler.java
+++ b/src/java/org/apache/cassandra/net/async/OptionalSslHandler.java
@@ -51,7 +51,7 @@ public class OptionalSslHandler extends ByteToMessageDecoder
         if (SslHandler.isEncrypted(in))
         {
             // Connection uses SSL/TLS, replace the detection handler with a 
SslHandler and so use encryption.
-            SslContext sslContext = 
SSLFactory.getSslContext(encryptionOptions, true, true);
+            SslContext sslContext = 
SSLFactory.getSslContext(encryptionOptions, true, 
SSLFactory.ConnectionType.INTERNODE_MESSAGING, SSLFactory.SocketType.SERVER);
             Channel channel = ctx.channel();
             InetSocketAddress peer = 
encryptionOptions.require_endpoint_verification ? (InetSocketAddress) 
channel.remoteAddress() : null;
             SslHandler sslHandler = NettyFactory.newSslHandler(channel, 
sslContext, peer);

http://git-wip-us.apache.org/repos/asf/cassandra/blob/11496039/src/java/org/apache/cassandra/security/SSLFactory.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/security/SSLFactory.java 
b/src/java/org/apache/cassandra/security/SSLFactory.java
index 395ea42..d64dded 100644
--- a/src/java/org/apache/cassandra/security/SSLFactory.java
+++ b/src/java/org/apache/cassandra/security/SSLFactory.java
@@ -30,9 +30,9 @@ import java.util.Arrays;
 import java.util.Date;
 import java.util.Enumeration;
 import java.util.List;
-import java.util.concurrent.CopyOnWriteArrayList;
+import java.util.Objects;
+import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.TimeUnit;
-import java.util.concurrent.atomic.AtomicReference;
 import javax.net.ssl.KeyManagerFactory;
 import javax.net.ssl.SSLContext;
 import javax.net.ssl.SSLSocket;
@@ -54,33 +54,47 @@ import io.netty.handler.ssl.SslContext;
 import io.netty.handler.ssl.SslContextBuilder;
 import io.netty.handler.ssl.SslProvider;
 import io.netty.handler.ssl.SupportedCipherSuiteFilter;
+import io.netty.util.ReferenceCountUtil;
 import org.apache.cassandra.concurrent.ScheduledExecutors;
 import org.apache.cassandra.config.EncryptionOptions;
 
 /**
  * A Factory for providing and setting up client {@link SSLSocket}s. Also 
provides
  * methods for creating both JSSE {@link SSLContext} instances as well as 
netty {@link SslContext} instances.
- *
+ * <p>
  * Netty {@link SslContext} instances are expensive to create (as well as to 
destroy) and consume a lof of resources
  * (especially direct memory), but instances can be reused across connections 
(assuming the SSL params are the same).
- * Hence we cache created instances in {@link #clientSslContext} and {@link 
#serverSslContext}.
+ * Hence we cache created instances in {@link #cachedSslContexts}.
  */
 public final class SSLFactory
 {
     private static final Logger logger = 
LoggerFactory.getLogger(SSLFactory.class);
 
-    @VisibleForTesting
-    static volatile boolean checkedExpiry = false;
+    /**
+     * Indicator if a connection is shared with a client application ({@link 
ConnectionType#NATIVE_TRANSPORT})
+     * or another cassandra node  ({@link ConnectionType#INTERNODE_MESSAGING}).
+     */
+    public enum ConnectionType
+    {
+        NATIVE_TRANSPORT, INTERNODE_MESSAGING
+    }
 
     /**
-     * A cached reference of the {@link SslContext} for client-facing 
connections.
+     * Indicates if the process holds the inbound/listening end of the socket 
({@link SocketType#SERVER})), or the
+     * outbound side ({@link SocketType#CLIENT}).
      */
-    private static final AtomicReference<SslContext> clientSslContext = new 
AtomicReference<>();
+    public enum SocketType
+    {
+        SERVER, CLIENT
+    }
+
+    @VisibleForTesting
+    static volatile boolean checkedExpiry = false;
 
     /**
-     * A cached reference of the {@link SslContext} for peer-to-peer, 
internode messaging connections.
+     * Cached references of SSL Contexts
      */
-    private static final AtomicReference<SslContext> serverSslContext = new 
AtomicReference<>();
+    private static final ConcurrentHashMap<CacheKey, SslContext> 
cachedSslContexts = new ConcurrentHashMap<>();
 
     /**
      * List of files that trigger hot reloading of SSL certificates
@@ -107,21 +121,13 @@ public final class SSLFactory
      */
     private static class HotReloadableFile
     {
-        enum Type
-        {
-            SERVER,
-            CLIENT
-        }
-
         private final File file;
         private volatile long lastModTime;
-        private final Type certType;
 
-        HotReloadableFile(String path, Type type)
+        HotReloadableFile(String path)
         {
             file = new File(path);
             lastModTime = file.lastModified();
-            certType = type;
         }
 
         boolean shouldReload()
@@ -131,16 +137,6 @@ public final class SSLFactory
             lastModTime = curModTime;
             return result;
         }
-
-        public boolean isServer()
-        {
-            return certType == Type.SERVER;
-        }
-
-        public boolean isClient()
-        {
-            return certType == Type.CLIENT;
-        }
     }
 
     /**
@@ -172,7 +168,7 @@ public final class SSLFactory
         try (InputStream tsf = 
Files.newInputStream(Paths.get(options.truststore)))
         {
             TrustManagerFactory tmf = TrustManagerFactory.getInstance(
-                options.algorithm == null ? 
TrustManagerFactory.getDefaultAlgorithm() : options.algorithm);
+            options.algorithm == null ? 
TrustManagerFactory.getDefaultAlgorithm() : options.algorithm);
             KeyStore ts = KeyStore.getInstance(options.store_type);
             ts.load(tsf, options.truststore_password.toCharArray());
             tmf.init(ts);
@@ -189,7 +185,7 @@ public final class SSLFactory
         try (InputStream ksf = 
Files.newInputStream(Paths.get(options.keystore)))
         {
             KeyManagerFactory kmf = KeyManagerFactory.getInstance(
-                options.algorithm == null ? 
KeyManagerFactory.getDefaultAlgorithm() : options.algorithm);
+            options.algorithm == null ? 
KeyManagerFactory.getDefaultAlgorithm() : options.algorithm);
             KeyStore ks = KeyStore.getInstance(options.store_type);
             ks.load(ksf, options.keystore_password.toCharArray());
             if (!checkedExpiry)
@@ -233,26 +229,41 @@ public final class SSLFactory
     /**
      * get a netty {@link SslContext} instance
      */
-    public static SslContext getSslContext(EncryptionOptions options, boolean 
buildTruststore, boolean forServer) throws IOException
+    public static SslContext getSslContext(EncryptionOptions options, boolean 
buildTruststore, ConnectionType connectionType,
+                                           SocketType socketType) throws 
IOException
     {
-        return getSslContext(options, buildTruststore, forServer, 
OpenSsl.isAvailable());
+        return getSslContext(options, buildTruststore, connectionType, 
socketType, OpenSsl.isAvailable());
     }
 
     /**
      * Get a netty {@link SslContext} instance.
      */
     @VisibleForTesting
-    static SslContext getSslContext(EncryptionOptions options, boolean 
buildTruststore, boolean forServer, boolean useOpenSsl) throws IOException
+    static SslContext getSslContext(EncryptionOptions options, boolean 
buildTruststore, ConnectionType connectionType,
+                                    SocketType socketType, boolean useOpenSsl) 
throws IOException
     {
-
+        CacheKey key = new CacheKey(options, connectionType, socketType);
         SslContext sslContext;
 
-        if (forServer && (sslContext = serverSslContext.get()) != null)
+        sslContext = cachedSslContexts.get(key);
+        if (sslContext != null)
             return sslContext;
 
-        if (!forServer && (sslContext = clientSslContext.get()) != null)
+        sslContext = createNettySslContext(options, buildTruststore, 
connectionType, socketType, useOpenSsl);
+        SslContext previous = cachedSslContexts.putIfAbsent(key, sslContext);
+        if (previous == null)
             return sslContext;
 
+        ReferenceCountUtil.release(sslContext);
+        return previous;
+    }
+
+    /**
+     * Create a Netty {@link SslContext}
+     */
+    static SslContext createNettySslContext(EncryptionOptions options, boolean 
buildTruststore, ConnectionType connectionType,
+                                            SocketType socketType, boolean 
useOpenSsl) throws IOException
+    {
         /*
             There is a case where the netty/openssl combo might not support 
using KeyManagerFactory. specifically,
             I've seen this with the netty-tcnative dynamic openssl 
implementation. using the netty-tcnative static-boringssl
@@ -261,12 +272,9 @@ public final class SSLFactory
             {@link SslContextBuilder#forServer(File, File, String)}). However, 
we are not supporting that now to keep
             the config/yaml API simple.
          */
-        KeyManagerFactory kmf = null;
-        if (forServer || options.require_client_auth)
-            kmf = buildKeyManagerFactory(options);
-
+        KeyManagerFactory kmf = buildKeyManagerFactory(options);
         SslContextBuilder builder;
-        if (forServer)
+        if (socketType == SocketType.SERVER)
         {
             builder = SslContextBuilder.forServer(kmf);
             builder.clientAuth(options.require_client_auth ? 
ClientAuth.REQUIRE : ClientAuth.NONE);
@@ -286,19 +294,14 @@ public final class SSLFactory
         if (buildTruststore)
             builder.trustManager(buildTrustManagerFactory(options));
 
-        SslContext ctx = builder.build();
-        AtomicReference<SslContext> ref = forServer ? serverSslContext : 
clientSslContext;
-        if (ref.compareAndSet(null, ctx))
-            return ctx;
-
-        return ref.get();
+        return builder.build();
     }
 
     /**
      * Performs a lightweight check whether the certificate files have been 
refreshed.
      *
      * @throws IllegalStateException if {@link 
#initHotReloading(EncryptionOptions.ServerEncryptionOptions, EncryptionOptions, 
boolean)}
-     * is not called first
+     *                               is not called first
      */
     public static void checkCertFilesForHotReloading()
     {
@@ -307,16 +310,10 @@ public final class SSLFactory
 
         logger.trace("Checking whether certificates have been updated");
 
-        if (hotReloadableFiles.stream().anyMatch(f -> f.isServer() && 
f.shouldReload()))
-        {
-            logger.info("Server ssl certificates have been updated. Reseting 
the context for new peer connections.");
-            serverSslContext.set(null);
-        }
-
-        if (hotReloadableFiles.stream().anyMatch(f -> f.isClient() && 
f.shouldReload()))
+        if 
(hotReloadableFiles.stream().anyMatch(HotReloadableFile::shouldReload))
         {
-            logger.info("Client ssl certificates have been updated. Reseting 
the context for new client connections.");
-            clientSslContext.set(null);
+            logger.info("SSL certificates have been updated. Reseting the ssl 
contexts for new connections.");
+            cachedSslContexts.clear();
         }
     }
 
@@ -339,14 +336,14 @@ public final class SSLFactory
 
         if (serverEncryptionOptions.enabled)
         {
-            fileList.add(new 
HotReloadableFile(serverEncryptionOptions.keystore, 
HotReloadableFile.Type.SERVER));
-            fileList.add(new 
HotReloadableFile(serverEncryptionOptions.truststore, 
HotReloadableFile.Type.SERVER));
+            fileList.add(new 
HotReloadableFile(serverEncryptionOptions.keystore));
+            fileList.add(new 
HotReloadableFile(serverEncryptionOptions.truststore));
         }
 
         if (clientEncryptionOptions.enabled)
         {
-            fileList.add(new 
HotReloadableFile(clientEncryptionOptions.keystore, 
HotReloadableFile.Type.CLIENT));
-            fileList.add(new 
HotReloadableFile(clientEncryptionOptions.truststore, 
HotReloadableFile.Type.CLIENT));
+            fileList.add(new 
HotReloadableFile(clientEncryptionOptions.keystore));
+            fileList.add(new 
HotReloadableFile(clientEncryptionOptions.truststore));
         }
 
         hotReloadableFiles = ImmutableList.copyOf(fileList);
@@ -360,4 +357,37 @@ public final class SSLFactory
 
         isHotReloadingInitialized = true;
     }
+
+    static class CacheKey
+    {
+        private final EncryptionOptions encryptionOptions;
+        private final ConnectionType connectionType;
+        private final SocketType socketType;
+
+        public CacheKey(EncryptionOptions encryptionOptions, ConnectionType 
connectionType, SocketType socketType)
+        {
+            this.encryptionOptions = encryptionOptions;
+            this.connectionType = connectionType;
+            this.socketType = socketType;
+        }
+
+        public boolean equals(Object o)
+        {
+            if (this == o) return true;
+            if (o == null || getClass() != o.getClass()) return false;
+            CacheKey cacheKey = (CacheKey) o;
+            return (connectionType == cacheKey.connectionType &&
+                    socketType == cacheKey.socketType &&
+                    Objects.equals(encryptionOptions, 
cacheKey.encryptionOptions));
+        }
+
+        public int hashCode()
+        {
+            int result = 0;
+            result += 31 * connectionType.hashCode();
+            result += 31 * socketType.hashCode();
+            result += 31 * encryptionOptions.hashCode();
+            return result;
+        }
+    }
 }

http://git-wip-us.apache.org/repos/asf/cassandra/blob/11496039/src/java/org/apache/cassandra/service/NativeTransportService.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/service/NativeTransportService.java 
b/src/java/org/apache/cassandra/service/NativeTransportService.java
index cec9b2b..d70e56e 100644
--- a/src/java/org/apache/cassandra/service/NativeTransportService.java
+++ b/src/java/org/apache/cassandra/service/NativeTransportService.java
@@ -29,7 +29,6 @@ import java.util.Map.Entry;
 import java.util.concurrent.TimeUnit;
 
 import com.google.common.annotations.VisibleForTesting;
-import com.google.common.collect.Lists;
 
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -92,7 +91,7 @@ public class NativeTransportService
                                                                 
.withEventLoopGroup(workerGroup)
                                                                 
.withHost(nativeAddr);
 
-        if (!DatabaseDescriptor.getClientEncryptionOptions().enabled)
+        if (!DatabaseDescriptor.getNativeProtocolEncryptionOptions().enabled)
         {
             servers = 
Collections.singleton(builder.withSSL(false).withPort(nativePort).build());
         }

http://git-wip-us.apache.org/repos/asf/cassandra/blob/11496039/src/java/org/apache/cassandra/streaming/DefaultConnectionFactory.java
----------------------------------------------------------------------
diff --git 
a/src/java/org/apache/cassandra/streaming/DefaultConnectionFactory.java 
b/src/java/org/apache/cassandra/streaming/DefaultConnectionFactory.java
index d9ed8be..609d2a0 100644
--- a/src/java/org/apache/cassandra/streaming/DefaultConnectionFactory.java
+++ b/src/java/org/apache/cassandra/streaming/DefaultConnectionFactory.java
@@ -49,7 +49,7 @@ public class DefaultConnectionFactory implements 
StreamConnectionFactory
     @Override
     public Channel createConnection(OutboundConnectionIdentifier connectionId, 
int protocolVersion) throws IOException
     {
-        ServerEncryptionOptions encryptionOptions = 
DatabaseDescriptor.getServerEncryptionOptions();
+        ServerEncryptionOptions encryptionOptions = 
DatabaseDescriptor.getInternodeMessagingEncyptionOptions();
 
         if (encryptionOptions.internode_encryption == 
ServerEncryptionOptions.InternodeEncryption.none)
             encryptionOptions = null;

http://git-wip-us.apache.org/repos/asf/cassandra/blob/11496039/src/java/org/apache/cassandra/transport/Server.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/transport/Server.java 
b/src/java/org/apache/cassandra/transport/Server.java
index 0f666d8..7aade66 100644
--- a/src/java/org/apache/cassandra/transport/Server.java
+++ b/src/java/org/apache/cassandra/transport/Server.java
@@ -24,8 +24,6 @@ import java.net.UnknownHostException;
 import java.util.*;
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.atomic.AtomicBoolean;
-import javax.net.ssl.SSLContext;
-import javax.net.ssl.SSLEngine;
 
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -140,7 +138,7 @@ public class Server implements CassandraDaemon.Server
 
         if (this.useSSL)
         {
-            final EncryptionOptions clientEnc = 
DatabaseDescriptor.getClientEncryptionOptions();
+            final EncryptionOptions clientEnc = 
DatabaseDescriptor.getNativeProtocolEncryptionOptions();
 
             if (clientEnc.optional)
             {
@@ -407,7 +405,8 @@ public class Server implements CassandraDaemon.Server
 
         protected final SslHandler createSslHandler(ByteBufAllocator 
allocator) throws IOException
         {
-            SslContext sslContext = 
SSLFactory.getSslContext(encryptionOptions, 
encryptionOptions.require_client_auth, true);
+            SslContext sslContext = 
SSLFactory.getSslContext(encryptionOptions, 
encryptionOptions.require_client_auth,
+                                                             
SSLFactory.ConnectionType.NATIVE_TRANSPORT, SSLFactory.SocketType.SERVER);
             return sslContext.newHandler(allocator);
         }
     }

http://git-wip-us.apache.org/repos/asf/cassandra/blob/11496039/src/java/org/apache/cassandra/transport/SimpleClient.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/transport/SimpleClient.java 
b/src/java/org/apache/cassandra/transport/SimpleClient.java
index 07463e2..db7de8d 100644
--- a/src/java/org/apache/cassandra/transport/SimpleClient.java
+++ b/src/java/org/apache/cassandra/transport/SimpleClient.java
@@ -52,12 +52,10 @@ import 
org.apache.cassandra.transport.messages.PrepareMessage;
 import org.apache.cassandra.transport.messages.QueryMessage;
 import org.apache.cassandra.transport.messages.ResultMessage;
 import org.apache.cassandra.transport.messages.StartupMessage;
-import org.apache.cassandra.utils.MD5Digest;
 import io.netty.channel.Channel;
 import io.netty.channel.ChannelFuture;
 import io.netty.channel.ChannelHandlerContext;
 import io.netty.channel.ChannelPipeline;
-import io.netty.handler.ssl.SslHandler;
 
 public class SimpleClient implements Closeable
 {
@@ -283,7 +281,8 @@ public class SimpleClient implements Closeable
         protected void initChannel(Channel channel) throws Exception
         {
             super.initChannel(channel);
-            SslContext sslContext = 
SSLFactory.getSslContext(encryptionOptions, 
encryptionOptions.require_client_auth, true);
+            SslContext sslContext = 
SSLFactory.getSslContext(encryptionOptions, 
encryptionOptions.require_client_auth,
+                                                             
SSLFactory.ConnectionType.NATIVE_TRANSPORT, SSLFactory.SocketType.CLIENT);
             channel.pipeline().addFirst("ssl", 
sslContext.newHandler(channel.alloc()));
         }
     }

http://git-wip-us.apache.org/repos/asf/cassandra/blob/11496039/test/unit/org/apache/cassandra/net/MessagingServiceTest.java
----------------------------------------------------------------------
diff --git a/test/unit/org/apache/cassandra/net/MessagingServiceTest.java 
b/test/unit/org/apache/cassandra/net/MessagingServiceTest.java
index 4ce3422..c3ebe32 100644
--- a/test/unit/org/apache/cassandra/net/MessagingServiceTest.java
+++ b/test/unit/org/apache/cassandra/net/MessagingServiceTest.java
@@ -22,7 +22,6 @@ package org.apache.cassandra.net;
 
 import java.io.IOException;
 import java.net.InetAddress;
-import java.net.InetSocketAddress;
 import java.net.UnknownHostException;
 import java.util.Arrays;
 import java.util.Collections;
@@ -48,9 +47,6 @@ import 
org.apache.cassandra.config.EncryptionOptions.ServerEncryptionOptions;
 import org.apache.cassandra.db.SystemKeyspace;
 import org.apache.cassandra.db.monitoring.ApproximateTime;
 import org.apache.cassandra.exceptions.ConfigurationException;
-import org.apache.cassandra.io.util.DataInputPlus.DataInputStreamPlus;
-import org.apache.cassandra.io.util.DataOutputStreamPlus;
-import org.apache.cassandra.io.util.WrappedDataOutputStreamPlus;
 import org.apache.cassandra.locator.InetAddressAndPort;
 import org.apache.cassandra.net.MessagingService.ServerChannel;
 import org.apache.cassandra.net.async.NettyFactory;
@@ -96,7 +92,7 @@ public class MessagingServiceTest
         DatabaseDescriptor.setBackPressureStrategy(new 
MockBackPressureStrategy(Collections.emptyMap()));
         
DatabaseDescriptor.setBroadcastAddress(InetAddress.getByName("127.0.0.1"));
         originalAuthenticator = DatabaseDescriptor.getInternodeAuthenticator();
-        originalServerEncryptionOptions = 
DatabaseDescriptor.getServerEncryptionOptions();
+        originalServerEncryptionOptions = 
DatabaseDescriptor.getInternodeMessagingEncyptionOptions();
         originalListenAddress = 
InetAddressAndPort.getByAddressOverrideDefaults(DatabaseDescriptor.getListenAddress(),
 DatabaseDescriptor.getStoragePort());
     }
 
@@ -115,7 +111,7 @@ public class MessagingServiceTest
     public void tearDown()
     {
         DatabaseDescriptor.setInternodeAuthenticator(originalAuthenticator);
-        
DatabaseDescriptor.setServerEncryptionOptions(originalServerEncryptionOptions);
+        
DatabaseDescriptor.setInternodeMessagingEncyptionOptions(originalServerEncryptionOptions);
         DatabaseDescriptor.setShouldListenOnBroadcastAddress(false);
         DatabaseDescriptor.setListenAddress(originalListenAddress.address);
         FBUtilities.reset();

http://git-wip-us.apache.org/repos/asf/cassandra/blob/11496039/test/unit/org/apache/cassandra/net/async/OutboundMessagingConnectionTest.java
----------------------------------------------------------------------
diff --git 
a/test/unit/org/apache/cassandra/net/async/OutboundMessagingConnectionTest.java 
b/test/unit/org/apache/cassandra/net/async/OutboundMessagingConnectionTest.java
index bf6e066..6a8dc83 100644
--- 
a/test/unit/org/apache/cassandra/net/async/OutboundMessagingConnectionTest.java
+++ 
b/test/unit/org/apache/cassandra/net/async/OutboundMessagingConnectionTest.java
@@ -20,7 +20,6 @@ package org.apache.cassandra.net.async;
 
 import java.io.IOException;
 import java.net.InetAddress;
-import java.net.InetSocketAddress;
 import java.util.HashMap;
 import java.util.Map;
 import java.util.Optional;
@@ -88,14 +87,14 @@ public class OutboundMessagingConnectionTest
         omc.setChannelWriter(ChannelWriter.create(channel, 
omc::handleMessageResult, Optional.empty()));
 
         snitch = DatabaseDescriptor.getEndpointSnitch();
-        encryptionOptions = DatabaseDescriptor.getServerEncryptionOptions();
+        encryptionOptions = 
DatabaseDescriptor.getInternodeMessagingEncyptionOptions();
     }
 
     @After
     public void tearDown()
     {
         DatabaseDescriptor.setEndpointSnitch(snitch);
-        DatabaseDescriptor.setServerEncryptionOptions(encryptionOptions);
+        
DatabaseDescriptor.setInternodeMessagingEncyptionOptions(encryptionOptions);
         channel.finishAndReleaseAll();
     }
 
@@ -506,7 +505,7 @@ public class OutboundMessagingConnectionTest
         ServerEncryptionOptions encryptionOptions = new 
ServerEncryptionOptions();
         encryptionOptions.enabled = true;
         encryptionOptions.internode_encryption = 
ServerEncryptionOptions.InternodeEncryption.all;
-        DatabaseDescriptor.setServerEncryptionOptions(encryptionOptions);
+        
DatabaseDescriptor.setInternodeMessagingEncyptionOptions(encryptionOptions);
         omc = new OutboundMessagingConnection(connectionId, encryptionOptions, 
Optional.empty(), new AllowAllInternodeAuthenticator());
         int peerVersion = MessagingService.VERSION_30;
         MessagingService.instance().setVersion(connectionId.remote(), 
MessagingService.VERSION_30);

http://git-wip-us.apache.org/repos/asf/cassandra/blob/11496039/test/unit/org/apache/cassandra/security/SSLFactoryTest.java
----------------------------------------------------------------------
diff --git a/test/unit/org/apache/cassandra/security/SSLFactoryTest.java 
b/test/unit/org/apache/cassandra/security/SSLFactoryTest.java
index 5153a11..19e88de 100644
--- a/test/unit/org/apache/cassandra/security/SSLFactoryTest.java
+++ b/test/unit/org/apache/cassandra/security/SSLFactoryTest.java
@@ -30,7 +30,9 @@ import org.junit.Test;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import io.netty.handler.ssl.JdkSslContext;
 import io.netty.handler.ssl.OpenSsl;
+import io.netty.handler.ssl.OpenSslContext;
 import io.netty.handler.ssl.SslContext;
 import io.netty.handler.ssl.util.SelfSignedCertificate;
 import org.apache.cassandra.config.DatabaseDescriptor;
@@ -93,16 +95,20 @@ public class SSLFactoryTest
         }
 
         EncryptionOptions options = addKeystoreOptions(encryptionOptions);
-        SslContext sslContext = SSLFactory.getSslContext(options, true, true, 
true);
+        SslContext sslContext = SSLFactory.getSslContext(options, true, 
SSLFactory.ConnectionType.NATIVE_TRANSPORT,
+                                                         
SSLFactory.SocketType.CLIENT, true);
         Assert.assertNotNull(sslContext);
+        Assert.assertTrue(sslContext instanceof OpenSslContext);
     }
 
     @Test
     public void getSslContext_JdkSsl() throws IOException
     {
         EncryptionOptions options = addKeystoreOptions(encryptionOptions);
-        SslContext sslContext = SSLFactory.getSslContext(options, true, true, 
false);
+        SslContext sslContext = SSLFactory.getSslContext(options, true, 
SSLFactory.ConnectionType.NATIVE_TRANSPORT,
+                                                         
SSLFactory.SocketType.CLIENT, false);
         Assert.assertNotNull(sslContext);
+        Assert.assertTrue(sslContext instanceof JdkSslContext);
         Assert.assertEquals(Arrays.asList(encryptionOptions.cipher_suites), 
sslContext.cipherSuites());
     }
 
@@ -113,14 +119,14 @@ public class SSLFactoryTest
         return options;
     }
 
-    @Test (expected = IOException.class)
+    @Test(expected = IOException.class)
     public void buildTrustManagerFactory_NoFile() throws IOException
     {
         encryptionOptions.truststore = 
"/this/is/probably/not/a/file/on/your/test/machine";
         SSLFactory.buildTrustManagerFactory(encryptionOptions);
     }
 
-    @Test (expected = IOException.class)
+    @Test(expected = IOException.class)
     public void buildTrustManagerFactory_BadPassword() throws IOException
     {
         encryptionOptions.truststore_password = "HomeOfBadPasswords";
@@ -134,7 +140,7 @@ public class SSLFactoryTest
         Assert.assertNotNull(trustManagerFactory);
     }
 
-    @Test (expected = IOException.class)
+    @Test(expected = IOException.class)
     public void buildKeyManagerFactory_NoFile() throws IOException
     {
         EncryptionOptions options = addKeystoreOptions(encryptionOptions);
@@ -142,7 +148,7 @@ public class SSLFactoryTest
         SSLFactory.buildKeyManagerFactory(options);
     }
 
-    @Test (expected = IOException.class)
+    @Test(expected = IOException.class)
     public void buildKeyManagerFactory_BadPassword() throws IOException
     {
         EncryptionOptions options = addKeystoreOptions(encryptionOptions);
@@ -169,7 +175,8 @@ public class SSLFactoryTest
 
             SSLFactory.initHotReloading((ServerEncryptionOptions) options, 
options, true);
 
-            SslContext oldCtx = SSLFactory.getSslContext(options, true, true, 
OpenSsl.isAvailable());
+            SslContext oldCtx = SSLFactory.getSslContext(options, true, 
SSLFactory.ConnectionType.NATIVE_TRANSPORT,
+                                                         
SSLFactory.SocketType.CLIENT, OpenSsl.isAvailable());
             File keystoreFile = new File(options.keystore);
 
             SSLFactory.checkCertFilesForHotReloading();
@@ -177,7 +184,8 @@ public class SSLFactoryTest
             keystoreFile.setLastModified(System.currentTimeMillis());
 
             SSLFactory.checkCertFilesForHotReloading();
-            SslContext newCtx = SSLFactory.getSslContext(options, true, true, 
OpenSsl.isAvailable());
+            SslContext newCtx = SSLFactory.getSslContext(options, true, 
SSLFactory.ConnectionType.NATIVE_TRANSPORT,
+                                                         
SSLFactory.SocketType.CLIENT, OpenSsl.isAvailable());
 
             Assert.assertNotSame(oldCtx, newCtx);
         }
@@ -190,4 +198,26 @@ public class SSLFactoryTest
             DatabaseDescriptor.loadConfig();
         }
     }
+
+    @Test
+    public void getSslContext_ParamChanges() throws IOException
+    {
+        EncryptionOptions options = addKeystoreOptions(encryptionOptions);
+        options.enabled = true;
+        options.cipher_suites = new String[]{ 
"TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256" };
+
+        SslContext ctx1 = SSLFactory.getSslContext(options, true, 
SSLFactory.ConnectionType.NATIVE_TRANSPORT,
+                                                   
SSLFactory.SocketType.CLIENT, OpenSsl.isAvailable());
+
+        Assert.assertTrue(ctx1.isClient());
+        Assert.assertArrayEquals(ctx1.cipherSuites().toArray(), 
options.cipher_suites);
+
+        options.cipher_suites = new String[]{ 
"TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256" };
+
+        SslContext ctx2 = SSLFactory.getSslContext(options, true, 
SSLFactory.ConnectionType.NATIVE_TRANSPORT,
+                                                   
SSLFactory.SocketType.CLIENT, OpenSsl.isAvailable());
+
+        Assert.assertTrue(ctx2.isClient());
+        Assert.assertArrayEquals(ctx2.cipherSuites().toArray(), 
options.cipher_suites);
+    }
 }

http://git-wip-us.apache.org/repos/asf/cassandra/blob/11496039/test/unit/org/apache/cassandra/service/NativeTransportServiceTest.java
----------------------------------------------------------------------
diff --git 
a/test/unit/org/apache/cassandra/service/NativeTransportServiceTest.java 
b/test/unit/org/apache/cassandra/service/NativeTransportServiceTest.java
index 334a9af..c918fd6 100644
--- a/test/unit/org/apache/cassandra/service/NativeTransportServiceTest.java
+++ b/test/unit/org/apache/cassandra/service/NativeTransportServiceTest.java
@@ -20,7 +20,6 @@ package org.apache.cassandra.service;
 import java.util.Arrays;
 import java.util.function.BooleanSupplier;
 import java.util.function.Consumer;
-import java.util.function.Supplier;
 import java.util.stream.Collectors;
 import java.util.stream.IntStream;
 
@@ -48,7 +47,7 @@ public class NativeTransportServiceTest
     @After
     public void resetConfig()
     {
-        DatabaseDescriptor.getClientEncryptionOptions().enabled = false;
+        DatabaseDescriptor.getNativeProtocolEncryptionOptions().enabled = 
false;
         DatabaseDescriptor.setNativeTransportPortSSL(null);
     }
 
@@ -129,8 +128,8 @@ public class NativeTransportServiceTest
     public void testSSLOnly()
     {
         // default ssl settings: client encryption enabled and default native 
transport port used for ssl only
-        DatabaseDescriptor.getClientEncryptionOptions().enabled = true;
-        DatabaseDescriptor.getClientEncryptionOptions().optional = false;
+        DatabaseDescriptor.getNativeProtocolEncryptionOptions().enabled = true;
+        DatabaseDescriptor.getNativeProtocolEncryptionOptions().optional = 
false;
 
         withService((NativeTransportService service) ->
                     {
@@ -146,8 +145,8 @@ public class NativeTransportServiceTest
     public void testSSLOptional()
     {
         // default ssl settings: client encryption enabled and default native 
transport port used for optional ssl
-        DatabaseDescriptor.getClientEncryptionOptions().enabled = true;
-        DatabaseDescriptor.getClientEncryptionOptions().optional = true;
+        DatabaseDescriptor.getNativeProtocolEncryptionOptions().enabled = true;
+        DatabaseDescriptor.getNativeProtocolEncryptionOptions().optional = 
true;
 
         withService((NativeTransportService service) ->
                     {
@@ -163,7 +162,7 @@ public class NativeTransportServiceTest
     public void testSSLWithNonSSL()
     {
         // ssl+non-ssl settings: client encryption enabled and additional ssl 
port specified
-        DatabaseDescriptor.getClientEncryptionOptions().enabled = true;
+        DatabaseDescriptor.getNativeProtocolEncryptionOptions().enabled = true;
         DatabaseDescriptor.setNativeTransportPortSSL(8432);
 
         withService((NativeTransportService service) ->


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscr...@cassandra.apache.org
For additional commands, e-mail: commits-h...@cassandra.apache.org

Reply via email to