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

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


The following commit(s) were added to refs/heads/trunk by this push:
     new bfcb21fbeb Set right client auth for creating SSL context in mTLS 
optional mode
bfcb21fbeb is described below

commit bfcb21fbebfef14fbfe626bfd39d66f5e5c51018
Author: Jyothsna Konisa <[email protected]>
AuthorDate: Wed Aug 30 11:58:21 2023 -0700

    Set right client auth for creating SSL context in mTLS optional mode
    
    patch by Jyothsna Konisa; reviewed by Francisco Guerrero, Jon Meredith for 
CASSANDRA-18811
---
 conf/cassandra.yaml                                |   3 +
 .../pages/getting-started/mtlsauthenticators.adoc  |  53 ++++++++
 .../KubernetesSecretsPEMSslContextFactoryTest.java |   2 +-
 .../KubernetesSecretsSslContextFactoryTest.java    |   2 +-
 .../cassandra/auth/MutualTlsAuthenticator.java     |  23 ++--
 .../auth/MutualTlsInternodeAuthenticator.java      |  23 ++--
 ...MutualTlsWithPasswordFallbackAuthenticator.java |  16 +++
 .../cassandra/config/DatabaseDescriptor.java       |   5 +-
 .../apache/cassandra/config/EncryptionOptions.java |  64 ++++++++--
 .../cassandra/net/InboundConnectionInitiator.java  |   3 +-
 .../cassandra/net/OutboundConnectionInitiator.java |  16 ++-
 .../security/AbstractSslContextFactory.java        |  45 ++++++-
 .../cassandra/security/ISslContextFactory.java     |  53 ++++++++
 .../org/apache/cassandra/security/SSLFactory.java  |  30 +++--
 .../org/apache/cassandra/tools/BulkLoader.java     |   3 +-
 .../org/apache/cassandra/tools/LoaderOptions.java  |   3 +-
 .../cassandra/transport/PipelineConfigurator.java  |   4 +-
 .../apache/cassandra/transport/SimpleClient.java   |   2 +-
 .../test/AbstractEncryptionOptionsImpl.java        |   5 +-
 .../test/NativeTransportEncryptionOptionsTest.java | 141 ++++++++++++++++++++-
 .../cassandra/auth/MutualTlsAuthenticatorTest.java |  20 ++-
 ...alTlsWithPasswordFallbackAuthenticatorTest.java |  10 +-
 .../cassandra/config/ConfigCompatibilityTest.java  |   3 +-
 .../config/EncryptionOptionsEqualityTest.java      |  16 ++-
 .../cassandra/config/EncryptionOptionsTest.java    |   6 +-
 .../cassandra/db/virtual/SettingsTableTest.java    |   4 +-
 .../org/apache/cassandra/net/ConnectionTest.java   |   3 +-
 .../org/apache/cassandra/net/HandshakeTest.java    |   6 +-
 .../security/DefaultSslContextFactoryTest.java     |   9 +-
 .../security/DummySslContextFactoryImpl.java       |  15 ++-
 .../security/FileBasedSslContextFactoryTest.java   |   4 +-
 .../security/PEMBasedSslContextFactoryTest.java    |  12 +-
 .../apache/cassandra/security/SSLFactoryTest.java  |  46 +++----
 .../cassandra/stress/util/JavaDriverClient.java    |   4 +-
 34 files changed, 528 insertions(+), 126 deletions(-)

diff --git a/conf/cassandra.yaml b/conf/cassandra.yaml
index 5c5019962e..978b991449 100644
--- a/conf/cassandra.yaml
+++ b/conf/cassandra.yaml
@@ -1567,6 +1567,9 @@ client_encryption_options:
   #     # Must be an instance of 
org.apache.cassandra.security.ISslContextFactory
   #     class_name: org.apache.cassandra.security.DefaultSslContextFactory
   # Verify client certificates
+  # - true/REQUIRED, Verifies the client and forces the client to send client 
certificate
+  # - false/NOT_REQUIRED, Doesn't verify the client
+  # - optional, Optionally verifies the client if client certificate is sent, 
but doesn't force client certificate to send certificates
   require_client_auth: false
   # require_endpoint_verification: false
   # Set trustore and truststore_password if require_client_auth is true
diff --git 
a/doc/modules/cassandra/pages/getting-started/mtlsauthenticators.adoc 
b/doc/modules/cassandra/pages/getting-started/mtlsauthenticators.adoc
index e3cd6ef79f..719f069739 100644
--- a/doc/modules/cassandra/pages/getting-started/mtlsauthenticators.adoc
+++ b/doc/modules/cassandra/pages/getting-started/mtlsauthenticators.adoc
@@ -66,6 +66,59 @@ authenticator:
 After the bounce, C* will accept mTLS connections from the clients and if their
 identity is present in the `identity_to_roles` table, access will be granted.
 
+== Configuring mTLS with password fallback authenticator for client connections
+
+Operators that wish to migrate cannot immediately change the configuration to 
require
+mTLS authentication as it will break existing non-mTLS based clients of the 
cluster.
+In order to make a smooth transition from non-mTLS based authentication to 
mTLS authentication,
+the operator can run Cassandra in optional mTLS mode and configure 
authenticator to be
+`MutualTlsWithPasswordFallbackAuthenticator` which can accept both certificate 
based
+and password based connections.
+
+Below are the steps to configure C* in optional mTLS mode with fallback 
authenticator.
+Note that the following steps uses SPIFFE identity as an example, If you are 
using
+a custom validator, use appropriate identity in place of 
`spiffe://testdomain.com/testIdentifier/testValue`.
+
+*STEP 1: Add authorized users to system_auth.identity_to_roles table*
+
+Note that only users with permissions to create/modify roles can add/remove 
identities.
+Client certificates with the identities in this table will be trusted by C*.
+[source, plaintext]
+----
+ADD IDENTITY 'spiffe://testdomain.com/testIdentifier/testValue' TO ROLE 
'read_only_user'
+----
+
+*STEP 2: Configure Cassandra.yaml with right properties*
+
+`client_encryption_options` configuration for mTLS connections, Note that 
require_client_auth configuration
+is optional.
+[source, plaintext]
+----
+client_encryption_options:
+  enabled: true
+  optional: true
+  keystore: conf/.keystore
+  keystore_password: cassandra
+  truststore: conf/.truststore
+  truststore_password: cassandra
+  require_client_auth: optional // to enable mTLS in optional mode
+----
+Configure fallback authenticator and the validator for client connections . If 
you are
+implementing a custom validator, use that instead of Spiffe validator
+[source, plaintext]
+----
+authenticator:
+  class_name : 
org.apache.cassandra.auth.MutualTlsWithPasswordFallbackAuthenticator
+  parameters :
+    validator_class_name: org.apache.cassandra.auth.SpiffeCertificateValidator
+----
+
+*STEP 3: Bounce the cluster*
+
+After the bounce, C* will accept both mTLS connections and password based 
connections from
+the clients. This configuration should be used during transition phase and the 
require_client_auth
+configuration should be set to true when all the clients start making mTLS 
connections to the cluster.
+
 == Configuring mTLS authenticator for Internode connections
 
 Internode authenticator trusts certificates whose identities are present in
diff --git 
a/examples/ssl-factory/test/unit/org/apache/cassandra/security/KubernetesSecretsPEMSslContextFactoryTest.java
 
b/examples/ssl-factory/test/unit/org/apache/cassandra/security/KubernetesSecretsPEMSslContextFactoryTest.java
index f101e8955d..5ecec4ed26 100644
--- 
a/examples/ssl-factory/test/unit/org/apache/cassandra/security/KubernetesSecretsPEMSslContextFactoryTest.java
+++ 
b/examples/ssl-factory/test/unit/org/apache/cassandra/security/KubernetesSecretsPEMSslContextFactoryTest.java
@@ -114,7 +114,7 @@ public class KubernetesSecretsPEMSslContextFactoryTest
          * In order to test with real 'env' variables comment out this line 
and set appropriate env variable. This is
          * done to avoid having a dependency on env in the unit test.
          */
-        commonConfig.put("require_client_auth", Boolean.FALSE);
+        commonConfig.put("require_client_auth", "false";
         commonConfig.put("cipher_suites", 
Arrays.asList("TLS_RSA_WITH_AES_128_CBC_SHA"));
     }
 
diff --git 
a/examples/ssl-factory/test/unit/org/apache/cassandra/security/KubernetesSecretsSslContextFactoryTest.java
 
b/examples/ssl-factory/test/unit/org/apache/cassandra/security/KubernetesSecretsSslContextFactoryTest.java
index 0c364196b8..77e9788d73 100644
--- 
a/examples/ssl-factory/test/unit/org/apache/cassandra/security/KubernetesSecretsSslContextFactoryTest.java
+++ 
b/examples/ssl-factory/test/unit/org/apache/cassandra/security/KubernetesSecretsSslContextFactoryTest.java
@@ -80,7 +80,7 @@ public class KubernetesSecretsSslContextFactoryTest
          * done to avoid having a dependency on env in the unit test.
          */
         commonConfig.put("MY_TRUSTSTORE_PASSWORD", "cassandra");
-        commonConfig.put("require_client_auth", Boolean.FALSE);
+        commonConfig.put("require_client_auth", "false");
         commonConfig.put("cipher_suites", 
Arrays.asList("TLS_RSA_WITH_AES_128_CBC_SHA"));
     }
 
diff --git a/src/java/org/apache/cassandra/auth/MutualTlsAuthenticator.java 
b/src/java/org/apache/cassandra/auth/MutualTlsAuthenticator.java
index c327a4bd21..01ff6919fa 100644
--- a/src/java/org/apache/cassandra/auth/MutualTlsAuthenticator.java
+++ b/src/java/org/apache/cassandra/auth/MutualTlsAuthenticator.java
@@ -40,6 +40,8 @@ import org.apache.cassandra.exceptions.ConfigurationException;
 import org.apache.cassandra.schema.SchemaConstants;
 import org.apache.cassandra.utils.NoSpamLogger;
 
