You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cassandra.apache.org by sm...@apache.org on 2025/04/23 10:53:40 UTC

(cassandra) 01/02: Refactor EncryptionOptions to use client / server encryption options builders

This is an automated email from the ASF dual-hosted git repository.

smiklosovic pushed a commit to branch trunk
in repository https://gitbox.apache.org/repos/asf/cassandra.git

commit bcea8f5815dbea3b1b4c6cba7bc0fdd97ed5bdc0
Author: maulin-vasavada <ma...@gmail.com>
AuthorDate: Fri Mar 7 16:02:00 2025 -0800

    Refactor EncryptionOptions to use client / server encryption options builders
    
    patch by Maulin Vasavada; reviewed by Maxwell Guo, Stefan Miklosovic for CASSANDRA-20404
---
 .../cassandra/auth/MutualTlsAuthenticator.java     |   2 +-
 .../auth/MutualTlsInternodeAuthenticator.java      |   2 +-
 ...MutualTlsWithPasswordFallbackAuthenticator.java |   2 +-
 src/java/org/apache/cassandra/config/Config.java   |   2 +-
 .../cassandra/config/DatabaseDescriptor.java       |  14 +-
 .../apache/cassandra/config/EncryptionOptions.java | 902 +++++++++------------
 .../apache/cassandra/config/JMXServerOptions.java  |  11 +-
 .../cassandra/net/InboundConnectionInitiator.java  |   4 +-
 .../cassandra/net/InboundConnectionSettings.java   |   2 +-
 .../cassandra/net/OutboundConnectionInitiator.java |   8 +-
 .../security/AbstractSslContextFactory.java        |  14 +-
 .../cassandra/security/ISslContextFactory.java     |   4 +-
 .../org/apache/cassandra/security/SSLFactory.java  |  12 +-
 .../org/apache/cassandra/tools/BulkLoader.java     |   2 +-
 .../org/apache/cassandra/tools/LoaderOptions.java  |  39 +-
 .../org/apache/cassandra/transport/Client.java     |   6 +-
 .../apache/cassandra/transport/SimpleClient.java   |  18 +-
 .../utils/jmx/AbstractJmxSocketFactory.java        |   2 +-
 .../cassandra/transport/SimpleClientBurnTest.java  |   4 +-
 .../cassandra/transport/SimpleClientPerfTest.java  |   8 +-
 .../cassandra/distributed/impl/IsolatedJmx.java    |  32 +-
 .../test/AbstractEncryptionOptionsImpl.java        |  15 +-
 .../org/apache/cassandra/auth/AuthConfigTest.java  |   7 +-
 .../cassandra/auth/MutualTlsAuthenticatorTest.java |  14 +-
 .../auth/MutualTlsInternodeAuthenticatorTest.java  |  13 +-
 ...alTlsWithPasswordFallbackAuthenticatorTest.java |   6 +-
 .../auth/jmx/JMXAuthJMXServerOptionsTest.java      |   2 +-
 .../config/EncryptionOptionsEqualityTest.java      | 114 +--
 .../cassandra/config/EncryptionOptionsTest.java    | 124 +--
 test/unit/org/apache/cassandra/cql3/CQLTester.java |  18 +-
 .../cassandra/db/virtual/SettingsTableTest.java    |  30 +-
 .../org/apache/cassandra/net/ConnectionTest.java   |  10 +-
 .../org/apache/cassandra/net/HandshakeTest.java    |  35 +-
 .../apache/cassandra/net/MessagingServiceTest.java |  51 +-
 .../security/DefaultSslContextFactoryTest.java     |  47 +-
 .../security/DummySslContextFactoryImpl.java       |   4 +-
 .../security/FileBasedSslContextFactoryTest.java   |  48 +-
 .../security/PEMBasedSslContextFactoryTest.java    |  36 +-
 .../apache/cassandra/security/SSLFactoryTest.java  | 189 +++--
 .../cassandra/service/ClientWarningsTest.java      |   6 +-
 .../service/NativeTransportServiceTest.java        |  18 +-
 .../cassandra/service/ProtocolBetaVersionTest.java |   4 +-
 .../apache/cassandra/tools/LoaderOptionsTest.java  |  30 +
 .../transport/EarlyAuthenticationTest.java         |  23 +-
 .../cassandra/transport/MessagePayloadTest.java    |   2 +-
 .../transport/SimpleClientSslContextFactory.java   |   8 +-
 .../apache/cassandra/transport/TlsTestUtils.java   |  13 +-
 .../stress/settings/SettingsTransport.java         |  31 +-
 .../cassandra/stress/settings/StressSettings.java  |   2 +-
 .../cassandra/stress/util/JavaDriverClient.java    |  12 +-
 50 files changed, 993 insertions(+), 1009 deletions(-)

diff --git a/src/java/org/apache/cassandra/auth/MutualTlsAuthenticator.java b/src/java/org/apache/cassandra/auth/MutualTlsAuthenticator.java
index 0337291a9d..7c5a6654f7 100644
--- a/src/java/org/apache/cassandra/auth/MutualTlsAuthenticator.java
+++ b/src/java/org/apache/cassandra/auth/MutualTlsAuthenticator.java
@@ -44,7 +44,7 @@ import org.apache.cassandra.schema.SchemaConstants;
 import org.apache.cassandra.utils.NoSpamLogger;
 
 import static org.apache.cassandra.auth.IAuthenticator.AuthenticationMode.MTLS;
-import static org.apache.cassandra.config.EncryptionOptions.ClientAuth.REQUIRED;
+import static org.apache.cassandra.config.EncryptionOptions.ClientEncryptionOptions.ClientAuth.REQUIRED;
 
 /**
  * Performs mTLS authentication for client connections by extracting identities from client certificate
diff --git a/src/java/org/apache/cassandra/auth/MutualTlsInternodeAuthenticator.java b/src/java/org/apache/cassandra/auth/MutualTlsInternodeAuthenticator.java
index c1fcbd6eab..91500cbeb2 100644
--- a/src/java/org/apache/cassandra/auth/MutualTlsInternodeAuthenticator.java
+++ b/src/java/org/apache/cassandra/auth/MutualTlsInternodeAuthenticator.java
@@ -49,7 +49,7 @@ import org.apache.cassandra.exceptions.ConfigurationException;
 import org.apache.cassandra.metrics.MutualTlsMetrics;
 import org.apache.cassandra.utils.NoSpamLogger;
 
-import static org.apache.cassandra.config.EncryptionOptions.ClientAuth.REQUIRED;
+import static org.apache.cassandra.config.EncryptionOptions.ClientEncryptionOptions.ClientAuth.REQUIRED;
 
 /**
  * Performs mTLS authentication for internode connections by extracting identities from the certificates of incoming
diff --git a/src/java/org/apache/cassandra/auth/MutualTlsWithPasswordFallbackAuthenticator.java b/src/java/org/apache/cassandra/auth/MutualTlsWithPasswordFallbackAuthenticator.java
index 219353d76a..f994399f21 100644
--- a/src/java/org/apache/cassandra/auth/MutualTlsWithPasswordFallbackAuthenticator.java
+++ b/src/java/org/apache/cassandra/auth/MutualTlsWithPasswordFallbackAuthenticator.java
@@ -81,7 +81,7 @@ public class MutualTlsWithPasswordFallbackAuthenticator extends PasswordAuthenti
     public void validateConfiguration() throws ConfigurationException
     {
         Config config = DatabaseDescriptor.getRawConfig();
-        if (config.client_encryption_options.getClientAuth() == EncryptionOptions.ClientAuth.NOT_REQUIRED)
+        if (config.client_encryption_options.getClientAuth() == EncryptionOptions.ClientEncryptionOptions.ClientAuth.NOT_REQUIRED)
         {
             String msg = "MutualTlsWithPasswordFallbackAuthenticator requires client_encryption_options.require_client_auth to be optional/true";
             throw new ConfigurationException(msg);
diff --git a/src/java/org/apache/cassandra/config/Config.java b/src/java/org/apache/cassandra/config/Config.java
index 65179fcd7e..1a3da1033f 100644
--- a/src/java/org/apache/cassandra/config/Config.java
+++ b/src/java/org/apache/cassandra/config/Config.java
@@ -454,7 +454,7 @@ public class Config
     public String failure_detector = "FailureDetector";
 
     public EncryptionOptions.ServerEncryptionOptions server_encryption_options = new EncryptionOptions.ServerEncryptionOptions();
-    public EncryptionOptions client_encryption_options = new EncryptionOptions();
+    public EncryptionOptions.ClientEncryptionOptions client_encryption_options = new EncryptionOptions.ClientEncryptionOptions();
 
     public JMXServerOptions jmx_server_options;
 
diff --git a/src/java/org/apache/cassandra/config/DatabaseDescriptor.java b/src/java/org/apache/cassandra/config/DatabaseDescriptor.java
index 0439dbb00c..6167352897 100644
--- a/src/java/org/apache/cassandra/config/DatabaseDescriptor.java
+++ b/src/java/org/apache/cassandra/config/DatabaseDescriptor.java
@@ -156,7 +156,7 @@ import static org.apache.cassandra.config.CassandraRelevantProperties.UNSAFE_SYS
 import static org.apache.cassandra.config.DataRateSpec.DataRateUnit.BYTES_PER_SECOND;
 import static org.apache.cassandra.config.DataRateSpec.DataRateUnit.MEBIBYTES_PER_SECOND;
 import static org.apache.cassandra.config.DataStorageSpec.DataStorageUnit.MEBIBYTES;
-import static org.apache.cassandra.config.EncryptionOptions.ClientAuth.REQUIRED;
+import static org.apache.cassandra.config.EncryptionOptions.ClientEncryptionOptions.ClientAuth.REQUIRED;
 import static org.apache.cassandra.db.ConsistencyLevel.ALL;
 import static org.apache.cassandra.db.ConsistencyLevel.EACH_QUORUM;
 import static org.apache.cassandra.db.ConsistencyLevel.LOCAL_QUORUM;
@@ -1088,10 +1088,10 @@ public class DatabaseDescriptor
         }
         else if (JMXServerOptions.isEnabledBySystemProperties())
         {
-            throw new ConfigurationException("Configure either jmx_server_options in cassandra.yaml and comment out " +
-                                             "configure_jmx function call in cassandra-env.sh or keep cassandra-env.sh " +
-                                             "to call configure_jmx function but you have to keep jmx_server_options " +
-                                             "in cassandra.yaml commented out.");
+                throw new ConfigurationException("Configure either jmx_server_options in cassandra.yaml and comment out " +
+                                                 "configure_jmx function call in cassandra-env.sh or keep cassandra-env.sh " +
+                                                 "to call configure_jmx function but you have to keep jmx_server_options " +
+                                                 "in cassandra.yaml commented out.");
         }
 
         conf.jmx_server_options.jmx_encryption_options.applyConfig();
@@ -3973,7 +3973,7 @@ public class DatabaseDescriptor
         conf.server_encryption_options = encryptionOptions;
     }
 
-    public static EncryptionOptions getNativeProtocolEncryptionOptions()
+    public static EncryptionOptions.ClientEncryptionOptions getNativeProtocolEncryptionOptions()
     {
         return conf.client_encryption_options;
     }
@@ -3984,7 +3984,7 @@ public class DatabaseDescriptor
     }
 
     @VisibleForTesting
-    public static void updateNativeProtocolEncryptionOptions(Function<EncryptionOptions, EncryptionOptions> update)
+    public static void updateNativeProtocolEncryptionOptions(Function<EncryptionOptions.ClientEncryptionOptions, EncryptionOptions.ClientEncryptionOptions> update)
     {
         conf.client_encryption_options = update.apply(conf.client_encryption_options);
     }
diff --git a/src/java/org/apache/cassandra/config/EncryptionOptions.java b/src/java/org/apache/cassandra/config/EncryptionOptions.java
index 07f78b9a5e..5f94c14bcb 100644
--- a/src/java/org/apache/cassandra/config/EncryptionOptions.java
+++ b/src/java/org/apache/cassandra/config/EncryptionOptions.java
@@ -17,7 +17,6 @@
  */
 package org.apache.cassandra.config;
 
-import java.util.Arrays;
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.List;
@@ -46,10 +45,8 @@ import static org.apache.cassandra.utils.LocalizeString.toLowerCaseLocalized;
  * Examples of such options are: supported cipher-suites, ssl protocol with version, accepted protocols, end-point
  * verification, require client-auth/cert etc.
  */
-public class EncryptionOptions
+public abstract class EncryptionOptions<T extends EncryptionOptions<T>>
 {
-    Logger logger = LoggerFactory.getLogger(EncryptionOptions.class);
-
     public enum TlsEncryptionPolicy
     {
         UNENCRYPTED("unencrypted"),
@@ -69,39 +66,50 @@ public class EncryptionOptions
         }
     }
 
-    public enum ClientAuth
+    public enum ConfigKey
     {
-        REQUIRED("true"),
-        NOT_REQUIRED("false"),
-        OPTIONAL("optional");
-        private final String value;
-        private static final Map<String, ClientAuth> VALUES = new HashMap<>();
-        static
+        KEYSTORE("keystore"),
+        KEYSTORE_PASSWORD("keystore_password"),
+        KEYSTORE_PASSWORD_FILE("keystore_password_file"),
+        OUTBOUND_KEYSTORE("outbound_keystore"),
+        OUTBOUND_KEYSTORE_PASSWORD("outbound_keystore_password"),
+        OUTBOUND_KEYSTORE_PASSWORD_FILE("outbound_keystore_password_file"),
+        TRUSTSTORE("truststore"),
+        TRUSTSTORE_PASSWORD("truststore_password"),
+        TRUSTSTORE_PASSWORD_FILE("truststore_password_file"),
+        CIPHER_SUITES("cipher_suites"),
+        PROTOCOL("protocol"),
+        ACCEPTED_PROTOCOLS("accepted_protocols"),
+        ALGORITHM("algorithm"),
+        STORE_TYPE("store_type"),
+        REQUIRE_CLIENT_AUTH("require_client_auth"),
+        REQUIRE_ENDPOINT_VERIFICATION("require_endpoint_verification"),
+        ENABLED("enabled"),
+        OPTIONAL("optional"),
+        MAX_CERTIFICATE_VALIDITY_PERIOD("max_certificate_validity_period"),
+        CERTIFICATE_VALIDITY_WARN_THRESHOLD("certificate_validity_warn_threshold");
+
+        final String keyName;
+
+        ConfigKey(String keyName)
         {
-            for (ClientAuth clientAuth : ClientAuth.values())
-            {
-                VALUES.put(clientAuth.value, clientAuth);
-                VALUES.put(toLowerCaseLocalized(clientAuth.name()), clientAuth);
-            }
+            this.keyName = keyName;
         }
 
-        ClientAuth(String value)
+        public String toString()
         {
-            this.value = value;
+            return keyName;
         }
 
-        public static ClientAuth from(String value)
+        static Set<String> asSet()
         {
-            if (VALUES.containsKey(toLowerCaseLocalized(value)))
+            Set<String> valueSet = new HashSet<>();
+            ConfigKey[] values = values();
+            for (ConfigKey key : values)
             {
-                return VALUES.get(toLowerCaseLocalized(value));
+                valueSet.add(toLowerCaseLocalized(key.toString()));
             }
-            throw new ConfigurationException(value + " is not a valid ClientAuth option");
-        }
-
-        public String value()
-        {
-            return value;
+            return valueSet;
         }
     }
 
@@ -153,53 +161,6 @@ public class EncryptionOptions
      */
     public transient ISslContextFactory sslContextFactoryInstance;
 
-    public enum ConfigKey
-    {
-        KEYSTORE("keystore"),
-        KEYSTORE_PASSWORD("keystore_password"),
-        KEYSTORE_PASSWORD_FILE("keystore_password_file"),
-        OUTBOUND_KEYSTORE("outbound_keystore"),
-        OUTBOUND_KEYSTORE_PASSWORD("outbound_keystore_password"),
-        OUTBOUND_KEYSTORE_PASSWORD_FILE("outbound_keystore_password_file"),
-        TRUSTSTORE("truststore"),
-        TRUSTSTORE_PASSWORD("truststore_password"),
-        TRUSTSTORE_PASSWORD_FILE("truststore_password_file"),
-        CIPHER_SUITES("cipher_suites"),
-        PROTOCOL("protocol"),
-        ACCEPTED_PROTOCOLS("accepted_protocols"),
-        ALGORITHM("algorithm"),
-        STORE_TYPE("store_type"),
-        REQUIRE_CLIENT_AUTH("require_client_auth"),
-        REQUIRE_ENDPOINT_VERIFICATION("require_endpoint_verification"),
-        ENABLED("enabled"),
-        OPTIONAL("optional"),
-        MAX_CERTIFICATE_VALIDITY_PERIOD("max_certificate_validity_period"),
-        CERTIFICATE_VALIDITY_WARN_THRESHOLD("certificate_validity_warn_threshold");
-
-        final String keyName;
-
-        ConfigKey(String keyName)
-        {
-            this.keyName = keyName;
-        }
-
-        public String toString()
-        {
-            return keyName;
-        }
-
-        static Set<String> asSet()
-        {
-            Set<String> valueSet = new HashSet<>();
-            ConfigKey[] values = values();
-            for (ConfigKey key : values)
-            {
-                valueSet.add(toLowerCaseLocalized(key.toString()));
-            }
-            return valueSet;
-        }
-    }
-
     public EncryptionOptions()
     {
         ssl_context_factory = new ParameterizedClass("org.apache.cassandra.security.DefaultSslContextFactory",
@@ -252,7 +213,7 @@ public class EncryptionOptions
         this.certificate_validity_warn_threshold = certificate_validity_warn_threshold;
     }
 
-    public EncryptionOptions(EncryptionOptions options)
+    public EncryptionOptions(EncryptionOptions<T> options)
     {
         ssl_context_factory = options.ssl_context_factory;
         keystore = options.keystore;
@@ -280,7 +241,7 @@ public class EncryptionOptions
      *
      * It also initializes the ISslContextFactory's instance
      */
-    public EncryptionOptions applyConfig()
+    public T applyConfig()
     {
         ensureConfigNotApplied();
 
@@ -304,7 +265,7 @@ public class EncryptionOptions
             // Otherwise if there's no keystore, not possible to establish an optional secure connection
             isOptional = false;
         }
-        return this;
+        return (T) this;
     }
 
     /**
@@ -312,22 +273,22 @@ public class EncryptionOptions
      * as the constructor for its implementation.
      *
      * @throws IllegalArgumentException in case any pre-defined key, as per {@link ConfigKey}, for the encryption
-     * options is duplicated in the parameterized keys.
+     *                                  options is duplicated in the parameterized keys.
      */
-    private void prepareSslContextFactoryParameterizedKeys(Map<String,Object> sslContextFactoryParameters)
+    private void prepareSslContextFactoryParameterizedKeys(Map<String, Object> sslContextFactoryParameters)
     {
         if (ssl_context_factory.parameters != null)
         {
             Set<String> configKeys = ConfigKey.asSet();
             for (Map.Entry<String, String> entry : ssl_context_factory.parameters.entrySet())
             {
-                if(configKeys.contains(toLowerCaseLocalized(entry.getKey())))
+                if (configKeys.contains(toLowerCaseLocalized(entry.getKey())))
                 {
-                    throw new IllegalArgumentException("SslContextFactory "+ssl_context_factory.class_name+" should " +
-                                                       "configure '"+entry.getKey()+"' as encryption_options instead of" +
+                    throw new IllegalArgumentException("SslContextFactory " + ssl_context_factory.class_name + " should " +
+                                                       "configure '" + entry.getKey() + "' as encryption_options instead of" +
                                                        " parameterized keys");
                 }
-                sslContextFactoryParameters.put(entry.getKey(),entry.getValue());
+                sslContextFactoryParameters.put(entry.getKey(), entry.getValue());
             }
         }
     }
@@ -375,7 +336,8 @@ public class EncryptionOptions
 
     protected static void putSslContextFactoryParameter(Map<String, Object> existingParameters, ConfigKey configKey, Object value)
     {
-        if (value != null) {
+        if (value != null)
+        {
             existingParameters.put(configKey.toString(), value);
         }
     }
@@ -480,9 +442,9 @@ public class EncryptionOptions
         return sslContextFactoryInstance == null ? null : sslContextFactoryInstance.getAcceptedProtocols();
     }
 
-    public ClientAuth getClientAuth()
+    public ClientEncryptionOptions.ClientAuth getClientAuth()
     {
-        return this.require_client_auth == null ? ClientAuth.NOT_REQUIRED : ClientAuth.from(this.require_client_auth);
+        return this.require_client_auth == null ? ClientEncryptionOptions.ClientAuth.NOT_REQUIRED : ClientEncryptionOptions.ClientAuth.from(this.require_client_auth);
     }
 
     public String[] acceptedProtocolsArray()
@@ -517,162 +479,6 @@ public class EncryptionOptions
         }
     }
 
