JeetKunDoug commented on code in PR #3638:
URL: https://github.com/apache/cassandra/pull/3638#discussion_r1846772307


##########
src/java/org/apache/cassandra/utils/RMICloseableServerSocketFactory.java:
##########
@@ -0,0 +1,34 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.cassandra.utils;
+
+import java.io.IOException;
+import java.rmi.server.RMIServerSocketFactory;
+
+/**
+ * This represents closeable RMI Server Socket factory.
+ */
+public interface RMICloseableServerSocketFactory extends RMIServerSocketFactory

Review Comment:
   This is essentially:
   ```suggestion
   public interface RMICloseableServerSocketFactory extends 
RMIServerSocketFactory, AutoCloseable
   ```
   I am trying to figure out if there's a reason we _wouldn't_ want to also 
extend `AutoCloseable` rather than adding a custom `close()` method... while I 
can't think of a reason why you'd want to use one in a "try-with-resources" 
block at this time, it also doesn't hurt anything to _allow it_ in the future, 
and by not doing it now we're artificially limiting the ability to do so. Also, 
there are some frameworks that can check if something is AutoCloseable and 
close it on shutdown/cleanup (again, nothing today seems to do this but it's 
possible we may want to some day).



##########
src/java/org/apache/cassandra/utils/RMICloseableServerSocketFactory.java:
##########
@@ -0,0 +1,34 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.cassandra.utils;
+
+import java.io.IOException;
+import java.rmi.server.RMIServerSocketFactory;
+
+/**
+ * This represents closeable RMI Server Socket factory.
+ */
+public interface RMICloseableServerSocketFactory extends RMIServerSocketFactory

Review Comment:
   FYI - this would go for the Client socket factory as well.