+import static 
org.apache.cassandra.config.EncryptionOptions.ClientAuth.REQUIRED;
+
 /*
  * Performs mTLS authentication for client connections by extracting 
identities from client certificate
  * and verifying them against the authorized identities in IdentityCache. 
IdentityCache is a loading cache that
@@ -79,7 +81,6 @@ public class MutualTlsAuthenticator implements IAuthenticator
         }
         certificateValidator = ParameterizedClass.newInstance(new 
ParameterizedClass(certificateValidatorClassName),
                                                               
Arrays.asList("", AuthConfig.class.getPackage().getName()));
-        checkMtlsConfigurationIsValid(DatabaseDescriptor.getRawConfig());
         AuthCacheService.instance.register(identityCache);
     }
 
@@ -98,7 +99,14 @@ public class MutualTlsAuthenticator implements IAuthenticator
     @Override
     public void validateConfiguration() throws ConfigurationException
     {
-
+        Config config = DatabaseDescriptor.getRawConfig();
+        if (!config.client_encryption_options.getEnabled() || 
config.client_encryption_options.getClientAuth() != REQUIRED)
+        {
+            String msg = "MutualTlsAuthenticator requires 
client_encryption_options.enabled to be true" +
+                         " & client_encryption_options.require_client_auth to 
be true";
+            logger.error(msg);
+            throw new ConfigurationException(msg);
+        }
     }
 
     @Override
@@ -175,17 +183,6 @@ public class MutualTlsAuthenticator implements 
IAuthenticator
         }
     }
 
-    private void checkMtlsConfigurationIsValid(Config config)
-    {
-        if (!config.client_encryption_options.getEnabled() || 
!config.client_encryption_options.require_client_auth)
-        {
-            String msg = "MutualTlsAuthenticator requires 
client_encryption_options.enabled to be true" +
-                         " & client_encryption_options.require_client_auth to 
be true";
-            logger.error(msg);
-            throw new ConfigurationException(msg);
-        }
-    }
-
     static class IdentityCache extends AuthCache<String, String>
     {
         IdentityCache()
diff --git 
a/src/java/org/apache/cassandra/auth/MutualTlsInternodeAuthenticator.java 
b/src/java/org/apache/cassandra/auth/MutualTlsInternodeAuthenticator.java
index 3c466df5fa..cf5d764c9d 100644
--- a/src/java/org/apache/cassandra/auth/MutualTlsInternodeAuthenticator.java
+++ b/src/java/org/apache/cassandra/auth/MutualTlsInternodeAuthenticator.java
@@ -46,6 +46,8 @@ import 
org.apache.cassandra.exceptions.AuthenticationException;
 import org.apache.cassandra.exceptions.ConfigurationException;
 import org.apache.cassandra.utils.NoSpamLogger;
 
+import static 
org.apache.cassandra.config.EncryptionOptions.ClientAuth.REQUIRED;
+
 /*
  * Performs mTLS authentication for internode connections by extracting 
identities from the certificates of incoming
  * connection and verifying them against a list of authorized peers. 
Authorized peers can be configured in
@@ -89,7 +91,6 @@ public class MutualTlsInternodeAuthenticator implements 
IInternodeAuthenticator
         certificateValidator = ParameterizedClass.newInstance(new 
ParameterizedClass(certificateValidatorClassName),
                                                               
Arrays.asList("", AuthConfig.class.getPackage().getName()));
         Config config = DatabaseDescriptor.getRawConfig();
-        checkInternodeMtlsConfigurationIsValid(config);
 
         if (parameters.containsKey(TRUSTED_PEER_IDENTITIES))
         {
@@ -146,6 +147,15 @@ public class MutualTlsInternodeAuthenticator implements 
IInternodeAuthenticator
     @Override
     public void validateConfiguration() throws ConfigurationException
     {
+        Config config = DatabaseDescriptor.getRawConfig();
+        if (config.server_encryption_options.internode_encryption == 
EncryptionOptions.ServerEncryptionOptions.InternodeEncryption.none
+            || config.server_encryption_options.getClientAuth() != REQUIRED)
+        {
+            String msg = "MutualTlsInternodeAuthenticator requires 
server_encryption_options.internode_encryption to be enabled" +
+                         " & server_encryption_options.require_client_auth to 
be true";
+            logger.error(msg);
+            throw new ConfigurationException(msg);
+        }
 
     }
 
@@ -212,15 +222,4 @@ public class MutualTlsInternodeAuthenticator implements 
IInternodeAuthenticator
         return allUsers;
     }
 
-    private void checkInternodeMtlsConfigurationIsValid(Config config)
-    {
-        if (config.server_encryption_options.internode_encryption == 
EncryptionOptions.ServerEncryptionOptions.InternodeEncryption.none
-            || !config.server_encryption_options.require_client_auth)
-        {
-            String msg = "MutualTlsInternodeAuthenticator requires 
server_encryption_options.internode_encryption to be enabled" +
-                         " & server_encryption_options.require_client_auth to 
be true";
-            logger.error(msg);
-            throw new ConfigurationException(msg);
-        }
-    }
 }
diff --git 
a/src/java/org/apache/cassandra/auth/MutualTlsWithPasswordFallbackAuthenticator.java
 
b/src/java/org/apache/cassandra/auth/MutualTlsWithPasswordFallbackAuthenticator.java
index eba0ea54c0..4c86f6a3fe 100644
--- 
a/src/java/org/apache/cassandra/auth/MutualTlsWithPasswordFallbackAuthenticator.java
+++ 
b/src/java/org/apache/cassandra/auth/MutualTlsWithPasswordFallbackAuthenticator.java
@@ -22,6 +22,11 @@ import java.net.InetAddress;
 import java.security.cert.Certificate;
 import java.util.Map;
 
+import org.apache.cassandra.config.Config;
+import org.apache.cassandra.config.DatabaseDescriptor;
+import org.apache.cassandra.config.EncryptionOptions;
+import org.apache.cassandra.exceptions.ConfigurationException;
+
 /**
  * This authenticator can be used in optional mTLS mode, If the client doesn't 
make an mTLS connection
  * this fallbacks to password authentication.
@@ -50,4 +55,15 @@ public class MutualTlsWithPasswordFallbackAuthenticator 
extends PasswordAuthenti
         }
         return mutualTlsAuthenticator.newSaslNegotiator(clientAddress, 
certificates);
     }
+
+    @Override
+    public void validateConfiguration() throws ConfigurationException
+    {
+        Config config = DatabaseDescriptor.getRawConfig();
+        if (config.client_encryption_options.getClientAuth() == 
EncryptionOptions.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/DatabaseDescriptor.java 
b/src/java/org/apache/cassandra/config/DatabaseDescriptor.java
index b304100957..4b0f036914 100644
--- a/src/java/org/apache/cassandra/config/DatabaseDescriptor.java
+++ b/src/java/org/apache/cassandra/config/DatabaseDescriptor.java
@@ -140,6 +140,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.db.ConsistencyLevel.ALL;
 import static org.apache.cassandra.db.ConsistencyLevel.EACH_QUORUM;
 import static org.apache.cassandra.db.ConsistencyLevel.LOCAL_QUORUM;
@@ -1241,8 +1242,8 @@ public class DatabaseDescriptor
 
         try
         {
-            SSLFactory.validateSslContext("Internode messaging", 
conf.server_encryption_options, true, true);
-            SSLFactory.validateSslContext("Native transport", 
conf.client_encryption_options, 
conf.client_encryption_options.require_client_auth, true);
+            SSLFactory.validateSslContext("Internode messaging", 
conf.server_encryption_options, REQUIRED, true);
+            SSLFactory.validateSslContext("Native transport", 
conf.client_encryption_options, conf.client_encryption_options.getClientAuth(), 
true);
             SSLFactory.initHotReloading(conf.server_encryption_options, 
conf.client_encryption_options, false);
         }
         catch (IOException e)
diff --git a/src/java/org/apache/cassandra/config/EncryptionOptions.java 
b/src/java/org/apache/cassandra/config/EncryptionOptions.java
index 9db2406a44..91d9ae5ee2 100644
--- a/src/java/org/apache/cassandra/config/EncryptionOptions.java
+++ b/src/java/org/apache/cassandra/config/EncryptionOptions.java
@@ -33,6 +33,7 @@ import com.google.common.collect.ImmutableList;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import org.apache.cassandra.exceptions.ConfigurationException;
 import org.apache.cassandra.locator.IEndpointSnitch;
 import org.apache.cassandra.locator.InetAddressAndPort;
 import org.apache.cassandra.security.DisableSslContextFactory;
@@ -67,6 +68,42 @@ public class EncryptionOptions
         }
     }
 
+    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(clientAuth.name().toLowerCase(), clientAuth);
+            }
+        }
+
+        ClientAuth(String value)
+        {
+            this.value = value;
+        }
+
+        public static ClientAuth from(String value)
+        {
+            if (VALUES.containsKey(value.toLowerCase()))
+            {
+                return VALUES.get(value.toLowerCase());
+            }
+            throw new ConfigurationException(value + " is not a valid 
ClientAuth option");
+        }
+
+        public String value()
+        {
+            return value;
+        }
+    }
+
     /*
      * If the ssl_context_factory is configured, most likely it won't use file 
based keystores and truststores and
      * can choose to completely customize SSL context's creation. Most likely 
it won't also use keystore_password and
@@ -84,7 +121,7 @@ public class EncryptionOptions
     protected List<String> accepted_protocols;
     public final String algorithm;
     public final String store_type;
-    public final boolean require_client_auth;
+    public final String require_client_auth;
     public final boolean require_endpoint_verification;
     // ServerEncryptionOptions does not use the enabled flag at all instead 
using the existing
     // internode_encryption option. So we force this private and expose 
through isEnabled
@@ -159,7 +196,7 @@ public class EncryptionOptions
         accepted_protocols = null;
         algorithm = null;
         store_type = "JKS";
-        require_client_auth = false;
+        require_client_auth = "false";
         require_endpoint_verification = false;
         enabled = null;
         optional = null;
@@ -168,7 +205,7 @@ public class EncryptionOptions
     public EncryptionOptions(ParameterizedClass ssl_context_factory, String 
keystore, String keystore_password,
                              String truststore, String truststore_password, 
List<String> cipher_suites,
                              String protocol, List<String> accepted_protocols, 
String algorithm, String store_type,
-                             boolean require_client_auth, boolean 
require_endpoint_verification, Boolean enabled,
+                             String require_client_auth, boolean 
require_endpoint_verification, Boolean enabled,
                              Boolean optional)
     {
         this.ssl_context_factory = ssl_context_factory;
@@ -402,6 +439,11 @@ public class EncryptionOptions
         return sslContextFactoryInstance == null ? null : 
sslContextFactoryInstance.getAcceptedProtocols();
     }
 
+    public ClientAuth getClientAuth()
+    {
+        return this.require_client_auth == null ? ClientAuth.NOT_REQUIRED : 
ClientAuth.from(this.require_client_auth);
+    }
+
     public String[] acceptedProtocolsArray()
     {
         List<String> ap = getAcceptedProtocols();
@@ -520,11 +562,11 @@ public class EncryptionOptions
                                      optional).applyConfig();
     }
 
-    public EncryptionOptions withRequireClientAuth(boolean require_client_auth)
+    public EncryptionOptions withRequireClientAuth(ClientAuth 
require_client_auth)
     {
         return new EncryptionOptions(ssl_context_factory, keystore, 
keystore_password, truststore,
                                      truststore_password, cipher_suites, 
protocol, accepted_protocols, algorithm,
-                                     store_type, require_client_auth, 
require_endpoint_verification, enabled,
+                                     store_type, require_client_auth.value, 
require_endpoint_verification, enabled,
                                      optional).applyConfig();
     }
 
@@ -567,7 +609,7 @@ public class EncryptionOptions
         EncryptionOptions opt = (EncryptionOptions)o;
         return enabled == opt.enabled &&
                optional == opt.optional &&
-               require_client_auth == opt.require_client_auth &&
+               require_client_auth.equals(opt.require_client_auth) &&
                require_endpoint_verification == 
opt.require_endpoint_verification &&
                Objects.equals(keystore, opt.keystore) &&
                Objects.equals(keystore_password, opt.keystore_password) &&
@@ -600,7 +642,7 @@ public class EncryptionOptions
         result += 31 * (enabled == null ? 0 : Boolean.hashCode(enabled));
         result += 31 * (optional == null ? 0 : Boolean.hashCode(optional));
         result += 31 * (cipher_suites == null ? 0 : cipher_suites.hashCode());
-        result += 31 * Boolean.hashCode(require_client_auth);
+        result += 31 * require_client_auth.hashCode();
         result += 31 * Boolean.hashCode(require_endpoint_verification);
         result += 31 * (ssl_context_factory == null ? 0 : 
ssl_context_factory.hashCode());
         return result;
@@ -632,7 +674,7 @@ public class EncryptionOptions
                                        String keystore_password,String 
outbound_keystore,
                                        String outbound_keystore_password, 
String truststore, String truststore_password,
                                        List<String> cipher_suites, String 
protocol, List<String> accepted_protocols,
-                                       String algorithm, String store_type, 
boolean require_client_auth,
+                                       String algorithm, String store_type, 
String require_client_auth,
                                        boolean require_endpoint_verification, 
Boolean optional,
                                        InternodeEncryption 
internode_encryption, boolean legacy_ssl_storage_port_enabled)
         {
@@ -679,7 +721,7 @@ public class EncryptionOptions
                 logger.warn("Setting server_encryption_options.enabled has no 
effect, use internode_encryption");
             }
 
-            if (require_client_auth && (internode_encryption == 
InternodeEncryption.rack || internode_encryption == InternodeEncryption.dc))
+            if (getClientAuth() != 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"
@@ -875,12 +917,12 @@ public class EncryptionOptions
                                                
legacy_ssl_storage_port_enabled).applyConfigInternal();
         }
 
-        public ServerEncryptionOptions withRequireClientAuth(boolean 
require_client_auth)
+        public ServerEncryptionOptions withRequireClientAuth(ClientAuth 
require_client_auth)
         {
             return new ServerEncryptionOptions(ssl_context_factory, keystore, 
keystore_password,
                                                outbound_keystore, 
outbound_keystore_password, truststore,
                                                truststore_password, 
cipher_suites, protocol, accepted_protocols,
-                                               algorithm, store_type, 
require_client_auth,
+                                               algorithm, store_type, 
require_client_auth.value,
                                                require_endpoint_verification, 
optional, internode_encryption,
                                                
legacy_ssl_storage_port_enabled).applyConfigInternal();
         }
diff --git a/src/java/org/apache/cassandra/net/InboundConnectionInitiator.java 
b/src/java/org/apache/cassandra/net/InboundConnectionInitiator.java
index c76d9b0375..cd4e33244c 100644
--- a/src/java/org/apache/cassandra/net/InboundConnectionInitiator.java
+++ b/src/java/org/apache/cassandra/net/InboundConnectionInitiator.java
@@ -64,6 +64,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.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;
@@ -521,7 +522,7 @@ public class InboundConnectionInitiator
 
     private static SslHandler getSslHandler(String description, Channel 
channel, EncryptionOptions.ServerEncryptionOptions encryptionOptions) throws 
IOException
     {
-        final boolean verifyPeerCertificate = true;
+        final EncryptionOptions.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/OutboundConnectionInitiator.java 
b/src/java/org/apache/cassandra/net/OutboundConnectionInitiator.java
index 63b99a45db..b95d20a158 100644
--- a/src/java/org/apache/cassandra/net/OutboundConnectionInitiator.java
+++ b/src/java/org/apache/cassandra/net/OutboundConnectionInitiator.java
@@ -29,6 +29,7 @@ import com.google.common.annotations.VisibleForTesting;
 
 import io.netty.util.concurrent.Future; //checkstyle: permit this import
 import io.netty.util.concurrent.Promise; //checkstyle: permit this import
+import org.apache.cassandra.config.EncryptionOptions;
 import org.apache.cassandra.utils.concurrent.AsyncPromise;
 
 import org.slf4j.Logger;
@@ -65,6 +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.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;
@@ -241,14 +245,18 @@ public class OutboundConnectionInitiator<SuccessType 
extends OutboundConnectionI
 
         private SslContext getSslContext(SslFallbackConnectionType 
connectionType) throws IOException
         {
-            boolean requireClientAuth = false;
-            if (connectionType == SslFallbackConnectionType.MTLS || 
connectionType == SslFallbackConnectionType.SSL)
+            EncryptionOptions.ClientAuth requireClientAuth = NOT_REQUIRED;
+            if (connectionType == SslFallbackConnectionType.MTLS )
             {
-                requireClientAuth = true;
+                requireClientAuth = REQUIRED;
+            }
+            else if(connectionType == SslFallbackConnectionType.SSL)
+            {
+                requireClientAuth = OPTIONAL;
             }
             else if (connectionType == SslFallbackConnectionType.SERVER_CONFIG)
             {
-                requireClientAuth = settings.withEncryption();
+                requireClientAuth = settings.withEncryption() ? REQUIRED: 
NOT_REQUIRED;
             }
             return SSLFactory.getOrCreateSslContext(settings.encryption, 
requireClientAuth, ISslContextFactory.SocketType.CLIENT, 
SSL_FACTORY_CONTEXT_DESCRIPTION);
         }
diff --git 
a/src/java/org/apache/cassandra/security/AbstractSslContextFactory.java 
b/src/java/org/apache/cassandra/security/AbstractSslContextFactory.java
index 406c4720f2..c2a7fdb975 100644
--- a/src/java/org/apache/cassandra/security/AbstractSslContextFactory.java
+++ b/src/java/org/apache/cassandra/security/AbstractSslContextFactory.java
@@ -35,6 +35,10 @@ import io.netty.handler.ssl.OpenSsl;
 import io.netty.handler.ssl.SslContext;
 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.CassandraRelevantProperties.DISABLE_TCACTIVE_OPENSSL;
 
@@ -64,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 boolean require_client_auth;
+    protected final EncryptionOptions.ClientAuth clientAuth;
     protected final boolean require_endpoint_verification;
     /*
     ServerEncryptionOptions does not use the enabled flag at all instead using 
the existing
@@ -86,7 +90,7 @@ abstract public class AbstractSslContextFactory implements 
ISslContextFactory
         accepted_protocols = null;
         algorithm = null;
         store_type = "JKS";
-        require_client_auth = false;
+        clientAuth = NOT_REQUIRED;
         require_endpoint_verification = false;
         enabled = null;
         optional = null;
@@ -101,7 +105,7 @@ abstract public class AbstractSslContextFactory implements 
ISslContextFactory
         accepted_protocols = getStringList("accepted_protocols");
         algorithm = getString("algorithm");
         store_type = getString("store_type", "JKS");
-        require_client_auth = getBoolean("require_client_auth", false);
+        clientAuth = parameters.get("require_client_auth") == null ? 
NOT_REQUIRED : 
EncryptionOptions.ClientAuth.from(getString("require_client_auth"));
         require_endpoint_verification = 
getBoolean("require_endpoint_verification", false);
         enabled = getBoolean("enabled");
         optional = getBoolean("optional");
@@ -149,9 +153,15 @@ abstract public class AbstractSslContextFactory implements 
ISslContextFactory
 
     @Override
     public SSLContext createJSSESslContext(boolean verifyPeerCertificate) 
throws SSLException
+    {
+        return createJSSESslContext(verifyPeerCertificate ? REQUIRED : 
NOT_REQUIRED);
+    }
+
+    @Override
+    public SSLContext createJSSESslContext(EncryptionOptions.ClientAuth 
clientAuth) throws SSLException
     {
         TrustManager[] trustManagers = null;
-        if (verifyPeerCertificate)
+        if (clientAuth != NOT_REQUIRED)
             trustManagers = buildTrustManagerFactory().getTrustManagers();
 
         KeyManagerFactory kmf = buildKeyManagerFactory();
@@ -171,6 +181,13 @@ abstract public class AbstractSslContextFactory implements 
ISslContextFactory
     @Override
     public SslContext createNettySslContext(boolean verifyPeerCertificate, 
SocketType socketType,
                                             CipherSuiteFilter cipherFilter) 
throws SSLException
+    {
+        return createNettySslContext(verifyPeerCertificate ? REQUIRED : 
NOT_REQUIRED, socketType, cipherFilter);
+    }
+
+    @Override
+    public SslContext createNettySslContext(EncryptionOptions.ClientAuth 
clientAuth, SocketType socketType,
+                                            CipherSuiteFilter cipherFilter) 
throws SSLException
     {
         /*
             There is a case where the netty/openssl combo might not support 
using KeyManagerFactory. Specifically,
@@ -184,8 +201,7 @@ abstract public class AbstractSslContextFactory implements 
ISslContextFactory
         if (socketType == SocketType.SERVER)
         {
             KeyManagerFactory kmf = buildKeyManagerFactory();
-            builder = 
SslContextBuilder.forServer(kmf).clientAuth(this.require_client_auth ? 
ClientAuth.REQUIRE :
-                                                                  
ClientAuth.NONE);
+            builder = 
SslContextBuilder.forServer(kmf).clientAuth(toNettyClientAuth(this.clientAuth));
         }
         else
         {
@@ -200,7 +216,7 @@ abstract public class AbstractSslContextFactory implements 
ISslContextFactory
         if (cipher_suites != null && !cipher_suites.isEmpty())
             builder.ciphers(cipher_suites, cipherFilter);
 
-        if (verifyPeerCertificate)
+        if (clientAuth != NOT_REQUIRED)
             builder.trustManager(buildTrustManagerFactory());
 
         return builder.build();
@@ -274,4 +290,19 @@ abstract public class AbstractSslContextFactory implements 
ISslContextFactory
      * @throws SSLException
      */
     abstract protected KeyManagerFactory buildOutboundKeyManagerFactory() 