-    public EncryptionOptions withSslContextFactory(ParameterizedClass sslContextFactoryClass)
-    {
-        return new EncryptionOptions(sslContextFactoryClass, keystore, keystore_password, keystore_password_file, truststore,
-                                     truststore_password, truststore_password_file, cipher_suites, protocol, accepted_protocols, algorithm,
-                                     store_type, require_client_auth, require_endpoint_verification, enabled,
-                                     optional, max_certificate_validity_period, max_certificate_validity_period).applyConfig();
-    }
-
-    public EncryptionOptions withKeyStore(String keystore)
-    {
-        return new EncryptionOptions(ssl_context_factory, keystore, keystore_password, keystore_password_file, truststore,
-                                     truststore_password, truststore_password_file, cipher_suites, protocol, accepted_protocols, algorithm,
-                                     store_type, require_client_auth, require_endpoint_verification, enabled,
-                                     optional, max_certificate_validity_period, max_certificate_validity_period).applyConfig();
-    }
-
-    public EncryptionOptions withKeyStorePassword(String keystore_password)
-    {
-        return new EncryptionOptions(ssl_context_factory, keystore, keystore_password, keystore_password_file, truststore,
-                                     truststore_password, truststore_password_file, cipher_suites, protocol, accepted_protocols, algorithm,
-                                     store_type, require_client_auth, require_endpoint_verification, enabled,
-                                     optional, max_certificate_validity_period, max_certificate_validity_period).applyConfig();
-    }
-
-    public EncryptionOptions withKeyStorePasswordFile(String keystore_password_file)
-    {
-        return new EncryptionOptions(ssl_context_factory, keystore, keystore_password, keystore_password_file, truststore,
-                                     truststore_password, truststore_password_file, cipher_suites, protocol, accepted_protocols, algorithm,
-                                     store_type, require_client_auth, require_endpoint_verification, enabled,
-                                     optional, max_certificate_validity_period, max_certificate_validity_period).applyConfig();
-    }
-
-    public EncryptionOptions withTrustStore(String truststore)
-    {
-        return new EncryptionOptions(ssl_context_factory, keystore, keystore_password, keystore_password_file, truststore,
-                                     truststore_password, truststore_password_file, cipher_suites, protocol, accepted_protocols, algorithm,
-                                     store_type, require_client_auth, require_endpoint_verification, enabled,
-                                     optional, max_certificate_validity_period, max_certificate_validity_period).applyConfig();
-    }
-
-    public EncryptionOptions withTrustStorePassword(String truststore_password)
-    {
-        return new EncryptionOptions(ssl_context_factory, keystore, keystore_password, keystore_password_file, truststore,
-                                     truststore_password, truststore_password_file, cipher_suites, protocol, accepted_protocols, algorithm,
-                                     store_type, require_client_auth, require_endpoint_verification, enabled,
-                                     optional, max_certificate_validity_period, max_certificate_validity_period).applyConfig();
-    }
-
-    public EncryptionOptions withTrustStorePasswordFile(String truststore_password_file)
-    {
-        return new EncryptionOptions(ssl_context_factory, keystore, keystore_password, keystore_password_file, truststore,
-                                     truststore_password, truststore_password_file, cipher_suites, protocol, accepted_protocols, algorithm,
-                                     store_type, require_client_auth, require_endpoint_verification, enabled,
-                                     optional, max_certificate_validity_period, max_certificate_validity_period).applyConfig();
-    }
-
-    public EncryptionOptions withCipherSuites(List<String> cipher_suites)
-    {
-        return new EncryptionOptions(ssl_context_factory, keystore, keystore_password, keystore_password_file, truststore,
-                                     truststore_password, truststore_password_file, cipher_suites, protocol, accepted_protocols, algorithm,
-                                     store_type, require_client_auth, require_endpoint_verification, enabled,
-                                     optional, max_certificate_validity_period, max_certificate_validity_period).applyConfig();
-    }
-
-    public EncryptionOptions withCipherSuites(String... cipher_suites)
-    {
-        return new EncryptionOptions(ssl_context_factory, keystore, keystore_password, keystore_password_file, truststore,
-                                     truststore_password, truststore_password_file, ImmutableList.copyOf(cipher_suites), protocol,
-                                     accepted_protocols, algorithm, store_type, require_client_auth,
-                                     require_endpoint_verification, enabled, optional, max_certificate_validity_period,
-                                     max_certificate_validity_period).applyConfig();
-    }
-
-    public EncryptionOptions withProtocol(String protocol)
-    {
-        return new EncryptionOptions(ssl_context_factory, keystore, keystore_password, keystore_password_file, truststore,
-                                     truststore_password, truststore_password_file, cipher_suites, protocol, accepted_protocols, algorithm,
-                                     store_type, require_client_auth, require_endpoint_verification, enabled,
-                                     optional, max_certificate_validity_period, max_certificate_validity_period).applyConfig();
-    }
-
-
-    public EncryptionOptions withAcceptedProtocols(List<String> accepted_protocols)
-    {
-        return new EncryptionOptions(ssl_context_factory, keystore, keystore_password, keystore_password_file, truststore,
-                                     truststore_password, truststore_password_file, cipher_suites, protocol, accepted_protocols == null ? null :
-                                                                                   ImmutableList.copyOf(accepted_protocols),
-                                     algorithm, store_type, require_client_auth, require_endpoint_verification,
-                                     enabled, optional, max_certificate_validity_period, max_certificate_validity_period).applyConfig();
-    }
-
-
-    public EncryptionOptions withAlgorithm(String algorithm)
-    {
-        return new EncryptionOptions(ssl_context_factory, keystore, keystore_password, keystore_password_file, truststore,
-                                     truststore_password, truststore_password_file, cipher_suites, protocol, accepted_protocols, algorithm,
-                                     store_type, require_client_auth, require_endpoint_verification, enabled,
-                                     optional, max_certificate_validity_period, max_certificate_validity_period).applyConfig();
-    }
-
-    public EncryptionOptions withStoreType(String store_type)
-    {
-        return new EncryptionOptions(ssl_context_factory, keystore, keystore_password, keystore_password_file, truststore,
-                                     truststore_password, truststore_password_file, cipher_suites, protocol, accepted_protocols, algorithm,
-                                     store_type, require_client_auth, require_endpoint_verification, enabled,
-                                     optional, max_certificate_validity_period, max_certificate_validity_period).applyConfig();
-    }
-
-    public EncryptionOptions withRequireClientAuth(ClientAuth require_client_auth)
-    {
-        return new EncryptionOptions(ssl_context_factory, keystore, keystore_password, keystore_password_file, truststore,
-                                     truststore_password, truststore_password_file, cipher_suites, protocol, accepted_protocols, algorithm,
-                                     store_type, require_client_auth.value, require_endpoint_verification, enabled,
-                                     optional, max_certificate_validity_period, max_certificate_validity_period).applyConfig();
-    }
-
-    public EncryptionOptions withRequireEndpointVerification(boolean require_endpoint_verification)
-    {
-        return new EncryptionOptions(ssl_context_factory, keystore, keystore_password, keystore_password_file, truststore,
-                                     truststore_password, truststore_password_file, cipher_suites, protocol, accepted_protocols, algorithm,
-                                     store_type, require_client_auth, require_endpoint_verification, enabled,
-                                     optional, max_certificate_validity_period, max_certificate_validity_period).applyConfig();
-    }
-
-    public EncryptionOptions withEnabled(boolean enabled)
-    {
-        return new EncryptionOptions(ssl_context_factory, keystore, keystore_password, keystore_password_file, truststore,
-                                     truststore_password, truststore_password_file, cipher_suites, protocol, accepted_protocols, algorithm,
-                                     store_type, require_client_auth, require_endpoint_verification, enabled,
-                                     optional, max_certificate_validity_period, max_certificate_validity_period).applyConfig();
-    }
-
-    public EncryptionOptions withOptional(Boolean optional)
-    {
-        return new EncryptionOptions(ssl_context_factory, keystore, keystore_password, keystore_password_file, truststore,
-                                     truststore_password, truststore_password_file, cipher_suites, protocol, accepted_protocols, algorithm,
-                                     store_type, require_client_auth, require_endpoint_verification, enabled,
-                                     optional, max_certificate_validity_period, max_certificate_validity_period).applyConfig();
-    }
-
-    public EncryptionOptions withMaxCertificateValidityPeriod(DurationSpec.IntMinutesBound maxCertificateValidityPeriod)
-    {
-        return new EncryptionOptions(ssl_context_factory, keystore, keystore_password, keystore_password_file, truststore,
-                                     truststore_password, truststore_password_file, cipher_suites, protocol, accepted_protocols, algorithm,
-                                     store_type, require_client_auth, require_endpoint_verification, enabled,
-                                     optional, maxCertificateValidityPeriod, certificate_validity_warn_threshold).applyConfig();
-    }
-
-    public EncryptionOptions withCertificateValidityWarnThreshold(DurationSpec.IntMinutesBound certificateValidityWarnThreshold)
-    {
-        return new EncryptionOptions(ssl_context_factory, keystore, keystore_password, keystore_password_file, truststore,
-                                     truststore_password, truststore_password_file, cipher_suites, protocol, accepted_protocols, algorithm,
-                                     store_type, require_client_auth, require_endpoint_verification, enabled,
-                                     optional, max_certificate_validity_period, certificateValidityWarnThreshold).applyConfig();
-    }
-
     /**
      * The method is being mainly used to cache SslContexts therefore, we only consider
      * fields that would make a difference when the TrustStore or KeyStore files are updated
@@ -685,7 +491,7 @@ public class EncryptionOptions
         if (o == null || getClass() != o.getClass())
             return false;
 
-        EncryptionOptions opt = (EncryptionOptions)o;
+        EncryptionOptions opt = (EncryptionOptions) o;
         return enabled == opt.enabled &&
                optional == opt.optional &&
                require_client_auth.equals(opt.require_client_auth) &&
@@ -731,8 +537,258 @@ public class EncryptionOptions
         return result;
     }
 
-    public static class ServerEncryptionOptions extends EncryptionOptions
+    public static abstract class Builder<T extends EncryptionOptions<T>>
     {
+        ParameterizedClass ssl_context_factory;
+        String keystore;
+        String keystore_password;
+        String keystore_password_file;
+        String truststore;
+        String truststore_password;
+        String truststore_password_file;
+        List<String> cipher_suites;
+        String protocol;
+        List<String> accepted_protocols;
+        String algorithm;
+        String store_type;
+        String require_client_auth;
+        boolean require_endpoint_verification;
+        DurationSpec.IntMinutesBound max_certificate_validity_period;
+        DurationSpec.IntMinutesBound certificate_validity_warn_threshold;
+        Boolean enabled;
+        Boolean optional;
+        Boolean isEnabled;
+        Boolean isOptional;
+
+        public Builder(EncryptionOptions<T> options)
+        {
+            ssl_context_factory = options.ssl_context_factory;
+            keystore = options.keystore;
+            keystore_password = options.keystore_password;
+            keystore_password_file = options.keystore_password_file;
+            truststore = options.truststore;
+            truststore_password = options.truststore_password;
+            truststore_password_file = options.truststore_password_file;
+            cipher_suites = options.cipher_suites;
+            protocol = options.protocol;
+            accepted_protocols = options.accepted_protocols;
+            algorithm = options.algorithm;
+            store_type = options.store_type;
+            require_client_auth = options.require_client_auth;
+            require_endpoint_verification = options.require_endpoint_verification;
+            enabled = options.enabled;
+            optional = options.optional;
+            max_certificate_validity_period = options.max_certificate_validity_period;
+            certificate_validity_warn_threshold = options.certificate_validity_warn_threshold;
+        }
+
+        public Builder<T> withSslContextFactory(ParameterizedClass sslContextFactoryClass)
+        {
+            this.ssl_context_factory = sslContextFactoryClass;
+            return this;
+        }
+
+        public Builder<T> withKeyStore(String keystore)
+        {
+            this.keystore = keystore;
+            return this;
+        }
+
+        public Builder<T> withKeyStorePassword(String keystore_password)
+        {
+            this.keystore_password = keystore_password;
+            return this;
+        }
+
+        public Builder<T> withKeyStorePasswordFile(String keystore_password_file)
+        {
+            this.keystore_password_file = keystore_password_file;
+            return this;
+        }
+
+        public Builder<T> withTrustStore(String truststore)
+        {
+            this.truststore = truststore;
+            return this;
+        }
+
+        public Builder<T> withTrustStorePassword(String truststore_password)
+        {
+            this.truststore_password = truststore_password;
+            return this;
+        }
+
+        public Builder<T> withTrustStorePasswordFile(String truststore_password_file)
+        {
+            this.truststore_password_file = truststore_password_file;
+            return this;
+        }
+
+        public Builder<T> withCipherSuites(List<String> cipher_suites)
+        {
+            this.cipher_suites = cipher_suites;
+            return this;
+        }
+
+        public Builder<T> withCipherSuites(String... cipher_suites)
+        {
+            this.cipher_suites = ImmutableList.copyOf(cipher_suites);
+            return this;
+        }
+
+        public Builder<T> withProtocol(String protocol)
+        {
+            this.protocol = protocol;
+            return this;
+        }
+
+        public Builder<T> withAcceptedProtocols(List<String> accepted_protocols)
+        {
+            this.accepted_protocols = accepted_protocols == null ? null :
+                                      ImmutableList.copyOf(accepted_protocols);
+            return this;
+        }
+
+        public Builder<T> withAlgorithm(String algorithm)
+        {
+            this.algorithm = algorithm;
+            return this;
+        }
+
+        public Builder<T> withStoreType(String store_type)
+        {
+            this.store_type = store_type;
+            return this;
+        }
+
+        public Builder<T> withRequireClientAuth(ClientEncryptionOptions.ClientAuth require_client_auth)
+        {
+            this.require_client_auth = require_client_auth.value;
+            return this;
+        }
+
+        public Builder<T> withRequireEndpointVerification(boolean require_endpoint_verification)
+        {
+            this.require_endpoint_verification = require_endpoint_verification;
+            return this;
+        }
+
+        public Builder<T> withEnabled(boolean enabled)
+        {
+            this.enabled = enabled;
+            return this;
+        }
+
+        public Builder<T> withOptional(Boolean optional)
+        {
+            this.optional = optional;
+            return this;
+        }
+
+        public Builder<T> withMaxCertificateValidityPeriod(DurationSpec.IntMinutesBound maxCertificateValidityPeriod)
+        {
+            this.max_certificate_validity_period = maxCertificateValidityPeriod;
+            return this;
+        }
+
+        public Builder<T> withCertificateValidityWarnThreshold(DurationSpec.IntMinutesBound certificateValidityWarnThreshold)
+        {
+            this.certificate_validity_warn_threshold = certificateValidityWarnThreshold;
+            return this;
+        }
+
+        public abstract T build();
+    }
+
+    public static class ClientEncryptionOptions extends EncryptionOptions<ClientEncryptionOptions>
+    {
+        public ClientEncryptionOptions()
+        {
+        }
+
+        public ClientEncryptionOptions(ParameterizedClass ssl_context_factory,
+                                       String keystore, String keystore_password, String keystore_password_file,
+                                       String truststore, String truststore_password, String truststore_password_file,
+                                       List<String> cipher_suites, String protocol, List<String> accepted_protocols,
+                                       String algorithm, String store_type, String require_client_auth,
+                                       boolean require_endpoint_verification, Boolean enabled, Boolean optional,
+                                       DurationSpec.IntMinutesBound max_certificate_validity_period,
+                                       DurationSpec.IntMinutesBound certificate_validity_warn_threshold)
+        {
+            super(ssl_context_factory, keystore, keystore_password, keystore_password_file, truststore, truststore_password,
+                  truststore_password_file, cipher_suites, protocol, accepted_protocols, algorithm, store_type, require_client_auth,
+                  require_endpoint_verification, enabled, optional, max_certificate_validity_period, certificate_validity_warn_threshold);
+        }
+
+        public ClientEncryptionOptions(ClientEncryptionOptions options)
+        {
+            super(options);
+        }
+
+        public enum ClientAuth
+        {
+            REQUIRED("true"),
+            NOT_REQUIRED("false"),
+            OPTIONAL("optional");
+            private final String value;
+            private static final Map<String, ClientAuth> VALUES = new HashMap<>();
+
+            static
+            {
+                for (ClientAuth clientAuth : ClientAuth.values())
+                {
+                    VALUES.put(clientAuth.value, clientAuth);
+                    VALUES.put(toLowerCaseLocalized(clientAuth.name()), clientAuth);
+                }
+            }
+
+            ClientAuth(String value)
+            {
+                this.value = value;
+            }
+
+            public static ClientAuth from(String value)
+            {
+                if (VALUES.containsKey(toLowerCaseLocalized(value)))
+                {
+                    return VALUES.get(toLowerCaseLocalized(value));
+                }
+                throw new ConfigurationException(value + " is not a valid ClientAuth option");
+            }
+
+            public String value()
+            {
+                return value;
+            }
+        }
+
+        public static class Builder extends EncryptionOptions.Builder<ClientEncryptionOptions>
+        {
+            public Builder()
+            {
+                this(new ClientEncryptionOptions());
+            }
+
+            public Builder(ClientEncryptionOptions options)
+            {
+                super(options);
+            }
+
+            @Override
+            public ClientEncryptionOptions build()
+            {
+                return new ClientEncryptionOptions(ssl_context_factory, keystore, keystore_password, keystore_password_file, truststore,
+                                                   truststore_password, truststore_password_file, cipher_suites, protocol, accepted_protocols, algorithm,
+                                                   store_type, require_client_auth, require_endpoint_verification, enabled,
+                                                   optional, max_certificate_validity_period, certificate_validity_warn_threshold).applyConfig();
+            }
+        }
+    }
+
+    public static class ServerEncryptionOptions extends EncryptionOptions<ServerEncryptionOptions>
+    {
+        private static final Logger logger = LoggerFactory.getLogger(ServerEncryptionOptions.class);
+
         public enum InternodeEncryption
         {
             all, none, dc, rack
@@ -788,6 +844,73 @@ public class EncryptionOptions
             this.outbound_keystore_password_file = options.outbound_keystore_password_file;
         }
 
+        public static class Builder extends EncryptionOptions.Builder<ServerEncryptionOptions>
+        {
+            private InternodeEncryption internode_encryption;
+            private boolean legacy_ssl_storage_port_enabled;
+            private String outbound_keystore;
+            private String outbound_keystore_password;
+            private String outbound_keystore_password_file;
+
+            public Builder()
+            {
+                this(new ServerEncryptionOptions());
+            }
+
+            public Builder(ServerEncryptionOptions options)
+            {
+                super(options);
+                this.internode_encryption = options.internode_encryption;
+                this.legacy_ssl_storage_port_enabled = options.legacy_ssl_storage_port_enabled;
+                this.outbound_keystore = options.outbound_keystore;
+                this.outbound_keystore_password = options.outbound_keystore_password;
+                this.outbound_keystore_password_file = options.outbound_keystore_password_file;
+            }
+
+            public Builder withInternodeEncryption(InternodeEncryption internode_encryption)
+            {
+                this.internode_encryption = internode_encryption;
+                return this;
+            }
+
+            public Builder withLegacySslStoragePort(boolean enable_legacy_ssl_storage_port)
+            {
+                this.legacy_ssl_storage_port_enabled = enable_legacy_ssl_storage_port;
+                return this;
+            }
+
+            public Builder withOutboundKeystore(String outboundKeystore)
+            {
+                this.outbound_keystore = outboundKeystore;
+                return this;
+            }
+
+            public Builder withOutboundKeystorePassword(String outboundKeystorePassword)
+            {
+                this.outbound_keystore_password = outboundKeystorePassword;
+                return this;
+            }
+
+            public Builder withOutboundKeystorePasswordFile(String outboundKeystorePasswordFile)
+            {
+                this.outbound_keystore_password_file = outboundKeystorePasswordFile;
+                return this;
+            }
+
+            @Override
+            public ServerEncryptionOptions build()
+            {
+                return new ServerEncryptionOptions(ssl_context_factory, keystore, keystore_password, keystore_password_file,
+                                                   outbound_keystore, outbound_keystore_password, outbound_keystore_password_file,
+                                                   truststore, truststore_password, truststore_password_file,
+                                                   cipher_suites, protocol, accepted_protocols,
+                                                   algorithm, store_type, require_client_auth,
+                                                   require_endpoint_verification, optional, internode_encryption,
+                                                   legacy_ssl_storage_port_enabled, max_certificate_validity_period,
+                                                   certificate_validity_warn_threshold).applyConfig();
+            }
+        }
+
         @Override
         protected void fillSslContextParams(Map<String, Object> sslContextFactoryParameters)
         {
@@ -798,7 +921,7 @@ public class EncryptionOptions
         }
 
         @Override
-        public EncryptionOptions applyConfig()
+        public ServerEncryptionOptions applyConfig()
         {
             return applyConfigInternal();
         }
@@ -814,13 +937,13 @@ public class EncryptionOptions
                 logger.warn("Setting server_encryption_options.enabled has no effect, use internode_encryption");
             }
 
-            if (getClientAuth() != ClientAuth.NOT_REQUIRED && (internode_encryption == InternodeEncryption.rack || internode_encryption == InternodeEncryption.dc))
+            if (getClientAuth() != ClientEncryptionOptions.ClientAuth.NOT_REQUIRED && (internode_encryption == InternodeEncryption.rack || internode_encryption == InternodeEncryption.dc))
             {
                 logger.warn("Setting require_client_auth is incompatible with 'rack' and 'dc' internode_encryption values."
-                          + " It is possible for an internode connection to pretend to be in the same rack/dc by spoofing"
-                          + " its broadcast address in the handshake and bypass authentication. To ensure that mutual TLS"
-                          + " authentication is not bypassed, please set internode_encryption to 'all'. Continuing with"
-                          + " insecure configuration.");
+                            + " It is possible for an internode connection to pretend to be in the same rack/dc by spoofing"
+                            + " its broadcast address in the handshake and bypass authentication. To ensure that mutual TLS"
+                            + " authentication is not bypassed, please set internode_encryption to 'all'. Continuing with"
+                            + " insecure configuration.");
             }
 
             // regardless of the optional flag, if the internode encryption is set to rack or dc
@@ -910,284 +1033,5 @@ public class EncryptionOptions
             result += 31 * (outbound_keystore_password_file == null ? 0 : outbound_keystore_password_file.hashCode());
             return result;
         }
-
-        @Override
-        public ServerEncryptionOptions withSslContextFactory(ParameterizedClass sslContextFactoryClass)
-        {
-            return new ServerEncryptionOptions(sslContextFactoryClass, keystore, keystore_password, keystore_password_file,
-                                               outbound_keystore, outbound_keystore_password, outbound_keystore_password_file,
-                                               truststore, truststore_password, truststore_password_file,
-                                               cipher_suites, protocol, accepted_protocols,
-                                               algorithm, store_type, require_client_auth,
-                                               require_endpoint_verification, optional, internode_encryption,
-                                               legacy_ssl_storage_port_enabled, max_certificate_validity_period,
-                                               max_certificate_validity_period).applyConfigInternal();
-        }
-
-        @Override
-        public ServerEncryptionOptions withKeyStore(String keystore)
-        {
-            return new ServerEncryptionOptions(ssl_context_factory, keystore, keystore_password, keystore_password_file,
-                                               outbound_keystore, outbound_keystore_password, outbound_keystore_password_file,
-                                               truststore, truststore_password, truststore_password_file,
-                                               cipher_suites, protocol, accepted_protocols,
-                                               algorithm, store_type, require_client_auth,
-                                               require_endpoint_verification, optional, internode_encryption,
-                                               legacy_ssl_storage_port_enabled, max_certificate_validity_period,
-                                               max_certificate_validity_period).applyConfigInternal();
-        }
-
-        @Override
-        public ServerEncryptionOptions withKeyStorePassword(String keystore_password)
-        {
-            return new ServerEncryptionOptions(ssl_context_factory, keystore, keystore_password, keystore_password_file,
-                                               outbound_keystore, outbound_keystore_password, outbound_keystore_password_file,
-                                               truststore, truststore_password, truststore_password_file,
-                                               cipher_suites, protocol, accepted_protocols,
-                                               algorithm, store_type, require_client_auth,
-                                               require_endpoint_verification, optional, internode_encryption,
-                                               legacy_ssl_storage_port_enabled, max_certificate_validity_period,
-                                               max_certificate_validity_period).applyConfigInternal();
-        }
-
-        @Override
-        public ServerEncryptionOptions withKeyStorePasswordFile(String keystore_password_file)
-        {
-            return new ServerEncryptionOptions(ssl_context_factory, keystore, keystore_password, keystore_password_file,
-                                               outbound_keystore, outbound_keystore_password, outbound_keystore_password_file,
-                                               truststore, truststore_password, truststore_password_file,
-                                               cipher_suites, protocol, accepted_protocols,
-                                               algorithm, store_type, require_client_auth,
-                                               require_endpoint_verification, optional, internode_encryption,
-                                               legacy_ssl_storage_port_enabled, max_certificate_validity_period,
-                                               max_certificate_validity_period).applyConfigInternal();
-        }
-
-        @Override
-        public ServerEncryptionOptions withTrustStore(String truststore)
-        {
-            return new ServerEncryptionOptions(ssl_context_factory, keystore, keystore_password, keystore_password_file,
-                                               outbound_keystore, outbound_keystore_password, outbound_keystore_password_file,
-                                               truststore, truststore_password, truststore_password_file,
-                                               cipher_suites, protocol, accepted_protocols,
-                                               algorithm, store_type, require_client_auth,
-                                               require_endpoint_verification, optional, internode_encryption,
-                                               legacy_ssl_storage_port_enabled, max_certificate_validity_period,
-                                               max_certificate_validity_period).applyConfigInternal();
-        }
-
-        @Override
-        public ServerEncryptionOptions withTrustStorePassword(String truststore_password)
-        {
-            return new ServerEncryptionOptions(ssl_context_factory, keystore, keystore_password, keystore_password_file,
-                                               outbound_keystore, outbound_keystore_password, outbound_keystore_password_file,
-                                               truststore, truststore_password, truststore_password_file,
-                                               cipher_suites, protocol, accepted_protocols,
-                                               algorithm, store_type, require_client_auth,
-                                               require_endpoint_verification, optional, internode_encryption,
-                                               legacy_ssl_storage_port_enabled, max_certificate_validity_period,
-                                               max_certificate_validity_period).applyConfigInternal();
-        }
-
-        @Override
-        public ServerEncryptionOptions withTrustStorePasswordFile(String truststore_password_file)
-        {
-            return new ServerEncryptionOptions(ssl_context_factory, keystore, keystore_password, keystore_password_file,
-                                               outbound_keystore, outbound_keystore_password, outbound_keystore_password_file,
-                                               truststore, truststore_password, truststore_password_file,
-                                               cipher_suites, protocol, accepted_protocols,
-                                               algorithm, store_type, require_client_auth,
-                                               require_endpoint_verification, optional, internode_encryption,
-                                               legacy_ssl_storage_port_enabled, max_certificate_validity_period,
-                                               max_certificate_validity_period).applyConfigInternal();
-        }
-
-        @Override
-        public ServerEncryptionOptions withCipherSuites(List<String> cipher_suites)
-        {
-            return new ServerEncryptionOptions(ssl_context_factory, keystore, keystore_password, keystore_password_file,
-                                               outbound_keystore, outbound_keystore_password, outbound_keystore_password_file,
-                                               truststore, truststore_password, truststore_password_file,
-                                               cipher_suites, protocol, accepted_protocols,
-                                               algorithm, store_type, require_client_auth,
-                                               require_endpoint_verification, optional, internode_encryption,
-                                               legacy_ssl_storage_port_enabled, max_certificate_validity_period,
-                                               max_certificate_validity_period).applyConfigInternal();
-        }
-
-        @Override
-        public ServerEncryptionOptions withCipherSuites(String... cipher_suites)
-        {
-            return new ServerEncryptionOptions(ssl_context_factory, keystore, keystore_password, keystore_password_file,
-                                               outbound_keystore, outbound_keystore_password, outbound_keystore_password_file,
-                                               truststore, truststore_password, truststore_password_file,
-                                               Arrays.asList(cipher_suites), protocol, accepted_protocols,
-                                               algorithm, store_type, require_client_auth,
-                                               require_endpoint_verification, optional, internode_encryption,
-                                               legacy_ssl_storage_port_enabled, max_certificate_validity_period,
-                                               max_certificate_validity_period).applyConfigInternal();
-        }
-
-        @Override
-        public ServerEncryptionOptions withProtocol(String protocol)
-        {
-            return new ServerEncryptionOptions(ssl_context_factory, keystore, keystore_password, keystore_password_file,
-                                               outbound_keystore, outbound_keystore_password, outbound_keystore_password_file,
-                                               truststore, truststore_password, truststore_password_file,
-                                               cipher_suites, protocol, accepted_protocols,
-                                               algorithm, store_type, require_client_auth,
-                                               require_endpoint_verification, optional, internode_encryption,
-                                               legacy_ssl_storage_port_enabled, max_certificate_validity_period,
-                                               max_certificate_validity_period).applyConfigInternal();
-        }
-
-        @Override
-        public ServerEncryptionOptions withAcceptedProtocols(List<String> accepted_protocols)
-        {
-            return new ServerEncryptionOptions(ssl_context_factory, keystore, keystore_password, keystore_password_file,
-                                               outbound_keystore, outbound_keystore_password, outbound_keystore_password_file,
-                                               truststore, truststore_password, truststore_password_file,
-                                               cipher_suites, protocol, accepted_protocols,
-                                               algorithm, store_type, require_client_auth,
-                                               require_endpoint_verification, optional, internode_encryption,
-                                               legacy_ssl_storage_port_enabled, max_certificate_validity_period,
-                                               max_certificate_validity_period).applyConfigInternal();
-        }
-
-        @Override
-        public ServerEncryptionOptions withAlgorithm(String algorithm)
-        {
-            return new ServerEncryptionOptions(ssl_context_factory, keystore, keystore_password, keystore_password_file,
-                                               outbound_keystore, outbound_keystore_password, outbound_keystore_password_file,
-                                               truststore, truststore_password, truststore_password_file,
-                                               cipher_suites, protocol, accepted_protocols,
-                                               algorithm, store_type, require_client_auth,
-                                               require_endpoint_verification, optional, internode_encryption,
-                                               legacy_ssl_storage_port_enabled, max_certificate_validity_period,
-                                               max_certificate_validity_period).applyConfigInternal();
-        }
-
-        @Override
-        public ServerEncryptionOptions withStoreType(String store_type)
-        {
-            return new ServerEncryptionOptions(ssl_context_factory, keystore, keystore_password, keystore_password_file,
-                                               outbound_keystore, outbound_keystore_password, outbound_keystore_password_file,
-                                               truststore, truststore_password, truststore_password_file,
-                                               cipher_suites, protocol, accepted_protocols,
-                                               algorithm, store_type, require_client_auth,
-                                               require_endpoint_verification, optional, internode_encryption,
-                                               legacy_ssl_storage_port_enabled, max_certificate_validity_period,
-                                               max_certificate_validity_period).applyConfigInternal();
-        }
-
-        @Override
-        public ServerEncryptionOptions withRequireClientAuth(ClientAuth require_client_auth)
-        {
-            return new ServerEncryptionOptions(ssl_context_factory, keystore, keystore_password, keystore_password_file,
-                                               outbound_keystore, outbound_keystore_password, outbound_keystore_password_file,
-                                               truststore, truststore_password, truststore_password_file,
-                                               cipher_suites, protocol, accepted_protocols,
-                                               algorithm, store_type, require_client_auth.value,
-                                               require_endpoint_verification, optional, internode_encryption,
-                                               legacy_ssl_storage_port_enabled, max_certificate_validity_period,
-                                               max_certificate_validity_period).applyConfigInternal();
-        }
-
-        @Override
-        public ServerEncryptionOptions withRequireEndpointVerification(boolean require_endpoint_verification)
-        {
-            return new ServerEncryptionOptions(ssl_context_factory, keystore, keystore_password, keystore_password_file,
-                                               outbound_keystore, outbound_keystore_password, outbound_keystore_password_file,
-                                               truststore, truststore_password, truststore_password_file,
-                                               cipher_suites, protocol, accepted_protocols,
-                                               algorithm, store_type, require_client_auth,
-                                               require_endpoint_verification, optional, internode_encryption,
-                                               legacy_ssl_storage_port_enabled, max_certificate_validity_period,
-                                               max_certificate_validity_period).applyConfigInternal();
-        }
-
-        public ServerEncryptionOptions withOptional(boolean optional)
-        {
-            return new ServerEncryptionOptions(ssl_context_factory, keystore, keystore_password, keystore_password_file,
-                                               outbound_keystore, outbound_keystore_password, outbound_keystore_password_file,
-                                               truststore, truststore_password, truststore_password_file,
-                                               cipher_suites, protocol, accepted_protocols,
-                                               algorithm, store_type, require_client_auth,
-                                               require_endpoint_verification, optional, internode_encryption,
-                                               legacy_ssl_storage_port_enabled, max_certificate_validity_period,
-                                               max_certificate_validity_period).applyConfigInternal();
-        }
-
-        public ServerEncryptionOptions withInternodeEncryption(InternodeEncryption internode_encryption)
-        {
-            return new ServerEncryptionOptions(ssl_context_factory, keystore, keystore_password, keystore_password_file,
-                                               outbound_keystore, outbound_keystore_password, outbound_keystore_password_file,
-                                               truststore, truststore_password, truststore_password_file,
-                                               cipher_suites, protocol, accepted_protocols,
-                                               algorithm, store_type, require_client_auth,
-                                               require_endpoint_verification, optional, internode_encryption,
-                                               legacy_ssl_storage_port_enabled, max_certificate_validity_period,
-                                               max_certificate_validity_period).applyConfigInternal();
-        }
-
-        public ServerEncryptionOptions withLegacySslStoragePort(boolean enable_legacy_ssl_storage_port)
-        {
-            return new ServerEncryptionOptions(ssl_context_factory, keystore, keystore_password, keystore_password_file,
-                                               outbound_keystore, outbound_keystore_password, outbound_keystore_password_file,
-                                               truststore, truststore_password, truststore_password_file,
-                                               cipher_suites, protocol, accepted_protocols,
-                                               algorithm, store_type, require_client_auth,
-                                               require_endpoint_verification, optional, internode_encryption,
-                                               enable_legacy_ssl_storage_port, max_certificate_validity_period,
-                                               max_certificate_validity_period).applyConfigInternal();
-        }
-
-        public ServerEncryptionOptions withOutboundKeystore(String outboundKeystore)
-        {
-            return new ServerEncryptionOptions(ssl_context_factory, keystore, keystore_password, keystore_password_file,
-                                               outboundKeystore, outbound_keystore_password, outbound_keystore_password_file,
-                                               truststore, truststore_password, truststore_password_file,
-                                               cipher_suites, protocol, accepted_protocols,
-                                               algorithm, store_type, require_client_auth,
-                                               require_endpoint_verification, optional, internode_encryption,
-                                               legacy_ssl_storage_port_enabled, max_certificate_validity_period,
-                                               max_certificate_validity_period).applyConfigInternal();
-        }
-
-        public ServerEncryptionOptions withOutboundKeystorePassword(String outboundKeystorePassword)
-        {
-            return new ServerEncryptionOptions(ssl_context_factory, keystore, keystore_password, keystore_password_file,
-                                               outbound_keystore, outboundKeystorePassword, outbound_keystore_password_file,
-                                               truststore, truststore_password, truststore_password_file,
-                                               cipher_suites, protocol, accepted_protocols,
-                                               algorithm, store_type, require_client_auth,
-                                               require_endpoint_verification, optional, internode_encryption,
-                                               legacy_ssl_storage_port_enabled, max_certificate_validity_period,
-                                               max_certificate_validity_period).applyConfigInternal();
-        }
-
-        public ServerEncryptionOptions withOutboundKeystorePasswordFile(String outboundKeystorePasswordFile)
-        {
-            return new ServerEncryptionOptions(ssl_context_factory, keystore, keystore_password, keystore_password_file,
-                                               outbound_keystore, outbound_keystore_password, outboundKeystorePasswordFile,
-                                               truststore, truststore_password, truststore_password_file,
-                                               cipher_suites, protocol, accepted_protocols,
-                                               algorithm, store_type, require_client_auth,
-                                               require_endpoint_verification, optional, internode_encryption,
-                                               legacy_ssl_storage_port_enabled, max_certificate_validity_period,
-                                               max_certificate_validity_period).applyConfigInternal();
-        }
-        @Override
-        public ServerEncryptionOptions withMaxCertificateValidityPeriod(DurationSpec.IntMinutesBound maxCertificateValidityPeriod)
-        {
-            return new ServerEncryptionOptions(ssl_context_factory, keystore, keystore_password, keystore_password_file,
-                                               outbound_keystore, outbound_keystore_password, outbound_keystore_password_file,
-                                               truststore, truststore_password, truststore_password_file,
-                                               cipher_suites, protocol, accepted_protocols,
-                                               algorithm, store_type, require_client_auth,
-                                               require_endpoint_verification, optional, internode_encryption,
-                                               legacy_ssl_storage_port_enabled, maxCertificateValidityPeriod,
-                                               certificate_validity_warn_threshold).applyConfigInternal();
-        }
     }
 }
diff --git a/src/java/org/apache/cassandra/config/JMXServerOptions.java b/src/java/org/apache/cassandra/config/JMXServerOptions.java
index 705ab02bb8..ab80307e54 100644
--- a/src/java/org/apache/cassandra/config/JMXServerOptions.java
+++ b/src/java/org/apache/cassandra/config/JMXServerOptions.java
@@ -52,7 +52,7 @@ public class JMXServerOptions
     public final Boolean authenticate;
 
     // ssl options
-    public final EncryptionOptions jmx_encryption_options;
+    public final EncryptionOptions.ClientEncryptionOptions jmx_encryption_options;
 
     // options for using Cassandra's own authentication mechanisms
     public final String login_config_name;
@@ -71,11 +71,11 @@ public class JMXServerOptions
     public JMXServerOptions()
     {
         this(true, false, 7199, 0, false,
-             new EncryptionOptions(), null, null, null,
+             new EncryptionOptions.ClientEncryptionOptions(), null, null, null,
              null, null);
     }
 
-    public static JMXServerOptions create(boolean enabled, boolean local, int jmxPort, EncryptionOptions options)
+    public static JMXServerOptions create(boolean enabled, boolean local, int jmxPort, EncryptionOptions.ClientEncryptionOptions options)
     {
         return new JMXServerOptions(enabled, !local, jmxPort, 0, false,
                                     options, null, null, null,
@@ -95,7 +95,7 @@ public class JMXServerOptions
                             int jmxPort,
                             int rmiPort,
                             Boolean authenticate,
-                            EncryptionOptions jmx_encryption_options,
+                            EncryptionOptions.ClientEncryptionOptions jmx_encryption_options,
                             String loginConfigName,
                             String loginConfigFile,
                             String passwordFile,
@@ -198,7 +198,8 @@ public class JMXServerOptions
         // in the `cassandra.yaml`. Since the JMX SSL Config can also leverage it as per CASSANDRA-18508, password file
         // support is not added to the JMX SSL configuration via the system properties. Hence, `null` is used as
         // the password file arguments for the keystore and the truststore while constructing the encryption options here.
-        EncryptionOptions encryptionOptions = new EncryptionOptions(new ParameterizedClass("org.apache.cassandra.security.DefaultSslContextFactory", new HashMap<>()),
+
+        EncryptionOptions.ClientEncryptionOptions encryptionOptions = new EncryptionOptions.ClientEncryptionOptions(new ParameterizedClass("org.apache.cassandra.security.DefaultSslContextFactory", new HashMap<>()),
                                                                     keystore,
                                                                     keystorePassword,
                                                                     null,
diff --git a/src/java/org/apache/cassandra/net/InboundConnectionInitiator.java b/src/java/org/apache/cassandra/net/InboundConnectionInitiator.java
index fd5710e297..c4cbc50a2b 100644
--- a/src/java/org/apache/cassandra/net/InboundConnectionInitiator.java
+++ b/src/java/org/apache/cassandra/net/InboundConnectionInitiator.java
@@ -67,7 +67,7 @@ import static java.lang.Math.*;
 import static java.util.concurrent.TimeUnit.MILLISECONDS;
 import static org.apache.cassandra.auth.IInternodeAuthenticator.InternodeConnectionDirection.INBOUND;
 import static org.apache.cassandra.concurrent.ExecutorFactory.Global.executorFactory;
-import static org.apache.cassandra.config.EncryptionOptions.ClientAuth.REQUIRED;
+import static org.apache.cassandra.config.EncryptionOptions.ClientEncryptionOptions.ClientAuth.REQUIRED;
 import static org.apache.cassandra.net.InternodeConnectionUtils.DISCARD_HANDLER_NAME;
 import static org.apache.cassandra.net.InternodeConnectionUtils.SSL_FACTORY_CONTEXT_DESCRIPTION;
 import static org.apache.cassandra.net.InternodeConnectionUtils.SSL_HANDLER_NAME;
@@ -530,7 +530,7 @@ public class InboundConnectionInitiator
 
     private static SslHandler getSslHandler(String description, Channel channel, EncryptionOptions.ServerEncryptionOptions encryptionOptions) throws IOException
     {
-        final EncryptionOptions.ClientAuth verifyPeerCertificate = REQUIRED;
+        final EncryptionOptions.ClientEncryptionOptions.ClientAuth verifyPeerCertificate = REQUIRED;
         SslContext sslContext = SSLFactory.getOrCreateSslContext(encryptionOptions, verifyPeerCertificate,
                                                                  ISslContextFactory.SocketType.SERVER,
                                                                  SSL_FACTORY_CONTEXT_DESCRIPTION);
diff --git a/src/java/org/apache/cassandra/net/InboundConnectionSettings.java b/src/java/org/apache/cassandra/net/InboundConnectionSettings.java
index 448da62cbb..4a9db7ca81 100644
--- a/src/java/org/apache/cassandra/net/InboundConnectionSettings.java
+++ b/src/java/org/apache/cassandra/net/InboundConnectionSettings.java
@@ -146,7 +146,7 @@ public class InboundConnectionSettings
         ServerEncryptionOptions encryption = this.encryption;
         if (encryption == null)
             encryption = DatabaseDescriptor.getInternodeMessagingEncyptionOptions();
-        encryption = encryption.withOptional(false).withInternodeEncryption(ServerEncryptionOptions.InternodeEncryption.all);
+        encryption = new ServerEncryptionOptions.Builder(encryption).withInternodeEncryption(ServerEncryptionOptions.InternodeEncryption.all).withOptional(false).build();
 
         return this.withBindAddress(bindAddress.withPort(DatabaseDescriptor.getSSLStoragePort()))
                    .withEncryption(encryption)
diff --git a/src/java/org/apache/cassandra/net/OutboundConnectionInitiator.java b/src/java/org/apache/cassandra/net/OutboundConnectionInitiator.java
index 27e55f6105..2bddc174f2 100644
--- a/src/java/org/apache/cassandra/net/OutboundConnectionInitiator.java
+++ b/src/java/org/apache/cassandra/net/OutboundConnectionInitiator.java
@@ -66,9 +66,9 @@ import org.apache.cassandra.utils.memory.BufferPools;
 import static java.util.concurrent.TimeUnit.*;
 import static org.apache.cassandra.auth.IInternodeAuthenticator.InternodeConnectionDirection.OUTBOUND;
 import static org.apache.cassandra.auth.IInternodeAuthenticator.InternodeConnectionDirection.OUTBOUND_PRECONNECT;
-import static org.apache.cassandra.config.EncryptionOptions.ClientAuth.NOT_REQUIRED;
-import static org.apache.cassandra.config.EncryptionOptions.ClientAuth.OPTIONAL;
-import static org.apache.cassandra.config.EncryptionOptions.ClientAuth.REQUIRED;
+import static org.apache.cassandra.config.EncryptionOptions.ClientEncryptionOptions.ClientAuth.NOT_REQUIRED;
+import static org.apache.cassandra.config.EncryptionOptions.ClientEncryptionOptions.ClientAuth.OPTIONAL;
+import static org.apache.cassandra.config.EncryptionOptions.ClientEncryptionOptions.ClientAuth.REQUIRED;
 import static org.apache.cassandra.net.InternodeConnectionUtils.DISCARD_HANDLER_NAME;
 import static org.apache.cassandra.net.InternodeConnectionUtils.SSL_FACTORY_CONTEXT_DESCRIPTION;
 import static org.apache.cassandra.net.InternodeConnectionUtils.SSL_HANDLER_NAME;
@@ -245,7 +245,7 @@ public class OutboundConnectionInitiator<SuccessType extends OutboundConnectionI
 
         private SslContext getSslContext(SslFallbackConnectionType connectionType) throws IOException
         {
-            EncryptionOptions.ClientAuth requireClientAuth = NOT_REQUIRED;
+            EncryptionOptions.ClientEncryptionOptions.ClientAuth requireClientAuth = NOT_REQUIRED;
             if (connectionType == SslFallbackConnectionType.MTLS )
             {
                 requireClientAuth = REQUIRED;
diff --git a/src/java/org/apache/cassandra/security/AbstractSslContextFactory.java b/src/java/org/apache/cassandra/security/AbstractSslContextFactory.java
index c2a7fdb975..0fc8f94352 100644
--- a/src/java/org/apache/cassandra/security/AbstractSslContextFactory.java
+++ b/src/java/org/apache/cassandra/security/AbstractSslContextFactory.java
@@ -37,8 +37,8 @@ import io.netty.handler.ssl.SslContextBuilder;
 import io.netty.handler.ssl.SslProvider;
 import org.apache.cassandra.config.EncryptionOptions;
 
-import static org.apache.cassandra.config.EncryptionOptions.ClientAuth.NOT_REQUIRED;
-import static org.apache.cassandra.config.EncryptionOptions.ClientAuth.REQUIRED;
+import static org.apache.cassandra.config.EncryptionOptions.ClientEncryptionOptions.ClientAuth.NOT_REQUIRED;
+import static org.apache.cassandra.config.EncryptionOptions.ClientEncryptionOptions.ClientAuth.REQUIRED;
 
 import static org.apache.cassandra.config.CassandraRelevantProperties.DISABLE_TCACTIVE_OPENSSL;
 
@@ -68,7 +68,7 @@ abstract public class AbstractSslContextFactory implements ISslContextFactory
     protected final List<String> accepted_protocols;
     protected final String algorithm;
     protected final String store_type;
-    protected final EncryptionOptions.ClientAuth clientAuth;
+    protected final EncryptionOptions.ClientEncryptionOptions.ClientAuth clientAuth;
     protected final boolean require_endpoint_verification;
     /*
     ServerEncryptionOptions does not use the enabled flag at all instead using the existing
@@ -105,7 +105,7 @@ abstract public class AbstractSslContextFactory implements ISslContextFactory
         accepted_protocols = getStringList("accepted_protocols");
         algorithm = getString("algorithm");
         store_type = getString("store_type", "JKS");
-        clientAuth = parameters.get("require_client_auth") == null ? NOT_REQUIRED : EncryptionOptions.ClientAuth.from(getString("require_client_auth"));
+        clientAuth = parameters.get("require_client_auth") == null ? NOT_REQUIRED : EncryptionOptions.ClientEncryptionOptions.ClientAuth.from(getString("require_client_auth"));
         require_endpoint_verification = getBoolean("require_endpoint_verification", false);
         enabled = getBoolean("enabled");
         optional = getBoolean("optional");
@@ -158,7 +158,7 @@ abstract public class AbstractSslContextFactory implements ISslContextFactory
     }
 
     @Override
-    public SSLContext createJSSESslContext(EncryptionOptions.ClientAuth clientAuth) throws SSLException
+    public SSLContext createJSSESslContext(EncryptionOptions.ClientEncryptionOptions.ClientAuth clientAuth) throws SSLException
     {
         TrustManager[] trustManagers = null;
         if (clientAuth != NOT_REQUIRED)
@@ -186,7 +186,7 @@ abstract public class AbstractSslContextFactory implements ISslContextFactory
     }
 
     @Override
-    public SslContext createNettySslContext(EncryptionOptions.ClientAuth clientAuth, SocketType socketType,
+    public SslContext createNettySslContext(EncryptionOptions.ClientEncryptionOptions.ClientAuth clientAuth, SocketType socketType,
                                             CipherSuiteFilter cipherFilter) throws SSLException
     {
         /*
@@ -291,7 +291,7 @@ abstract public class AbstractSslContextFactory implements ISslContextFactory
      */
     abstract protected KeyManagerFactory buildOutboundKeyManagerFactory() throws SSLException;
 