##########
src/java/org/apache/cassandra/config/DatabaseDescriptor.java:
##########
@@ -1306,7 +1309,14 @@ public static void applySslContext()
         {
             SSLFactory.validateSslContext("Internode messaging", 
conf.server_encryption_options, REQUIRED, true);
             SSLFactory.validateSslContext("Native transport", 
conf.client_encryption_options, conf.client_encryption_options.getClientAuth(), 
true);
+            // For JMX SSL the validation is pretty much the same as the 
Native transport
+            SSLFactory.validateSslContext("JMX transport", 
conf.jmx_encryption_options, conf.jmx_encryption_options.getClientAuth(), true);
             SSLFactory.initHotReloading(conf.server_encryption_options, 
conf.client_encryption_options, false);
+            /*
+            For JMX SSL, the hot reloading of the SSLContext is out of scope 
for CASSANDRA-18508.

Review Comment:
   Did we create a JIRA to track this, as the lack of hot-reloading of SSL 
certificates is going to be a real issue for folks who use short-lived SSL 
certs.



##########
test/distributed/org/apache/cassandra/distributed/impl/CollectingSslRMIServerSocketFactoryImpl.java:
##########
@@ -0,0 +1,157 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.cassandra.distributed.impl;
+
+import java.io.IOException;
+import java.net.InetAddress;
+import java.net.ServerSocket;
+import java.net.Socket;
+import java.net.SocketException;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Objects;
+import javax.net.ssl.SSLContext;
+import javax.net.ssl.SSLSocket;
+import javax.net.ssl.SSLSocketFactory;
+
+import org.apache.cassandra.utils.RMICloseableServerSocketFactory;
+
+
+/**
+ * This class is used to keep track of SSL based RMI servers created during a 
cluster creation to
+ * later close the sockets, which would otherwise be left with a thread 
running waiting for
+ * connections that would never show up as the server was otherwise closed.
+ */
+class CollectingSslRMIServerSocketFactoryImpl implements 
RMICloseableServerSocketFactory
+{
+    private final InetAddress bindAddress;
+    private final String[] enabledCipherSuites;
+    private final String[] enabledProtocols;
+    private final boolean needClientAuth;
+    private SSLContext sslContext;

Review Comment:
   If we change this field to be:
   ```suggestion
       private final SSLSocketFactory sslSocketFactory;
   ```
   We can then initialize it using the `sslContext` passed in to the 
constructor that uses it, _or_ use `getDefaultSSLSocketFactory` in the other, 
which gets rid of the ternary operator in `createSslServerSocket`. Do you 
envision a need to hold on to the `sslContext` itself, or could we do this in 
stead?



##########
test/distributed/org/apache/cassandra/distributed/impl/IsolatedJmx.java:
##########
@@ -137,6 +143,50 @@ public void startJmx() {
         }
     }
 
+    /**
+     * Builds {@code EncryptionOptions} from the map based SSL configuration 
properties.
+     * @param encryptionOptionsMap of SSL configuration properties
+     * @return EncryptionOptions built object
+     */
+    @SuppressWarnings("unchecked")
+    private EncryptionOptions getJmxEncryptionOptions(Map<String,Object> 
encryptionOptionsMap)
+    {
+        if (encryptionOptionsMap != null)
+        {
+            EncryptionOptions jmxEncryptionOptions = new EncryptionOptions();
+            String[] cipherSuitesArray = 
(String[])encryptionOptionsMap.get(EncryptionOptions.ConfigKey.CIPHER_SUITES.toString());
+            if (cipherSuitesArray != null )
+            {
+                jmxEncryptionOptions = 
jmxEncryptionOptions.withCipherSuites(cipherSuitesArray);
+            }
+            List<String> acceptedProtocols = 
(List<String>)encryptionOptionsMap.get(EncryptionOptions.ConfigKey.ACCEPTED_PROTOCOLS.toString());
+            if (acceptedProtocols != null )
+            {
+                jmxEncryptionOptions = 
jmxEncryptionOptions.withAcceptedProtocols(acceptedProtocols);
+            }
+
+            Boolean requireClientAuthValue = (Boolean) 
encryptionOptionsMap.get(EncryptionOptions.ConfigKey.REQUIRE_CLIENT_AUTH.toString());
+            EncryptionOptions.ClientAuth requireClientAuth = 
requireClientAuthValue == null ?
+                                                             
EncryptionOptions.ClientAuth.NOT_REQUIRED :
+                                                             
EncryptionOptions.ClientAuth.from(String.valueOf(requireClientAuthValue));
+            Object enabledOption = 
encryptionOptionsMap.get(EncryptionOptions.ConfigKey.ENABLED.toString());
+            boolean enabled = enabledOption != null ? 
(Boolean)encryptionOptionsMap.get(EncryptionOptions.ConfigKey.ENABLED.toString())
 : false;
+
+            //CASSANDRA-18508 NOTE- We do not populate sslContextFactory 
configuration here for tests, it could be enhanced
+            jmxEncryptionOptions = jmxEncryptionOptions
+                   
.withKeyStore((String)encryptionOptionsMap.get(EncryptionOptions.ConfigKey.KEYSTORE.toString()))
+                   
.withKeyStorePassword((String)encryptionOptionsMap.get(EncryptionOptions.ConfigKey.KEYSTORE_PASSWORD.toString()))
+                   
.withTrustStore((String)encryptionOptionsMap.get(EncryptionOptions.ConfigKey.TRUSTSTORE.toString()))
+                   
.withTrustStorePassword((String)encryptionOptionsMap.get(EncryptionOptions.ConfigKey.TRUSTSTORE_PASSWORD.toString()))
+                   .withRequireClientAuth(requireClientAuth)
+                   .withEnabled(enabled);
+            return jmxEncryptionOptions;
+        } else
+        {
+            return null;
+        }

Review Comment:
   I tend to try to invert these kinds of things, which generally allows a 
quick return on `null` and then you don't actually need the extra 
indentation/else statement:
   ```suggestion
       private EncryptionOptions getJmxEncryptionOptions(Map<String,Object> 
encryptionOptionsMap)
       {
           if (encryptionOptionsMap == null)
           {
               return null;
           }
           EncryptionOptions jmxEncryptionOptions = new EncryptionOptions();
           String[] cipherSuitesArray = 
(String[])encryptionOptionsMap.get(EncryptionOptions.ConfigKey.CIPHER_SUITES.toString());
           if (cipherSuitesArray != null )
           {
               jmxEncryptionOptions = 
jmxEncryptionOptions.withCipherSuites(cipherSuitesArray);
           }
           List<String> acceptedProtocols = 
(List<String>)encryptionOptionsMap.get(EncryptionOptions.ConfigKey.ACCEPTED_PROTOCOLS.toString());
           if (acceptedProtocols != null )
           {
               jmxEncryptionOptions = 
jmxEncryptionOptions.withAcceptedProtocols(acceptedProtocols);
           }
   
           Boolean requireClientAuthValue = (Boolean) 
encryptionOptionsMap.get(EncryptionOptions.ConfigKey.REQUIRE_CLIENT_AUTH.toString());
           EncryptionOptions.ClientAuth requireClientAuth = 
requireClientAuthValue == null ?
                                                            
EncryptionOptions.ClientAuth.NOT_REQUIRED :
                                                            
EncryptionOptions.ClientAuth.from(String.valueOf(requireClientAuthValue));
           Object enabledOption = 
encryptionOptionsMap.get(EncryptionOptions.ConfigKey.ENABLED.toString());
           boolean enabled = enabledOption != null ? 
(Boolean)encryptionOptionsMap.get(EncryptionOptions.ConfigKey.ENABLED.toString())
 : false;
   
           //CASSANDRA-18508 NOTE- We do not populate sslContextFactory 
configuration here for tests, it could be enhanced
           jmxEncryptionOptions = jmxEncryptionOptions
                  
.withKeyStore((String)encryptionOptionsMap.get(EncryptionOptions.ConfigKey.KEYSTORE.toString()))
                  
.withKeyStorePassword((String)encryptionOptionsMap.get(EncryptionOptions.ConfigKey.KEYSTORE_PASSWORD.toString()))
                  
.withTrustStore((String)encryptionOptionsMap.get(EncryptionOptions.ConfigKey.TRUSTSTORE.toString()))
                  
.withTrustStorePassword((String)encryptionOptionsMap.get(EncryptionOptions.ConfigKey.TRUSTSTORE_PASSWORD.toString()))
                  .withRequireClientAuth(requireClientAuth)
                  .withEnabled(enabled);
           return jmxEncryptionOptions;
       }
   ```



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to