throws SSLException;
+
+    private ClientAuth toNettyClientAuth(EncryptionOptions.ClientAuth 
clientAuth)
+    {
+        switch (clientAuth)
+        {
+            case REQUIRED:
+                return ClientAuth.REQUIRE;
+            case NOT_REQUIRED:
+                return ClientAuth.NONE;
+            case OPTIONAL:
+                return ClientAuth.OPTIONAL;
+            default:
+                throw new RuntimeException("Unsupported client auth " + 
clientAuth);
+        }
+    }
 }
diff --git a/src/java/org/apache/cassandra/security/ISslContextFactory.java 
b/src/java/org/apache/cassandra/security/ISslContextFactory.java
index 11c4717b3c..1db5f579b1 100644
--- a/src/java/org/apache/cassandra/security/ISslContextFactory.java
+++ b/src/java/org/apache/cassandra/security/ISslContextFactory.java
@@ -24,6 +24,7 @@ import javax.net.ssl.SSLException;
 
 import io.netty.handler.ssl.CipherSuiteFilter;
 import io.netty.handler.ssl.SslContext;
+import org.apache.cassandra.config.EncryptionOptions;
 
 /**
  * The purpose of this interface is to provide pluggable mechanism for 
creating custom JSSE and Netty SSLContext
@@ -57,9 +58,33 @@ public interface ISslContextFactory
      * @param verifyPeerCertificate {@code true} if SSL peer's certificate 
needs to be verified; {@code false} otherwise
      * @return JSSE's {@link SSLContext}
      * @throws SSLException in case the Ssl Context creation fails for some 
reason
+     *
+     * @deprecated See CASSANDRA-18811
      */
+    @Deprecated(since = "5.1")
     SSLContext createJSSESslContext(boolean verifyPeerCertificate) throws 
SSLException;
 
+    /**
+     * Creates JSSE SSLContext.
+     *
+     * @param clientAuth {@code REQUIRED} if SSL peer's certificate needs to 
be verified; {@code OPTIONAL} if peer's
+     *                                   certificate needs to be optionally 
verfied; {@code NOT_REQUIRED} otherwise.
+     * @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
+    {
+        switch (clientAuth)
+        {
+            case REQUIRED:
+                return createJSSESslContext(true);
+            case NOT_REQUIRED:
+            case OPTIONAL:
+            default:
+                return createJSSESslContext(false);
+        }
+    }
+
     /**
      * Creates Netty's SslContext object.
      *
@@ -69,10 +94,38 @@ public interface ISslContextFactory
      *                              {@link 
io.netty.handler.ssl.SslContextBuilder#ciphers(Iterable, CipherSuiteFilter)}
      * @return Netty's {@link SslContext}
      * @throws SSLException in case the Ssl Context creation fails for some 
reason
+     *
+     * @deprecated See CASSANDRA-18811
      */
+    @Deprecated(since = "5.1")
     SslContext createNettySslContext(boolean verifyPeerCertificate, SocketType 
socketType,
                                      CipherSuiteFilter cipherFilter) throws 
SSLException;
 