-    private ClientAuth toNettyClientAuth(EncryptionOptions.ClientAuth clientAuth)
+    private ClientAuth toNettyClientAuth(EncryptionOptions.ClientEncryptionOptions.ClientAuth clientAuth)
     {
         switch (clientAuth)
         {
diff --git a/src/java/org/apache/cassandra/security/ISslContextFactory.java b/src/java/org/apache/cassandra/security/ISslContextFactory.java
index 1db5f579b1..2f8b53d166 100644
--- a/src/java/org/apache/cassandra/security/ISslContextFactory.java
+++ b/src/java/org/apache/cassandra/security/ISslContextFactory.java
@@ -72,7 +72,7 @@ public interface ISslContextFactory
      * @return JSSE's {@link SSLContext}
      * @throws SSLException in case the Ssl Context creation fails for some reason
      */
-    default SSLContext createJSSESslContext(EncryptionOptions.ClientAuth clientAuth) throws SSLException
+    default SSLContext createJSSESslContext(EncryptionOptions.ClientEncryptionOptions.ClientAuth clientAuth) throws SSLException
     {
         switch (clientAuth)
         {
@@ -112,7 +112,7 @@ public interface ISslContextFactory
      * @return Netty's {@link SslContext}
      * @throws SSLException in case the Ssl Context creation fails for some reason
      */
-    default SslContext createNettySslContext(EncryptionOptions.ClientAuth clientAuth, SocketType socketType,
+    default SslContext createNettySslContext(EncryptionOptions.ClientEncryptionOptions.ClientAuth clientAuth, SocketType socketType,
                                              CipherSuiteFilter cipherFilter) throws SSLException
     {
         switch (clientAuth)
diff --git a/src/java/org/apache/cassandra/security/SSLFactory.java b/src/java/org/apache/cassandra/security/SSLFactory.java
index a9b4be9d5c..65a6dfa24f 100644
--- a/src/java/org/apache/cassandra/security/SSLFactory.java
+++ b/src/java/org/apache/cassandra/security/SSLFactory.java
@@ -47,7 +47,7 @@ import org.apache.cassandra.security.ISslContextFactory.SocketType;
 
 import static org.apache.cassandra.config.CassandraRelevantProperties.DISABLE_TCACTIVE_OPENSSL;
 
-import static org.apache.cassandra.config.EncryptionOptions.ClientAuth.REQUIRED;
+import static org.apache.cassandra.config.EncryptionOptions.ClientEncryptionOptions.ClientAuth.REQUIRED;
 import static org.apache.cassandra.utils.LocalizeString.toLowerCaseLocalized;
 
 /**
@@ -125,7 +125,7 @@ public final class SSLFactory
     /**
      * Create a JSSE {@link SSLContext}.
      */
-    public static SSLContext createSSLContext(EncryptionOptions options, EncryptionOptions.ClientAuth clientAuth) throws IOException
+    public static SSLContext createSSLContext(EncryptionOptions options, EncryptionOptions.ClientEncryptionOptions.ClientAuth clientAuth) throws IOException
     {
         return options.sslContextFactoryInstance.createJSSESslContext(clientAuth);
     }
@@ -133,7 +133,7 @@ public final class SSLFactory
     /**
      * get a netty {@link SslContext} instance
      */
-    public static SslContext getOrCreateSslContext(EncryptionOptions options, EncryptionOptions.ClientAuth clientAuth,
+    public static SslContext getOrCreateSslContext(EncryptionOptions options, EncryptionOptions.ClientEncryptionOptions.ClientAuth clientAuth,
                                                    SocketType socketType,
                                                    String contextDescription) throws IOException
     {
@@ -157,7 +157,7 @@ public final class SSLFactory
     /**
      * Create a Netty {@link SslContext}
      */
-    static SslContext createNettySslContext(EncryptionOptions options, EncryptionOptions.ClientAuth clientAuth,
+    static SslContext createNettySslContext(EncryptionOptions options, EncryptionOptions.ClientEncryptionOptions.ClientAuth clientAuth,
                                             SocketType socketType) throws IOException
     {
         return createNettySslContext(options, clientAuth, socketType,
@@ -167,7 +167,7 @@ public final class SSLFactory
     /**
      * Create a Netty {@link SslContext} with a supplied cipherFilter
      */
-    static SslContext createNettySslContext(EncryptionOptions options, EncryptionOptions.ClientAuth clientAuth,
+    static SslContext createNettySslContext(EncryptionOptions options, EncryptionOptions.ClientEncryptionOptions.ClientAuth clientAuth,
                                             SocketType socketType, CipherSuiteFilter cipherFilter) throws IOException
     {
         return options.sslContextFactoryInstance.createNettySslContext(clientAuth, socketType,
@@ -356,7 +356,7 @@ public final class SSLFactory
         return !string.equals("SSLv2Hello");
     }
 
-    public static void validateSslContext(String contextDescription, EncryptionOptions options, EncryptionOptions.ClientAuth clientAuth, boolean logProtocolAndCiphers) throws IOException
+    public static void validateSslContext(String contextDescription, EncryptionOptions options, EncryptionOptions.ClientEncryptionOptions.ClientAuth clientAuth, boolean logProtocolAndCiphers) throws IOException
     {
         if (options != null && options.tlsEncryptionPolicy() != EncryptionOptions.TlsEncryptionPolicy.UNENCRYPTED)
         {
diff --git a/src/java/org/apache/cassandra/tools/BulkLoader.java b/src/java/org/apache/cassandra/tools/BulkLoader.java
index ecd6a5d31b..92ccbb96be 100644
--- a/src/java/org/apache/cassandra/tools/BulkLoader.java
+++ b/src/java/org/apache/cassandra/tools/BulkLoader.java
@@ -48,7 +48,7 @@ import org.apache.cassandra.utils.JVMStabilityInspector;
 import org.apache.cassandra.utils.NativeSSTableLoaderClient;
 import org.apache.cassandra.utils.OutputHandler;
 
-import static org.apache.cassandra.config.EncryptionOptions.ClientAuth.REQUIRED;
+import static org.apache.cassandra.config.EncryptionOptions.ClientEncryptionOptions.ClientAuth.REQUIRED;
 import static org.apache.cassandra.utils.Clock.Global.nanoTime;
 
 public class BulkLoader
diff --git a/src/java/org/apache/cassandra/tools/LoaderOptions.java b/src/java/org/apache/cassandra/tools/LoaderOptions.java
index c3d2072ff4..a68fb012eb 100644
--- a/src/java/org/apache/cassandra/tools/LoaderOptions.java
+++ b/src/java/org/apache/cassandra/tools/LoaderOptions.java
@@ -52,7 +52,7 @@ import org.apache.cassandra.locator.InetAddressAndPort;
 import org.apache.cassandra.tools.BulkLoader.CmdLineOptions;
 
 import static org.apache.cassandra.config.DataRateSpec.DataRateUnit.MEBIBYTES_PER_SECOND;
-import static org.apache.cassandra.config.EncryptionOptions.ClientAuth.REQUIRED;
+import static org.apache.cassandra.config.EncryptionOptions.ClientEncryptionOptions.ClientAuth.REQUIRED;
 
 public class LoaderOptions
 {
@@ -121,7 +121,7 @@ public class LoaderOptions
     public final int entireSSTableInterDcThrottleMebibytes;
     public final int storagePort;
     public final int sslStoragePort;
-    public final EncryptionOptions clientEncOptions;
+    public final EncryptionOptions.ClientEncryptionOptions clientEncOptions;
     public final int connectionsPerHost;
     public final EncryptionOptions.ServerEncryptionOptions serverEncOptions;
     public final Set<InetSocketAddress> hosts;
@@ -172,9 +172,11 @@ public class LoaderOptions
 
         int storagePort;
         int sslStoragePort;
-        EncryptionOptions clientEncOptions = new EncryptionOptions();
+        EncryptionOptions.ClientEncryptionOptions clientEncOptions = new EncryptionOptions.ClientEncryptionOptions();
+        EncryptionOptions.ClientEncryptionOptions.Builder clientEncOptionsBuilder = new EncryptionOptions.ClientEncryptionOptions.Builder(clientEncOptions);
         int connectionsPerHost = 1;
         EncryptionOptions.ServerEncryptionOptions serverEncOptions = new EncryptionOptions.ServerEncryptionOptions();
+        EncryptionOptions.ServerEncryptionOptions.Builder serverEncOptionsBuilder = new EncryptionOptions.ServerEncryptionOptions.Builder(serverEncOptions);
         Set<InetAddress> hostsArg = new HashSet<>();
         Set<InetAddress> ignoresArg = new HashSet<>();
         Set<InetSocketAddress> hosts = new HashSet<>();
@@ -333,9 +335,10 @@ public class LoaderOptions
             return this;
         }
 
-        public Builder encOptions(EncryptionOptions encOptions)
+        public Builder encOptions(EncryptionOptions.ClientEncryptionOptions encOptions)
         {
             this.clientEncOptions = encOptions;
+            this.clientEncOptionsBuilder = new EncryptionOptions.ClientEncryptionOptions.Builder(encOptions);
             return this;
         }
 
@@ -348,6 +351,7 @@ public class LoaderOptions
         public Builder serverEncOptions(EncryptionOptions.ServerEncryptionOptions serverEncOptions)
         {
             this.serverEncOptions = serverEncOptions;
+            this.serverEncOptionsBuilder = new EncryptionOptions.ServerEncryptionOptions.Builder(serverEncOptions);
             return this;
         }
 
@@ -551,9 +555,10 @@ public class LoaderOptions
                                 "which is able to handle encrypted communication too.");
 
                 // Copy the encryption options and apply the config so that argument parsing can accesss isEnabled.
-                clientEncOptions = config.client_encryption_options.applyConfig();
-                serverEncOptions = config.server_encryption_options;
-                serverEncOptions.applyConfig();
+                clientEncOptionsBuilder = new EncryptionOptions.ClientEncryptionOptions.Builder(config.client_encryption_options);
+                clientEncOptions = clientEncOptionsBuilder.build();
+                serverEncOptionsBuilder = new EncryptionOptions.ServerEncryptionOptions.Builder(config.server_encryption_options);
+                serverEncOptions = serverEncOptionsBuilder.build();
 
                 if (cmd.hasOption(NATIVE_PORT_OPTION))
                     nativePort = Integer.parseInt(cmd.getOptionValue(NATIVE_PORT_OPTION));
@@ -625,51 +630,53 @@ public class LoaderOptions
                 if (cmd.hasOption(SSL_TRUSTSTORE) || cmd.hasOption(SSL_TRUSTSTORE_PW) ||
                     cmd.hasOption(SSL_KEYSTORE) || cmd.hasOption(SSL_KEYSTORE_PW))
                 {
-                    clientEncOptions = clientEncOptions.withEnabled(true);
+                    clientEncOptionsBuilder.withEnabled(true);
                 }
 
                 if (cmd.hasOption(SSL_TRUSTSTORE))
                 {
-                    clientEncOptions = clientEncOptions.withTrustStore(cmd.getOptionValue(SSL_TRUSTSTORE));
+                    clientEncOptionsBuilder.withTrustStore(cmd.getOptionValue(SSL_TRUSTSTORE));
                 }
 
                 if (cmd.hasOption(SSL_TRUSTSTORE_PW))
                 {
-                    clientEncOptions = clientEncOptions.withTrustStorePassword(cmd.getOptionValue(SSL_TRUSTSTORE_PW));
+                    clientEncOptionsBuilder.withTrustStorePassword(cmd.getOptionValue(SSL_TRUSTSTORE_PW));
                 }
 
                 if (cmd.hasOption(SSL_KEYSTORE))
                 {
                     // if a keystore was provided, lets assume we'll need to use
-                    clientEncOptions = clientEncOptions.withKeyStore(cmd.getOptionValue(SSL_KEYSTORE))
+                    clientEncOptionsBuilder.withKeyStore(cmd.getOptionValue(SSL_KEYSTORE))
                                                        .withRequireClientAuth(REQUIRED);
                 }
 
                 if (cmd.hasOption(SSL_KEYSTORE_PW))
                 {
-                    clientEncOptions = clientEncOptions.withKeyStorePassword(cmd.getOptionValue(SSL_KEYSTORE_PW));
+                    clientEncOptionsBuilder.withKeyStorePassword(cmd.getOptionValue(SSL_KEYSTORE_PW));
                 }
 
                 if (cmd.hasOption(SSL_PROTOCOL))
                 {
-                    clientEncOptions = clientEncOptions.withProtocol(cmd.getOptionValue(SSL_PROTOCOL));
+                    clientEncOptionsBuilder.withProtocol(cmd.getOptionValue(SSL_PROTOCOL));
                 }
 
                 if (cmd.hasOption(SSL_ALGORITHM))
                 {
-                    clientEncOptions = clientEncOptions.withAlgorithm(cmd.getOptionValue(SSL_ALGORITHM));
+                    clientEncOptionsBuilder.withAlgorithm(cmd.getOptionValue(SSL_ALGORITHM));
                 }
 
                 if (cmd.hasOption(SSL_STORE_TYPE))
                 {
-                    clientEncOptions = clientEncOptions.withStoreType(cmd.getOptionValue(SSL_STORE_TYPE));
+                    clientEncOptionsBuilder.withStoreType(cmd.getOptionValue(SSL_STORE_TYPE));
                 }
 
                 if (cmd.hasOption(SSL_CIPHER_SUITES))
                 {
-                    clientEncOptions = clientEncOptions.withCipherSuites(cmd.getOptionValue(SSL_CIPHER_SUITES).split(","));
+                    clientEncOptionsBuilder.withCipherSuites(cmd.getOptionValue(SSL_CIPHER_SUITES).split(","));
                 }
 
+                clientEncOptions = clientEncOptionsBuilder.build();
+
                 if (cmd.hasOption(TARGET_KEYSPACE))
                 {
                     targetKeyspace = cmd.getOptionValue(TARGET_KEYSPACE);
diff --git a/src/java/org/apache/cassandra/transport/Client.java b/src/java/org/apache/cassandra/transport/Client.java
index 96fea832a8..6c60f6508c 100644
--- a/src/java/org/apache/cassandra/transport/Client.java
+++ b/src/java/org/apache/cassandra/transport/Client.java
@@ -45,9 +45,9 @@ public class Client extends SimpleClient
 {
     private final SimpleEventHandler eventHandler = new SimpleEventHandler();
 
-    public Client(String host, int port, ProtocolVersion version, EncryptionOptions encryptionOptions)
+    public Client(String host, int port, ProtocolVersion version, EncryptionOptions.ClientEncryptionOptions encryptionOptions)
     {
-        super(host, port, version, version.isBeta(), new EncryptionOptions(encryptionOptions).applyConfig());
+        super(host, port, version, version.isBeta(), encryptionOptions.applyConfig());
         setEventHandler(eventHandler);
     }
 
@@ -260,7 +260,7 @@ public class Client extends SimpleClient
         int port = Integer.parseInt(args[1]);
         ProtocolVersion version = args.length == 3 ? ProtocolVersion.decode(Integer.parseInt(args[2]), DatabaseDescriptor.getNativeTransportAllowOlderProtocols()) : ProtocolVersion.CURRENT;
 
-        EncryptionOptions encryptionOptions = new EncryptionOptions().applyConfig();
+        EncryptionOptions.ClientEncryptionOptions encryptionOptions = new EncryptionOptions.ClientEncryptionOptions().applyConfig();
         System.out.println("CQL binary protocol console " + host + "@" + port + " using native protocol version " + version);
 
         try (Client client = new Client(host, port, version, encryptionOptions))
diff --git a/src/java/org/apache/cassandra/transport/SimpleClient.java b/src/java/org/apache/cassandra/transport/SimpleClient.java
index f86b128be0..dea3535757 100644
--- a/src/java/org/apache/cassandra/transport/SimpleClient.java
+++ b/src/java/org/apache/cassandra/transport/SimpleClient.java
@@ -74,7 +74,7 @@ public class SimpleClient implements Closeable
 
     public final String host;
     public final int port;
-    private final EncryptionOptions encryptionOptions;
+    private final EncryptionOptions.ClientEncryptionOptions encryptionOptions;
     private final int largeMessageThreshold;
 
     protected final ResponseHandler responseHandler = new ResponseHandler();
@@ -92,7 +92,7 @@ public class SimpleClient implements Closeable
     {
         private final String host;
         private final int port;
-        private EncryptionOptions encryptionOptions = new EncryptionOptions();
+        private EncryptionOptions.ClientEncryptionOptions encryptionOptions = new EncryptionOptions.ClientEncryptionOptions();
         private ProtocolVersion version = ProtocolVersion.CURRENT;
         private boolean useBeta = false;
         private int largeMessageThreshold = FrameEncoder.Payload.MAX_SIZE;
@@ -103,7 +103,7 @@ public class SimpleClient implements Closeable
             this.port = port;
         }
 
-        public Builder encryption(EncryptionOptions options)
+        public Builder encryption(EncryptionOptions.ClientEncryptionOptions options)
         {
             this.encryptionOptions = options;
             return this;
@@ -149,22 +149,22 @@ public class SimpleClient implements Closeable
         this.largeMessageThreshold = builder.largeMessageThreshold;
     }
 
-    public SimpleClient(String host, int port, ProtocolVersion version, EncryptionOptions encryptionOptions)
+    public SimpleClient(String host, int port, ProtocolVersion version, EncryptionOptions.ClientEncryptionOptions encryptionOptions)
     {
         this(host, port, version, false, encryptionOptions);
     }
 
-    public SimpleClient(String host, int port, EncryptionOptions encryptionOptions)
+    public SimpleClient(String host, int port, EncryptionOptions.ClientEncryptionOptions encryptionOptions)
     {
         this(host, port, ProtocolVersion.CURRENT, encryptionOptions);
     }
 
     public SimpleClient(String host, int port, ProtocolVersion version)
     {
-        this(host, port, version, new EncryptionOptions());
+        this(host, port, version, new EncryptionOptions.ClientEncryptionOptions());
     }
 
-    public SimpleClient(String host, int port, ProtocolVersion version, boolean useBeta, EncryptionOptions encryptionOptions)
+    public SimpleClient(String host, int port, ProtocolVersion version, boolean useBeta, EncryptionOptions.ClientEncryptionOptions encryptionOptions)
     {
         this.host = host;
         this.port = port;
@@ -172,7 +172,7 @@ public class SimpleClient implements Closeable
             throw new IllegalArgumentException(String.format("Beta version of server used (%s), but USE_BETA flag is not set", version));
 
         this.version = version;
-        this.encryptionOptions = new EncryptionOptions(encryptionOptions).applyConfig();
+        this.encryptionOptions = encryptionOptions.applyConfig();
         this.largeMessageThreshold = FrameEncoder.Payload.MAX_SIZE -
                                         Math.max(FrameEncoderCrc.HEADER_AND_TRAILER_LENGTH,
                                                  FrameEncoderLZ4.HEADER_AND_TRAILER_LENGTH);
@@ -180,7 +180,7 @@ public class SimpleClient implements Closeable
 
     public SimpleClient(String host, int port)
     {
-        this(host, port, new EncryptionOptions());
+        this(host, port, new EncryptionOptions.ClientEncryptionOptions());
     }
 
     public SimpleClient connect(boolean useCompression) throws IOException
diff --git a/src/java/org/apache/cassandra/utils/jmx/AbstractJmxSocketFactory.java b/src/java/org/apache/cassandra/utils/jmx/AbstractJmxSocketFactory.java
index 3990c64ee7..ef68f52486 100644
--- a/src/java/org/apache/cassandra/utils/jmx/AbstractJmxSocketFactory.java
+++ b/src/java/org/apache/cassandra/utils/jmx/AbstractJmxSocketFactory.java
@@ -82,7 +82,7 @@ abstract public class AbstractJmxSocketFactory
                 JMXServerOptions.setJmxSystemProperties(jmxEncryptionOptions.getAcceptedProtocols(), jmxEncryptionOptions.getCipherSuites());
 
             logger.info("Enabling JMX SSL using jmx_encryption_options");
-            boolean requireClientAuth = jmxEncryptionOptions.getClientAuth() == EncryptionOptions.ClientAuth.REQUIRED;
+            boolean requireClientAuth = jmxEncryptionOptions.getClientAuth() == EncryptionOptions.ClientEncryptionOptions.ClientAuth.REQUIRED;
             String[] ciphers = jmxEncryptionOptions.cipherSuitesArray();
             String[] protocols = jmxEncryptionOptions.acceptedProtocolsArray();
             SSLContext sslContext = jmxEncryptionOptions.sslContextFactoryInstance.createJSSESslContext(jmxEncryptionOptions.getClientAuth());
diff --git a/test/burn/org/apache/cassandra/transport/SimpleClientBurnTest.java b/test/burn/org/apache/cassandra/transport/SimpleClientBurnTest.java
index ed3406d8bc..3247051197 100644
--- a/test/burn/org/apache/cassandra/transport/SimpleClientBurnTest.java
+++ b/test/burn/org/apache/cassandra/transport/SimpleClientBurnTest.java
@@ -138,11 +138,11 @@ public class SimpleClientBurnTest
         Arrays.asList(
         () -> new SimpleClient(address.getHostAddress(),
                                port, ProtocolVersion.V5, true,
-                               new EncryptionOptions())
+                               new EncryptionOptions.ClientEncryptionOptions())
               .connect(false),
         () -> new SimpleClient(address.getHostAddress(),
                                port, ProtocolVersion.V4, false,
-                               new EncryptionOptions())
+                               new EncryptionOptions.ClientEncryptionOptions())
               .connect(false)
         );
 
diff --git a/test/burn/org/apache/cassandra/transport/SimpleClientPerfTest.java b/test/burn/org/apache/cassandra/transport/SimpleClientPerfTest.java
index 4417b7cb89..ca5adfff02 100644
--- a/test/burn/org/apache/cassandra/transport/SimpleClientPerfTest.java
+++ b/test/burn/org/apache/cassandra/transport/SimpleClientPerfTest.java
@@ -102,7 +102,7 @@ public class SimpleClientPerfTest
                  new SizeCaps(10, 20, 5, 10),
                  () -> new SimpleClient(address.getHostAddress(),
                                         port, version, true,
-                                        new EncryptionOptions())
+                                        new EncryptionOptions.ClientEncryptionOptions())
                        .connect(false),
                  version);
     }
@@ -114,7 +114,7 @@ public class SimpleClientPerfTest
                  new SizeCaps(10, 20, 5, 10),
                  () -> new SimpleClient(address.getHostAddress(),
                                         port, version, true,
-                                        new EncryptionOptions())
+                                        new EncryptionOptions.ClientEncryptionOptions())
                        .connect(true),
                  version);
     }
@@ -126,7 +126,7 @@ public class SimpleClientPerfTest
                  new SizeCaps(1000, 2000, 5, 150),
                  () -> new SimpleClient(address.getHostAddress(),
                                         port, version, true,
-                                        new EncryptionOptions())
+                                        new EncryptionOptions.ClientEncryptionOptions())
                        .connect(false),
                  version);
     }
@@ -138,7 +138,7 @@ public class SimpleClientPerfTest
                  new SizeCaps(1000, 2000, 5, 150),
                  () -> new SimpleClient(address.getHostAddress(),
                                         port, version, true,
-                                        new EncryptionOptions())
+                                        new EncryptionOptions.ClientEncryptionOptions())
                        .connect(true),
                  version);
     }
diff --git a/test/distributed/org/apache/cassandra/distributed/impl/IsolatedJmx.java b/test/distributed/org/apache/cassandra/distributed/impl/IsolatedJmx.java
index 59e9e8ca04..7ad57a52b6 100644
--- a/test/distributed/org/apache/cassandra/distributed/impl/IsolatedJmx.java
+++ b/test/distributed/org/apache/cassandra/distributed/impl/IsolatedJmx.java
@@ -94,7 +94,7 @@ public class IsolatedJmx
 
             // CASSANDRA-18508: Sensitive JMX SSL configuration options can be easily exposed
             Map<String, Object> jmxServerOptionsMap = (Map<String, Object>) config.getParams().get("jmx_server_options");
-            EncryptionOptions jmxEncryptionOptions;
+            EncryptionOptions.ClientEncryptionOptions jmxEncryptionOptions;
             if (jmxServerOptionsMap == null)
             {
                 JMXServerOptions parsingSystemProperties = JMXServerOptions.createParsingSystemProperties();
@@ -175,7 +175,7 @@ public class IsolatedJmx
      * @return EncryptionOptions built object
      */
     @SuppressWarnings("unchecked")
-    private EncryptionOptions getJmxEncryptionOptions(Map<String, Object> jmxServerOptionsMap)
+    private EncryptionOptions.ClientEncryptionOptions getJmxEncryptionOptions(Map<String, Object> jmxServerOptionsMap)
     {
         if (jmxServerOptionsMap == null)
             return null;
@@ -186,34 +186,34 @@ public class IsolatedJmx
         {
             return null;
         }
-        EncryptionOptions jmxEncryptionOptions = new EncryptionOptions();
+        EncryptionOptions.ClientEncryptionOptions.Builder jmxEncryptionOptionsBuilder = new EncryptionOptions.ClientEncryptionOptions.Builder();
         String[] cipherSuitesArray = (String[]) encryptionOptionsMap.get(EncryptionOptions.ConfigKey.CIPHER_SUITES.toString());
         if (cipherSuitesArray != null)
         {
-            jmxEncryptionOptions = jmxEncryptionOptions.withCipherSuites(cipherSuitesArray);
+            jmxEncryptionOptionsBuilder.withCipherSuites(cipherSuitesArray);
         }
         List<String> acceptedProtocols = (List<String>) encryptionOptionsMap.get(EncryptionOptions.ConfigKey.ACCEPTED_PROTOCOLS.toString());
         if (acceptedProtocols != null)
         {
-            jmxEncryptionOptions = jmxEncryptionOptions.withAcceptedProtocols(acceptedProtocols);
+            jmxEncryptionOptionsBuilder.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));
+        EncryptionOptions.ClientEncryptionOptions.ClientAuth requireClientAuth = requireClientAuthValue == null ?
+                                                                                 EncryptionOptions.ClientEncryptionOptions.ClientAuth.NOT_REQUIRED :
+                                                                                 EncryptionOptions.ClientEncryptionOptions.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;
+        return jmxEncryptionOptionsBuilder
+               .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)
+               .build();
     }
 
     private void waitForJmxAvailability(Map<String, ?> env)
diff --git a/test/distributed/org/apache/cassandra/distributed/test/AbstractEncryptionOptionsImpl.java b/test/distributed/org/apache/cassandra/distributed/test/AbstractEncryptionOptionsImpl.java
index 25e9e64b63..7c3b91127a 100644
--- a/test/distributed/org/apache/cassandra/distributed/test/AbstractEncryptionOptionsImpl.java
+++ b/test/distributed/org/apache/cassandra/distributed/test/AbstractEncryptionOptionsImpl.java
@@ -56,7 +56,7 @@ import org.apache.cassandra.security.ISslContextFactory;
 import org.apache.cassandra.security.SSLFactory;
 
 import static java.util.concurrent.TimeUnit.SECONDS;
-import static org.apache.cassandra.config.EncryptionOptions.ClientAuth.REQUIRED;
+import static org.apache.cassandra.config.EncryptionOptions.ClientEncryptionOptions.ClientAuth.REQUIRED;
 import static org.apache.cassandra.distributed.test.AbstractEncryptionOptionsImpl.ConnectResult.CONNECTING;
 import static org.apache.cassandra.distributed.test.AbstractEncryptionOptionsImpl.ConnectResult.UNINITIALIZED;
 import static org.apache.cassandra.utils.concurrent.Condition.newOneTimeCondition;
@@ -118,10 +118,13 @@ public class AbstractEncryptionOptionsImpl extends TestBaseImpl
         final int port;
         final List<String> acceptedProtocols;
         final List<String> cipherSuites;
-        final EncryptionOptions encryptionOptions = new EncryptionOptions()
-                                                    .withEnabled(true)
-                                                    .withKeyStore(validKeyStorePath).withKeyStorePassword(validKeyStorePassword)
-                                                    .withTrustStore(validTrustStorePath).withTrustStorePassword(validTrustStorePassword);
+        final EncryptionOptions.ClientEncryptionOptions encryptionOptions = new EncryptionOptions.ClientEncryptionOptions.Builder()
+                                                                            .withEnabled(true)
+                                                                            .withKeyStore(validKeyStorePath)
+                                                                            .withKeyStorePassword(validKeyStorePassword)
+                                                                            .withTrustStore(validTrustStorePath)
+                                                                            .withTrustStorePassword(validTrustStorePassword)
+                                                                            .build();
         private Throwable lastThrowable;
         private String lastProtocol;
         private String lastCipher;
@@ -202,7 +205,7 @@ public class AbstractEncryptionOptionsImpl extends TestBaseImpl
             setProtocolAndCipher(null, null);
 
             SslContext sslContext = SSLFactory.getOrCreateSslContext(
-            encryptionOptions.withAcceptedProtocols(acceptedProtocols).withCipherSuites(cipherSuites),
+            new EncryptionOptions.ClientEncryptionOptions.Builder(encryptionOptions).withAcceptedProtocols(acceptedProtocols).withCipherSuites(cipherSuites).build(),
             REQUIRED, ISslContextFactory.SocketType.CLIENT, "test");
 
             EventLoopGroup workerGroup = new NioEventLoopGroup();
diff --git a/test/unit/org/apache/cassandra/auth/AuthConfigTest.java b/test/unit/org/apache/cassandra/auth/AuthConfigTest.java
index b9bde913be..580c48eb9f 100644
--- a/test/unit/org/apache/cassandra/auth/AuthConfigTest.java
+++ b/test/unit/org/apache/cassandra/auth/AuthConfigTest.java
@@ -30,6 +30,7 @@ import org.junit.rules.ExpectedException;
 
 import org.apache.cassandra.config.Config;
 import org.apache.cassandra.config.DatabaseDescriptor;
+import org.apache.cassandra.config.EncryptionOptions.ServerEncryptionOptions.Builder;
 import org.apache.cassandra.config.ParameterizedClass;
 import org.apache.cassandra.locator.InetAddressAndPort;
 import org.apache.cassandra.utils.MBeanWrapper;
@@ -52,8 +53,10 @@ public class AuthConfigTest
         Config config = load("cassandra-mtls.yaml");
         config.internode_authenticator.class_name = "org.apache.cassandra.auth.MutualTlsInternodeAuthenticator";
         config.internode_authenticator.parameters = Collections.singletonMap("validator_class_name", "org.apache.cassandra.auth.SpiffeCertificateValidator");
-        config.server_encryption_options = config.server_encryption_options.withOutboundKeystore("test/conf/cassandra_ssl_test_outbound.keystore")
-                                                                           .withOutboundKeystorePassword("cassandra");
+        config.server_encryption_options = new Builder(config.server_encryption_options)
+                                           .withOutboundKeystore("test/conf/cassandra_ssl_test_outbound.keystore")
+                                           .withOutboundKeystorePassword("cassandra")
+                                           .build();
         DatabaseDescriptor.setConfig(config);
         MutualTlsInternodeAuthenticator authenticator = ParameterizedClass.newInstance(config.internode_authenticator,
                                                                                        Arrays.asList("", "org.apache.cassandra.auth."));
diff --git a/test/unit/org/apache/cassandra/auth/MutualTlsAuthenticatorTest.java b/test/unit/org/apache/cassandra/auth/MutualTlsAuthenticatorTest.java
index 14b31a3c87..88e44cf0ab 100644
--- a/test/unit/org/apache/cassandra/auth/MutualTlsAuthenticatorTest.java
+++ b/test/unit/org/apache/cassandra/auth/MutualTlsAuthenticatorTest.java
@@ -48,7 +48,7 @@ import org.apache.cassandra.utils.MBeanWrapper;
 import static org.apache.cassandra.auth.AuthTestUtils.getMockInetAddress;
 import static org.apache.cassandra.auth.AuthTestUtils.initializeIdentityRolesTable;
 import static org.apache.cassandra.auth.AuthTestUtils.loadCertificateChain;
-import static org.apache.cassandra.config.EncryptionOptions.ClientAuth.REQUIRED;
+import static org.apache.cassandra.config.EncryptionOptions.ClientEncryptionOptions.ClientAuth.REQUIRED;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertNull;
@@ -79,8 +79,10 @@ public class MutualTlsAuthenticatorTest
         StorageService.instance.initServer();
         ((CassandraRoleManager)DatabaseDescriptor.getRoleManager()).loadIdentityStatement();
         final Config config = DatabaseDescriptor.getRawConfig();
-        config.client_encryption_options = config.client_encryption_options.withEnabled(true)
-                                                                           .withRequireClientAuth(REQUIRED);
+        config.client_encryption_options = new EncryptionOptions.ClientEncryptionOptions.Builder(config.client_encryption_options)
+                                           .withEnabled(true)
+                                           .withRequireClientAuth(REQUIRED)
+                                           .build();
     }
 
     @After
@@ -183,8 +185,10 @@ public class MutualTlsAuthenticatorTest
                      " & client_encryption_options.require_client_auth to be true";
         MutualTlsAuthenticator mutualTlsAuthenticator = createAndInitializeMtlsAuthenticator();
 
-        config.client_encryption_options = config.client_encryption_options.withEnabled(true)
-                                                                           .withRequireClientAuth(EncryptionOptions.ClientAuth.NOT_REQUIRED);
+        config.client_encryption_options = new EncryptionOptions.ClientEncryptionOptions.Builder(config.client_encryption_options)
+                                           .withEnabled(true)
+                                           .withRequireClientAuth(EncryptionOptions.ClientEncryptionOptions.ClientAuth.NOT_REQUIRED)
+                                           .build();
         expectedException.expect(ConfigurationException.class);
         expectedException.expectMessage(msg);
         mutualTlsAuthenticator.validateConfiguration();
diff --git a/test/unit/org/apache/cassandra/auth/MutualTlsInternodeAuthenticatorTest.java b/test/unit/org/apache/cassandra/auth/MutualTlsInternodeAuthenticatorTest.java
index 8fdd23a444..94fe66133b 100644
--- a/test/unit/org/apache/cassandra/auth/MutualTlsInternodeAuthenticatorTest.java
+++ b/test/unit/org/apache/cassandra/auth/MutualTlsInternodeAuthenticatorTest.java
@@ -39,6 +39,7 @@ import org.junit.runners.Parameterized;
 import org.apache.cassandra.SchemaLoader;
 import org.apache.cassandra.config.Config;
 import org.apache.cassandra.config.DatabaseDescriptor;
+import org.apache.cassandra.config.EncryptionOptions.ServerEncryptionOptions.Builder;
 import org.apache.cassandra.exceptions.ConfigurationException;
 import org.apache.cassandra.locator.InetAddressAndPort;
 import org.apache.cassandra.transport.TlsTestUtils;
@@ -81,8 +82,10 @@ public class MutualTlsInternodeAuthenticatorTest
     public void before()
     {
         Config config = DatabaseDescriptor.getRawConfig();
-        config.server_encryption_options = config.server_encryption_options.withOutboundKeystore("test/conf/cassandra_ssl_test_outbound.keystore")
-                                                                           .withOutboundKeystorePassword("cassandra");
+        config.server_encryption_options = new Builder(config.server_encryption_options)
+                                           .withOutboundKeystore("test/conf/cassandra_ssl_test_outbound.keystore")
+                                           .withOutboundKeystorePassword("cassandra")
+                                           .build();
     }
 
     String getValidatorClass()
@@ -164,8 +167,10 @@ public class MutualTlsInternodeAuthenticatorTest
     public void testNoIdentitiesInKeystore()
     {
         Config config = DatabaseDescriptor.getRawConfig();
-        config.server_encryption_options = config.server_encryption_options.withOutboundKeystore(TlsTestUtils.SERVER_KEYSTORE_PATH)
-                                                                           .withOutboundKeystorePassword(TlsTestUtils.SERVER_KEYSTORE_PASSWORD);
+        config.server_encryption_options = new Builder(config.server_encryption_options)
+                                           .withOutboundKeystore(TlsTestUtils.SERVER_KEYSTORE_PATH)
+                                           .withOutboundKeystorePassword(TlsTestUtils.SERVER_KEYSTORE_PASSWORD)
+                                           .build();
         expectedException.expect(ConfigurationException.class);
         expectedException.expectMessage(String.format("No identity was extracted from the outbound keystore '%s'", TlsTestUtils.SERVER_KEYSTORE_PATH));
         new MutualTlsInternodeAuthenticator(getParams());
diff --git a/test/unit/org/apache/cassandra/auth/MutualTlsWithPasswordFallbackAuthenticatorTest.java b/test/unit/org/apache/cassandra/auth/MutualTlsWithPasswordFallbackAuthenticatorTest.java
index 95f7c133ea..f0c642846b 100644
--- a/test/unit/org/apache/cassandra/auth/MutualTlsWithPasswordFallbackAuthenticatorTest.java
+++ b/test/unit/org/apache/cassandra/auth/MutualTlsWithPasswordFallbackAuthenticatorTest.java
@@ -50,8 +50,10 @@ public class MutualTlsWithPasswordFallbackAuthenticatorTest
         DatabaseDescriptor.daemonInitialization();
         SchemaLoader.loadSchema();
         Config config = DatabaseDescriptor.getRawConfig();
-        config.client_encryption_options = config.client_encryption_options.withEnabled(true)
-                                                                           .withRequireClientAuth(EncryptionOptions.ClientAuth.OPTIONAL);
+        config.client_encryption_options = new EncryptionOptions.ClientEncryptionOptions.Builder(config.client_encryption_options)
+                                           .withEnabled(true)
+                                           .withRequireClientAuth(EncryptionOptions.ClientEncryptionOptions.ClientAuth.OPTIONAL)
+                                           .build();
         Map<String, String> parameters = Collections.singletonMap("validator_class_name", "org.apache.cassandra.auth.SpiffeCertificateValidator");
         fallbackAuthenticator = new MutualTlsWithPasswordFallbackAuthenticator(parameters);
         fallbackAuthenticator.setup();
diff --git a/test/unit/org/apache/cassandra/auth/jmx/JMXAuthJMXServerOptionsTest.java b/test/unit/org/apache/cassandra/auth/jmx/JMXAuthJMXServerOptionsTest.java
index cb83a61eda..98749ca314 100644
--- a/test/unit/org/apache/cassandra/auth/jmx/JMXAuthJMXServerOptionsTest.java
+++ b/test/unit/org/apache/cassandra/auth/jmx/JMXAuthJMXServerOptionsTest.java
@@ -42,7 +42,7 @@ public class JMXAuthJMXServerOptionsTest extends AbstractJMXAuthTest
         String config = Paths.get(ClassLoader.getSystemResource("auth/cassandra-test-jaas.conf").toURI()).toString();
 
         return new JMXServerOptions(true, false, 9999, 0, true,
-                                    new EncryptionOptions(), "TestLogin", config, null, null,
+                                    new EncryptionOptions.ClientEncryptionOptions(), "TestLogin", config, null, null,
                                     NoSuperUserAuthorizationProxy.class.getName());
     }
 }
diff --git a/test/unit/org/apache/cassandra/config/EncryptionOptionsEqualityTest.java b/test/unit/org/apache/cassandra/config/EncryptionOptionsEqualityTest.java
index 5e6d26b817..b2770c2361 100644
--- a/test/unit/org/apache/cassandra/config/EncryptionOptionsEqualityTest.java
+++ b/test/unit/org/apache/cassandra/config/EncryptionOptionsEqualityTest.java
@@ -27,8 +27,8 @@ import org.apache.cassandra.security.DefaultSslContextFactory;
 import org.apache.cassandra.security.DummySslContextFactoryImpl;
 import org.apache.cassandra.transport.TlsTestUtils;
 
-import static org.apache.cassandra.config.EncryptionOptions.ClientAuth.NOT_REQUIRED;
-import static org.apache.cassandra.config.EncryptionOptions.ClientAuth.REQUIRED;
+import static org.apache.cassandra.config.EncryptionOptions.ClientEncryptionOptions.ClientAuth.NOT_REQUIRED;
+import static org.apache.cassandra.config.EncryptionOptions.ClientEncryptionOptions.ClientAuth.REQUIRED;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNotEquals;
 
@@ -40,23 +40,25 @@ public class EncryptionOptionsEqualityTest
 {
     private EncryptionOptions.ServerEncryptionOptions createServerEncryptionOptions()
     {
-        return new EncryptionOptions.ServerEncryptionOptions()
+        EncryptionOptions.ServerEncryptionOptions.Builder serverEncryptionOptionsBuilder = new EncryptionOptions.ServerEncryptionOptions.Builder();
+        return serverEncryptionOptionsBuilder
+               .withOutboundKeystore(TlsTestUtils.SERVER_OUTBOUND_KEYSTORE_PATH)
+               .withOutboundKeystorePassword(TlsTestUtils.SERVER_OUTBOUND_KEYSTORE_PASSWORD)
                .withStoreType("JKS")
                .withKeyStore(TlsTestUtils.SERVER_KEYSTORE_PATH)
                .withKeyStorePassword(TlsTestUtils.SERVER_KEYSTORE_PASSWORD)
                .withTrustStore(TlsTestUtils.SERVER_TRUSTSTORE_PATH)
                .withTrustStorePassword(TlsTestUtils.SERVER_TRUSTSTORE_PASSWORD)
-               .withOutboundKeystore(TlsTestUtils.SERVER_OUTBOUND_KEYSTORE_PATH)
-               .withOutboundKeystorePassword(TlsTestUtils.SERVER_OUTBOUND_KEYSTORE_PASSWORD)
                .withProtocol("TLSv1.1")
                .withRequireClientAuth(REQUIRED)
-               .withRequireEndpointVerification(false);
+               .withRequireEndpointVerification(false)
+               .build();
     }
 
     @Test
     public void testKeystoreOptions() {
-        EncryptionOptions encryptionOptions1 =
-        new EncryptionOptions()
+        EncryptionOptions.ServerEncryptionOptions encryptionOptions1 =
+        new EncryptionOptions.ServerEncryptionOptions.Builder()
         .withStoreType("JKS")
         .withKeyStore(TlsTestUtils.SERVER_KEYSTORE_PATH)
         .withKeyStorePassword(TlsTestUtils.SERVER_KEYSTORE_PASSWORD)
@@ -64,10 +66,11 @@ public class EncryptionOptionsEqualityTest
         .withTrustStorePassword(TlsTestUtils.SERVER_TRUSTSTORE_PASSWORD)
         .withProtocol("TLSv1.1")
         .withRequireClientAuth(REQUIRED)
-        .withRequireEndpointVerification(false);
+        .withRequireEndpointVerification(false)
+        .build();
 
-        EncryptionOptions encryptionOptions2 =
-        new EncryptionOptions()
+        EncryptionOptions.ServerEncryptionOptions encryptionOptions2 =
+        new EncryptionOptions.ServerEncryptionOptions.Builder()
         .withStoreType("JKS")
         .withKeyStore(TlsTestUtils.SERVER_KEYSTORE_PATH)
         .withKeyStorePassword(TlsTestUtils.SERVER_KEYSTORE_PASSWORD)
@@ -75,7 +78,8 @@ public class EncryptionOptionsEqualityTest
         .withTrustStorePassword(TlsTestUtils.SERVER_TRUSTSTORE_PASSWORD)
         .withProtocol("TLSv1.1")
         .withRequireClientAuth(REQUIRED)
-        .withRequireEndpointVerification(false);
+        .withRequireEndpointVerification(false)
+        .build();
 
         assertEquals(encryptionOptions1, encryptionOptions2);
         assertEquals(encryptionOptions1.hashCode(), encryptionOptions2.hashCode());
@@ -83,8 +87,8 @@ public class EncryptionOptionsEqualityTest
 
     @Test
     public void testKeystoreOptionsWithPasswordFile() {
-        EncryptionOptions encryptionOptions1 =
-        new EncryptionOptions()
+        EncryptionOptions.ServerEncryptionOptions encryptionOptions1 =
+        new EncryptionOptions.ServerEncryptionOptions.Builder()
         .withStoreType("JKS")
         .withKeyStore(TlsTestUtils.SERVER_KEYSTORE_PATH)
         .withKeyStorePasswordFile(TlsTestUtils.SERVER_KEYSTORE_PASSWORD_FILE)
@@ -92,10 +96,11 @@ public class EncryptionOptionsEqualityTest
         .withTrustStorePasswordFile(TlsTestUtils.SERVER_TRUSTSTORE_PASSWORD_FILE)
         .withProtocol("TLSv1.1")
         .withRequireClientAuth(REQUIRED)
-        .withRequireEndpointVerification(false);
+        .withRequireEndpointVerification(false)
+        .build();
 
-        EncryptionOptions encryptionOptions2 =
-        new EncryptionOptions()
+        EncryptionOptions.ServerEncryptionOptions encryptionOptions2 =
+        new EncryptionOptions.ServerEncryptionOptions.Builder()
         .withStoreType("JKS")
         .withKeyStore(TlsTestUtils.SERVER_KEYSTORE_PATH)
         .withKeyStorePasswordFile(TlsTestUtils.SERVER_KEYSTORE_PASSWORD_FILE)
@@ -103,7 +108,8 @@ public class EncryptionOptionsEqualityTest
         .withTrustStorePasswordFile(TlsTestUtils.SERVER_TRUSTSTORE_PASSWORD_FILE)
         .withProtocol("TLSv1.1")
         .withRequireClientAuth(REQUIRED)
-        .withRequireEndpointVerification(false);
+        .withRequireEndpointVerification(false)
+        .build();
 
         assertEquals(encryptionOptions1, encryptionOptions2);
         assertEquals(encryptionOptions1.hashCode(), encryptionOptions2.hashCode());
@@ -115,15 +121,17 @@ public class EncryptionOptionsEqualityTest
         EncryptionOptions.ServerEncryptionOptions encryptionOptions1 = createServerEncryptionOptions();
         EncryptionOptions.ServerEncryptionOptions encryptionOptions2 = createServerEncryptionOptions();
 
-        encryptionOptions1 = encryptionOptions1
+        encryptionOptions1 = new EncryptionOptions.ServerEncryptionOptions.Builder(encryptionOptions1)
                              .withKeyStore(TlsTestUtils.SERVER_KEYSTORE_PATH)
                              .withKeyStorePassword(null)
-                             .withKeyStorePasswordFile(TlsTestUtils.SERVER_KEYSTORE_PASSWORD_FILE);
+                             .withKeyStorePasswordFile(TlsTestUtils.SERVER_KEYSTORE_PASSWORD_FILE)
+                             .build();
 
-        encryptionOptions2 = encryptionOptions2
+        encryptionOptions2 = new EncryptionOptions.ServerEncryptionOptions.Builder(encryptionOptions2)
                              .withKeyStore(TlsTestUtils.SERVER_KEYSTORE_PATH)
                              .withKeyStorePassword(null)
-                             .withKeyStorePasswordFile(TlsTestUtils.SERVER_TRUSTSTORE_PASSWORD_FILE);
+                             .withKeyStorePasswordFile(TlsTestUtils.SERVER_TRUSTSTORE_PASSWORD_FILE)
+                             .build();
 
         assertNotEquals(encryptionOptions1, encryptionOptions2);
         assertNotEquals(encryptionOptions1.hashCode(), encryptionOptions2.hashCode());
@@ -135,22 +143,24 @@ public class EncryptionOptionsEqualityTest
         Map<String,String> parameters1 = new HashMap<>();
         parameters1.put("key1", "value1");
         parameters1.put("key2", "value2");
-        EncryptionOptions encryptionOptions1 =
-        new EncryptionOptions()
+        EncryptionOptions.ClientEncryptionOptions encryptionOptions1 =
+        new EncryptionOptions.ClientEncryptionOptions.Builder()
         .withSslContextFactory(new ParameterizedClass(DummySslContextFactoryImpl.class.getName(), parameters1))
         .withProtocol("TLSv1.1")
         .withRequireClientAuth(REQUIRED)
-        .withRequireEndpointVerification(false);
+        .withRequireEndpointVerification(false)
+        .build();
 
         Map<String,String> parameters2 = new HashMap<>();
         parameters2.put("key1", "value1");
         parameters2.put("key2", "value2");
-        EncryptionOptions encryptionOptions2 =
-        new EncryptionOptions()
+        EncryptionOptions.ClientEncryptionOptions encryptionOptions2 =
+        new EncryptionOptions.ClientEncryptionOptions.Builder()
         .withSslContextFactory(new ParameterizedClass(DummySslContextFactoryImpl.class.getName(), parameters2))
         .withProtocol("TLSv1.1")
         .withRequireClientAuth(REQUIRED)
-        .withRequireEndpointVerification(false);
+        .withRequireEndpointVerification(false)
+        .build();
 
         assertEquals(encryptionOptions1, encryptionOptions2);
         assertEquals(encryptionOptions1.hashCode(), encryptionOptions2.hashCode());
@@ -162,22 +172,24 @@ public class EncryptionOptionsEqualityTest
         Map<String,String> parameters1 = new HashMap<>();
         parameters1.put("key1", "value1");
         parameters1.put("key2", "value2");
-        EncryptionOptions encryptionOptions1 =
-        new EncryptionOptions()
+        EncryptionOptions.ClientEncryptionOptions encryptionOptions1 =
+        new EncryptionOptions.ClientEncryptionOptions.Builder()
         .withSslContextFactory(new ParameterizedClass(DummySslContextFactoryImpl.class.getName(), parameters1))
         .withProtocol("TLSv1.1")
         .withRequireClientAuth(NOT_REQUIRED)
-        .withRequireEndpointVerification(true);
+        .withRequireEndpointVerification(true)
+        .build();
 
         Map<String,String> parameters2 = new HashMap<>();
         parameters2.put("key1", "value1");
         parameters2.put("key2", "value2");
-        EncryptionOptions encryptionOptions2 =
-        new EncryptionOptions()
+        EncryptionOptions.ClientEncryptionOptions encryptionOptions2 =
+        new EncryptionOptions.ClientEncryptionOptions.Builder()
         .withSslContextFactory(new ParameterizedClass(DefaultSslContextFactory.class.getName(), parameters2))
         .withProtocol("TLSv1.1")
         .withRequireClientAuth(NOT_REQUIRED)
-        .withRequireEndpointVerification(true);
+        .withRequireEndpointVerification(true)
+        .build();
 
         assertNotEquals(encryptionOptions1, encryptionOptions2);
         assertNotEquals(encryptionOptions1.hashCode(), encryptionOptions2.hashCode());
@@ -189,18 +201,20 @@ public class EncryptionOptionsEqualityTest
         Map<String,String> parameters1 = new HashMap<>();
         parameters1.put("key1", "value11");
         parameters1.put("key2", "value12");
-        EncryptionOptions encryptionOptions1 =
-        new EncryptionOptions()
+        EncryptionOptions.ClientEncryptionOptions encryptionOptions1 =
+        new EncryptionOptions.ClientEncryptionOptions.Builder()
         .withSslContextFactory(new ParameterizedClass(DummySslContextFactoryImpl.class.getName(), parameters1))
-        .withProtocol("TLSv1.1");
+        .withProtocol("TLSv1.1")
+        .build();
 
         Map<String,String> parameters2 = new HashMap<>();
         parameters2.put("key1", "value21");
         parameters2.put("key2", "value22");
-        EncryptionOptions encryptionOptions2 =
-        new EncryptionOptions()
+        EncryptionOptions.ClientEncryptionOptions encryptionOptions2 =
+        new EncryptionOptions.ClientEncryptionOptions.Builder()
         .withSslContextFactory(new ParameterizedClass(DummySslContextFactoryImpl.class.getName(), parameters2))
-        .withProtocol("TLSv1.1");
+        .withProtocol("TLSv1.1")
+        .build();
 
         assertNotEquals(encryptionOptions1, encryptionOptions2);
         assertNotEquals(encryptionOptions1.hashCode(), encryptionOptions2.hashCode());
@@ -222,13 +236,15 @@ public class EncryptionOptionsEqualityTest
         EncryptionOptions.ServerEncryptionOptions encryptionOptions1 = createServerEncryptionOptions();
         EncryptionOptions.ServerEncryptionOptions encryptionOptions2 = createServerEncryptionOptions();
 
-        encryptionOptions1 = encryptionOptions1
+        encryptionOptions1 = new EncryptionOptions.ServerEncryptionOptions.Builder(encryptionOptions1)
                              .withOutboundKeystore("test/conf/cassandra_outbound1.keystore")
-                             .withOutboundKeystorePassword("cassandra1");
+                             .withOutboundKeystorePassword("cassandra1")
+                             .build();
 
-        encryptionOptions2 = encryptionOptions2
+        encryptionOptions2 = new EncryptionOptions.ServerEncryptionOptions.Builder(encryptionOptions2)
                              .withOutboundKeystore("test/conf/cassandra_outbound2.keystore")
-                             .withOutboundKeystorePassword("cassandra2");
+                             .withOutboundKeystorePassword("cassandra2")
+                             .build();
 
         assertNotEquals(encryptionOptions1, encryptionOptions2);
         assertNotEquals(encryptionOptions1.hashCode(), encryptionOptions2.hashCode());
@@ -240,13 +256,15 @@ public class EncryptionOptionsEqualityTest
         EncryptionOptions.ServerEncryptionOptions encryptionOptions1 = createServerEncryptionOptions();
         EncryptionOptions.ServerEncryptionOptions encryptionOptions2 = createServerEncryptionOptions();
 
-        encryptionOptions1 = encryptionOptions1
+        encryptionOptions1 = new EncryptionOptions.ServerEncryptionOptions.Builder(encryptionOptions1)
                              .withKeyStore("test/conf/cassandra1.keystore")
-                             .withKeyStorePassword("cassandra1");
+                             .withKeyStorePassword("cassandra1")
+                             .build();
 
-        encryptionOptions2 = encryptionOptions2
+        encryptionOptions2 = new EncryptionOptions.ServerEncryptionOptions.Builder(encryptionOptions2)
                              .withKeyStore("test/conf/cassandra2.keystore")
-                             .withKeyStorePassword("cassandra2");
+                             .withKeyStorePassword("cassandra2")
+                             .build();
 
         assertNotEquals(encryptionOptions1, encryptionOptions2);
         assertNotEquals(encryptionOptions1.hashCode(), encryptionOptions2.hashCode());
diff --git a/test/unit/org/apache/cassandra/config/EncryptionOptionsTest.java b/test/unit/org/apache/cassandra/config/EncryptionOptionsTest.java
index 5ef08eb060..cec982d0c5 100644
--- a/test/unit/org/apache/cassandra/config/EncryptionOptionsTest.java
+++ b/test/unit/org/apache/cassandra/config/EncryptionOptionsTest.java
@@ -23,11 +23,11 @@ import java.util.HashMap;
 import java.util.Map;
 
 import com.google.common.collect.ImmutableMap;
-import org.apache.cassandra.io.util.File;
 import org.junit.Assert;
 import org.junit.Test;
 
 import org.apache.cassandra.exceptions.ConfigurationException;
+import org.apache.cassandra.io.util.File;
 import org.assertj.core.api.Assertions;
 import org.yaml.snakeyaml.constructor.ConstructorException;
 
@@ -46,11 +46,11 @@ public class EncryptionOptionsTest
 {
     static class EncryptionOptionsTestCase
     {
-        final EncryptionOptions encryptionOptions;
+        final EncryptionOptions.ClientEncryptionOptions encryptionOptions;
         final EncryptionOptions.TlsEncryptionPolicy expected;
         final String description;
 
-        public EncryptionOptionsTestCase(EncryptionOptions encryptionOptions, EncryptionOptions.TlsEncryptionPolicy expected, String description)
+        public EncryptionOptionsTestCase(EncryptionOptions.ClientEncryptionOptions encryptionOptions, EncryptionOptions.TlsEncryptionPolicy expected, String description)
         {
             this.encryptionOptions = encryptionOptions;
             this.expected = expected;
@@ -59,25 +59,25 @@ public class EncryptionOptionsTest
 
         public static EncryptionOptionsTestCase of(Boolean optional, String keystorePath, Boolean enabled, EncryptionOptions.TlsEncryptionPolicy expected)
         {
-            return new EncryptionOptionsTestCase(new EncryptionOptions(new ParameterizedClass("org.apache.cassandra.security.DefaultSslContextFactory",
-                                                                                              new HashMap<>()),
-                                                                       keystorePath, "dummypass", null,
-                                                                       "dummytruststore", "dummypass", null,
-                                                                       Collections.emptyList(), null, null, null, "JKS", "false", false, enabled, optional, null, null)
+            return new EncryptionOptionsTestCase(new EncryptionOptions.ClientEncryptionOptions(new ParameterizedClass("org.apache.cassandra.security.DefaultSslContextFactory",
+                                                                                                                      new HashMap<>()),
+                                                                                               keystorePath, "dummypass", null,
+                                                                                               "dummytruststore", "dummypass", null,
+                                                                                               Collections.emptyList(), null, null, null, "JKS", "false", false, enabled, optional, null, null)
                                                  .applyConfig(),
                                                  expected,
                                                  String.format("optional=%s keystore=%s enabled=%s", optional, keystorePath, enabled));
         }
 
         public static EncryptionOptionsTestCase of(Boolean optional, String keystorePath, Boolean enabled,
-                                                   Map<String,String> customSslContextFactoryParams,
+                                                   Map<String, String> customSslContextFactoryParams,
                                                    EncryptionOptions.TlsEncryptionPolicy expected)
         {
-            return new EncryptionOptionsTestCase(new EncryptionOptions(new ParameterizedClass("org.apache.cassandra.security.DefaultSslContextFactory",
-                                                                                              customSslContextFactoryParams),
-                                                                       keystorePath, "dummypass", null,
-                                                                       "dummytruststore", "dummypass", null,
-                                                                       Collections.emptyList(), null, null, null, "JKS", "false", false, enabled, optional, null, null)
+            return new EncryptionOptionsTestCase(new EncryptionOptions.ClientEncryptionOptions(new ParameterizedClass("org.apache.cassandra.security.DefaultSslContextFactory",
+                                                                                                                      customSslContextFactoryParams),
+                                                                                               keystorePath, "dummypass", null,
+                                                                                               "dummytruststore", "dummypass", null,
+                                                                                               Collections.emptyList(), null, null, null, "JKS", "false", false, enabled, optional, null, null)
                                                  .applyConfig(),
                                                  expected,
                                                  String.format("optional=%s keystore=%s enabled=%s", optional, keystorePath, enabled));
@@ -87,15 +87,15 @@ public class EncryptionOptionsTest
     static final String absentKeystore = "test/conf/missing-keystore-is-not-here";
     static final String presentKeystore = "test/conf/keystore.jks";
     final EncryptionOptionsTestCase[] encryptionOptionTestCases = {
-        //                         Optional    Keystore     Enabled  Expected
-        EncryptionOptionsTestCase.of(null, absentKeystore,  false, UNENCRYPTED),
-        EncryptionOptionsTestCase.of(null, absentKeystore,  true,  ENCRYPTED),
-        EncryptionOptionsTestCase.of(null, presentKeystore, false, OPTIONAL),
-        EncryptionOptionsTestCase.of(null, presentKeystore, true,  ENCRYPTED),
-        EncryptionOptionsTestCase.of(false, absentKeystore, false, UNENCRYPTED),
-        EncryptionOptionsTestCase.of(false, absentKeystore, true,  ENCRYPTED),
-        EncryptionOptionsTestCase.of(true, presentKeystore, false, OPTIONAL),
-        EncryptionOptionsTestCase.of(true, presentKeystore, true,  OPTIONAL)
+    //                         Optional    Keystore     Enabled  Expected
+    EncryptionOptionsTestCase.of(null, absentKeystore, false, UNENCRYPTED),
+    EncryptionOptionsTestCase.of(null, absentKeystore, true, ENCRYPTED),
+    EncryptionOptionsTestCase.of(null, presentKeystore, false, OPTIONAL),
+    EncryptionOptionsTestCase.of(null, presentKeystore, true, ENCRYPTED),
+    EncryptionOptionsTestCase.of(false, absentKeystore, false, UNENCRYPTED),
+    EncryptionOptionsTestCase.of(false, absentKeystore, true, ENCRYPTED),
+    EncryptionOptionsTestCase.of(true, presentKeystore, false, OPTIONAL),
+    EncryptionOptionsTestCase.of(true, presentKeystore, true, OPTIONAL)
     };
 
     @Test
@@ -111,11 +111,11 @@ public class EncryptionOptionsTest
 
     static class ServerEncryptionOptionsTestCase
     {
-        final EncryptionOptions encryptionOptions;
+        final EncryptionOptions.ServerEncryptionOptions encryptionOptions;
         final EncryptionOptions.TlsEncryptionPolicy expected;
         final String description;
 
-        public ServerEncryptionOptionsTestCase(EncryptionOptions encryptionOptions, EncryptionOptions.TlsEncryptionPolicy expected, String description)
+        public ServerEncryptionOptionsTestCase(EncryptionOptions.ServerEncryptionOptions encryptionOptions, EncryptionOptions.TlsEncryptionPolicy expected, String description)
         {
             this.encryptionOptions = encryptionOptions;
             this.expected = expected;
@@ -131,10 +131,10 @@ public class EncryptionOptionsTest
                                                                                                      keystorePath, "dummypass", null,
                                                                                                      keystorePath, "dummypass", null,
                                                                                                      "dummytruststore", "dummypass", null,
-                                                                                               Collections.emptyList(), null, null, null, "JKS", "false", false, optional, internodeEncryption, false, null, null)
+                                                                                                     Collections.emptyList(), null, null, null, "JKS", "false", false, optional, internodeEncryption, false, null, null)
                                                        .applyConfig(),
-                                                 expected,
-                                                 String.format("optional=%s keystore=%s internode=%s", optional, keystorePath, internodeEncryption));
+                                                       expected,
+                                                       String.format("optional=%s keystore=%s internode=%s", optional, keystorePath, internodeEncryption));
         }
     }
 
@@ -143,8 +143,8 @@ public class EncryptionOptionsTest
     {
         Map<String, Object> yaml = ImmutableMap.of(
         "server_encryption_options", ImmutableMap.of(
-            "isEnabled", false
-            )
+        "isEnabled", false
+        )
         );
 
         Assertions.assertThatThrownBy(() -> YamlConfigurationLoader.fromMap(yaml, Config.class))
@@ -157,8 +157,8 @@ public class EncryptionOptionsTest
     {
         Map<String, Object> yaml = ImmutableMap.of(
         "server_encryption_options", ImmutableMap.of(
-            "isOptional", false
-            )
+        "isOptional", false
+        )
         );
 
         Assertions.assertThatThrownBy(() -> YamlConfigurationLoader.fromMap(yaml, Config.class))
@@ -171,11 +171,11 @@ public class EncryptionOptionsTest
     {
         Map<String, Object> yaml = ImmutableMap.of(
         "server_encryption_options", ImmutableMap.of(
-            "max_certificate_validity_period", "2d"
-            ),
+        "max_certificate_validity_period", "2d"
+        ),
         "client_encryption_options", ImmutableMap.of(
-            "max_certificate_validity_period", "10d"
-            )
+        "max_certificate_validity_period", "10d"
+        )
         );
 
         Config config = YamlConfigurationLoader.fromMap(yaml, Config.class);
@@ -188,8 +188,8 @@ public class EncryptionOptionsTest
     {
         Map<String, Object> yaml = ImmutableMap.of(
         "server_encryption_options", ImmutableMap.of(
-            "max_certificate_validity_period", "not-a-valid-input"
-            )
+        "max_certificate_validity_period", "not-a-valid-input"
+        )
         );
 
         Assertions.assertThatThrownBy(() -> YamlConfigurationLoader.fromMap(yaml, Config.class))
@@ -202,8 +202,8 @@ public class EncryptionOptionsTest
     {
         Map<String, Object> yaml = ImmutableMap.of(
         "server_encryption_options", ImmutableMap.of(
-            "max_certificate_validity_period", "-2d"
-            )
+        "max_certificate_validity_period", "-2d"
+        )
         );
 
         Assertions.assertThatThrownBy(() -> YamlConfigurationLoader.fromMap(yaml, Config.class))
@@ -213,26 +213,26 @@ public class EncryptionOptionsTest
 
     final ServerEncryptionOptionsTestCase[] serverEncryptionOptionTestCases = {
 
-        //                               Optional    Keystore    Internode  Expected
-        ServerEncryptionOptionsTestCase.of(null, absentKeystore, none, UNENCRYPTED),
-        ServerEncryptionOptionsTestCase.of(null, absentKeystore, rack, OPTIONAL),
-        ServerEncryptionOptionsTestCase.of(null, absentKeystore, dc,   OPTIONAL),
-        ServerEncryptionOptionsTestCase.of(null, absentKeystore, all,  ENCRYPTED),
-
-        ServerEncryptionOptionsTestCase.of(null, presentKeystore, none, OPTIONAL),
-        ServerEncryptionOptionsTestCase.of(null, presentKeystore, rack, OPTIONAL),
-        ServerEncryptionOptionsTestCase.of(null, absentKeystore,  dc,   OPTIONAL),
-        ServerEncryptionOptionsTestCase.of(null, absentKeystore,  all,  ENCRYPTED),
-
-        ServerEncryptionOptionsTestCase.of(false, absentKeystore, none, UNENCRYPTED),
-        ServerEncryptionOptionsTestCase.of(false, absentKeystore, rack, OPTIONAL),
-        ServerEncryptionOptionsTestCase.of(false, absentKeystore, dc,   OPTIONAL),
-        ServerEncryptionOptionsTestCase.of(false, absentKeystore, all,  ENCRYPTED),
-
-        ServerEncryptionOptionsTestCase.of(true, presentKeystore, none, OPTIONAL),
-        ServerEncryptionOptionsTestCase.of(true, presentKeystore, rack, OPTIONAL),
-        ServerEncryptionOptionsTestCase.of(true, absentKeystore,  dc,   OPTIONAL),
-        ServerEncryptionOptionsTestCase.of(true, absentKeystore,  all,  OPTIONAL),
+    //                               Optional    Keystore    Internode  Expected
+    ServerEncryptionOptionsTestCase.of(null, absentKeystore, none, UNENCRYPTED),
+    ServerEncryptionOptionsTestCase.of(null, absentKeystore, rack, OPTIONAL),
+    ServerEncryptionOptionsTestCase.of(null, absentKeystore, dc, OPTIONAL),
+    ServerEncryptionOptionsTestCase.of(null, absentKeystore, all, ENCRYPTED),
+
+    ServerEncryptionOptionsTestCase.of(null, presentKeystore, none, OPTIONAL),
+    ServerEncryptionOptionsTestCase.of(null, presentKeystore, rack, OPTIONAL),
+    ServerEncryptionOptionsTestCase.of(null, absentKeystore, dc, OPTIONAL),
+    ServerEncryptionOptionsTestCase.of(null, absentKeystore, all, ENCRYPTED),
+
+    ServerEncryptionOptionsTestCase.of(false, absentKeystore, none, UNENCRYPTED),
+    ServerEncryptionOptionsTestCase.of(false, absentKeystore, rack, OPTIONAL),
+    ServerEncryptionOptionsTestCase.of(false, absentKeystore, dc, OPTIONAL),
+    ServerEncryptionOptionsTestCase.of(false, absentKeystore, all, ENCRYPTED),
+
+    ServerEncryptionOptionsTestCase.of(true, presentKeystore, none, OPTIONAL),
+    ServerEncryptionOptionsTestCase.of(true, presentKeystore, rack, OPTIONAL),
+    ServerEncryptionOptionsTestCase.of(true, absentKeystore, dc, OPTIONAL),
+    ServerEncryptionOptionsTestCase.of(true, absentKeystore, all, OPTIONAL),
     };
 
     @Test
@@ -246,12 +246,12 @@ public class EncryptionOptionsTest
         }
     }
 
-    @Test(expected =  IllegalArgumentException.class)
+    @Test(expected = IllegalArgumentException.class)
     public void testMisplacedConfigKey()
     {
         Map<String, String> customSslContextFactoryParams = new HashMap<>();
 
-        for(EncryptionOptions.ConfigKey configKey: EncryptionOptions.ConfigKey.values())
+        for (EncryptionOptions.ConfigKey configKey : EncryptionOptions.ConfigKey.values())
         {
             customSslContextFactoryParams.put(configKey.toString(), "my-custom-value");
         }
diff --git a/test/unit/org/apache/cassandra/cql3/CQLTester.java b/test/unit/org/apache/cassandra/cql3/CQLTester.java
index 91d86d2c81..05c64f956e 100644
--- a/test/unit/org/apache/cassandra/cql3/CQLTester.java
+++ b/test/unit/org/apache/cassandra/cql3/CQLTester.java
@@ -663,13 +663,15 @@ public abstract class CQLTester
     public static void requireNativeProtocolClientEncryption()
     {
         DatabaseDescriptor.updateNativeProtocolEncryptionOptions((encryptionOptions) ->
-                                                                 encryptionOptions.withEnabled(true)
-                                                                                  .withKeyStore(TlsTestUtils.SERVER_KEYSTORE_PATH)
-                                                                                  .withKeyStorePassword(TlsTestUtils.SERVER_KEYSTORE_PASSWORD)
-                                                                                  .withTrustStore(TlsTestUtils.SERVER_TRUSTSTORE_PATH)
-                                                                                  .withTrustStorePassword(TlsTestUtils.SERVER_TRUSTSTORE_PASSWORD)
-                                                                                  .withRequireEndpointVerification(false)
-                                                                                  .withRequireClientAuth(EncryptionOptions.ClientAuth.OPTIONAL));
+                                                                 new EncryptionOptions.ClientEncryptionOptions.Builder(encryptionOptions)
+                                                                 .withEnabled(true)
+                                                                 .withKeyStore(TlsTestUtils.SERVER_KEYSTORE_PATH)
+                                                                 .withKeyStorePassword(TlsTestUtils.SERVER_KEYSTORE_PASSWORD)
+                                                                 .withTrustStore(TlsTestUtils.SERVER_TRUSTSTORE_PATH)
+                                                                 .withTrustStorePassword(TlsTestUtils.SERVER_TRUSTSTORE_PASSWORD)
+                                                                 .withRequireEndpointVerification(false)
+                                                                 .withRequireClientAuth(EncryptionOptions.ClientEncryptionOptions.ClientAuth.OPTIONAL)
+                                                                 .build());
     }
 
     /**
@@ -1691,7 +1693,7 @@ public abstract class CQLTester
 
     protected SimpleClient newSimpleClient(ProtocolVersion version) throws IOException
     {
-        return new SimpleClient(nativeAddr.getHostAddress(), nativePort, version, version.isBeta(), new EncryptionOptions().applyConfig())
+        return new SimpleClient(nativeAddr.getHostAddress(), nativePort, version, version.isBeta(), new EncryptionOptions.ClientEncryptionOptions())
                .connect(false, false);
     }
 
diff --git a/test/unit/org/apache/cassandra/db/virtual/SettingsTableTest.java b/test/unit/org/apache/cassandra/db/virtual/SettingsTableTest.java
index 71b9172da7..78fb0d47d6 100644
--- a/test/unit/org/apache/cassandra/db/virtual/SettingsTableTest.java
+++ b/test/unit/org/apache/cassandra/db/virtual/SettingsTableTest.java
@@ -31,6 +31,7 @@ import com.datastax.driver.core.ResultSet;
 import com.datastax.driver.core.Row;
 import org.apache.cassandra.config.Config;
 import org.apache.cassandra.config.DurationSpec;
+import org.apache.cassandra.config.EncryptionOptions.ServerEncryptionOptions.Builder;
 import org.apache.cassandra.config.EncryptionOptions.ServerEncryptionOptions.InternodeEncryption;
 import org.apache.cassandra.config.JMXServerOptions;
 import org.apache.cassandra.config.ParameterizedClass;
@@ -38,7 +39,7 @@ import org.apache.cassandra.cql3.CQLTester;
 import org.apache.cassandra.security.SSLFactory;
 import org.yaml.snakeyaml.introspector.Property;
 
-import static org.apache.cassandra.config.EncryptionOptions.ClientAuth.REQUIRED;
+import static org.apache.cassandra.config.EncryptionOptions.ClientEncryptionOptions.ClientAuth.REQUIRED;
 
 public class SettingsTableTest extends CQLTester
 {
@@ -176,52 +177,53 @@ public class SettingsTableTest extends CQLTester
         List<String> expectedNames = SettingsTable.PROPERTIES.keySet().stream().filter(n -> n.startsWith("server_encryption")).collect(Collectors.toList());
         Assert.assertEquals(expectedNames.size(), executeNet(all).all().size());
 
+        Builder serverEncryptionOptionsBuilder = new Builder(config.server_encryption_options);
         check(pre + "algorithm", null);
-        config.server_encryption_options = config.server_encryption_options.withAlgorithm("SUPERSSL");
+        config.server_encryption_options = serverEncryptionOptionsBuilder.withAlgorithm("SUPERSSL").build();
         check(pre + "algorithm", "SUPERSSL");
 
         check(pre + "cipher_suites", null);
-        config.server_encryption_options = config.server_encryption_options.withCipherSuites("c1", "c2");
+        config.server_encryption_options = serverEncryptionOptionsBuilder.withCipherSuites("c1", "c2").build();
         check(pre + "cipher_suites", "[c1, c2]");
 
         // name doesn't match yaml
         check(pre + "protocol", null);
-        config.server_encryption_options = config.server_encryption_options.withProtocol("TLSv5");
+        config.server_encryption_options = serverEncryptionOptionsBuilder.withProtocol("TLSv5").build();
         check(pre + "protocol", "[TLSv5]");
 
-        config.server_encryption_options = config.server_encryption_options.withProtocol("TLS");
+        config.server_encryption_options = serverEncryptionOptionsBuilder.withProtocol("TLS").build();
         check(pre + "protocol", SSLFactory.tlsInstanceProtocolSubstitution().toString());
 
-        config.server_encryption_options = config.server_encryption_options.withProtocol("TLS");
-        config.server_encryption_options = config.server_encryption_options.withAcceptedProtocols(ImmutableList.of("TLSv1.2","TLSv1.1"));
+        config.server_encryption_options = serverEncryptionOptionsBuilder.withProtocol("TLS").build();
+        config.server_encryption_options = serverEncryptionOptionsBuilder.withAcceptedProtocols(ImmutableList.of("TLSv1.2","TLSv1.1")).build();
         check(pre + "protocol", "[TLSv1.2, TLSv1.1]");
 
-        config.server_encryption_options = config.server_encryption_options.withProtocol("TLSv2");
-        config.server_encryption_options = config.server_encryption_options.withAcceptedProtocols(ImmutableList.of("TLSv1.2","TLSv1.1"));
+        config.server_encryption_options = serverEncryptionOptionsBuilder.withProtocol("TLSv2").build();
+        config.server_encryption_options = serverEncryptionOptionsBuilder.withAcceptedProtocols(ImmutableList.of("TLSv1.2","TLSv1.1")).build();
         check(pre + "protocol", "[TLSv1.2, TLSv1.1, TLSv2]"); // protocol goes after the explicit accept list if non-TLS
 
         check(pre + "optional", "false");
-        config.server_encryption_options = config.server_encryption_options.withOptional(true);
+        config.server_encryption_options = serverEncryptionOptionsBuilder.withOptional(true).build();
         check(pre + "optional", "true");
 
         // name doesn't match yaml
         check(pre + "client_auth", "false");
-        config.server_encryption_options = config.server_encryption_options.withRequireClientAuth(REQUIRED);
+        config.server_encryption_options = serverEncryptionOptionsBuilder.withRequireClientAuth(REQUIRED).build();
         check(pre + "client_auth", "true");
 
         // name doesn't match yaml
         check(pre + "endpoint_verification", "false");
-        config.server_encryption_options = config.server_encryption_options.withRequireEndpointVerification(true);
+        config.server_encryption_options = serverEncryptionOptionsBuilder.withRequireEndpointVerification(true).build();
         check(pre + "endpoint_verification", "true");
 
         check(pre + "internode_encryption", "none");
-        config.server_encryption_options = config.server_encryption_options.withInternodeEncryption(InternodeEncryption.all);
+        config.server_encryption_options = serverEncryptionOptionsBuilder.withInternodeEncryption(InternodeEncryption.all).build();
         check(pre + "internode_encryption", "all");
         check(pre + "enabled", "true");
 
         // name doesn't match yaml
         check(pre + "legacy_ssl_storage_port", "false");
-        config.server_encryption_options = config.server_encryption_options.withLegacySslStoragePort(true);
+        config.server_encryption_options = serverEncryptionOptionsBuilder.withLegacySslStoragePort(true).build();
         check(pre + "legacy_ssl_storage_port", "true");
     }
 
diff --git a/test/unit/org/apache/cassandra/net/ConnectionTest.java b/test/unit/org/apache/cassandra/net/ConnectionTest.java
index 70bb0c8046..233d067d12 100644
--- a/test/unit/org/apache/cassandra/net/ConnectionTest.java
+++ b/test/unit/org/apache/cassandra/net/ConnectionTest.java
@@ -57,6 +57,7 @@ import io.netty.channel.ChannelOutboundHandlerAdapter;
 import io.netty.channel.ChannelPromise;
 import org.apache.cassandra.config.DatabaseDescriptor;
 import org.apache.cassandra.config.EncryptionOptions;
+import org.apache.cassandra.config.EncryptionOptions.ServerEncryptionOptions.Builder;
 import org.apache.cassandra.db.commitlog.CommitLog;
 import org.apache.cassandra.distributed.test.log.ClusterMetadataTestHelper;
 import org.apache.cassandra.exceptions.RequestFailure;
@@ -72,7 +73,7 @@ import org.apache.cassandra.utils.FBUtilities;
 import static java.util.concurrent.TimeUnit.MILLISECONDS;
 import static java.util.concurrent.TimeUnit.MINUTES;
 import static java.util.concurrent.TimeUnit.SECONDS;
-import static org.apache.cassandra.config.EncryptionOptions.ClientAuth.NOT_REQUIRED;
+import static org.apache.cassandra.config.EncryptionOptions.ClientEncryptionOptions.ClientAuth.NOT_REQUIRED;
 import static org.apache.cassandra.net.MessagingService.VERSION_40;
 import static org.apache.cassandra.net.NoPayload.noPayload;
 import static org.apache.cassandra.net.MessagingService.current_version;
@@ -176,17 +177,18 @@ public class ConnectionTest
         }
     }
 
-    static final EncryptionOptions.ServerEncryptionOptions encryptionOptions =
-            new EncryptionOptions.ServerEncryptionOptions()
+    static final EncryptionOptions.Builder<EncryptionOptions.ServerEncryptionOptions> encryptionOptionsBuilder =
+            new Builder()
             .withLegacySslStoragePort(true)
-            .withOptional(true)
             .withInternodeEncryption(EncryptionOptions.ServerEncryptionOptions.InternodeEncryption.all)
+            .withOptional(true)
             .withKeyStore(TlsTestUtils.SERVER_KEYSTORE_PATH)
             .withKeyStorePassword(TlsTestUtils.SERVER_KEYSTORE_PASSWORD)
             .withTrustStore(TlsTestUtils.SERVER_TRUSTSTORE_PATH)
             .withTrustStorePassword(TlsTestUtils.SERVER_TRUSTSTORE_PASSWORD)
             .withRequireClientAuth(NOT_REQUIRED)
             .withCipherSuites("TLS_RSA_WITH_AES_128_CBC_SHA");
+    static final EncryptionOptions.ServerEncryptionOptions encryptionOptions = encryptionOptionsBuilder.build();
 
     static final List<Function<Settings, Settings>> MODIFIERS = ImmutableList.of(
         settings -> settings.outbound(outbound -> outbound.withEncryption(encryptionOptions))
diff --git a/test/unit/org/apache/cassandra/net/HandshakeTest.java b/test/unit/org/apache/cassandra/net/HandshakeTest.java
index c84643497d..2806bac86d 100644
--- a/test/unit/org/apache/cassandra/net/HandshakeTest.java
+++ b/test/unit/org/apache/cassandra/net/HandshakeTest.java
@@ -39,6 +39,7 @@ import io.netty.channel.EventLoop;
 import io.netty.util.concurrent.Future;
 import org.apache.cassandra.config.DatabaseDescriptor;
 import org.apache.cassandra.config.EncryptionOptions.ServerEncryptionOptions;
+import org.apache.cassandra.config.EncryptionOptions.ServerEncryptionOptions.Builder;
 import org.apache.cassandra.config.ParameterizedClass;
 import org.apache.cassandra.db.commitlog.CommitLog;
 import org.apache.cassandra.distributed.test.log.ClusterMetadataTestHelper;
@@ -49,9 +50,9 @@ import org.apache.cassandra.security.DefaultSslContextFactory;
 import org.apache.cassandra.transport.TlsTestUtils;
 import org.apache.cassandra.utils.concurrent.AsyncPromise;
 
+import static org.apache.cassandra.config.EncryptionOptions.ClientEncryptionOptions.ClientAuth.NOT_REQUIRED;
+import static org.apache.cassandra.config.EncryptionOptions.ClientEncryptionOptions.ClientAuth.REQUIRED;
 import static org.apache.cassandra.net.ConnectionType.SMALL_MESSAGES;
-import static org.apache.cassandra.config.EncryptionOptions.ClientAuth.NOT_REQUIRED;
-import static org.apache.cassandra.config.EncryptionOptions.ClientAuth.REQUIRED;
 import static org.apache.cassandra.net.MessagingService.current_version;
 import static org.apache.cassandra.net.MessagingService.minimum_version;
 import static org.apache.cassandra.net.OutboundConnectionInitiator.Result;
@@ -279,26 +280,28 @@ public class HandshakeTest
 
     private ServerEncryptionOptions getServerEncryptionOptions(SslFallbackConnectionType sslConnectionType, boolean optional)
     {
-        ServerEncryptionOptions serverEncryptionOptions = new ServerEncryptionOptions().withOptional(optional)
-                                                                                       .withKeyStore(TlsTestUtils.SERVER_KEYSTORE_PATH)
-                                                                                       .withKeyStorePassword(TlsTestUtils.SERVER_KEYSTORE_PASSWORD)
-                                                                                       .withOutboundKeystore(TlsTestUtils.SERVER_OUTBOUND_KEYSTORE_PATH)
-                                                                                       .withOutboundKeystorePassword(TlsTestUtils.SERVER_OUTBOUND_KEYSTORE_PASSWORD)
-                                                                                       .withTrustStore(TlsTestUtils.SERVER_TRUSTSTORE_PATH)
-                                                                                       .withTrustStorePassword(TlsTestUtils.SERVER_TRUSTSTORE_PASSWORD)
-                                                                                       .withSslContextFactory((new ParameterizedClass(DefaultSslContextFactory.class.getName(),
-                                                                                                                                      new HashMap<>())));
+        Builder serverEncryptionOptionsBuilder = new Builder();
+
+        serverEncryptionOptionsBuilder.withOutboundKeystore(TlsTestUtils.SERVER_OUTBOUND_KEYSTORE_PATH)
+                                      .withOutboundKeystorePassword(TlsTestUtils.SERVER_OUTBOUND_KEYSTORE_PASSWORD)
+                                      .withOptional(optional)
+                                      .withKeyStore(TlsTestUtils.SERVER_KEYSTORE_PATH)
+                                      .withKeyStorePassword(TlsTestUtils.SERVER_KEYSTORE_PASSWORD)
+                                      .withTrustStore(TlsTestUtils.SERVER_TRUSTSTORE_PATH).withTrustStorePassword(TlsTestUtils.SERVER_TRUSTSTORE_PASSWORD)
+                                      .withSslContextFactory((new ParameterizedClass(DefaultSslContextFactory.class.getName(),
+                                                                                      new HashMap<>())));
+
         if (sslConnectionType == SslFallbackConnectionType.MTLS)
         {
-            serverEncryptionOptions = serverEncryptionOptions.withInternodeEncryption(ServerEncryptionOptions.InternodeEncryption.all)
-                                                             .withRequireClientAuth(REQUIRED);
+            serverEncryptionOptionsBuilder.withInternodeEncryption(ServerEncryptionOptions.InternodeEncryption.all)
+                                          .withRequireClientAuth(REQUIRED);
         }
         else if (sslConnectionType == SslFallbackConnectionType.SSL)
         {
-            serverEncryptionOptions = serverEncryptionOptions.withInternodeEncryption(ServerEncryptionOptions.InternodeEncryption.all)
-                                                             .withRequireClientAuth(NOT_REQUIRED);
+            serverEncryptionOptionsBuilder.withInternodeEncryption(ServerEncryptionOptions.InternodeEncryption.all)
+                                          .withRequireClientAuth(NOT_REQUIRED);
         }
-        return serverEncryptionOptions;
+        return serverEncryptionOptionsBuilder.build();
     }
 
     private InboundSockets getInboundSocket(ServerEncryptionOptions serverEncryptionOptions)
diff --git a/test/unit/org/apache/cassandra/net/MessagingServiceTest.java b/test/unit/org/apache/cassandra/net/MessagingServiceTest.java
index 95c72f4bc0..45746d5e6e 100644
--- a/test/unit/org/apache/cassandra/net/MessagingServiceTest.java
+++ b/test/unit/org/apache/cassandra/net/MessagingServiceTest.java
@@ -50,6 +50,7 @@ import com.codahale.metrics.Timer;
 import org.apache.cassandra.auth.IInternodeAuthenticator;
 import org.apache.cassandra.config.DatabaseDescriptor;
 import org.apache.cassandra.config.EncryptionOptions.ServerEncryptionOptions;
+import org.apache.cassandra.config.EncryptionOptions.ServerEncryptionOptions.Builder;
 import org.apache.cassandra.db.commitlog.CommitLog;
 import org.apache.cassandra.distributed.test.log.ClusterMetadataTestHelper;
 import org.apache.cassandra.exceptions.ConfigurationException;
@@ -257,8 +258,7 @@ public class MessagingServiceTest
     public void testFailedOutboundInternodeAuth() throws Exception
     {
         // Listen on serverside for connections
-        ServerEncryptionOptions serverEncryptionOptions = new ServerEncryptionOptions()
-        .withInternodeEncryption(ServerEncryptionOptions.InternodeEncryption.none);
+        ServerEncryptionOptions serverEncryptionOptions = new Builder().withInternodeEncryption(ServerEncryptionOptions.InternodeEncryption.none).build();
 
         DatabaseDescriptor.setInternodeAuthenticator(REJECT_OUTBOUND_AUTHENTICATOR);
         InetAddress listenAddress = FBUtilities.getJustLocalAddress();
@@ -293,8 +293,7 @@ public class MessagingServiceTest
     @Test
     public void testFailedInboundInternodeAuth() throws IOException, InterruptedException
     {
-        ServerEncryptionOptions serverEncryptionOptions = new ServerEncryptionOptions()
-            .withInternodeEncryption(ServerEncryptionOptions.InternodeEncryption.none);
+        ServerEncryptionOptions serverEncryptionOptions = new Builder().withInternodeEncryption(ServerEncryptionOptions.InternodeEncryption.none).build();
 
         DatabaseDescriptor.setInternodeAuthenticator(ALLOW_NOTHING_AUTHENTICATOR);
         InetAddress listenAddress = FBUtilities.getJustLocalAddress();
@@ -348,56 +347,54 @@ public class MessagingServiceTest
     @Test
     public void listenPlainConnection() throws InterruptedException
     {
-        ServerEncryptionOptions serverEncryptionOptions = new ServerEncryptionOptions()
-                                                          .withInternodeEncryption(ServerEncryptionOptions.InternodeEncryption.none);
+        ServerEncryptionOptions serverEncryptionOptions = new Builder().withInternodeEncryption(ServerEncryptionOptions.InternodeEncryption.none).build();
         listen(serverEncryptionOptions, false);
     }
 
     @Test
     public void listenPlainConnectionWithBroadcastAddr() throws InterruptedException
     {
-        ServerEncryptionOptions serverEncryptionOptions = new ServerEncryptionOptions()
-                                                          .withInternodeEncryption(ServerEncryptionOptions.InternodeEncryption.none);
+        ServerEncryptionOptions serverEncryptionOptions = new Builder().withInternodeEncryption(ServerEncryptionOptions.InternodeEncryption.none).build();
         listen(serverEncryptionOptions, true);
     }
 
     @Test
     public void listenRequiredSecureConnection() throws InterruptedException
     {
-        ServerEncryptionOptions serverEncryptionOptions = new ServerEncryptionOptions()
-                                                          .withOptional(false)
-                                                          .withInternodeEncryption(ServerEncryptionOptions.InternodeEncryption.all)
-                                                          .withLegacySslStoragePort(false);
+        ServerEncryptionOptions serverEncryptionOptions = new Builder().withInternodeEncryption(ServerEncryptionOptions.InternodeEncryption.all)
+                                                                       .withLegacySslStoragePort(false)
+                                                                       .withOptional(false)
+                                                                       .build();
         listen(serverEncryptionOptions, false);
     }
 
     @Test
     public void listenRequiredSecureConnectionWithBroadcastAddr() throws InterruptedException
     {
-        ServerEncryptionOptions serverEncryptionOptions = new ServerEncryptionOptions()
-                                                          .withOptional(false)
-                                                          .withInternodeEncryption(ServerEncryptionOptions.InternodeEncryption.all)
-                                                          .withLegacySslStoragePort(false);
+        ServerEncryptionOptions serverEncryptionOptions = new Builder().withInternodeEncryption(ServerEncryptionOptions.InternodeEncryption.all)
+                                                                       .withLegacySslStoragePort(false)
+                                                                       .withOptional(false)
+                                                                       .build();
         listen(serverEncryptionOptions, true);
     }
 
     @Test
     public void listenRequiredSecureConnectionWithLegacyPort() throws InterruptedException
     {
-        ServerEncryptionOptions serverEncryptionOptions = new ServerEncryptionOptions()
-                                                          .withInternodeEncryption(ServerEncryptionOptions.InternodeEncryption.all)
-                                                          .withOptional(false)
-                                                          .withLegacySslStoragePort(true);
+        ServerEncryptionOptions serverEncryptionOptions = new Builder().withInternodeEncryption(ServerEncryptionOptions.InternodeEncryption.all)
+                                                                       .withLegacySslStoragePort(true)
+                                                                       .withOptional(false)
+                                                                       .build();
         listen(serverEncryptionOptions, false);
     }
 
     @Test
     public void listenRequiredSecureConnectionWithBroadcastAddrAndLegacyPort() throws InterruptedException
     {
-        ServerEncryptionOptions serverEncryptionOptions = new ServerEncryptionOptions()
-                                                          .withInternodeEncryption(ServerEncryptionOptions.InternodeEncryption.all)
-                                                          .withOptional(false)
-                                                          .withLegacySslStoragePort(true);
+        ServerEncryptionOptions serverEncryptionOptions = new Builder().withInternodeEncryption(ServerEncryptionOptions.InternodeEncryption.all)
+                                                                       .withLegacySslStoragePort(true)
+                                                                       .withOptional(false)
+                                                                       .build();
         listen(serverEncryptionOptions, true);
     }
 
@@ -406,8 +403,7 @@ public class MessagingServiceTest
     {
         for (int i = 0; i < 500; i++) // test used to be flaky, so run in a loop to make sure stable (see CASSANDRA-17033)
         {
-            ServerEncryptionOptions serverEncryptionOptions = new ServerEncryptionOptions()
-                                                              .withOptional(true);
+            ServerEncryptionOptions serverEncryptionOptions = new Builder().withOptional(true).build();
             listen(serverEncryptionOptions, false);
         }
     }
@@ -415,8 +411,7 @@ public class MessagingServiceTest
     @Test
     public void listenOptionalSecureConnectionWithBroadcastAddr() throws InterruptedException
     {
-        ServerEncryptionOptions serverEncryptionOptions = new ServerEncryptionOptions()
-                                                          .withOptional(true);
+        ServerEncryptionOptions serverEncryptionOptions = new Builder().withOptional(true).build();
         listen(serverEncryptionOptions, true);
     }
 
diff --git a/test/unit/org/apache/cassandra/security/DefaultSslContextFactoryTest.java b/test/unit/org/apache/cassandra/security/DefaultSslContextFactoryTest.java
index fa3eb7c845..5dc6d7e39b 100644
--- a/test/unit/org/apache/cassandra/security/DefaultSslContextFactoryTest.java
+++ b/test/unit/org/apache/cassandra/security/DefaultSslContextFactoryTest.java
@@ -33,17 +33,17 @@ import io.netty.handler.ssl.OpenSslContext;
 import io.netty.handler.ssl.SslContext;
 import io.netty.handler.ssl.SslProvider;
 import org.apache.cassandra.config.EncryptionOptions;
+import org.apache.cassandra.config.EncryptionOptions.ServerEncryptionOptions.Builder;
 import org.apache.cassandra.distributed.shared.WithProperties;
 import org.apache.cassandra.transport.TlsTestUtils;
 
 import static org.apache.cassandra.config.CassandraRelevantProperties.DISABLE_TCACTIVE_OPENSSL;
-
-import static org.apache.cassandra.config.EncryptionOptions.ClientAuth.NOT_REQUIRED;
-import static org.apache.cassandra.config.EncryptionOptions.ClientAuth.REQUIRED;
+import static org.apache.cassandra.config.EncryptionOptions.ClientEncryptionOptions.ClientAuth.NOT_REQUIRED;
+import static org.apache.cassandra.config.EncryptionOptions.ClientEncryptionOptions.ClientAuth.REQUIRED;
 
 public class DefaultSslContextFactoryTest
 {
-    private Map<String,Object> commonConfig = new HashMap<>();
+    private Map<String, Object> commonConfig = new HashMap<>();
 
     @Before
     public void setup()
@@ -54,7 +54,7 @@ public class DefaultSslContextFactoryTest
         commonConfig.put("cipher_suites", Arrays.asList("TLS_RSA_WITH_AES_128_CBC_SHA"));
     }
 
-    private void addKeystoreOptions(Map<String,Object> config)
+    private void addKeystoreOptions(Map<String, Object> config)
     {
         config.put("keystore", TlsTestUtils.SERVER_KEYSTORE_PATH);
         config.put("keystore_password", TlsTestUtils.SERVER_KEYSTORE_PASSWORD);
@@ -69,14 +69,18 @@ public class DefaultSslContextFactoryTest
     @Test
     public void getSslContextOpenSSL() throws IOException
     {
-        EncryptionOptions.ServerEncryptionOptions options = new EncryptionOptions.ServerEncryptionOptions().withTrustStore(TlsTestUtils.SERVER_TRUSTSTORE_PATH)
-                                                                                                           .withTrustStorePassword(TlsTestUtils.SERVER_TRUSTSTORE_PASSWORD)
-                                                                                                           .withKeyStore(TlsTestUtils.SERVER_KEYSTORE_PATH)
-                                                                                                           .withKeyStorePassword(TlsTestUtils.SERVER_KEYSTORE_PASSWORD)
-                                                                                                           .withOutboundKeystore(TlsTestUtils.SERVER_OUTBOUND_KEYSTORE_PATH)
-                                                                                                           .withOutboundKeystorePassword(TlsTestUtils.SERVER_OUTBOUND_KEYSTORE_PASSWORD)
-                                                                                                           .withRequireClientAuth(NOT_REQUIRED)
-                                                                                                           .withCipherSuites("TLS_RSA_WITH_AES_128_CBC_SHA");
+        EncryptionOptions.ServerEncryptionOptions.Builder builder = new Builder();
+        EncryptionOptions.ServerEncryptionOptions options = builder
+                                                            .withOutboundKeystore(TlsTestUtils.SERVER_OUTBOUND_KEYSTORE_PATH)
+                                                            .withOutboundKeystorePassword(TlsTestUtils.SERVER_OUTBOUND_KEYSTORE_PASSWORD)
+                                                            .withTrustStore(TlsTestUtils.SERVER_TRUSTSTORE_PATH)
+                                                            .withTrustStorePassword(TlsTestUtils.SERVER_TRUSTSTORE_PASSWORD)
+                                                            .withKeyStore(TlsTestUtils.SERVER_KEYSTORE_PATH)
+                                                            .withKeyStorePassword(TlsTestUtils.SERVER_KEYSTORE_PASSWORD)
+                                                            .withRequireClientAuth(NOT_REQUIRED)
+                                                            .withCipherSuites("TLS_RSA_WITH_AES_128_CBC_SHA")
+                                                            .build();
+
         SslContext sslContext = SSLFactory.getOrCreateSslContext(options, REQUIRED, ISslContextFactory.SocketType.CLIENT, "test");
         Assert.assertNotNull(sslContext);
         if (OpenSsl.isAvailable())
@@ -88,7 +92,7 @@ public class DefaultSslContextFactoryTest
     @Test(expected = IOException.class)
     public void buildTrustManagerFactoryWithInvalidTruststoreFile() throws IOException
     {
-        Map<String,Object> config = new HashMap<>();
+        Map<String, Object> config = new HashMap<>();
         config.putAll(commonConfig);
         config.put("truststore", "/this/is/probably/not/a/file/on/your/test/machine");
 
@@ -100,7 +104,7 @@ public class DefaultSslContextFactoryTest
     @Test(expected = IOException.class)
     public void buildTrustManagerFactoryWithBadPassword() throws IOException
     {
-        Map<String,Object> config = new HashMap<>();
+        Map<String, Object> config = new HashMap<>();
         config.putAll(commonConfig);
         config.put("truststore_password", "HomeOfBadPasswords");
 
@@ -112,7 +116,7 @@ public class DefaultSslContextFactoryTest
     @Test
     public void buildTrustManagerFactoryHappyPath() throws IOException
     {
-        Map<String,Object> config = new HashMap<>();
+        Map<String, Object> config = new HashMap<>();
         config.putAll(commonConfig);
 
         DefaultSslContextFactory defaultSslContextFactoryImpl = new DefaultSslContextFactory(config);
@@ -124,7 +128,7 @@ public class DefaultSslContextFactoryTest
     @Test(expected = IOException.class)
     public void buildKeyManagerFactoryWithInvalidKeystoreFile() throws IOException
     {
-        Map<String,Object> config = new HashMap<>();
+        Map<String, Object> config = new HashMap<>();
         config.putAll(commonConfig);
         config.put("keystore", "/this/is/probably/not/a/file/on/your/test/machine");
         config.put("keystore_password", "ThisWontMatter");
@@ -137,7 +141,7 @@ public class DefaultSslContextFactoryTest
     @Test(expected = IOException.class)
     public void buildKeyManagerFactoryWithBadPassword() throws IOException
     {
-        Map<String,Object> config = new HashMap<>();
+        Map<String, Object> config = new HashMap<>();
         config.putAll(commonConfig);
         addKeystoreOptions(config);
         config.put("keystore_password", "HomeOfBadPasswords");
@@ -149,7 +153,7 @@ public class DefaultSslContextFactoryTest
     @Test
     public void buildKeyManagerFactoryHappyPath() throws IOException
     {
-        Map<String,Object> config = new HashMap<>();
+        Map<String, Object> config = new HashMap<>();
         config.putAll(commonConfig);
 
         DefaultSslContextFactory defaultSslContextFactoryImpl = new DefaultSslContextFactory(config);
@@ -222,12 +226,13 @@ public class DefaultSslContextFactoryTest
     }
 
     @Test
-    public void testDisableOpenSslForInJvmDtests() {
+    public void testDisableOpenSslForInJvmDtests()
+    {
         // The configuration name below is hard-coded intentionally to make sure we don't break the contract without
         // changing the documentation appropriately
         try (WithProperties properties = new WithProperties().set(DISABLE_TCACTIVE_OPENSSL, true))
         {
-            Map<String,Object> config = new HashMap<>();
+            Map<String, Object> config = new HashMap<>();
             config.putAll(commonConfig);
 
             DefaultSslContextFactory defaultSslContextFactoryImpl = new DefaultSslContextFactory(config);
diff --git a/test/unit/org/apache/cassandra/security/DummySslContextFactoryImpl.java b/test/unit/org/apache/cassandra/security/DummySslContextFactoryImpl.java
index ca4f4e86f0..12649cfb0c 100644
--- a/test/unit/org/apache/cassandra/security/DummySslContextFactoryImpl.java
+++ b/test/unit/org/apache/cassandra/security/DummySslContextFactoryImpl.java
@@ -44,7 +44,7 @@ public class DummySslContextFactoryImpl implements ISslContextFactory
     }
 
     @Override
-    public SSLContext createJSSESslContext(EncryptionOptions.ClientAuth clientAuth) throws SSLException
+    public SSLContext createJSSESslContext(EncryptionOptions.ClientEncryptionOptions.ClientAuth clientAuth) throws SSLException
     {
         return null;
     }
@@ -56,7 +56,7 @@ public class DummySslContextFactoryImpl implements ISslContextFactory
     }
 
     @Override
-    public SslContext createNettySslContext(EncryptionOptions.ClientAuth clientAuth, SocketType socketType,
+    public SslContext createNettySslContext(EncryptionOptions.ClientEncryptionOptions.ClientAuth clientAuth, SocketType socketType,
                                             CipherSuiteFilter cipherFilter) throws SSLException
     {
         return null;
diff --git a/test/unit/org/apache/cassandra/security/FileBasedSslContextFactoryTest.java b/test/unit/org/apache/cassandra/security/FileBasedSslContextFactoryTest.java
index d6d936ba0e..cc6c05af5d 100644
--- a/test/unit/org/apache/cassandra/security/FileBasedSslContextFactoryTest.java
+++ b/test/unit/org/apache/cassandra/security/FileBasedSslContextFactoryTest.java
@@ -36,11 +36,12 @@ import org.apache.cassandra.transport.TlsTestUtils;
 
 import static org.apache.cassandra.config.CassandraRelevantProperties.CASSANDRA_CONFIG;
 
-import static org.apache.cassandra.config.EncryptionOptions.ClientAuth.NOT_REQUIRED;
+import static org.apache.cassandra.config.EncryptionOptions.ClientEncryptionOptions.ClientAuth.NOT_REQUIRED;
 
 public class FileBasedSslContextFactoryTest
 {
     private EncryptionOptions.ServerEncryptionOptions encryptionOptions;
+    private EncryptionOptions.ServerEncryptionOptions.Builder encryptionOptionsBuilder;
 
     static WithProperties properties;
 
@@ -60,7 +61,10 @@ public class FileBasedSslContextFactoryTest
     @Before
     public void setup()
     {
-        encryptionOptions = new EncryptionOptions.ServerEncryptionOptions()
+        encryptionOptionsBuilder = new EncryptionOptions.ServerEncryptionOptions.Builder();
+        encryptionOptions = encryptionOptionsBuilder
+                            .withOutboundKeystore(TlsTestUtils.SERVER_OUTBOUND_KEYSTORE_PATH)
+                            .withOutboundKeystorePassword(TlsTestUtils.SERVER_OUTBOUND_KEYSTORE_PASSWORD)
                             .withSslContextFactory(new ParameterizedClass(TestFileBasedSSLContextFactory.class.getName(),
                                                                           new HashMap<>()))
                             .withTrustStore(TlsTestUtils.SERVER_TRUSTSTORE_PATH)
@@ -69,8 +73,7 @@ public class FileBasedSslContextFactoryTest
                             .withCipherSuites("TLS_RSA_WITH_AES_128_CBC_SHA")
                             .withKeyStore(TlsTestUtils.SERVER_KEYSTORE_PATH)
                             .withKeyStorePassword(TlsTestUtils.SERVER_KEYSTORE_PASSWORD)
-                            .withOutboundKeystore(TlsTestUtils.SERVER_OUTBOUND_KEYSTORE_PATH)
-                            .withOutboundKeystorePassword(TlsTestUtils.SERVER_OUTBOUND_KEYSTORE_PASSWORD);
+                            .build();
     }
 
     @Test
@@ -95,11 +98,12 @@ public class FileBasedSslContextFactoryTest
     @Test
     public void testEmptyKeystorePasswords() throws SSLException
     {
-        EncryptionOptions.ServerEncryptionOptions localEncryptionOptions = encryptionOptions
+        EncryptionOptions.ServerEncryptionOptions localEncryptionOptions = encryptionOptionsBuilder
+                                                                           .withOutboundKeystorePassword("")
+                                                                           .withOutboundKeystore("test/conf/cassandra_ssl_test_nopassword.keystore")
                                                                            .withKeyStorePassword("")
                                                                            .withKeyStore("test/conf/cassandra_ssl_test_nopassword.keystore")
-                                                                           .withOutboundKeystorePassword("")
-                                                                           .withOutboundKeystore("test/conf/cassandra_ssl_test_nopassword.keystore");
+                                                                           .build();
 
         Assert.assertEquals("org.apache.cassandra.security.FileBasedSslContextFactoryTest$TestFileBasedSSLContextFactory",
                             localEncryptionOptions.ssl_context_factory.class_name);
@@ -118,13 +122,14 @@ public class FileBasedSslContextFactoryTest
     {
         // Here we only override password configuration and specify password_file configuration since keystore paths
         // are already loaded in the `encryptionOptions`
-        EncryptionOptions.ServerEncryptionOptions localEncryptionOptions = encryptionOptions
-                                                                           .withKeyStorePassword(null)
-                                                                           .withKeyStorePasswordFile(TlsTestUtils.SERVER_KEYSTORE_PASSWORD_FILE)
+        EncryptionOptions.ServerEncryptionOptions localEncryptionOptions = encryptionOptionsBuilder
                                                                            .withOutboundKeystorePassword(null)
                                                                            .withOutboundKeystorePasswordFile(TlsTestUtils.SERVER_OUTBOUND_KEYSTORE_PASSWORD_FILE)
+                                                                           .withKeyStorePassword(null)
+                                                                           .withKeyStorePasswordFile(TlsTestUtils.SERVER_KEYSTORE_PASSWORD_FILE)
                                                                            .withTrustStorePassword(null)
-                                                                           .withTrustStorePasswordFile(TlsTestUtils.SERVER_TRUSTSTORE_PASSWORD_FILE);
+                                                                           .withTrustStorePasswordFile(TlsTestUtils.SERVER_TRUSTSTORE_PASSWORD_FILE)
+                                                                           .build();
 
         Assert.assertEquals("org.apache.cassandra.security.FileBasedSslContextFactoryTest$TestFileBasedSSLContextFactory",
                             localEncryptionOptions.ssl_context_factory.class_name);
@@ -144,13 +149,14 @@ public class FileBasedSslContextFactoryTest
     {
         // Here we only override password configuration and specify password_file configuration since keystore paths
         // are already loaded in the `encryptionOptions`
-        encryptionOptions
-        .withKeyStorePassword(null)
-        .withKeyStorePasswordFile("/path/to/non-existance-password-file")
+        encryptionOptionsBuilder
         .withOutboundKeystorePassword(null)
         .withOutboundKeystorePasswordFile("/path/to/non-existance-password-file")
+        .withKeyStorePassword(null)
+        .withKeyStorePasswordFile("/path/to/non-existance-password-file")
         .withTrustStorePassword(null)
-        .withTrustStorePasswordFile("/path/to/non-existance-password-file");
+        .withTrustStorePasswordFile("/path/to/non-existance-password-file")
+        .build();
     }
 
     /**
@@ -159,7 +165,9 @@ public class FileBasedSslContextFactoryTest
     @Test(expected = IllegalArgumentException.class)
     public void testNullKeystorePasswordDisallowed() throws SSLException
     {
-        EncryptionOptions.ServerEncryptionOptions localEncryptionOptions = encryptionOptions.withKeyStorePassword(null);
+        EncryptionOptions.ServerEncryptionOptions localEncryptionOptions = encryptionOptionsBuilder
+                                                                           .withKeyStorePassword(null)
+                                                                           .build();
 
         Assert.assertEquals("org.apache.cassandra.security.FileBasedSslContextFactoryTest$TestFileBasedSSLContextFactory",
                             localEncryptionOptions.ssl_context_factory.class_name);
@@ -187,7 +195,9 @@ public class FileBasedSslContextFactoryTest
     @Test
     public void testOnlyEmptyOutboundKeystorePassword() throws SSLException
     {
-        EncryptionOptions.ServerEncryptionOptions localEncryptionOptions = encryptionOptions.withOutboundKeystorePassword(null);
+        EncryptionOptions.ServerEncryptionOptions localEncryptionOptions = encryptionOptionsBuilder
+                                                                           .withOutboundKeystorePassword(null)
+                                                                           .build();
 
         Assert.assertEquals("org.apache.cassandra.security.FileBasedSslContextFactoryTest$TestFileBasedSSLContextFactory",
                             localEncryptionOptions.ssl_context_factory.class_name);
@@ -203,7 +213,9 @@ public class FileBasedSslContextFactoryTest
     @Test
     public void testEmptyTruststorePassword() throws SSLException
     {
-        EncryptionOptions.ServerEncryptionOptions localEncryptionOptions = encryptionOptions.withTrustStorePassword(null);
+        EncryptionOptions.ServerEncryptionOptions localEncryptionOptions = encryptionOptionsBuilder
+                                                                           .withTrustStorePassword(null)
+                                                                           .build();
         Assert.assertEquals("org.apache.cassandra.security.FileBasedSslContextFactoryTest$TestFileBasedSSLContextFactory",
                             localEncryptionOptions.ssl_context_factory.class_name);
         Assert.assertNotNull("keystore_password must not be null", localEncryptionOptions.keystore_password);
diff --git a/test/unit/org/apache/cassandra/security/PEMBasedSslContextFactoryTest.java b/test/unit/org/apache/cassandra/security/PEMBasedSslContextFactoryTest.java
index 9781e9d08a..18d323286d 100644
--- a/test/unit/org/apache/cassandra/security/PEMBasedSslContextFactoryTest.java
+++ b/test/unit/org/apache/cassandra/security/PEMBasedSslContextFactoryTest.java
@@ -39,8 +39,8 @@ import org.apache.cassandra.distributed.shared.WithProperties;
 import org.apache.cassandra.transport.TlsTestUtils;
 
 import static org.apache.cassandra.config.CassandraRelevantProperties.DISABLE_TCACTIVE_OPENSSL;
-import static org.apache.cassandra.config.EncryptionOptions.ClientAuth.NOT_REQUIRED;
-import static org.apache.cassandra.config.EncryptionOptions.ClientAuth.REQUIRED;
+import static org.apache.cassandra.config.EncryptionOptions.ClientEncryptionOptions.ClientAuth.NOT_REQUIRED;
+import static org.apache.cassandra.config.EncryptionOptions.ClientEncryptionOptions.ClientAuth.REQUIRED;
 import static org.apache.cassandra.security.PEMBasedSslContextFactory.ConfigKey.ENCODED_CERTIFICATES;
 import static org.apache.cassandra.security.PEMBasedSslContextFactory.ConfigKey.ENCODED_KEY;
 import static org.apache.cassandra.security.PEMBasedSslContextFactory.ConfigKey.KEY_PASSWORD;
@@ -215,12 +215,14 @@ public class PEMBasedSslContextFactoryTest
     {
         ParameterizedClass sslContextFactory = new ParameterizedClass(PEMBasedSslContextFactory.class.getSimpleName()
         , new HashMap<>());
-        EncryptionOptions options = new EncryptionOptions().withTrustStore(TlsTestUtils.SERVER_TRUSTSTORE_PEM_PATH)
-                                                           .withKeyStore(TlsTestUtils.SERVER_KEYSTORE_PATH_PEM)
-                                                           .withKeyStorePassword(TlsTestUtils.SERVER_KEYSTORE_PASSWORD)
-                                                           .withRequireClientAuth(NOT_REQUIRED)
-                                                           .withCipherSuites("TLS_RSA_WITH_AES_128_CBC_SHA")
-                                                           .withSslContextFactory(sslContextFactory);
+        EncryptionOptions.ClientEncryptionOptions options = new EncryptionOptions.ClientEncryptionOptions.Builder()
+                                                            .withTrustStore(TlsTestUtils.SERVER_TRUSTSTORE_PEM_PATH)
+                                                            .withKeyStore(TlsTestUtils.SERVER_KEYSTORE_PATH_PEM)
+                                                            .withKeyStorePassword(TlsTestUtils.SERVER_KEYSTORE_PASSWORD)
+                                                            .withRequireClientAuth(NOT_REQUIRED)
+                                                            .withCipherSuites("TLS_RSA_WITH_AES_128_CBC_SHA")
+                                                            .withSslContextFactory(sslContextFactory)
+                                                            .build();
         SslContext sslContext = SSLFactory.getOrCreateSslContext(options, REQUIRED, ISslContextFactory.SocketType.SERVER, "test");
         Assert.assertNotNull(sslContext);
         if (OpenSsl.isAvailable())
@@ -234,14 +236,16 @@ public class PEMBasedSslContextFactoryTest
     {
         ParameterizedClass sslContextFactory = new ParameterizedClass(PEMBasedSslContextFactory.class.getSimpleName()
         , new HashMap<>());
-        EncryptionOptions.ServerEncryptionOptions options = new EncryptionOptions.ServerEncryptionOptions().withTrustStore(TlsTestUtils.SERVER_TRUSTSTORE_PEM_PATH)
-                                                                                                           .withKeyStore(TlsTestUtils.SERVER_KEYSTORE_PATH_PEM)
-                                                                                                           .withKeyStorePassword(TlsTestUtils.SERVER_KEYSTORE_PASSWORD)
-                                                                                                           .withOutboundKeystore(TlsTestUtils.SERVER_KEYSTORE_PATH_PEM)
-                                                                                                           .withOutboundKeystorePassword(TlsTestUtils.SERVER_KEYSTORE_PASSWORD)
-                                                                                                           .withRequireClientAuth(NOT_REQUIRED)
-                                                                                                           .withCipherSuites("TLS_RSA_WITH_AES_128_CBC_SHA")
-                                                                                                           .withSslContextFactory(sslContextFactory);
+        EncryptionOptions.ServerEncryptionOptions options =
+        new EncryptionOptions.ServerEncryptionOptions.Builder().withOutboundKeystore(TlsTestUtils.SERVER_KEYSTORE_PATH_PEM)
+                                                               .withOutboundKeystorePassword(TlsTestUtils.SERVER_KEYSTORE_PASSWORD)
+                                                               .withTrustStore(TlsTestUtils.SERVER_TRUSTSTORE_PEM_PATH)
+                                                               .withKeyStore(TlsTestUtils.SERVER_KEYSTORE_PATH_PEM)
+                                                               .withKeyStorePassword(TlsTestUtils.SERVER_KEYSTORE_PASSWORD)
+                                                               .withRequireClientAuth(NOT_REQUIRED)
+                                                               .withCipherSuites("TLS_RSA_WITH_AES_128_CBC_SHA")
+                                                               .withSslContextFactory(sslContextFactory)
+                                                               .build();
         SslContext sslContext = SSLFactory.getOrCreateSslContext(options, REQUIRED, ISslContextFactory.SocketType.CLIENT, "test");
         Assert.assertNotNull(sslContext);
         if (OpenSsl.isAvailable())
diff --git a/test/unit/org/apache/cassandra/security/SSLFactoryTest.java b/test/unit/org/apache/cassandra/security/SSLFactoryTest.java
index ba46588686..7ac9517337 100644
--- a/test/unit/org/apache/cassandra/security/SSLFactoryTest.java
+++ b/test/unit/org/apache/cassandra/security/SSLFactoryTest.java
@@ -1,21 +1,21 @@
 /*
-* 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.
-*/
+ * 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.security;
 
 import java.io.FileInputStream;
@@ -46,18 +46,20 @@ import io.netty.handler.ssl.util.SelfSignedCertificate;
 import org.apache.cassandra.config.DatabaseDescriptor;
 import org.apache.cassandra.config.EncryptionOptions;
 import org.apache.cassandra.config.EncryptionOptions.ServerEncryptionOptions;
+import org.apache.cassandra.config.EncryptionOptions.ServerEncryptionOptions.Builder;
 import org.apache.cassandra.config.ParameterizedClass;
 import org.apache.cassandra.io.util.File;
 import org.apache.cassandra.transport.TlsTestUtils;
 
-import static org.apache.cassandra.config.EncryptionOptions.ClientAuth.NOT_REQUIRED;
-import static org.apache.cassandra.config.EncryptionOptions.ClientAuth.REQUIRED;
+import static org.apache.cassandra.config.EncryptionOptions.ClientEncryptionOptions.ClientAuth.NOT_REQUIRED;
+import static org.apache.cassandra.config.EncryptionOptions.ClientEncryptionOptions.ClientAuth.REQUIRED;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNotNull;
 
 public class SSLFactoryTest
 {
     static final SelfSignedCertificate ssc;
+
     static
     {
         DatabaseDescriptor.daemonInitialization();
@@ -77,33 +79,41 @@ public class SSLFactoryTest
     public void setup()
     {
         SSLFactory.clearSslContextCache();
-        encryptionOptions = new ServerEncryptionOptions()
-                            .withTrustStore(TlsTestUtils.SERVER_TRUSTSTORE_PATH)
-                            .withTrustStorePassword(TlsTestUtils.SERVER_TRUSTSTORE_PASSWORD)
-                            .withRequireClientAuth(NOT_REQUIRED)
-                            .withCipherSuites("TLS_RSA_WITH_AES_128_CBC_SHA")
-                            .withSslContextFactory(new ParameterizedClass(TestFileBasedSSLContextFactory.class.getName(),
-                                                                          new HashMap<>()));
+        encryptionOptions = new Builder().withTrustStore(TlsTestUtils.SERVER_TRUSTSTORE_PATH)
+                                         .withTrustStorePassword(TlsTestUtils.SERVER_TRUSTSTORE_PASSWORD)
+                                         .withRequireClientAuth(NOT_REQUIRED)
+                                         .withCipherSuites("TLS_RSA_WITH_AES_128_CBC_SHA")
+                                         .withSslContextFactory(new ParameterizedClass(TestFileBasedSSLContextFactory.class.getName(),
+                                                                                       new HashMap<>()))
+                                         .build();
     }
 
-    private ServerEncryptionOptions addKeystoreOptions(ServerEncryptionOptions options)
+    private Builder addKeystoreOptions(ServerEncryptionOptions options)
     {
-        return options.withKeyStore(TlsTestUtils.SERVER_KEYSTORE_PATH)
-                      .withKeyStorePassword(TlsTestUtils.SERVER_KEYSTORE_PASSWORD)
-                      .withOutboundKeystore(TlsTestUtils.SERVER_OUTBOUND_KEYSTORE_PATH)
-                      .withOutboundKeystorePassword(TlsTestUtils.SERVER_OUTBOUND_KEYSTORE_PASSWORD);
+        EncryptionOptions.ServerEncryptionOptions.Builder builder = new EncryptionOptions.ServerEncryptionOptions.Builder(options);
+
+        builder.withOutboundKeystorePassword(TlsTestUtils.SERVER_OUTBOUND_KEYSTORE_PASSWORD)
+               .withOutboundKeystore(TlsTestUtils.SERVER_OUTBOUND_KEYSTORE_PATH)
+               .withKeyStorePassword(TlsTestUtils.SERVER_KEYSTORE_PASSWORD)
+               .withKeyStore(TlsTestUtils.SERVER_KEYSTORE_PATH);
+
+        return builder;
     }
 
-    private ServerEncryptionOptions addPEMKeystoreOptions(ServerEncryptionOptions options)
+    private Builder addPEMKeystoreOptions(ServerEncryptionOptions options)
     {
         ParameterizedClass sslContextFactoryClass = new ParameterizedClass("org.apache.cassandra.security.PEMBasedSslContextFactory",
                                                                            new HashMap<>());
-        return options.withSslContextFactory(sslContextFactoryClass)
-                      .withKeyStore(TlsTestUtils.SERVER_KEYSTORE_PATH_PEM)
-                      .withKeyStorePassword(TlsTestUtils.SERVER_KEYSTORE_PASSWORD)
-                      .withOutboundKeystore(TlsTestUtils.SERVER_KEYSTORE_PATH_PEM)
-                      .withOutboundKeystorePassword(TlsTestUtils.SERVER_KEYSTORE_PASSWORD)
-                      .withTrustStore(TlsTestUtils.SERVER_TRUSTSTORE_PEM_PATH);
+        EncryptionOptions.ServerEncryptionOptions.Builder builder = new EncryptionOptions.ServerEncryptionOptions.Builder(options);
+
+        builder.withOutboundKeystore(TlsTestUtils.SERVER_KEYSTORE_PATH_PEM)
+               .withOutboundKeystorePassword(TlsTestUtils.SERVER_KEYSTORE_PASSWORD)
+               .withSslContextFactory(sslContextFactoryClass)
+               .withKeyStore(TlsTestUtils.SERVER_KEYSTORE_PATH_PEM)
+               .withKeyStorePassword(TlsTestUtils.SERVER_KEYSTORE_PASSWORD)
+               .withTrustStore(TlsTestUtils.SERVER_TRUSTSTORE_PEM_PATH);
+
+        return builder;
     }
 
     @Test
@@ -111,9 +121,13 @@ public class SSLFactoryTest
     {
         try
         {
-            ServerEncryptionOptions options = addKeystoreOptions(encryptionOptions)
-                                              .withInternodeEncryption(ServerEncryptionOptions.InternodeEncryption.all);
-            ServerEncryptionOptions legacyOptions = options.withOptional(false).withInternodeEncryption(ServerEncryptionOptions.InternodeEncryption.all);
+            Builder optionsBuilder = addKeystoreOptions(encryptionOptions)
+                                     .withInternodeEncryption(ServerEncryptionOptions.InternodeEncryption.all);
+            ServerEncryptionOptions options = optionsBuilder.build();
+            ServerEncryptionOptions legacyOptions = optionsBuilder
+                                                    .withInternodeEncryption(ServerEncryptionOptions.InternodeEncryption.all)
+                                                    .withOptional(false)
+                                                    .build();
             options.sslContextFactoryInstance.initHotReloading();
             legacyOptions.sslContextFactoryInstance.initHotReloading();
 
@@ -146,8 +160,9 @@ public class SSLFactoryTest
     public void testServerSocketShouldUseKeystore() throws IOException, CertificateException, KeyStoreException, NoSuchAlgorithmException, NoSuchFieldException, IllegalAccessException, ClassNotFoundException, NoSuchMethodException, InvocationTargetException
     {
         ServerEncryptionOptions options = addKeystoreOptions(encryptionOptions)
-        .withOutboundKeystore("dummyKeystore")
-        .withOutboundKeystorePassword("dummyPassword");
+                                          .withOutboundKeystore("dummyKeystore")
+                                          .withOutboundKeystorePassword("dummyPassword")
+                                          .build();
 
         // Server socket type should create a keystore with keystore & keystore password
         final OpenSslServerContext context = (OpenSslServerContext) SSLFactory.createNettySslContext(options, REQUIRED, ISslContextFactory.SocketType.SERVER);
@@ -163,8 +178,9 @@ public class SSLFactoryTest
     public void testClientSocketShouldUseOutboundKeystore() throws IOException, CertificateException, KeyStoreException, NoSuchAlgorithmException, NoSuchFieldException, ClassNotFoundException, InvocationTargetException, IllegalAccessException, NoSuchMethodException
     {
         ServerEncryptionOptions options = addKeystoreOptions(encryptionOptions)
-        .withKeyStore("dummyKeystore")
-        .withKeyStorePassword("dummyPassword");
+                                          .withKeyStore("dummyKeystore")
+                                          .withKeyStorePassword("dummyPassword")
+                                          .build();
 
         // Client socket type should create a keystore with outbound Keystore & outbound password
         final OpenSslClientContext context = (OpenSslClientContext) SSLFactory.createNettySslContext(options, REQUIRED, ISslContextFactory.SocketType.CLIENT);
@@ -181,10 +197,14 @@ public class SSLFactoryTest
     {
         try
         {
-            ServerEncryptionOptions options = addPEMKeystoreOptions(encryptionOptions)
-                                              .withInternodeEncryption(ServerEncryptionOptions.InternodeEncryption.dc);
+            Builder optionsBuilder = addPEMKeystoreOptions(encryptionOptions);
+            ServerEncryptionOptions options = optionsBuilder.withInternodeEncryption(ServerEncryptionOptions.InternodeEncryption.dc)
+                                                            .build();
             // emulate InboundSockets and share the cert but with different options, no extra hot reloading init
-            ServerEncryptionOptions legacyOptions = options.withOptional(false).withInternodeEncryption(ServerEncryptionOptions.InternodeEncryption.all);
+            ServerEncryptionOptions legacyOptions = optionsBuilder
+                                                    .withInternodeEncryption(ServerEncryptionOptions.InternodeEncryption.all)
+                                                    .withOptional(false)
+                                                    .build();
             options.sslContextFactoryInstance.initHotReloading();
             legacyOptions.sslContextFactoryInstance.initHotReloading();
 
@@ -217,8 +237,9 @@ public class SSLFactoryTest
     public void testSslFactorySslInit_BadPassword_ThrowsException() throws IOException
     {
         ServerEncryptionOptions options = addKeystoreOptions(encryptionOptions)
-                                    .withKeyStorePassword("bad password")
-                                    .withInternodeEncryption(ServerEncryptionOptions.InternodeEncryption.all);
+                                          .withInternodeEncryption(ServerEncryptionOptions.InternodeEncryption.all)
+                                          .withKeyStorePassword("bad password")
+                                          .build();
 
         SSLFactory.validateSslContext("testSslFactorySslInit_BadPassword_ThrowsException", options, NOT_REQUIRED, true);
     }
@@ -228,13 +249,17 @@ public class SSLFactoryTest
     {
         try
         {
-            ServerEncryptionOptions options = addKeystoreOptions(encryptionOptions);
+            Builder optionsBuilder = addKeystoreOptions(encryptionOptions);
+            ServerEncryptionOptions options = optionsBuilder.build();
             // emulate InboundSockets and share the cert but with different options, no extra hot reloading init
-            ServerEncryptionOptions legacyOptions = options.withOptional(false).withInternodeEncryption(ServerEncryptionOptions.InternodeEncryption.all);
+            ServerEncryptionOptions legacyOptions = optionsBuilder
+                                                    .withInternodeEncryption(ServerEncryptionOptions.InternodeEncryption.all)
+                                                    .withOptional(false)
+                                                    .build();
 
             File testKeystoreFile = new File(options.keystore + ".test");
             FileUtils.copyFile(new File(options.keystore).toJavaIOFile(), testKeystoreFile.toJavaIOFile());
-            options = options.withKeyStore(testKeystoreFile.path());
+            options = new Builder(options).withKeyStore(testKeystoreFile.path()).build();
 
             SSLFactory.initHotReloading(options, options, true);  // deliberately not initializing with legacyOptions to match InboundSockets.addBindings
 
@@ -261,11 +286,12 @@ public class SSLFactoryTest
     {
         try
         {
-            ServerEncryptionOptions options = addKeystoreOptions(encryptionOptions);
+            Builder optionsBuilder = addKeystoreOptions(encryptionOptions);
+            ServerEncryptionOptions options = optionsBuilder.build();
 
             File testKeystoreFile = new File(options.keystore + ".test");
             FileUtils.copyFile(new File(options.keystore).toJavaIOFile(), testKeystoreFile.toJavaIOFile());
-            options = options.withKeyStore(testKeystoreFile.path());
+            options = optionsBuilder.withKeyStore(testKeystoreFile.path()).build();
 
 
             SSLFactory.initHotReloading(options, options, true);
@@ -294,8 +320,10 @@ public class SSLFactoryTest
     @Test
     public void getSslContext_ParamChanges() throws IOException
     {
-        ServerEncryptionOptions options = addKeystoreOptions(encryptionOptions)
-                                    .withCipherSuites("TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256");
+        Builder optionsBuilder = addKeystoreOptions(encryptionOptions);
+        ServerEncryptionOptions options = optionsBuilder
+                                          .withCipherSuites("TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256")
+                                          .build();
 
         SslContext ctx1 = SSLFactory.getOrCreateSslContext(options, REQUIRED,
                                                            ISslContextFactory.SocketType.SERVER, "test");
@@ -303,7 +331,7 @@ public class SSLFactoryTest
         Assert.assertTrue(ctx1.isServer());
         Assert.assertEquals(ctx1.cipherSuites(), options.cipher_suites);
 
-        options = options.withCipherSuites("TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256");
+        options = optionsBuilder.withCipherSuites("TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256").build();
 
         SslContext ctx2 = SSLFactory.getOrCreateSslContext(options, REQUIRED,
                                                            ISslContextFactory.SocketType.CLIENT, "test");
@@ -313,30 +341,33 @@ public class SSLFactoryTest
     }
 
     @Test
-    public void testCacheKeyEqualityForCustomSslContextFactory() {
+    public void testCacheKeyEqualityForCustomSslContextFactory()
+    {
 
-        Map<String,String> parameters1 = new HashMap<>();
+        Map<String, String> parameters1 = new HashMap<>();
         parameters1.put("key1", "value1");
         parameters1.put("key2", "value2");
-        EncryptionOptions encryptionOptions1 =
-        new EncryptionOptions()
+        EncryptionOptions.ClientEncryptionOptions encryptionOptions1 =
+        new EncryptionOptions.ClientEncryptionOptions.Builder()
         .withSslContextFactory(new ParameterizedClass(DummySslContextFactoryImpl.class.getName(), parameters1))
         .withProtocol("TLSv1.1")
         .withRequireClientAuth(REQUIRED)
-        .withRequireEndpointVerification(false);
+        .withRequireEndpointVerification(false)
+        .build();
 
         SSLFactory.CacheKey cacheKey1 = new SSLFactory.CacheKey(encryptionOptions1, ISslContextFactory.SocketType.SERVER, "test"
         );
 
-        Map<String,String> parameters2 = new HashMap<>();
+        Map<String, String> parameters2 = new HashMap<>();
         parameters2.put("key1", "value1");
         parameters2.put("key2", "value2");
-        EncryptionOptions encryptionOptions2 =
-        new EncryptionOptions()
+        EncryptionOptions.ClientEncryptionOptions encryptionOptions2 =
+        new EncryptionOptions.ClientEncryptionOptions.Builder()
         .withSslContextFactory(new ParameterizedClass(DummySslContextFactoryImpl.class.getName(), parameters2))
         .withProtocol("TLSv1.1")
         .withRequireClientAuth(REQUIRED)
-        .withRequireEndpointVerification(false);
+        .withRequireEndpointVerification(false)
+        .build();
 
         SSLFactory.CacheKey cacheKey2 = new SSLFactory.CacheKey(encryptionOptions2, ISslContextFactory.SocketType.SERVER, "test"
         );
@@ -345,26 +376,29 @@ public class SSLFactoryTest
     }
 
     @Test
-    public void testCacheKeyInequalityForCustomSslContextFactory() {
+    public void testCacheKeyInequalityForCustomSslContextFactory()
+    {
 
-        Map<String,String> parameters1 = new HashMap<>();
+        Map<String, String> parameters1 = new HashMap<>();
         parameters1.put("key1", "value11");
         parameters1.put("key2", "value12");
-        EncryptionOptions encryptionOptions1 =
-        new EncryptionOptions()
+        EncryptionOptions.ClientEncryptionOptions encryptionOptions1 =
+        new EncryptionOptions.ClientEncryptionOptions.Builder()
         .withSslContextFactory(new ParameterizedClass(DummySslContextFactoryImpl.class.getName(), parameters1))
-        .withProtocol("TLSv1.1");
+        .withProtocol("TLSv1.1")
+        .build();
 
         SSLFactory.CacheKey cacheKey1 = new SSLFactory.CacheKey(encryptionOptions1, ISslContextFactory.SocketType.SERVER, "test"
         );
 
-        Map<String,String> parameters2 = new HashMap<>();
+        Map<String, String> parameters2 = new HashMap<>();
         parameters2.put("key1", "value21");
         parameters2.put("key2", "value22");
-        EncryptionOptions encryptionOptions2 =
-        new EncryptionOptions()
+        EncryptionOptions.ClientEncryptionOptions encryptionOptions2 =
+        new EncryptionOptions.ClientEncryptionOptions.Builder()
         .withSslContextFactory(new ParameterizedClass(DummySslContextFactoryImpl.class.getName(), parameters2))
-        .withProtocol("TLSv1.1");
+        .withProtocol("TLSv1.1")
+        .build();
 
         SSLFactory.CacheKey cacheKey2 = new SSLFactory.CacheKey(encryptionOptions2, ISslContextFactory.SocketType.SERVER, "test"
         );
@@ -372,7 +406,8 @@ public class SSLFactoryTest
         Assert.assertNotEquals(cacheKey1, cacheKey2);
     }
 
-    public static class TestFileBasedSSLContextFactory extends FileBasedSslContextFactory {
+    public static class TestFileBasedSSLContextFactory extends FileBasedSslContextFactory
+    {
         public TestFileBasedSSLContextFactory(Map<String, Object> parameters)
         {
             super(parameters);
diff --git a/test/unit/org/apache/cassandra/service/ClientWarningsTest.java b/test/unit/org/apache/cassandra/service/ClientWarningsTest.java
index cf6d6ed400..fb9f594801 100644
--- a/test/unit/org/apache/cassandra/service/ClientWarningsTest.java
+++ b/test/unit/org/apache/cassandra/service/ClientWarningsTest.java
@@ -70,7 +70,7 @@ public class ClientWarningsTest extends CQLTester
         createTable("CREATE TABLE %s (pk int PRIMARY KEY, v text)");
 
         // v4 and higher
-        try (SimpleClient client = new SimpleClient(nativeAddr.getHostAddress(), nativePort, version, true, new EncryptionOptions()))
+        try (SimpleClient client = new SimpleClient(nativeAddr.getHostAddress(), nativePort, version, true, new EncryptionOptions.ClientEncryptionOptions()))
         {
             client.connect(false);
 
@@ -90,7 +90,7 @@ public class ClientWarningsTest extends CQLTester
         createTable("CREATE TABLE %s (pk int PRIMARY KEY, v text)");
 
         // v4 and higher
-        try (SimpleClient client = new SimpleClient(nativeAddr.getHostAddress(), nativePort, version, true, new EncryptionOptions()))
+        try (SimpleClient client = new SimpleClient(nativeAddr.getHostAddress(), nativePort, version, true, new EncryptionOptions.ClientEncryptionOptions()))
         {
             client.connect(false);
 
@@ -112,7 +112,7 @@ public class ClientWarningsTest extends CQLTester
         final int iterations = 10000;
         createTable("CREATE TABLE %s (pk int, ck int, v int, PRIMARY KEY (pk, ck))");
 
-        try (SimpleClient client = new SimpleClient(nativeAddr.getHostAddress(), nativePort, version, true, new EncryptionOptions()))
+        try (SimpleClient client = new SimpleClient(nativeAddr.getHostAddress(), nativePort, version, true, new EncryptionOptions.ClientEncryptionOptions()))
         {
             client.connect(false);
 
diff --git a/test/unit/org/apache/cassandra/service/NativeTransportServiceTest.java b/test/unit/org/apache/cassandra/service/NativeTransportServiceTest.java
index 645d5b8f8b..9602899400 100644
--- a/test/unit/org/apache/cassandra/service/NativeTransportServiceTest.java
+++ b/test/unit/org/apache/cassandra/service/NativeTransportServiceTest.java
@@ -36,7 +36,7 @@ import static org.junit.Assert.assertTrue;
 
 public class NativeTransportServiceTest
 {
-    static EncryptionOptions defaultOptions;
+    static EncryptionOptions.ClientEncryptionOptions defaultOptions;
 
     @BeforeClass
     public static void setupDD()
@@ -48,7 +48,7 @@ public class NativeTransportServiceTest
     @After
     public void resetConfig()
     {
-        DatabaseDescriptor.updateNativeProtocolEncryptionOptions(update -> new EncryptionOptions(defaultOptions).applyConfig());
+        DatabaseDescriptor.updateNativeProtocolEncryptionOptions(update -> new EncryptionOptions.ClientEncryptionOptions.Builder(defaultOptions).build());
     }
 
     @Test
@@ -127,8 +127,11 @@ public class NativeTransportServiceTest
     public void testSSLOnly()
     {
         // default ssl settings: client encryption enabled and default native transport port used for ssl only
-        DatabaseDescriptor.updateNativeProtocolEncryptionOptions(options -> options.withEnabled(true)
-                                                                                   .withOptional(false));
+        DatabaseDescriptor.updateNativeProtocolEncryptionOptions(options ->
+                                                                 new EncryptionOptions.ClientEncryptionOptions.Builder(options)
+                                                                 .withEnabled(true)
+                                                                 .withOptional(false)
+                                                                 .build());
 
         withService((NativeTransportService service) ->
                     {
@@ -144,8 +147,11 @@ public class NativeTransportServiceTest
     public void testSSLOptional()
     {
         // default ssl settings: client encryption enabled and default native transport port used for optional ssl
-        DatabaseDescriptor.updateNativeProtocolEncryptionOptions(options -> options.withEnabled(true)
-                                                                                   .withOptional(true));
+        DatabaseDescriptor.updateNativeProtocolEncryptionOptions(options ->
+                                                                 new EncryptionOptions.ClientEncryptionOptions.Builder(options)
+                                                                 .withEnabled(true)
+                                                                 .withOptional(true)
+                                                                 .build());
 
         withService((NativeTransportService service) ->
                     {
diff --git a/test/unit/org/apache/cassandra/service/ProtocolBetaVersionTest.java b/test/unit/org/apache/cassandra/service/ProtocolBetaVersionTest.java
index a5b32bfa1f..22324f178b 100644
--- a/test/unit/org/apache/cassandra/service/ProtocolBetaVersionTest.java
+++ b/test/unit/org/apache/cassandra/service/ProtocolBetaVersionTest.java
@@ -68,7 +68,7 @@ public class ProtocolBetaVersionTest extends CQLTester
         createTable("CREATE TABLE %s (pk int PRIMARY KEY, v int)");
         assertTrue(betaVersion.isBeta()); // change to another beta version or remove test if no beta version
 
-        try (SimpleClient client = new SimpleClient(nativeAddr.getHostAddress(), nativePort, betaVersion, true, new EncryptionOptions()))
+        try (SimpleClient client = new SimpleClient(nativeAddr.getHostAddress(), nativePort, betaVersion, true, new EncryptionOptions.ClientEncryptionOptions()))
         {
             client.connect(false);
             for (int i = 0; i < 10; i++)
@@ -103,7 +103,7 @@ public class ProtocolBetaVersionTest extends CQLTester
         }
 
         assertTrue(betaVersion.isBeta()); // change to another beta version or remove test if no beta version
-        try (SimpleClient client = new SimpleClient(nativeAddr.getHostAddress(), nativePort, betaVersion, false, new EncryptionOptions()))
+        try (SimpleClient client = new SimpleClient(nativeAddr.getHostAddress(), nativePort, betaVersion, false, new EncryptionOptions.ClientEncryptionOptions()))
         {
             client.connect(false);
             fail("Exception should have been thrown");
diff --git a/test/unit/org/apache/cassandra/tools/LoaderOptionsTest.java b/test/unit/org/apache/cassandra/tools/LoaderOptionsTest.java
index 4fc2325677..b203af1b43 100644
--- a/test/unit/org/apache/cassandra/tools/LoaderOptionsTest.java
+++ b/test/unit/org/apache/cassandra/tools/LoaderOptionsTest.java
@@ -28,6 +28,7 @@ import com.google.common.net.HostAndPort;
 import org.junit.Test;
 
 import org.apache.cassandra.io.util.File;
+import org.apache.cassandra.transport.TlsTestUtils;
 
 import static org.apache.cassandra.tools.OfflineToolUtils.sstableDirName;
 import static org.junit.Assert.assertEquals;
@@ -85,6 +86,35 @@ public class LoaderOptionsTest
         assertEquals("test.jks", options.clientEncOptions.keystore);
     }
 
+    /**
+     * Tests for client_encryption_options override from the command line.
+     */
+    @Test
+    public void testEncryptionSettingsOverride() throws Exception
+    {
+        // Default Cassandra config
+        File config = new File(Paths.get(".", "test", "conf", "cassandra-mtls.yaml").normalize());
+        String[] args = { "-d", "127.9.9.1", "-f", config.absolutePath(),
+                          "-ts", "test.jks", "-tspw", "truststorePass1",
+                          "-ks", "test.jks", "-kspw", "testdata1",
+                          "--ssl-ciphers", "TLS_RSA_WITH_AES_256_CBC_SHA",
+                          "--ssl-alg", "SunX509", "--store-type", "JKS", "--ssl-protocol", "TLS",
+                          sstableDirName("legacy_sstables", "legacy_ma_simple") };
+        LoaderOptions options = LoaderOptions.builder().parseArgs(args).build();
+        // Below two lines validating server encryption options is to verify that we are loading config from the yaml
+        assertEquals(TlsTestUtils.SERVER_KEYSTORE_PATH, options.serverEncOptions.keystore);
+        assertEquals(TlsTestUtils.SERVER_KEYSTORE_PASSWORD, options.serverEncOptions.keystore_password);
+        // Below asserts validate the overrides for the client encryption options from the command line
+        // Since the values are provided by (and local to) this test, they are hardcoded
+        assertEquals("JKS", options.clientEncOptions.store_type);
+        assertEquals("test.jks", options.clientEncOptions.truststore);
+        assertEquals("truststorePass1", options.clientEncOptions.truststore_password);
+        assertEquals("test.jks", options.clientEncOptions.keystore);
+        assertEquals("testdata1", options.clientEncOptions.keystore_password);
+        assertEquals("TLS_RSA_WITH_AES_256_CBC_SHA", options.clientEncOptions.cipherSuitesArray()[0]);
+        assertEquals("SunX509", options.clientEncOptions.algorithm);
+    }
+
     @Test
     public void testThrottleDefaultSettings()
     {
diff --git a/test/unit/org/apache/cassandra/transport/EarlyAuthenticationTest.java b/test/unit/org/apache/cassandra/transport/EarlyAuthenticationTest.java
index ed98140b9b..a581086c76 100644
--- a/test/unit/org/apache/cassandra/transport/EarlyAuthenticationTest.java
+++ b/test/unit/org/apache/cassandra/transport/EarlyAuthenticationTest.java
@@ -84,23 +84,23 @@ public class EarlyAuthenticationTest extends CQLTester
         });
     }
 
-    private EncryptionOptions clientEncryptionOptions(boolean presentClientCertificate)
+    private EncryptionOptions.ClientEncryptionOptions clientEncryptionOptions(boolean presentClientCertificate)
     {
-        EncryptionOptions encryptionOptions = new EncryptionOptions()
-                                              .withEnabled(true)
-                                              .withRequireClientAuth(EncryptionOptions.ClientAuth.OPTIONAL)
-                                              .withTrustStore(TlsTestUtils.CLIENT_TRUSTSTORE_PATH)
-                                              .withTrustStorePassword(TlsTestUtils.CLIENT_TRUSTSTORE_PASSWORD)
-                                              .withSslContextFactory(new ParameterizedClass(SimpleClientSslContextFactory.class.getName()));
+        EncryptionOptions.ClientEncryptionOptions.Builder builder = new EncryptionOptions.ClientEncryptionOptions.Builder();
+        builder.withEnabled(true)
+               .withRequireClientAuth(EncryptionOptions.ClientEncryptionOptions.ClientAuth.OPTIONAL)
+               .withTrustStore(TlsTestUtils.CLIENT_TRUSTSTORE_PATH)
+               .withTrustStorePassword(TlsTestUtils.CLIENT_TRUSTSTORE_PASSWORD)
+               .withSslContextFactory(new ParameterizedClass(SimpleClientSslContextFactory.class.getName()));
 
         if (presentClientCertificate)
         {
-            encryptionOptions = encryptionOptions.withKeyStore(TlsTestUtils.CLIENT_SPIFFE_KEYSTORE_PATH)
-                             .withStoreType("JKS")
-                             .withKeyStorePassword(TlsTestUtils.CLIENT_SPIFFE_KEYSTORE_PASSWORD);
+            builder.withKeyStore(TlsTestUtils.CLIENT_SPIFFE_KEYSTORE_PATH)
+                                    .withStoreType("JKS")
+                                    .withKeyStorePassword(TlsTestUtils.CLIENT_SPIFFE_KEYSTORE_PASSWORD);
         }
 
-        return new EncryptionOptions(encryptionOptions);
+        return new EncryptionOptions.ClientEncryptionOptions(builder.build());
     }
 
     @Test
@@ -180,6 +180,5 @@ public class EarlyAuthenticationTest extends CQLTester
             }
         };
     }
-
 }
 
diff --git a/test/unit/org/apache/cassandra/transport/MessagePayloadTest.java b/test/unit/org/apache/cassandra/transport/MessagePayloadTest.java
index a50174bd87..42c6cbd021 100644
--- a/test/unit/org/apache/cassandra/transport/MessagePayloadTest.java
+++ b/test/unit/org/apache/cassandra/transport/MessagePayloadTest.java
@@ -127,7 +127,7 @@ public class MessagePayloadTest extends CQLTester
                                                    nativePort,
                                                    ProtocolVersion.V5,
                                                    true,
-                                                   new EncryptionOptions());
+                                                   new EncryptionOptions.ClientEncryptionOptions());
             try
             {
                 client.connect(false);
diff --git a/test/unit/org/apache/cassandra/transport/SimpleClientSslContextFactory.java b/test/unit/org/apache/cassandra/transport/SimpleClientSslContextFactory.java
index 1a6871716a..468c9cbc17 100644
--- a/test/unit/org/apache/cassandra/transport/SimpleClientSslContextFactory.java
+++ b/test/unit/org/apache/cassandra/transport/SimpleClientSslContextFactory.java
@@ -30,12 +30,12 @@ import io.netty.handler.ssl.SslContextBuilder;
 import org.apache.cassandra.config.EncryptionOptions;
 import org.apache.cassandra.security.FileBasedSslContextFactory;
 
-import static org.apache.cassandra.config.EncryptionOptions.ClientAuth.NOT_REQUIRED;
+import static org.apache.cassandra.config.EncryptionOptions.ClientEncryptionOptions.ClientAuth.NOT_REQUIRED;
 
 /**
  * A custom implementation of {@link FileBasedSslContextFactory} to be used by tests utilizing {@link SimpleClient}.
  * <p>
- * Provides a subtly different implementation of {@link #createNettySslContext(EncryptionOptions.ClientAuth, SocketType, CipherSuiteFilter)}
+ * Provides a subtly different implementation of {@link #createNettySslContext(EncryptionOptions.ClientEncryptionOptions.ClientAuth, SocketType, CipherSuiteFilter)}
  * that only configures an {@link SslContext} for clients and most importantly only configures a key manager if an
  * outbound keystore is configured, where the existing implementation always does this.  This is useful for tests
  * that try to create a client that uses encryption but does not provide a certificate.
@@ -49,7 +49,7 @@ public class SimpleClientSslContextFactory extends FileBasedSslContextFactory
     }
 
     @Override
-    public SSLContext createJSSESslContext(EncryptionOptions.ClientAuth clientAuth) throws SSLException
+    public SSLContext createJSSESslContext(EncryptionOptions.ClientEncryptionOptions.ClientAuth clientAuth) throws SSLException
     {
         TrustManager[] trustManagers = null;
         if (clientAuth != NOT_REQUIRED)
@@ -76,7 +76,7 @@ public class SimpleClientSslContextFactory extends FileBasedSslContextFactory
     }
 
     @Override
-    public SslContext createNettySslContext(EncryptionOptions.ClientAuth clientAuth, SocketType socketType,
+    public SslContext createNettySslContext(EncryptionOptions.ClientEncryptionOptions.ClientAuth clientAuth, SocketType socketType,
                                             CipherSuiteFilter cipherFilter) throws SSLException
     {
         SslContextBuilder builder = SslContextBuilder.forClient();
diff --git a/test/unit/org/apache/cassandra/transport/TlsTestUtils.java b/test/unit/org/apache/cassandra/transport/TlsTestUtils.java
index 30a6054127..76faec85b1 100644
--- a/test/unit/org/apache/cassandra/transport/TlsTestUtils.java
+++ b/test/unit/org/apache/cassandra/transport/TlsTestUtils.java
@@ -86,17 +86,18 @@ public class TlsTestUtils
     public static String CLIENT_TRUSTSTORE_PATH = "test/conf/cassandra_ssl_test.truststore";
     public static String CLIENT_TRUSTSTORE_PASSWORD = "cassandra";
 
-    public static EncryptionOptions getClientEncryptionOptions()
+    public static EncryptionOptions.ClientEncryptionOptions getClientEncryptionOptions()
     {
-        return new EncryptionOptions(new EncryptionOptions()
+        return new EncryptionOptions.ClientEncryptionOptions(new EncryptionOptions.ClientEncryptionOptions.Builder()
                               .withEnabled(true)
-                              .withRequireClientAuth(EncryptionOptions.ClientAuth.OPTIONAL)
+                              .withRequireClientAuth(EncryptionOptions.ClientEncryptionOptions.ClientAuth.OPTIONAL)
                               .withOptional(true)
                               .withKeyStore(SERVER_KEYSTORE_PATH)
                               .withKeyStorePassword(SERVER_KEYSTORE_PASSWORD)
                               .withTrustStore(SERVER_TRUSTSTORE_PATH)
                               .withTrustStorePassword(SERVER_TRUSTSTORE_PASSWORD)
-                              .withRequireEndpointVerification(false));
+                              .withRequireEndpointVerification(false)
+                              .build());
     }
 
     public static void configureWithMutualTlsWithPasswordFallbackAuthenticator(Config config)
@@ -129,7 +130,7 @@ public class TlsTestUtils
     {
         return RemoteEndpointAwareJdkSSLOptions.builder()
                                                .withSSLContext(getClientSslContextFactory(provideClientCert)
-                                                               .createJSSESslContext(EncryptionOptions.ClientAuth.OPTIONAL))
+                                                               .createJSSESslContext(EncryptionOptions.ClientEncryptionOptions.ClientAuth.OPTIONAL))
                                                .build();
     }
 
@@ -139,7 +140,7 @@ public class TlsTestUtils
         {
             return RemoteEndpointAwareJdkSSLOptions.builder()
                                                    .withSSLContext(getClientSslContextFactory(keystorePath, truststorePath)
-                                                                   .createJSSESslContext(EncryptionOptions.ClientAuth.OPTIONAL))
+                                                                   .createJSSESslContext(EncryptionOptions.ClientEncryptionOptions.ClientAuth.OPTIONAL))
                                                    .build();
         }
         catch (SSLException e)
diff --git a/tools/stress/src/org/apache/cassandra/stress/settings/SettingsTransport.java b/tools/stress/src/org/apache/cassandra/stress/settings/SettingsTransport.java
index cf62999822..ccdf0a53b2 100644
--- a/tools/stress/src/org/apache/cassandra/stress/settings/SettingsTransport.java
+++ b/tools/stress/src/org/apache/cassandra/stress/settings/SettingsTransport.java
@@ -44,31 +44,32 @@ public class SettingsTransport implements Serializable
         this.credentials = credentials;
     }
 
-    public EncryptionOptions getEncryptionOptions()
+    public EncryptionOptions.ClientEncryptionOptions getEncryptionOptions()
     {
-        EncryptionOptions encOptions = new EncryptionOptions().applyConfig();
+        EncryptionOptions.ClientEncryptionOptions encOptions = new EncryptionOptions.ClientEncryptionOptions().applyConfig();
         if (options.trustStore.present())
         {
-            encOptions = encOptions
-                         .withEnabled(true)
-                         .withTrustStore(options.trustStore.value())
-                         .withTrustStorePassword(options.trustStorePw.setByUser() ? options.trustStorePw.value() : credentials.transportTruststorePassword)
-                         .withAlgorithm(options.alg.value())
-                         .withProtocol(options.protocol.value())
-                         .withCipherSuites(options.ciphers.value().split(","));
+            EncryptionOptions.Builder<EncryptionOptions.ClientEncryptionOptions> encOptionsBuilder = new EncryptionOptions.ClientEncryptionOptions.Builder(encOptions)
+                                        .withEnabled(true)
+                                        .withTrustStore(options.trustStore.value())
+                                        .withTrustStorePassword(options.trustStorePw.setByUser() ? options.trustStorePw.value() : credentials.transportTruststorePassword)
+                                        .withAlgorithm(options.alg.value())
+                                        .withProtocol(options.protocol.value())
+                                        .withCipherSuites(options.ciphers.value().split(","));
+
             if (options.keyStore.present())
             {
-                encOptions = encOptions
-                             .withKeyStore(options.keyStore.value())
-                             .withKeyStorePassword(options.keyStorePw.setByUser() ? options.keyStorePw.value() : credentials.transportKeystorePassword);
+                encOptionsBuilder.withKeyStore(options.keyStore.value())
+                                 .withKeyStorePassword(options.keyStorePw.setByUser() ? options.keyStorePw.value() : credentials.transportKeystorePassword);
             }
             else
             {
                 // mandatory for SSLFactory.createSSLContext(), see CASSANDRA-9325
-                encOptions = encOptions
-                             .withKeyStore(encOptions.truststore)
-                             .withKeyStorePassword(encOptions.truststore_password != null ? encOptions.truststore_password : credentials.transportTruststorePassword);
+                encOptionsBuilder.withKeyStore(encOptions.truststore)
+                                 .withKeyStorePassword(encOptions.truststore_password != null ? encOptions.truststore_password : credentials.transportTruststorePassword);
             }
+
+            encOptions = encOptionsBuilder.build();
         }
         return encOptions;
     }
diff --git a/tools/stress/src/org/apache/cassandra/stress/settings/StressSettings.java b/tools/stress/src/org/apache/cassandra/stress/settings/StressSettings.java
index 6aea048b4c..f81c4a9787 100644
--- a/tools/stress/src/org/apache/cassandra/stress/settings/StressSettings.java
+++ b/tools/stress/src/org/apache/cassandra/stress/settings/StressSettings.java
@@ -139,7 +139,7 @@ public class StressSettings implements Serializable
                 if (client != null)
                     return client;
 
-                EncryptionOptions encOptions = transport.getEncryptionOptions();
+                EncryptionOptions.ClientEncryptionOptions encOptions = transport.getEncryptionOptions();
                 JavaDriverClient c = new JavaDriverClient(this, node.nodes, port.nativePort, encOptions);
                 c.connect(mode.compression());
                 if (keyspace != null)
diff --git a/tools/stress/src/org/apache/cassandra/stress/util/JavaDriverClient.java b/tools/stress/src/org/apache/cassandra/stress/util/JavaDriverClient.java
index 3d72828daf..f2a92fe5aa 100644
--- a/tools/stress/src/org/apache/cassandra/stress/util/JavaDriverClient.java
+++ b/tools/stress/src/org/apache/cassandra/stress/util/JavaDriverClient.java
@@ -41,7 +41,7 @@ import org.apache.cassandra.config.EncryptionOptions;
 import org.apache.cassandra.security.SSLFactory;
 import org.apache.cassandra.stress.settings.StressSettings;
 
-import static org.apache.cassandra.config.EncryptionOptions.ClientAuth.REQUIRED;
+import static org.apache.cassandra.config.EncryptionOptions.ClientEncryptionOptions.ClientAuth.REQUIRED;
 
 public class JavaDriverClient
 {
@@ -60,7 +60,7 @@ public class JavaDriverClient
     public final int connectionsPerHost;
 
     private final ProtocolVersion protocolVersion;
-    private final EncryptionOptions encryptionOptions;
+    private final EncryptionOptions.ClientEncryptionOptions encryptionOptions;
     private Cluster cluster;
     private Session session;
     private final LoadBalancingPolicy loadBalancingPolicy;
@@ -69,15 +69,15 @@ public class JavaDriverClient
 
     public JavaDriverClient(StressSettings settings, String host, int port)
     {
-        this(settings, Collections.singletonList(host), port, new EncryptionOptions());
+        this(settings, Collections.singletonList(host), port, new EncryptionOptions.ClientEncryptionOptions());
     }
 
     public JavaDriverClient(StressSettings settings, List<String> hosts, int port)
     {
-        this(settings, hosts, port, new EncryptionOptions());
+        this(settings, hosts, port, new EncryptionOptions.ClientEncryptionOptions());
     }
 
-    public JavaDriverClient(StressSettings settings, List<String> hosts, int port, EncryptionOptions encryptionOptions)
+    public JavaDriverClient(StressSettings settings, List<String> hosts, int port, EncryptionOptions.ClientEncryptionOptions encryptionOptions)
     {
         this.protocolVersion = settings.mode.protocolVersion;
         this.hosts = hosts;
@@ -85,7 +85,7 @@ public class JavaDriverClient
         this.username = settings.mode.username;
         this.password = settings.mode.password;
         this.authProvider = settings.mode.authProvider;
-        this.encryptionOptions = new EncryptionOptions(encryptionOptions).applyConfig();
+        this.encryptionOptions = new EncryptionOptions.ClientEncryptionOptions(encryptionOptions).applyConfig();
         this.loadBalancingPolicy = loadBalancingPolicy(settings);
         this.connectionsPerHost = settings.mode.connectionsPerHost == null ? 8 : settings.mode.connectionsPerHost;
 


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