+    /**
+     * Creates Netty's SslContext object.
+     *
+     * @param clientAuth {@code REQUIRED} if SSL peer's certificate needs to 
be verified; {@code OPTIONAL} if peer's
+     *      *                             certificate needs to be optionally 
verfied; {@code NOT_REQUIRED} otherwise.
+     * @param socketType            {@link SocketType} for Netty's Inbound or 
Outbound channels
+     * @param cipherFilter          to allow Netty's cipher suite filtering, 
e.g.
+     *                              {@link 
io.netty.handler.ssl.SslContextBuilder#ciphers(Iterable, CipherSuiteFilter)}
+     * @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,
+                                             CipherSuiteFilter cipherFilter) 
throws SSLException
+    {
+        switch (clientAuth)
+        {
+            case REQUIRED:
+                return createNettySslContext(true, socketType, cipherFilter);
+            case NOT_REQUIRED:
+            case OPTIONAL:
+            default:
+                return createNettySslContext(false, socketType, cipherFilter);
+        }
+    }
+
     /**
      * Initializes hot reloading of the security keys/certs. The 
implementation must guarantee this to be thread safe.
      *
diff --git a/src/java/org/apache/cassandra/security/SSLFactory.java 
b/src/java/org/apache/cassandra/security/SSLFactory.java
index 5a175b3fd6..c55e970b4f 100644
--- a/src/java/org/apache/cassandra/security/SSLFactory.java
+++ b/src/java/org/apache/cassandra/security/SSLFactory.java
@@ -47,6 +47,8 @@ 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;
+
 /**
  * A Factory for providing and setting up client {@link SSLSocket}s. Also 
provides
  * methods for creating both JSSE {@link SSLContext} instances as well as 
netty {@link SslContext} instances.
@@ -122,15 +124,15 @@ public final class SSLFactory
     /**
      * Create a JSSE {@link SSLContext}.
      */
-    public static SSLContext createSSLContext(EncryptionOptions options, 
boolean verifyPeerCertificate) throws IOException
+    public static SSLContext createSSLContext(EncryptionOptions options, 
EncryptionOptions.ClientAuth clientAuth) throws IOException
     {
-        return 
options.sslContextFactoryInstance.createJSSESslContext(verifyPeerCertificate);
+        return 
options.sslContextFactoryInstance.createJSSESslContext(clientAuth);
     }
 
     /**
      * get a netty {@link SslContext} instance
      */
-    public static SslContext getOrCreateSslContext(EncryptionOptions options, 
boolean verifyPeerCertificate,
+    public static SslContext getOrCreateSslContext(EncryptionOptions options, 
EncryptionOptions.ClientAuth clientAuth,
                                                    SocketType socketType,
                                                    String contextDescription) 
throws IOException
     {
@@ -141,7 +143,7 @@ public final class SSLFactory
         if (sslContext != null)
             return sslContext;
 
-        sslContext = createNettySslContext(options, verifyPeerCertificate, 
socketType);
+        sslContext = createNettySslContext(options, clientAuth, socketType);
 
         SslContext previous = cachedSslContexts.putIfAbsent(key, sslContext);
         if (previous == null)
@@ -154,20 +156,20 @@ public final class SSLFactory
     /**
      * Create a Netty {@link SslContext}
      */
-    static SslContext createNettySslContext(EncryptionOptions options, boolean 
verifyPeerCertificate,
+    static SslContext createNettySslContext(EncryptionOptions options, 
EncryptionOptions.ClientAuth clientAuth,
                                             SocketType socketType) throws 
IOException
     {
-        return createNettySslContext(options, verifyPeerCertificate, 
socketType,
+        return createNettySslContext(options, clientAuth, socketType,
                                      LoggingCipherSuiteFilter.QUIET_FILTER);
     }
 
     /**
      * Create a Netty {@link SslContext} with a supplied cipherFilter
      */
-    static SslContext createNettySslContext(EncryptionOptions options, boolean 
verifyPeerCertificate,
+    static SslContext createNettySslContext(EncryptionOptions options, 
EncryptionOptions.ClientAuth clientAuth,
                                             SocketType socketType, 
CipherSuiteFilter cipherFilter) throws IOException
     {
-        return 
options.sslContextFactoryInstance.createNettySslContext(verifyPeerCertificate, 
socketType,
+        return 
options.sslContextFactoryInstance.createNettySslContext(clientAuth, socketType,
                                                                        
cipherFilter);
     }
 
@@ -206,7 +208,7 @@ public final class SSLFactory
                 try
                 {
                     validateSslContext(key.contextDescription, opts,
-                            opts instanceof 
EncryptionOptions.ServerEncryptionOptions || opts.require_client_auth, false);
+                            opts instanceof 
EncryptionOptions.ServerEncryptionOptions? REQUIRED : opts.getClientAuth(), 
false);
                     logger.info("SSL certificates have been updated for {}. 
Resetting the ssl contexts for new " +
                                 "connections.", key.contextDescription);
                     clearSslContextCache(key.encryptionOptions, keysToCheck);
@@ -353,7 +355,7 @@ public final class SSLFactory
         return !string.equals("SSLv2Hello");
     }
 
-    public static void validateSslContext(String contextDescription, 
EncryptionOptions options, boolean verifyPeerCertificate, boolean 
logProtocolAndCiphers) throws IOException
+    public static void validateSslContext(String contextDescription, 
EncryptionOptions options, EncryptionOptions.ClientAuth clientAuth, boolean 
logProtocolAndCiphers) throws IOException
     {
         if (options != null && options.tlsEncryptionPolicy() != 
EncryptionOptions.TlsEncryptionPolicy.UNENCRYPTED)
         {
@@ -361,7 +363,7 @@ public final class SSLFactory
             {
                 CipherSuiteFilter loggingCipherSuiteFilter = 
logProtocolAndCiphers ? new LoggingCipherSuiteFilter(contextDescription)
                                                                                
    : LoggingCipherSuiteFilter.QUIET_FILTER;
-                SslContext serverSslContext = createNettySslContext(options, 
verifyPeerCertificate, SocketType.SERVER, loggingCipherSuiteFilter);
+                SslContext serverSslContext = createNettySslContext(options, 
clientAuth, SocketType.SERVER, loggingCipherSuiteFilter);
                 try
                 {
                     SSLEngine engine = 
serverSslContext.newEngine(ByteBufAllocator.DEFAULT);
@@ -406,7 +408,7 @@ public final class SSLFactory
                 }
 
                 // Make sure it is possible to build the client context too
-                SslContext clientSslContext = createNettySslContext(options, 
verifyPeerCertificate, SocketType.CLIENT);
+                SslContext clientSslContext = createNettySslContext(options, 
clientAuth, SocketType.CLIENT);
                 ReferenceCountUtil.release(clientSslContext);
             }
             catch (Exception e)
@@ -421,8 +423,8 @@ public final class SSLFactory
      */
     public static void 
validateSslCerts(EncryptionOptions.ServerEncryptionOptions serverOpts, 
EncryptionOptions clientOpts) throws IOException
     {
-        validateSslContext("server_encryption_options", serverOpts, true, 
false);
-        validateSslContext("client_encryption_options", clientOpts, 
clientOpts.require_client_auth, false);
+        validateSslContext("server_encryption_options", serverOpts, REQUIRED, 
false);
+        validateSslContext("client_encryption_options", clientOpts, 
clientOpts.getClientAuth(), false);
     }
 
     static class CacheKey
diff --git a/src/java/org/apache/cassandra/tools/BulkLoader.java 
b/src/java/org/apache/cassandra/tools/BulkLoader.java
index 8802b9e837..367903a595 100644
--- a/src/java/org/apache/cassandra/tools/BulkLoader.java
+++ b/src/java/org/apache/cassandra/tools/BulkLoader.java
@@ -48,6 +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.utils.Clock.Global.nanoTime;
 
 public class BulkLoader
@@ -264,7 +265,7 @@ public class BulkLoader
         SSLContext sslContext;
         try
         {
-            sslContext = SSLFactory.createSSLContext(clientEncryptionOptions, 
true);
+            sslContext = SSLFactory.createSSLContext(clientEncryptionOptions, 
REQUIRED);
         }
         catch (IOException e)
         {
diff --git a/src/java/org/apache/cassandra/tools/LoaderOptions.java 
b/src/java/org/apache/cassandra/tools/LoaderOptions.java
index 03c8ee6024..1f368168a7 100644
--- a/src/java/org/apache/cassandra/tools/LoaderOptions.java
+++ b/src/java/org/apache/cassandra/tools/LoaderOptions.java
@@ -52,6 +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;
 
 public class LoaderOptions
 {
@@ -648,7 +649,7 @@ public class LoaderOptions
                 {
                     // if a keystore was provided, lets assume we'll need to 
use
                     clientEncOptions = 
clientEncOptions.withKeyStore(cmd.getOptionValue(SSL_KEYSTORE))
-                                                       
.withRequireClientAuth(true);
+                                                       
.withRequireClientAuth(REQUIRED);
                 }
 
                 if (cmd.hasOption(SSL_KEYSTORE_PW))
diff --git a/src/java/org/apache/cassandra/transport/PipelineConfigurator.java 
b/src/java/org/apache/cassandra/transport/PipelineConfigurator.java
index d19af211e2..1bcebf96cf 100644
--- a/src/java/org/apache/cassandra/transport/PipelineConfigurator.java
+++ b/src/java/org/apache/cassandra/transport/PipelineConfigurator.java
@@ -168,7 +168,7 @@ public class PipelineConfigurator
                 logger.debug("Enabling optionally encrypted CQL connections 
between client and server");
                 return channel -> {
                     SslContext sslContext = 
SSLFactory.getOrCreateSslContext(encryptionOptions,
-                                                                             
encryptionOptions.require_client_auth,
+                                                                             
encryptionOptions.getClientAuth(),
                                                                              
ISslContextFactory.SocketType.SERVER,
                                                                              
SSL_FACTORY_CONTEXT_DESCRIPTION);
 
@@ -204,7 +204,7 @@ public class PipelineConfigurator
                 logger.debug("Enabling encrypted CQL connections between 
client and server");
                 return channel -> {
                     SslContext sslContext = 
SSLFactory.getOrCreateSslContext(encryptionOptions,
-                                                                             
encryptionOptions.require_client_auth,
+                                                                             
encryptionOptions.getClientAuth(),
                                                                              
ISslContextFactory.SocketType.SERVER,
                                                                              
SSL_FACTORY_CONTEXT_DESCRIPTION);
                     InetSocketAddress peer = 
encryptionOptions.require_endpoint_verification ? (InetSocketAddress) 
channel.remoteAddress() : null;
diff --git a/src/java/org/apache/cassandra/transport/SimpleClient.java 
b/src/java/org/apache/cassandra/transport/SimpleClient.java
index f4a1b9fd3f..0fa3a7af31 100644
--- a/src/java/org/apache/cassandra/transport/SimpleClient.java
+++ b/src/java/org/apache/cassandra/transport/SimpleClient.java
@@ -623,7 +623,7 @@ public class SimpleClient implements Closeable
         protected void initChannel(Channel channel) throws Exception
         {
             super.initChannel(channel);
-            SslContext sslContext = 
SSLFactory.getOrCreateSslContext(encryptionOptions, 
encryptionOptions.require_client_auth,
+            SslContext sslContext = 
SSLFactory.getOrCreateSslContext(encryptionOptions, 
encryptionOptions.getClientAuth(),
                                                                      
ISslContextFactory.SocketType.CLIENT, SSL_FACTORY_CONTEXT_DESCRIPTION);
             InetSocketAddress peer = 
encryptionOptions.require_endpoint_verification ? new InetSocketAddress(host, 
port) : null;
             channel.pipeline().addFirst("ssl", newSslHandler(channel, 
sslContext, peer));
diff --git 
a/test/distributed/org/apache/cassandra/distributed/test/AbstractEncryptionOptionsImpl.java
 
b/test/distributed/org/apache/cassandra/distributed/test/AbstractEncryptionOptionsImpl.java
index b488867433..5f119c6bdf 100644
--- 
a/test/distributed/org/apache/cassandra/distributed/test/AbstractEncryptionOptionsImpl.java
+++ 
b/test/distributed/org/apache/cassandra/distributed/test/AbstractEncryptionOptionsImpl.java
@@ -54,6 +54,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.distributed.test.AbstractEncryptionOptionsImpl.ConnectResult.CONNECTING;
 import static 
org.apache.cassandra.distributed.test.AbstractEncryptionOptionsImpl.ConnectResult.UNINITIALIZED;
 import static 
org.apache.cassandra.utils.concurrent.Condition.newOneTimeCondition;
@@ -199,8 +200,8 @@ public class AbstractEncryptionOptionsImpl extends 
TestBaseImpl
             setProtocolAndCipher(null, null);
 
             SslContext sslContext = SSLFactory.getOrCreateSslContext(
-                
encryptionOptions.withAcceptedProtocols(acceptedProtocols).withCipherSuites(cipherSuites),
-                true, ISslContextFactory.SocketType.CLIENT, "test");
+            
encryptionOptions.withAcceptedProtocols(acceptedProtocols).withCipherSuites(cipherSuites),
+            REQUIRED, ISslContextFactory.SocketType.CLIENT, "test");
 
             EventLoopGroup workerGroup = new NioEventLoopGroup();
             Bootstrap b = new Bootstrap();
diff --git 
a/test/distributed/org/apache/cassandra/distributed/test/NativeTransportEncryptionOptionsTest.java
 
b/test/distributed/org/apache/cassandra/distributed/test/NativeTransportEncryptionOptionsTest.java
index 3e8c926480..86d4e8fa26 100644
--- 
a/test/distributed/org/apache/cassandra/distributed/test/NativeTransportEncryptionOptionsTest.java
+++ 
b/test/distributed/org/apache/cassandra/distributed/test/NativeTransportEncryptionOptionsTest.java
@@ -41,6 +41,9 @@ import 
com.datastax.shaded.netty.handler.ssl.SslContextBuilder;
 import org.apache.cassandra.distributed.Cluster;
 import org.apache.cassandra.distributed.api.Feature;
 
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+
 public class NativeTransportEncryptionOptionsTest extends 
AbstractEncryptionOptionsImpl
 {
     @Rule
@@ -154,9 +157,9 @@ public class NativeTransportEncryptionOptionsTest extends 
AbstractEncryptionOpti
 
     /**
      * Tests that the negotiated protocol is the highest common protocol 
between the client and server.
-     * <p> 
-     * Note: This test uses TLSV1.1, which is disabled by default in JDK 8 and 
higher. If the test fails with 
-     * FAILED_TO_NEGOTIATE, it may be necessary to check the java.security 
file in your JDK installation and remove 
+     * <p>
+     * Note: This test uses TLSV1.1, which is disabled by default in JDK 8 and 
higher. If the test fails with
+     * FAILED_TO_NEGOTIATE, it may be necessary to check the java.security 
file in your JDK installation and remove
      * TLSv1.1 from the jdk.tls.disabledAlgorithms.
      * @see <a 
href="https://issues.apache.org/jira/browse/CASSANDRA-18540";>CASSANDRA-18540</a>
      * @see <a 
href="https://senthilnayagan.medium.com/tlsv1-and-tlsv1-1-protocols-disabled-by-default-in-javas-latest-patch-released-on-april-20-2021-52c309f6b16d";>
@@ -278,6 +281,138 @@ public class NativeTransportEncryptionOptionsTest extends 
AbstractEncryptionOpti
         testEndpointVerification(true, true);
     }
 
+    @Test
+    public void testOptionalMtlsModeAllowNonSSLConnections() throws Exception
+    {
+        // When server is configured in optional mTLS mode and allowing ssl 
connections, it should accept
+        // non-ssl, ssl, mTLS based connections
+        try (Cluster cluster = builder().withNodes(1).withConfig(c -> {
+            c.with(Feature.NATIVE_PROTOCOL);
+            c.set("client_encryption_options",
+                  ImmutableMap.builder().putAll(validKeystore)
+                              .put("enabled", true)
+                              .put("require_client_auth", "optional")
+                              .put("optional", true)
+                              .build());
+        }).start())
+        {
+            InetAddress address = 
cluster.get(1).config().broadcastAddress().getAddress();
+
+            // non-ssl connections should succeed
+            com.datastax.driver.core.Cluster nonSSLDriver = 
com.datastax.driver.core.Cluster.builder()
+                                                                               
             .addContactPoint(address.getHostAddress())
+                                                                               
             .build();
+            assertNotNull(nonSSLDriver.connect());
+
+            // ssl connections should succeed
+            com.datastax.driver.core.Cluster sslDriver = 
com.datastax.driver.core.Cluster.builder()
+                                                                               
          .addContactPoint(address.getHostAddress())
+                                                                               
          .withSSL(sslOptions(false))
+                                                                               
          .build();
+            assertNotNull(sslDriver.connect());
+
+            // mtls connections should succeed
+            com.datastax.driver.core.Cluster mtlsDriver = 
com.datastax.driver.core.Cluster.builder()
+                                                                               
           .addContactPoint(address.getHostAddress())
+                                                                               
           .withSSL(sslOptions(true))
+                                                                               
           .build();
+            assertNotNull(mtlsDriver.connect());
+        }
+    }
+
+    @Test
+    public void testOptionalMtlsModeDoNotAllowNonSSLConnections() throws 
Exception
+    {
+        // When server is configured in optional mTLS mode restricting non-ssl 
connections, it should accept
+        // ssl, mTLS based connections and reject any non-ssl based connections
+        try (Cluster cluster = builder().withNodes(1).withConfig(c -> {
+            c.with(Feature.NATIVE_PROTOCOL);
+            c.set("client_encryption_options",
+                  ImmutableMap.builder().putAll(validKeystore)
+                              .put("enabled", true)
+                              .put("require_client_auth", "optional")
+                              .put("optional", false)
+                              .build());
+        }).start())
+        {
+            InetAddress address = 
cluster.get(1).config().broadcastAddress().getAddress();
+
+            // ssl connections should succeed
+            com.datastax.driver.core.Cluster sslDriver = 
com.datastax.driver.core.Cluster.builder()
+                                                                               
          .addContactPoint(address.getHostAddress())
+                                                                               
          .withSSL(sslOptions(false))
+                                                                               
          .build();
+            assertNotNull(sslDriver.connect());
+
+            // mtls connections should succeed
+            com.datastax.driver.core.Cluster mtlsDriver = 
com.datastax.driver.core.Cluster.builder()
+                                                                               
           .addContactPoint(address.getHostAddress())
+                                                                               
           .withSSL(sslOptions(true))
+                                                                               
           .build();
+            assertNotNull(mtlsDriver.connect());
+
+            // non-ssl connections should not succeed
+            com.datastax.driver.core.Cluster nonSSLDriver = 
com.datastax.driver.core.Cluster.builder()
+                                                                               
             .addContactPoint(address.getHostAddress())
+                                                                               
             .build();
+            expectedException.expect(NoHostAvailableException.class);
+            assertNull(nonSSLDriver.connect());
+        }
+    }
+
+    @Test
+    public void testOptionalSSLMode() throws Exception
+    {
+        // When server is configured in optional ssl mode, it should accept
+        // non-ssl, ssl
+        try (Cluster cluster = builder().withNodes(1).withConfig(c -> {
+            // Server configuration for optional mTLS mode
+            c.with(Feature.NATIVE_PROTOCOL);
+            c.set("client_encryption_options",
+                  ImmutableMap.builder().putAll(validKeystore)
+                              .put("enabled", true)
+                              .put("require_client_auth", "false")
+                              .put("optional", true)
+                              .build());
+        }).start())
+        {
+            InetAddress address = 
cluster.get(1).config().broadcastAddress().getAddress();
+
+            // non-ssl connections should succeed
+            com.datastax.driver.core.Cluster nonSSLDriver = 
com.datastax.driver.core.Cluster.builder()
+                                                                               
             .addContactPoint(address.getHostAddress())
+                                                                               
             .build();
+            assertNotNull(nonSSLDriver.connect());
+
+            // ssl connections should succeed
+            com.datastax.driver.core.Cluster sslDriver = 
com.datastax.driver.core.Cluster.builder()
+                                                                               
          .addContactPoint(address.getHostAddress())
+                                                                               
          .withSSL(sslOptions(false))
+                                                                               
          .build();
+            assertNotNull(sslDriver.connect());
+
+            // mtls connections should succeed
+            com.datastax.driver.core.Cluster mtlsDriver = 
com.datastax.driver.core.Cluster.builder()
+                                                                               
           .addContactPoint(address.getHostAddress())
+                                                                               
           .withSSL(sslOptions(true))
+                                                                               
           .build();
+            assertNotNull(mtlsDriver.connect());
+        }
+    }
+
+    private SSLOptions sslOptions(boolean withKeyStore) throws Exception
+    {
+        SslContextBuilder sslContextBuilder = SslContextBuilder.forClient();
+        
sslContextBuilder.trustManager(createTrustManagerFactory("test/conf/cassandra_ssl_test.truststore",
 "cassandra"));
+        if (withKeyStore)
+        {
+            
sslContextBuilder.keyManager(createKeyManagerFactory("test/conf/cassandra_ssl_test_outbound.keystore",
 "cassandra"));
+        }
+
+        SslContext sslContext = sslContextBuilder.build();
+        return socketChannel -> sslContext.newHandler(socketChannel.alloc());
+    }
+
     private void testEndpointVerification(boolean requireEndpointVerification, 
boolean ipInSAN) throws Throwable
     {
         try (Cluster cluster = builder().withNodes(1).withConfig(c -> {
diff --git 
a/test/unit/org/apache/cassandra/auth/MutualTlsAuthenticatorTest.java 
b/test/unit/org/apache/cassandra/auth/MutualTlsAuthenticatorTest.java
index b30a8f8d0b..14b31a3c87 100644
--- a/test/unit/org/apache/cassandra/auth/MutualTlsAuthenticatorTest.java
+++ b/test/unit/org/apache/cassandra/auth/MutualTlsAuthenticatorTest.java
@@ -37,6 +37,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;
 import org.apache.cassandra.exceptions.AuthenticationException;
 import org.apache.cassandra.exceptions.ConfigurationException;
 import org.apache.cassandra.net.MessagingService;
@@ -47,6 +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.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertNull;
@@ -78,7 +80,7 @@ public class MutualTlsAuthenticatorTest
         
((CassandraRoleManager)DatabaseDescriptor.getRoleManager()).loadIdentityStatement();
         final Config config = DatabaseDescriptor.getRawConfig();
         config.client_encryption_options = 
config.client_encryption_options.withEnabled(true)
-                                                                           
.withRequireClientAuth(true);
+                                                                           
.withRequireClientAuth(REQUIRED);
     }
 
     @After
@@ -172,6 +174,22 @@ public class MutualTlsAuthenticatorTest
         assertEquals("readonly_user", urnCache.get(identity2));
     }
 
+    @Test
+    public void testValidateConfiguration()
+    {
+        // In strict mTLS mode mtls authenticator should check for 
require_client_auth to be true
+        final Config config = DatabaseDescriptor.getRawConfig();
+        String msg = "MutualTlsAuthenticator requires 
client_encryption_options.enabled to be true" +
+                     " & 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);
+        expectedException.expect(ConfigurationException.class);
+        expectedException.expectMessage(msg);
+        mutualTlsAuthenticator.validateConfiguration();
+    }
+
     MutualTlsAuthenticator createAndInitializeMtlsAuthenticator()
     {
         Map<String, String> parameters = 
Collections.singletonMap("validator_class_name", getValidatorClass());
diff --git 
a/test/unit/org/apache/cassandra/auth/MutualTlsWithPasswordFallbackAuthenticatorTest.java
 
b/test/unit/org/apache/cassandra/auth/MutualTlsWithPasswordFallbackAuthenticatorTest.java
index 6a522ca853..95f7c133ea 100644
--- 
a/test/unit/org/apache/cassandra/auth/MutualTlsWithPasswordFallbackAuthenticatorTest.java
+++ 
b/test/unit/org/apache/cassandra/auth/MutualTlsWithPasswordFallbackAuthenticatorTest.java
@@ -33,6 +33,7 @@ import org.junit.Test;
 import org.apache.cassandra.SchemaLoader;
 import org.apache.cassandra.config.Config;
 import org.apache.cassandra.config.DatabaseDescriptor;
+import org.apache.cassandra.config.EncryptionOptions;
 
 import static org.apache.cassandra.auth.AuthTestUtils.getMockInetAddress;
 import static org.junit.Assert.assertNotNull;
@@ -50,7 +51,7 @@ public class MutualTlsWithPasswordFallbackAuthenticatorTest
         SchemaLoader.loadSchema();
         Config config = DatabaseDescriptor.getRawConfig();
         config.client_encryption_options = 
config.client_encryption_options.withEnabled(true)
-                                                                           
.withRequireClientAuth(true);
+                                                                           
.withRequireClientAuth(EncryptionOptions.ClientAuth.OPTIONAL);
         Map<String, String> parameters = 
Collections.singletonMap("validator_class_name", 
"org.apache.cassandra.auth.SpiffeCertificateValidator");
         fallbackAuthenticator = new 
MutualTlsWithPasswordFallbackAuthenticator(parameters);
         fallbackAuthenticator.setup();
@@ -88,4 +89,11 @@ public class MutualTlsWithPasswordFallbackAuthenticatorTest
         IAuthenticator.SaslNegotiator mutualtlsAuthenticator = 
fallbackAuthenticator.newSaslNegotiator(getMockInetAddress(), 
clientCertificatesCorp);
         assertTrue(mutualtlsAuthenticator instanceof 
MutualTlsAuthenticator.CertificateNegotiator);
     }
+
+    @Test
+    public void testValidateConfiguration()
+    {
+        // In optional mTLS mode fallback authenticator should not check for 
require_client_auth to be true
+        fallbackAuthenticator.validateConfiguration();
+    }
 }
diff --git a/test/unit/org/apache/cassandra/config/ConfigCompatibilityTest.java 
b/test/unit/org/apache/cassandra/config/ConfigCompatibilityTest.java
index e6e714daaa..f965182915 100644
--- a/test/unit/org/apache/cassandra/config/ConfigCompatibilityTest.java
+++ b/test/unit/org/apache/cassandra/config/ConfigCompatibilityTest.java
@@ -104,6 +104,7 @@ public class ConfigCompatibilityTest
                                                                    
.add("authenticator types do not match; 
org.apache.cassandra.config.ParameterizedClass != java.lang.String")
                                                                    
.add("Property internode_authenticator used to be a value-type, but now is 
nested type class org.apache.cassandra.config.ParameterizedClass")
                                                                    
.add("Property authenticator used to be a value-type, but now is nested type 
class org.apache.cassandra.config.ParameterizedClass")
+                                                                   
.add("require_client_auth types do not match; java.lang.String != 
java.lang.Boolean")
                                                                    .build();
 
     /**
@@ -146,7 +147,7 @@ public class ConfigCompatibilityTest
     public void diff_5_0() throws IOException
     {
         diff(TEST_DIR + "/version=5.0-alpha1.yml", 
ImmutableSet.<String>builder()
-                                                               .build(), 
ImmutableSet.of());
+                                                               .build(), 
EXPECTED_FOR_50);
     }
 
     private void diff(String original, Set<String> ignore, Set<String> 
expectedErrors) throws IOException
diff --git 
a/test/unit/org/apache/cassandra/config/EncryptionOptionsEqualityTest.java 
b/test/unit/org/apache/cassandra/config/EncryptionOptionsEqualityTest.java
index e5aabc8ff3..7c86069a80 100644
--- a/test/unit/org/apache/cassandra/config/EncryptionOptionsEqualityTest.java
+++ b/test/unit/org/apache/cassandra/config/EncryptionOptionsEqualityTest.java
@@ -26,6 +26,8 @@ import org.junit.Test;
 import org.apache.cassandra.security.DefaultSslContextFactory;
 import org.apache.cassandra.security.DummySslContextFactoryImpl;
 
+import static 
org.apache.cassandra.config.EncryptionOptions.ClientAuth.NOT_REQUIRED;
+import static 
org.apache.cassandra.config.EncryptionOptions.ClientAuth.REQUIRED;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNotEquals;
 
@@ -46,7 +48,7 @@ public class EncryptionOptionsEqualityTest
                .withOutboundKeystore("test/conf/cassandra_outbound.keystore")
                .withOutboundKeystorePassword("cassandra")
                .withProtocol("TLSv1.1")
-               .withRequireClientAuth(true)
+               .withRequireClientAuth(REQUIRED)
                .withRequireEndpointVerification(false);
     }
 
@@ -60,7 +62,7 @@ public class EncryptionOptionsEqualityTest
         .withTrustStore("test/conf/cassandra_ssl_test.truststore")
         .withTrustStorePassword("cassandra")
         .withProtocol("TLSv1.1")
-        .withRequireClientAuth(true)
+        .withRequireClientAuth(REQUIRED)
         .withRequireEndpointVerification(false);
 
         EncryptionOptions encryptionOptions2 =
@@ -71,7 +73,7 @@ public class EncryptionOptionsEqualityTest
         .withTrustStore("test/conf/cassandra_ssl_test.truststore")
         .withTrustStorePassword("cassandra")
         .withProtocol("TLSv1.1")
-        .withRequireClientAuth(true)
+        .withRequireClientAuth(REQUIRED)
         .withRequireEndpointVerification(false);
 
         assertEquals(encryptionOptions1, encryptionOptions2);
@@ -88,7 +90,7 @@ public class EncryptionOptionsEqualityTest
         new EncryptionOptions()
         .withSslContextFactory(new 
ParameterizedClass(DummySslContextFactoryImpl.class.getName(), parameters1))
         .withProtocol("TLSv1.1")
-        .withRequireClientAuth(true)
+        .withRequireClientAuth(REQUIRED)
         .withRequireEndpointVerification(false);
 
         Map<String,String> parameters2 = new HashMap<>();
@@ -98,7 +100,7 @@ public class EncryptionOptionsEqualityTest
         new EncryptionOptions()
         .withSslContextFactory(new 
ParameterizedClass(DummySslContextFactoryImpl.class.getName(), parameters2))
         .withProtocol("TLSv1.1")
-        .withRequireClientAuth(true)
+        .withRequireClientAuth(REQUIRED)
         .withRequireEndpointVerification(false);
 
         assertEquals(encryptionOptions1, encryptionOptions2);
@@ -115,7 +117,7 @@ public class EncryptionOptionsEqualityTest
         new EncryptionOptions()
         .withSslContextFactory(new 
ParameterizedClass(DummySslContextFactoryImpl.class.getName(), parameters1))
         .withProtocol("TLSv1.1")
-        .withRequireClientAuth(false)
+        .withRequireClientAuth(NOT_REQUIRED)
         .withRequireEndpointVerification(true);
 
         Map<String,String> parameters2 = new HashMap<>();
@@ -125,7 +127,7 @@ public class EncryptionOptionsEqualityTest
         new EncryptionOptions()
         .withSslContextFactory(new 
ParameterizedClass(DefaultSslContextFactory.class.getName(), parameters2))
         .withProtocol("TLSv1.1")
-        .withRequireClientAuth(false)
+        .withRequireClientAuth(NOT_REQUIRED)
         .withRequireEndpointVerification(true);
 
         assertNotEquals(encryptionOptions1, encryptionOptions2);
diff --git a/test/unit/org/apache/cassandra/config/EncryptionOptionsTest.java 
b/test/unit/org/apache/cassandra/config/EncryptionOptionsTest.java
index 0ff2124794..f09527067f 100644
--- a/test/unit/org/apache/cassandra/config/EncryptionOptionsTest.java
+++ b/test/unit/org/apache/cassandra/config/EncryptionOptionsTest.java
@@ -61,7 +61,7 @@ public class EncryptionOptionsTest
                                                                                
               new HashMap<>()),
                                                                        
keystorePath, "dummypass",
                                                                        
"dummytruststore", "dummypass",
-                                                                       
Collections.emptyList(), null, null, null, "JKS", false, false, enabled, 
optional)
+                                                                       
Collections.emptyList(), null, null, null, "JKS", "false", false, enabled, 
optional)
                                                  .applyConfig(),
                                                  expected,
                                                  String.format("optional=%s 
keystore=%s enabled=%s", optional, keystorePath, enabled));
@@ -75,7 +75,7 @@ public class EncryptionOptionsTest
                                                                                
               customSslContextFactoryParams),
                                                                        
keystorePath, "dummypass",
                                                                        
"dummytruststore", "dummypass",
-                                                                       
Collections.emptyList(), null, null, null, "JKS", false, false, enabled, 
optional)
+                                                                       
Collections.emptyList(), null, null, null, "JKS", "false", false, enabled, 
optional)
                                                  .applyConfig(),
                                                  expected,
                                                  String.format("optional=%s 
keystore=%s enabled=%s", optional, keystorePath, enabled));
@@ -126,7 +126,7 @@ public class EncryptionOptionsTest
         {
             return new ServerEncryptionOptionsTestCase(new 
EncryptionOptions.ServerEncryptionOptions(new 
ParameterizedClass("org.apache.cassandra.security.DefaultSslContextFactory",
                                                                                
                                             new HashMap<>()), keystorePath, 
"dummypass", keystorePath, "dummypass", "dummytruststore", "dummypass",
-                                                                               
                Collections.emptyList(), null, null, null, "JKS", false, false, 
optional, internodeEncryption, false)
+                                                                               
                Collections.emptyList(), null, null, null, "JKS", "false", 
false, optional, internodeEncryption, false)
                                                        .applyConfig(),
                                                  expected,
                                                  String.format("optional=%s 
keystore=%s internode=%s", optional, keystorePath, internodeEncryption));
diff --git a/test/unit/org/apache/cassandra/db/virtual/SettingsTableTest.java 
b/test/unit/org/apache/cassandra/db/virtual/SettingsTableTest.java
index d9aabcb054..e52ec022ed 100644
--- a/test/unit/org/apache/cassandra/db/virtual/SettingsTableTest.java
+++ b/test/unit/org/apache/cassandra/db/virtual/SettingsTableTest.java
@@ -37,6 +37,8 @@ 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;
+
 public class SettingsTableTest extends CQLTester
 {
     private static final String KS_NAME = "vts";
@@ -201,7 +203,7 @@ public class SettingsTableTest extends CQLTester
 
         // name doesn't match yaml
         check(pre + "client_auth", "false");
-        config.server_encryption_options = 
config.server_encryption_options.withRequireClientAuth(true);
+        config.server_encryption_options = 
config.server_encryption_options.withRequireClientAuth(REQUIRED);
         check(pre + "client_auth", "true");
 
         // name doesn't match yaml
diff --git a/test/unit/org/apache/cassandra/net/ConnectionTest.java 
b/test/unit/org/apache/cassandra/net/ConnectionTest.java
index ff11f9dbb0..1f8c6f612d 100644
--- a/test/unit/org/apache/cassandra/net/ConnectionTest.java
+++ b/test/unit/org/apache/cassandra/net/ConnectionTest.java
@@ -71,6 +71,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.net.MessagingService.VERSION_40;
 import static org.apache.cassandra.net.NoPayload.noPayload;
 import static org.apache.cassandra.net.MessagingService.current_version;
@@ -182,7 +183,7 @@ public class ConnectionTest
             .withKeyStorePassword("cassandra")
             .withTrustStore("test/conf/cassandra_ssl_test.truststore")
             .withTrustStorePassword("cassandra")
-            .withRequireClientAuth(false)
+            .withRequireClientAuth(NOT_REQUIRED)
             .withCipherSuites("TLS_RSA_WITH_AES_128_CBC_SHA");
 
     static final List<Function<Settings, Settings>> MODIFIERS = 
ImmutableList.of(
diff --git a/test/unit/org/apache/cassandra/net/HandshakeTest.java 
b/test/unit/org/apache/cassandra/net/HandshakeTest.java
index f2fa960566..ec7e26b322 100644
--- a/test/unit/org/apache/cassandra/net/HandshakeTest.java
+++ b/test/unit/org/apache/cassandra/net/HandshakeTest.java
@@ -49,6 +49,8 @@ import org.apache.cassandra.security.DefaultSslContextFactory;
 import org.apache.cassandra.utils.concurrent.AsyncPromise;
 
 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;
@@ -285,12 +287,12 @@ public class HandshakeTest
         if (sslConnectionType == SslFallbackConnectionType.MTLS)
         {
             serverEncryptionOptions = 
serverEncryptionOptions.withInternodeEncryption(ServerEncryptionOptions.InternodeEncryption.all)
-                                                             
.withRequireClientAuth(true);
+                                                             
.withRequireClientAuth(REQUIRED);
         }
         else if (sslConnectionType == SslFallbackConnectionType.SSL)
         {
             serverEncryptionOptions = 
serverEncryptionOptions.withInternodeEncryption(ServerEncryptionOptions.InternodeEncryption.all)
-                                                             
.withRequireClientAuth(false);
+                                                             
.withRequireClientAuth(NOT_REQUIRED);
         }
         return serverEncryptionOptions;
     }
diff --git 
a/test/unit/org/apache/cassandra/security/DefaultSslContextFactoryTest.java 
b/test/unit/org/apache/cassandra/security/DefaultSslContextFactoryTest.java
index c169b9e775..1b7db326e1 100644
--- a/test/unit/org/apache/cassandra/security/DefaultSslContextFactoryTest.java
+++ b/test/unit/org/apache/cassandra/security/DefaultSslContextFactoryTest.java
@@ -37,6 +37,9 @@ import org.apache.cassandra.distributed.shared.WithProperties;
 
 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;
+
 public class DefaultSslContextFactoryTest
 {
     private Map<String,Object> commonConfig = new HashMap<>();
@@ -46,7 +49,7 @@ public class DefaultSslContextFactoryTest
     {
         commonConfig.put("truststore", 
"test/conf/cassandra_ssl_test.truststore");
         commonConfig.put("truststore_password", "cassandra");
-        commonConfig.put("require_client_auth", Boolean.FALSE);
+        commonConfig.put("require_client_auth", "false");
         commonConfig.put("cipher_suites", 
Arrays.asList("TLS_RSA_WITH_AES_128_CBC_SHA"));
     }
 
@@ -71,9 +74,9 @@ public class DefaultSslContextFactoryTest
                                                                                
                            .withKeyStorePassword("cassandra")
                                                                                
                            
.withOutboundKeystore("test/conf/cassandra_ssl_test_outbound.keystore")
                                                                                
                            .withOutboundKeystorePassword("cassandra")
-                                                                               
                            .withRequireClientAuth(false)
+                                                                               
                            .withRequireClientAuth(NOT_REQUIRED)
                                                                                
                            .withCipherSuites("TLS_RSA_WITH_AES_128_CBC_SHA");
-        SslContext sslContext = SSLFactory.getOrCreateSslContext(options, 
true, ISslContextFactory.SocketType.CLIENT, "test");
+        SslContext sslContext = SSLFactory.getOrCreateSslContext(options, 
REQUIRED, ISslContextFactory.SocketType.CLIENT, "test");
         Assert.assertNotNull(sslContext);
         if (OpenSsl.isAvailable())
             Assert.assertTrue(sslContext instanceof OpenSslContext);
diff --git 
a/test/unit/org/apache/cassandra/security/DummySslContextFactoryImpl.java 
b/test/unit/org/apache/cassandra/security/DummySslContextFactoryImpl.java
index 3a14ff2937..ca4f4e86f0 100644
--- a/test/unit/org/apache/cassandra/security/DummySslContextFactoryImpl.java
+++ b/test/unit/org/apache/cassandra/security/DummySslContextFactoryImpl.java
@@ -25,6 +25,7 @@ import javax.net.ssl.SSLException;
 
 import io.netty.handler.ssl.CipherSuiteFilter;
 import io.netty.handler.ssl.SslContext;
+import org.apache.cassandra.config.EncryptionOptions;
 
 /**
  * TEST ONLY Class. DON'T use it for anything else.
@@ -43,7 +44,19 @@ public class DummySslContextFactoryImpl implements 
ISslContextFactory
     }
 
     @Override
-    public SslContext createNettySslContext(boolean verifyPeerCertificate, 
SocketType socketType,
+    public SSLContext createJSSESslContext(EncryptionOptions.ClientAuth 
clientAuth) throws SSLException
+    {
+        return null;
+    }
+
+    @Override
+    public SslContext createNettySslContext(boolean verifyPeerCertificate, 
SocketType socketType, CipherSuiteFilter cipherFilter) throws SSLException
+    {
+        return null;
+    }
+
+    @Override
+    public SslContext createNettySslContext(EncryptionOptions.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 98e0342797..73fe80b304 100644
--- 
a/test/unit/org/apache/cassandra/security/FileBasedSslContextFactoryTest.java
+++ 
b/test/unit/org/apache/cassandra/security/FileBasedSslContextFactoryTest.java
@@ -36,6 +36,8 @@ import org.apache.cassandra.distributed.shared.WithProperties;
 
 import static 
org.apache.cassandra.config.CassandraRelevantProperties.CASSANDRA_CONFIG;
 
+import static 
org.apache.cassandra.config.EncryptionOptions.ClientAuth.NOT_REQUIRED;
+
 public class FileBasedSslContextFactoryTest
 {
     private static final Logger logger = 
LoggerFactory.getLogger(FileBasedSslContextFactoryTest.class);
@@ -65,7 +67,7 @@ public class FileBasedSslContextFactoryTest
                                                                           new 
HashMap<>()))
                             
.withTrustStore("test/conf/cassandra_ssl_test.truststore")
                             .withTrustStorePassword("cassandra")
-                            .withRequireClientAuth(false)
+                            .withRequireClientAuth(NOT_REQUIRED)
                             .withCipherSuites("TLS_RSA_WITH_AES_128_CBC_SHA")
                             
.withKeyStore("test/conf/cassandra_ssl_test.keystore")
                             .withKeyStorePassword("cassandra")
diff --git 
a/test/unit/org/apache/cassandra/security/PEMBasedSslContextFactoryTest.java 
b/test/unit/org/apache/cassandra/security/PEMBasedSslContextFactoryTest.java
index a1fb37c1b9..ca319de5fd 100644
--- a/test/unit/org/apache/cassandra/security/PEMBasedSslContextFactoryTest.java
+++ b/test/unit/org/apache/cassandra/security/PEMBasedSslContextFactoryTest.java
@@ -38,6 +38,8 @@ import org.apache.cassandra.config.ParameterizedClass;
 import org.apache.cassandra.distributed.shared.WithProperties;
 
 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.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;
@@ -176,7 +178,7 @@ public class PEMBasedSslContextFactoryTest
     public void setup()
     {
         commonConfig.put(ENCODED_CERTIFICATES.getKeyName(), 
trusted_certificates);
-        commonConfig.put("require_client_auth", Boolean.FALSE);
+        commonConfig.put("require_client_auth", "false");
         commonConfig.put("cipher_suites", 
Arrays.asList("TLS_RSA_WITH_AES_128_CBC_SHA"));
     }
 
@@ -215,10 +217,10 @@ public class PEMBasedSslContextFactoryTest
         EncryptionOptions options = new 
EncryptionOptions().withTrustStore("test/conf/cassandra_ssl_test.truststore.pem")
                                                            
.withKeyStore("test/conf/cassandra_ssl_test.keystore.pem")
                                                            
.withKeyStorePassword("cassandra")
-                                                           
.withRequireClientAuth(false)
+                                                           
.withRequireClientAuth(NOT_REQUIRED)
                                                            
.withCipherSuites("TLS_RSA_WITH_AES_128_CBC_SHA")
                                                            
.withSslContextFactory(sslContextFactory);
-        SslContext sslContext = SSLFactory.getOrCreateSslContext(options, 
true, ISslContextFactory.SocketType.SERVER, "test");
+        SslContext sslContext = SSLFactory.getOrCreateSslContext(options, 
REQUIRED, ISslContextFactory.SocketType.SERVER, "test");
         Assert.assertNotNull(sslContext);
         if (OpenSsl.isAvailable())
             Assert.assertTrue(sslContext instanceof OpenSslContext);
@@ -236,10 +238,10 @@ public class PEMBasedSslContextFactoryTest
                                                                                
                            .withKeyStorePassword("cassandra")
                                                                                
                            
.withOutboundKeystore("test/conf/cassandra_ssl_test.keystore.pem")
                                                                                
                            .withOutboundKeystorePassword("cassandra")
-                                                                               
                            .withRequireClientAuth(false)
+                                                                               
                            .withRequireClientAuth(NOT_REQUIRED)
                                                                                
                            .withCipherSuites("TLS_RSA_WITH_AES_128_CBC_SHA")
                                                                                
                            .withSslContextFactory(sslContextFactory);
-        SslContext sslContext = SSLFactory.getOrCreateSslContext(options, 
true, ISslContextFactory.SocketType.CLIENT, "test");
+        SslContext sslContext = SSLFactory.getOrCreateSslContext(options, 
REQUIRED, ISslContextFactory.SocketType.CLIENT, "test");
         Assert.assertNotNull(sslContext);
         if (OpenSsl.isAvailable())
             Assert.assertTrue(sslContext instanceof OpenSslContext);
diff --git a/test/unit/org/apache/cassandra/security/SSLFactoryTest.java 
b/test/unit/org/apache/cassandra/security/SSLFactoryTest.java
index b6e0b8e4b5..a7c14dfcfb 100644
--- a/test/unit/org/apache/cassandra/security/SSLFactoryTest.java
+++ b/test/unit/org/apache/cassandra/security/SSLFactoryTest.java
@@ -51,6 +51,8 @@ import 
org.apache.cassandra.config.EncryptionOptions.ServerEncryptionOptions;
 import org.apache.cassandra.config.ParameterizedClass;
 import org.apache.cassandra.io.util.File;
 
+import static 
org.apache.cassandra.config.EncryptionOptions.ClientAuth.NOT_REQUIRED;
+import static 
org.apache.cassandra.config.EncryptionOptions.ClientAuth.REQUIRED;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNotNull;
 
@@ -81,7 +83,7 @@ public class SSLFactoryTest
         encryptionOptions = new ServerEncryptionOptions()
                             
.withTrustStore("test/conf/cassandra_ssl_test.truststore")
                             .withTrustStorePassword("cassandra")
-                            .withRequireClientAuth(false)
+                            .withRequireClientAuth(NOT_REQUIRED)
                             .withCipherSuites("TLS_RSA_WITH_AES_128_CBC_SHA")
                             .withSslContextFactory(new 
ParameterizedClass(TestFileBasedSSLContextFactory.class.getName(),
                                                                           new 
HashMap<>()));
@@ -118,8 +120,8 @@ public class SSLFactoryTest
             options.sslContextFactoryInstance.initHotReloading();
             legacyOptions.sslContextFactoryInstance.initHotReloading();
 
-            SslContext oldCtx = SSLFactory.getOrCreateSslContext(options, 
true, ISslContextFactory.SocketType.CLIENT, "test");
-            SslContext oldLegacyCtx = 
SSLFactory.getOrCreateSslContext(legacyOptions, true, 
ISslContextFactory.SocketType.CLIENT, "test legacy");
+            SslContext oldCtx = SSLFactory.getOrCreateSslContext(options, 
REQUIRED, ISslContextFactory.SocketType.CLIENT, "test");
+            SslContext oldLegacyCtx = 
SSLFactory.getOrCreateSslContext(legacyOptions, REQUIRED, 
ISslContextFactory.SocketType.CLIENT, "test legacy");
             File keystoreFile = new File(options.keystore);
 
             SSLFactory.checkCertFilesForHotReloading();
@@ -127,8 +129,8 @@ public class SSLFactoryTest
             keystoreFile.trySetLastModified(System.currentTimeMillis() + 
15000);
 
             SSLFactory.checkCertFilesForHotReloading();
-            SslContext newCtx = SSLFactory.getOrCreateSslContext(options, 
true, ISslContextFactory.SocketType.CLIENT, "test");
-            SslContext newLegacyCtx = 
SSLFactory.getOrCreateSslContext(legacyOptions, true, 
ISslContextFactory.SocketType.CLIENT, "test legacy");
+            SslContext newCtx = SSLFactory.getOrCreateSslContext(options, 
REQUIRED, ISslContextFactory.SocketType.CLIENT, "test");
+            SslContext newLegacyCtx = 
SSLFactory.getOrCreateSslContext(legacyOptions, REQUIRED, 
ISslContextFactory.SocketType.CLIENT, "test legacy");
 
             Assert.assertNotSame(oldCtx, newCtx);
             Assert.assertNotSame(oldLegacyCtx, newLegacyCtx);
@@ -151,7 +153,7 @@ public class SSLFactoryTest
         .withOutboundKeystorePassword("dummyPassword");
 
         // Server socket type should create a keystore with keystore & 
keystore password
-        final OpenSslServerContext context = (OpenSslServerContext) 
SSLFactory.createNettySslContext(options, true, 
ISslContextFactory.SocketType.SERVER);
+        final OpenSslServerContext context = (OpenSslServerContext) 
SSLFactory.createNettySslContext(options, REQUIRED, 
ISslContextFactory.SocketType.SERVER);
         assertNotNull(context);
 
         // Verify if right certificate is loaded into SslContext
@@ -168,7 +170,7 @@ public class SSLFactoryTest
         .withKeyStorePassword("dummyPassword");
 
         // Client socket type should create a keystore with outbound Keystore 
& outbound password
-        final OpenSslClientContext context = (OpenSslClientContext) 
SSLFactory.createNettySslContext(options, true, 
ISslContextFactory.SocketType.CLIENT);
+        final OpenSslClientContext context = (OpenSslClientContext) 
SSLFactory.createNettySslContext(options, REQUIRED, 
ISslContextFactory.SocketType.CLIENT);
         assertNotNull(context);
 
         // Verify if right certificate is loaded into SslContext
@@ -189,8 +191,8 @@ public class SSLFactoryTest
             options.sslContextFactoryInstance.initHotReloading();
             legacyOptions.sslContextFactoryInstance.initHotReloading();
 
-            SslContext oldCtx = SSLFactory.getOrCreateSslContext(options, 
true, ISslContextFactory.SocketType.CLIENT, "test");
-            SslContext oldLegacyCtx = 
SSLFactory.getOrCreateSslContext(legacyOptions, true, 
ISslContextFactory.SocketType.CLIENT, "test legacy");
+            SslContext oldCtx = SSLFactory.getOrCreateSslContext(options, 
REQUIRED, ISslContextFactory.SocketType.CLIENT, "test");
+            SslContext oldLegacyCtx = 
SSLFactory.getOrCreateSslContext(legacyOptions, REQUIRED, 
ISslContextFactory.SocketType.CLIENT, "test legacy");
             File keystoreFile = new File(options.keystore);
 
             SSLFactory.checkCertFilesForHotReloading();
@@ -198,8 +200,8 @@ public class SSLFactoryTest
             keystoreFile.trySetLastModified(System.currentTimeMillis() + 
15000);
 
             SSLFactory.checkCertFilesForHotReloading();
-            SslContext newCtx = SSLFactory.getOrCreateSslContext(options, 
true, ISslContextFactory.SocketType.CLIENT, "test");
-            SslContext newLegacyCtx = 
SSLFactory.getOrCreateSslContext(legacyOptions, true, 
ISslContextFactory.SocketType.CLIENT, "test legacy");
+            SslContext newCtx = SSLFactory.getOrCreateSslContext(options, 
REQUIRED, ISslContextFactory.SocketType.CLIENT, "test");
+            SslContext newLegacyCtx = 
SSLFactory.getOrCreateSslContext(legacyOptions, REQUIRED, 
ISslContextFactory.SocketType.CLIENT, "test legacy");
 
             Assert.assertNotSame(oldCtx, newCtx);
             Assert.assertNotSame(oldLegacyCtx, newLegacyCtx);
@@ -221,7 +223,7 @@ public class SSLFactoryTest
                                     .withKeyStorePassword("bad password")
                                     
.withInternodeEncryption(ServerEncryptionOptions.InternodeEncryption.all);
 
-        
SSLFactory.validateSslContext("testSslFactorySslInit_BadPassword_ThrowsException",
 options, false, true);
+        
SSLFactory.validateSslContext("testSslFactorySslInit_BadPassword_ThrowsException",
 options, NOT_REQUIRED, true);
     }
 
     @Test
@@ -239,14 +241,14 @@ public class SSLFactoryTest
 
             SSLFactory.initHotReloading(options, options, true);  // 
deliberately not initializing with legacyOptions to match 
InboundSockets.addBindings
 
-            SslContext oldCtx = SSLFactory.getOrCreateSslContext(options, 
true, ISslContextFactory.SocketType.CLIENT, "test");
-            SslContext oldLegacyCtx = 
SSLFactory.getOrCreateSslContext(legacyOptions, true, 
ISslContextFactory.SocketType.CLIENT, "test legacy");
+            SslContext oldCtx = SSLFactory.getOrCreateSslContext(options, 
REQUIRED, ISslContextFactory.SocketType.CLIENT, "test");
+            SslContext oldLegacyCtx = 
SSLFactory.getOrCreateSslContext(legacyOptions, REQUIRED, 
ISslContextFactory.SocketType.CLIENT, "test legacy");
 
             changeKeystorePassword(options.keystore, 
options.keystore_password, "bad password");
 
             SSLFactory.checkCertFilesForHotReloading();
-            SslContext newCtx = SSLFactory.getOrCreateSslContext(options, 
true, ISslContextFactory.SocketType.CLIENT, "test");
-            SslContext newLegacyCtx = 
SSLFactory.getOrCreateSslContext(legacyOptions, true, 
ISslContextFactory.SocketType.CLIENT, "test legacy");
+            SslContext newCtx = SSLFactory.getOrCreateSslContext(options, 
REQUIRED, ISslContextFactory.SocketType.CLIENT, "test");
+            SslContext newLegacyCtx = 
SSLFactory.getOrCreateSslContext(legacyOptions, REQUIRED, 
ISslContextFactory.SocketType.CLIENT, "test legacy");
 
             Assert.assertSame(oldCtx, newCtx);
             Assert.assertSame(oldLegacyCtx, newLegacyCtx);
@@ -270,14 +272,14 @@ public class SSLFactoryTest
 
 
             SSLFactory.initHotReloading(options, options, true);
-            SslContext oldCtx = SSLFactory.getOrCreateSslContext(options, 
true, ISslContextFactory.SocketType.CLIENT, "test");
+            SslContext oldCtx = SSLFactory.getOrCreateSslContext(options, 
REQUIRED, ISslContextFactory.SocketType.CLIENT, "test");
             SSLFactory.checkCertFilesForHotReloading();
 
             testKeystoreFile.trySetLastModified(System.currentTimeMillis() + 
15000);
             FileUtils.forceDelete(testKeystoreFile.toJavaIOFile());
 
             SSLFactory.checkCertFilesForHotReloading();
-            SslContext newCtx = SSLFactory.getOrCreateSslContext(options, 
true, ISslContextFactory.SocketType.CLIENT, "test");
+            SslContext newCtx = SSLFactory.getOrCreateSslContext(options, 
REQUIRED, ISslContextFactory.SocketType.CLIENT, "test");
 
             Assert.assertSame(oldCtx, newCtx);
         }
@@ -298,7 +300,7 @@ public class SSLFactoryTest
         ServerEncryptionOptions options = addKeystoreOptions(encryptionOptions)
                                     
.withCipherSuites("TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256");
 
-        SslContext ctx1 = SSLFactory.getOrCreateSslContext(options, true,
+        SslContext ctx1 = SSLFactory.getOrCreateSslContext(options, REQUIRED,
                                                            
ISslContextFactory.SocketType.SERVER, "test");
 
         Assert.assertTrue(ctx1.isServer());
@@ -306,7 +308,7 @@ public class SSLFactoryTest
 
         options = 
options.withCipherSuites("TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256");
 
-        SslContext ctx2 = SSLFactory.getOrCreateSslContext(options, true,
+        SslContext ctx2 = SSLFactory.getOrCreateSslContext(options, REQUIRED,
                                                            
ISslContextFactory.SocketType.CLIENT, "test");
 
         Assert.assertTrue(ctx2.isClient());
@@ -323,7 +325,7 @@ public class SSLFactoryTest
         new EncryptionOptions()
         .withSslContextFactory(new 
ParameterizedClass(DummySslContextFactoryImpl.class.getName(), parameters1))
         .withProtocol("TLSv1.1")
-        .withRequireClientAuth(true)
+        .withRequireClientAuth(REQUIRED)
         .withRequireEndpointVerification(false);
 
         SSLFactory.CacheKey cacheKey1 = new 
SSLFactory.CacheKey(encryptionOptions1, ISslContextFactory.SocketType.SERVER, 
"test"
@@ -336,7 +338,7 @@ public class SSLFactoryTest
         new EncryptionOptions()
         .withSslContextFactory(new 
ParameterizedClass(DummySslContextFactoryImpl.class.getName(), parameters2))
         .withProtocol("TLSv1.1")
-        .withRequireClientAuth(true)
+        .withRequireClientAuth(REQUIRED)
         .withRequireEndpointVerification(false);
 
         SSLFactory.CacheKey cacheKey2 = new 
SSLFactory.CacheKey(encryptionOptions2, ISslContextFactory.SocketType.SERVER, 
"test"
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 f938cd9887..3d72828daf 100644
--- a/tools/stress/src/org/apache/cassandra/stress/util/JavaDriverClient.java
+++ b/tools/stress/src/org/apache/cassandra/stress/util/JavaDriverClient.java
@@ -41,6 +41,8 @@ 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;
+
 public class JavaDriverClient
 {
 
@@ -161,7 +163,7 @@ public class JavaDriverClient
         if (encryptionOptions.getEnabled())
         {
             SSLContext sslContext;
-            sslContext = SSLFactory.createSSLContext(encryptionOptions, true);
+            sslContext = SSLFactory.createSSLContext(encryptionOptions, 
REQUIRED);
 
             // Temporarily override newSSLEngine to set accepted protocols 
until it is added to
             // RemoteEndpointAwareJdkSSLOptions.  See CASSANDRA-13325 and 
CASSANDRA-16362.


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

Reply via email to