Refactor EncryptionOptions to use client / server encryption options builders

patch by Maulin Vasavada; reviewed by Maxwell Guo, Stefan Miklosovic for CASSANDRA-20404
This commit is contained in:
maulin-vasavada 2025-03-07 16:02:00 -08:00 committed by Stefan Miklosovic
parent 4805123eb8
commit bcea8f5815
No known key found for this signature in database
GPG Key ID: 32F35CB2F546D93E
50 changed files with 996 additions and 1012 deletions

View File

@ -44,7 +44,7 @@ import org.apache.cassandra.schema.SchemaConstants;
import org.apache.cassandra.utils.NoSpamLogger;
import static org.apache.cassandra.auth.IAuthenticator.AuthenticationMode.MTLS;
import static org.apache.cassandra.config.EncryptionOptions.ClientAuth.REQUIRED;
import static org.apache.cassandra.config.EncryptionOptions.ClientEncryptionOptions.ClientAuth.REQUIRED;
/**
* Performs mTLS authentication for client connections by extracting identities from client certificate

View File

@ -49,7 +49,7 @@ import org.apache.cassandra.exceptions.ConfigurationException;
import org.apache.cassandra.metrics.MutualTlsMetrics;
import org.apache.cassandra.utils.NoSpamLogger;
import static org.apache.cassandra.config.EncryptionOptions.ClientAuth.REQUIRED;
import static org.apache.cassandra.config.EncryptionOptions.ClientEncryptionOptions.ClientAuth.REQUIRED;
/**
* Performs mTLS authentication for internode connections by extracting identities from the certificates of incoming

View File

@ -81,7 +81,7 @@ public class MutualTlsWithPasswordFallbackAuthenticator extends PasswordAuthenti
public void validateConfiguration() throws ConfigurationException
{
Config config = DatabaseDescriptor.getRawConfig();
if (config.client_encryption_options.getClientAuth() == EncryptionOptions.ClientAuth.NOT_REQUIRED)
if (config.client_encryption_options.getClientAuth() == EncryptionOptions.ClientEncryptionOptions.ClientAuth.NOT_REQUIRED)
{
String msg = "MutualTlsWithPasswordFallbackAuthenticator requires client_encryption_options.require_client_auth to be optional/true";
throw new ConfigurationException(msg);

View File

@ -454,7 +454,7 @@ public class Config
public String failure_detector = "FailureDetector";
public EncryptionOptions.ServerEncryptionOptions server_encryption_options = new EncryptionOptions.ServerEncryptionOptions();
public EncryptionOptions client_encryption_options = new EncryptionOptions();
public EncryptionOptions.ClientEncryptionOptions client_encryption_options = new EncryptionOptions.ClientEncryptionOptions();
public JMXServerOptions jmx_server_options;

View File

@ -156,7 +156,7 @@ import static org.apache.cassandra.config.CassandraRelevantProperties.UNSAFE_SYS
import static org.apache.cassandra.config.DataRateSpec.DataRateUnit.BYTES_PER_SECOND;
import static org.apache.cassandra.config.DataRateSpec.DataRateUnit.MEBIBYTES_PER_SECOND;
import static org.apache.cassandra.config.DataStorageSpec.DataStorageUnit.MEBIBYTES;
import static org.apache.cassandra.config.EncryptionOptions.ClientAuth.REQUIRED;
import static org.apache.cassandra.config.EncryptionOptions.ClientEncryptionOptions.ClientAuth.REQUIRED;
import static org.apache.cassandra.db.ConsistencyLevel.ALL;
import static org.apache.cassandra.db.ConsistencyLevel.EACH_QUORUM;
import static org.apache.cassandra.db.ConsistencyLevel.LOCAL_QUORUM;
@ -1088,10 +1088,10 @@ public class DatabaseDescriptor
}
else if (JMXServerOptions.isEnabledBySystemProperties())
{
throw new ConfigurationException("Configure either jmx_server_options in cassandra.yaml and comment out " +
"configure_jmx function call in cassandra-env.sh or keep cassandra-env.sh " +
"to call configure_jmx function but you have to keep jmx_server_options " +
"in cassandra.yaml commented out.");
throw new ConfigurationException("Configure either jmx_server_options in cassandra.yaml and comment out " +
"configure_jmx function call in cassandra-env.sh or keep cassandra-env.sh " +
"to call configure_jmx function but you have to keep jmx_server_options " +
"in cassandra.yaml commented out.");
}
conf.jmx_server_options.jmx_encryption_options.applyConfig();
@ -3973,7 +3973,7 @@ public class DatabaseDescriptor
conf.server_encryption_options = encryptionOptions;
}
public static EncryptionOptions getNativeProtocolEncryptionOptions()
public static EncryptionOptions.ClientEncryptionOptions getNativeProtocolEncryptionOptions()
{
return conf.client_encryption_options;
}
@ -3984,7 +3984,7 @@ public class DatabaseDescriptor
}
@VisibleForTesting
public static void updateNativeProtocolEncryptionOptions(Function<EncryptionOptions, EncryptionOptions> update)
public static void updateNativeProtocolEncryptionOptions(Function<EncryptionOptions.ClientEncryptionOptions, EncryptionOptions.ClientEncryptionOptions> update)
{
conf.client_encryption_options = update.apply(conf.client_encryption_options);
}

File diff suppressed because it is too large Load Diff

View File

@ -52,7 +52,7 @@ public class JMXServerOptions
public final Boolean authenticate;
// ssl options
public final EncryptionOptions jmx_encryption_options;
public final EncryptionOptions.ClientEncryptionOptions jmx_encryption_options;
// options for using Cassandra's own authentication mechanisms
public final String login_config_name;
@ -71,11 +71,11 @@ public class JMXServerOptions
public JMXServerOptions()
{
this(true, false, 7199, 0, false,
new EncryptionOptions(), null, null, null,
new EncryptionOptions.ClientEncryptionOptions(), null, null, null,
null, null);
}
public static JMXServerOptions create(boolean enabled, boolean local, int jmxPort, EncryptionOptions options)
public static JMXServerOptions create(boolean enabled, boolean local, int jmxPort, EncryptionOptions.ClientEncryptionOptions options)
{
return new JMXServerOptions(enabled, !local, jmxPort, 0, false,
options, null, null, null,
@ -95,7 +95,7 @@ public class JMXServerOptions
int jmxPort,
int rmiPort,
Boolean authenticate,
EncryptionOptions jmx_encryption_options,
EncryptionOptions.ClientEncryptionOptions jmx_encryption_options,
String loginConfigName,
String loginConfigFile,
String passwordFile,
@ -198,7 +198,8 @@ public class JMXServerOptions
// in the `cassandra.yaml`. Since the JMX SSL Config can also leverage it as per CASSANDRA-18508, password file
// support is not added to the JMX SSL configuration via the system properties. Hence, `null` is used as
// the password file arguments for the keystore and the truststore while constructing the encryption options here.
EncryptionOptions encryptionOptions = new EncryptionOptions(new ParameterizedClass("org.apache.cassandra.security.DefaultSslContextFactory", new HashMap<>()),
EncryptionOptions.ClientEncryptionOptions encryptionOptions = new EncryptionOptions.ClientEncryptionOptions(new ParameterizedClass("org.apache.cassandra.security.DefaultSslContextFactory", new HashMap<>()),
keystore,
keystorePassword,
null,

View File

@ -67,7 +67,7 @@ import static java.lang.Math.*;
import static java.util.concurrent.TimeUnit.MILLISECONDS;
import static org.apache.cassandra.auth.IInternodeAuthenticator.InternodeConnectionDirection.INBOUND;
import static org.apache.cassandra.concurrent.ExecutorFactory.Global.executorFactory;
import static org.apache.cassandra.config.EncryptionOptions.ClientAuth.REQUIRED;
import static org.apache.cassandra.config.EncryptionOptions.ClientEncryptionOptions.ClientAuth.REQUIRED;
import static org.apache.cassandra.net.InternodeConnectionUtils.DISCARD_HANDLER_NAME;
import static org.apache.cassandra.net.InternodeConnectionUtils.SSL_FACTORY_CONTEXT_DESCRIPTION;
import static org.apache.cassandra.net.InternodeConnectionUtils.SSL_HANDLER_NAME;
@ -530,7 +530,7 @@ public class InboundConnectionInitiator
private static SslHandler getSslHandler(String description, Channel channel, EncryptionOptions.ServerEncryptionOptions encryptionOptions) throws IOException
{
final EncryptionOptions.ClientAuth verifyPeerCertificate = REQUIRED;
final EncryptionOptions.ClientEncryptionOptions.ClientAuth verifyPeerCertificate = REQUIRED;
SslContext sslContext = SSLFactory.getOrCreateSslContext(encryptionOptions, verifyPeerCertificate,
ISslContextFactory.SocketType.SERVER,
SSL_FACTORY_CONTEXT_DESCRIPTION);

View File

@ -146,7 +146,7 @@ public class InboundConnectionSettings
ServerEncryptionOptions encryption = this.encryption;
if (encryption == null)
encryption = DatabaseDescriptor.getInternodeMessagingEncyptionOptions();
encryption = encryption.withOptional(false).withInternodeEncryption(ServerEncryptionOptions.InternodeEncryption.all);
encryption = new ServerEncryptionOptions.Builder(encryption).withInternodeEncryption(ServerEncryptionOptions.InternodeEncryption.all).withOptional(false).build();
return this.withBindAddress(bindAddress.withPort(DatabaseDescriptor.getSSLStoragePort()))
.withEncryption(encryption)

View File

@ -66,9 +66,9 @@ import org.apache.cassandra.utils.memory.BufferPools;
import static java.util.concurrent.TimeUnit.*;
import static org.apache.cassandra.auth.IInternodeAuthenticator.InternodeConnectionDirection.OUTBOUND;
import static org.apache.cassandra.auth.IInternodeAuthenticator.InternodeConnectionDirection.OUTBOUND_PRECONNECT;
import static org.apache.cassandra.config.EncryptionOptions.ClientAuth.NOT_REQUIRED;
import static org.apache.cassandra.config.EncryptionOptions.ClientAuth.OPTIONAL;
import static org.apache.cassandra.config.EncryptionOptions.ClientAuth.REQUIRED;
import static org.apache.cassandra.config.EncryptionOptions.ClientEncryptionOptions.ClientAuth.NOT_REQUIRED;
import static org.apache.cassandra.config.EncryptionOptions.ClientEncryptionOptions.ClientAuth.OPTIONAL;
import static org.apache.cassandra.config.EncryptionOptions.ClientEncryptionOptions.ClientAuth.REQUIRED;
import static org.apache.cassandra.net.InternodeConnectionUtils.DISCARD_HANDLER_NAME;
import static org.apache.cassandra.net.InternodeConnectionUtils.SSL_FACTORY_CONTEXT_DESCRIPTION;
import static org.apache.cassandra.net.InternodeConnectionUtils.SSL_HANDLER_NAME;
@ -245,7 +245,7 @@ public class OutboundConnectionInitiator<SuccessType extends OutboundConnectionI
private SslContext getSslContext(SslFallbackConnectionType connectionType) throws IOException
{
EncryptionOptions.ClientAuth requireClientAuth = NOT_REQUIRED;
EncryptionOptions.ClientEncryptionOptions.ClientAuth requireClientAuth = NOT_REQUIRED;
if (connectionType == SslFallbackConnectionType.MTLS )
{
requireClientAuth = REQUIRED;

View File

@ -37,8 +37,8 @@ import io.netty.handler.ssl.SslContextBuilder;
import io.netty.handler.ssl.SslProvider;
import org.apache.cassandra.config.EncryptionOptions;
import static org.apache.cassandra.config.EncryptionOptions.ClientAuth.NOT_REQUIRED;
import static org.apache.cassandra.config.EncryptionOptions.ClientAuth.REQUIRED;
import static org.apache.cassandra.config.EncryptionOptions.ClientEncryptionOptions.ClientAuth.NOT_REQUIRED;
import static org.apache.cassandra.config.EncryptionOptions.ClientEncryptionOptions.ClientAuth.REQUIRED;
import static org.apache.cassandra.config.CassandraRelevantProperties.DISABLE_TCACTIVE_OPENSSL;
@ -68,7 +68,7 @@ abstract public class AbstractSslContextFactory implements ISslContextFactory
protected final List<String> accepted_protocols;
protected final String algorithm;
protected final String store_type;
protected final EncryptionOptions.ClientAuth clientAuth;
protected final EncryptionOptions.ClientEncryptionOptions.ClientAuth clientAuth;
protected final boolean require_endpoint_verification;
/*
ServerEncryptionOptions does not use the enabled flag at all instead using the existing
@ -105,7 +105,7 @@ abstract public class AbstractSslContextFactory implements ISslContextFactory
accepted_protocols = getStringList("accepted_protocols");
algorithm = getString("algorithm");
store_type = getString("store_type", "JKS");
clientAuth = parameters.get("require_client_auth") == null ? NOT_REQUIRED : EncryptionOptions.ClientAuth.from(getString("require_client_auth"));
clientAuth = parameters.get("require_client_auth") == null ? NOT_REQUIRED : EncryptionOptions.ClientEncryptionOptions.ClientAuth.from(getString("require_client_auth"));
require_endpoint_verification = getBoolean("require_endpoint_verification", false);
enabled = getBoolean("enabled");
optional = getBoolean("optional");
@ -158,7 +158,7 @@ abstract public class AbstractSslContextFactory implements ISslContextFactory
}
@Override
public SSLContext createJSSESslContext(EncryptionOptions.ClientAuth clientAuth) throws SSLException
public SSLContext createJSSESslContext(EncryptionOptions.ClientEncryptionOptions.ClientAuth clientAuth) throws SSLException
{
TrustManager[] trustManagers = null;
if (clientAuth != NOT_REQUIRED)
@ -186,7 +186,7 @@ abstract public class AbstractSslContextFactory implements ISslContextFactory
}
@Override
public SslContext createNettySslContext(EncryptionOptions.ClientAuth clientAuth, SocketType socketType,
public SslContext createNettySslContext(EncryptionOptions.ClientEncryptionOptions.ClientAuth clientAuth, SocketType socketType,
CipherSuiteFilter cipherFilter) throws SSLException
{
/*
@ -291,7 +291,7 @@ abstract public class AbstractSslContextFactory implements ISslContextFactory
*/
abstract protected KeyManagerFactory buildOutboundKeyManagerFactory() throws SSLException;
private ClientAuth toNettyClientAuth(EncryptionOptions.ClientAuth clientAuth)
private ClientAuth toNettyClientAuth(EncryptionOptions.ClientEncryptionOptions.ClientAuth clientAuth)
{
switch (clientAuth)
{

View File

@ -72,7 +72,7 @@ public interface ISslContextFactory
* @return JSSE's {@link SSLContext}
* @throws SSLException in case the Ssl Context creation fails for some reason
*/
default SSLContext createJSSESslContext(EncryptionOptions.ClientAuth clientAuth) throws SSLException
default SSLContext createJSSESslContext(EncryptionOptions.ClientEncryptionOptions.ClientAuth clientAuth) throws SSLException
{
switch (clientAuth)
{
@ -112,7 +112,7 @@ public interface ISslContextFactory
* @return Netty's {@link SslContext}
* @throws SSLException in case the Ssl Context creation fails for some reason
*/
default SslContext createNettySslContext(EncryptionOptions.ClientAuth clientAuth, SocketType socketType,
default SslContext createNettySslContext(EncryptionOptions.ClientEncryptionOptions.ClientAuth clientAuth, SocketType socketType,
CipherSuiteFilter cipherFilter) throws SSLException
{
switch (clientAuth)

View File

@ -47,7 +47,7 @@ import org.apache.cassandra.security.ISslContextFactory.SocketType;
import static org.apache.cassandra.config.CassandraRelevantProperties.DISABLE_TCACTIVE_OPENSSL;
import static org.apache.cassandra.config.EncryptionOptions.ClientAuth.REQUIRED;
import static org.apache.cassandra.config.EncryptionOptions.ClientEncryptionOptions.ClientAuth.REQUIRED;
import static org.apache.cassandra.utils.LocalizeString.toLowerCaseLocalized;
/**
@ -125,7 +125,7 @@ public final class SSLFactory
/**
* Create a JSSE {@link SSLContext}.
*/
public static SSLContext createSSLContext(EncryptionOptions options, EncryptionOptions.ClientAuth clientAuth) throws IOException
public static SSLContext createSSLContext(EncryptionOptions options, EncryptionOptions.ClientEncryptionOptions.ClientAuth clientAuth) throws IOException
{
return options.sslContextFactoryInstance.createJSSESslContext(clientAuth);
}
@ -133,7 +133,7 @@ public final class SSLFactory
/**
* get a netty {@link SslContext} instance
*/
public static SslContext getOrCreateSslContext(EncryptionOptions options, EncryptionOptions.ClientAuth clientAuth,
public static SslContext getOrCreateSslContext(EncryptionOptions options, EncryptionOptions.ClientEncryptionOptions.ClientAuth clientAuth,
SocketType socketType,
String contextDescription) throws IOException
{
@ -157,7 +157,7 @@ public final class SSLFactory
/**
* Create a Netty {@link SslContext}
*/
static SslContext createNettySslContext(EncryptionOptions options, EncryptionOptions.ClientAuth clientAuth,
static SslContext createNettySslContext(EncryptionOptions options, EncryptionOptions.ClientEncryptionOptions.ClientAuth clientAuth,
SocketType socketType) throws IOException
{
return createNettySslContext(options, clientAuth, socketType,
@ -167,7 +167,7 @@ public final class SSLFactory
/**
* Create a Netty {@link SslContext} with a supplied cipherFilter
*/
static SslContext createNettySslContext(EncryptionOptions options, EncryptionOptions.ClientAuth clientAuth,
static SslContext createNettySslContext(EncryptionOptions options, EncryptionOptions.ClientEncryptionOptions.ClientAuth clientAuth,
SocketType socketType, CipherSuiteFilter cipherFilter) throws IOException
{
return options.sslContextFactoryInstance.createNettySslContext(clientAuth, socketType,
@ -356,7 +356,7 @@ public final class SSLFactory
return !string.equals("SSLv2Hello");
}
public static void validateSslContext(String contextDescription, EncryptionOptions options, EncryptionOptions.ClientAuth clientAuth, boolean logProtocolAndCiphers) throws IOException
public static void validateSslContext(String contextDescription, EncryptionOptions options, EncryptionOptions.ClientEncryptionOptions.ClientAuth clientAuth, boolean logProtocolAndCiphers) throws IOException
{
if (options != null && options.tlsEncryptionPolicy() != EncryptionOptions.TlsEncryptionPolicy.UNENCRYPTED)
{

View File

@ -48,7 +48,7 @@ import org.apache.cassandra.utils.JVMStabilityInspector;
import org.apache.cassandra.utils.NativeSSTableLoaderClient;
import org.apache.cassandra.utils.OutputHandler;
import static org.apache.cassandra.config.EncryptionOptions.ClientAuth.REQUIRED;
import static org.apache.cassandra.config.EncryptionOptions.ClientEncryptionOptions.ClientAuth.REQUIRED;
import static org.apache.cassandra.utils.Clock.Global.nanoTime;
public class BulkLoader

View File

@ -52,7 +52,7 @@ import org.apache.cassandra.locator.InetAddressAndPort;
import org.apache.cassandra.tools.BulkLoader.CmdLineOptions;
import static org.apache.cassandra.config.DataRateSpec.DataRateUnit.MEBIBYTES_PER_SECOND;
import static org.apache.cassandra.config.EncryptionOptions.ClientAuth.REQUIRED;
import static org.apache.cassandra.config.EncryptionOptions.ClientEncryptionOptions.ClientAuth.REQUIRED;
public class LoaderOptions
{
@ -121,7 +121,7 @@ public class LoaderOptions
public final int entireSSTableInterDcThrottleMebibytes;
public final int storagePort;
public final int sslStoragePort;
public final EncryptionOptions clientEncOptions;
public final EncryptionOptions.ClientEncryptionOptions clientEncOptions;
public final int connectionsPerHost;
public final EncryptionOptions.ServerEncryptionOptions serverEncOptions;
public final Set<InetSocketAddress> hosts;
@ -172,9 +172,11 @@ public class LoaderOptions
int storagePort;
int sslStoragePort;
EncryptionOptions clientEncOptions = new EncryptionOptions();
EncryptionOptions.ClientEncryptionOptions clientEncOptions = new EncryptionOptions.ClientEncryptionOptions();
EncryptionOptions.ClientEncryptionOptions.Builder clientEncOptionsBuilder = new EncryptionOptions.ClientEncryptionOptions.Builder(clientEncOptions);
int connectionsPerHost = 1;
EncryptionOptions.ServerEncryptionOptions serverEncOptions = new EncryptionOptions.ServerEncryptionOptions();
EncryptionOptions.ServerEncryptionOptions.Builder serverEncOptionsBuilder = new EncryptionOptions.ServerEncryptionOptions.Builder(serverEncOptions);
Set<InetAddress> hostsArg = new HashSet<>();
Set<InetAddress> ignoresArg = new HashSet<>();
Set<InetSocketAddress> hosts = new HashSet<>();
@ -333,9 +335,10 @@ public class LoaderOptions
return this;
}
public Builder encOptions(EncryptionOptions encOptions)
public Builder encOptions(EncryptionOptions.ClientEncryptionOptions encOptions)
{
this.clientEncOptions = encOptions;
this.clientEncOptionsBuilder = new EncryptionOptions.ClientEncryptionOptions.Builder(encOptions);
return this;
}
@ -348,6 +351,7 @@ public class LoaderOptions
public Builder serverEncOptions(EncryptionOptions.ServerEncryptionOptions serverEncOptions)
{
this.serverEncOptions = serverEncOptions;
this.serverEncOptionsBuilder = new EncryptionOptions.ServerEncryptionOptions.Builder(serverEncOptions);
return this;
}
@ -551,9 +555,10 @@ public class LoaderOptions
"which is able to handle encrypted communication too.");
// Copy the encryption options and apply the config so that argument parsing can accesss isEnabled.
clientEncOptions = config.client_encryption_options.applyConfig();
serverEncOptions = config.server_encryption_options;
serverEncOptions.applyConfig();
clientEncOptionsBuilder = new EncryptionOptions.ClientEncryptionOptions.Builder(config.client_encryption_options);
clientEncOptions = clientEncOptionsBuilder.build();
serverEncOptionsBuilder = new EncryptionOptions.ServerEncryptionOptions.Builder(config.server_encryption_options);
serverEncOptions = serverEncOptionsBuilder.build();
if (cmd.hasOption(NATIVE_PORT_OPTION))
nativePort = Integer.parseInt(cmd.getOptionValue(NATIVE_PORT_OPTION));
@ -625,51 +630,53 @@ public class LoaderOptions
if (cmd.hasOption(SSL_TRUSTSTORE) || cmd.hasOption(SSL_TRUSTSTORE_PW) ||
cmd.hasOption(SSL_KEYSTORE) || cmd.hasOption(SSL_KEYSTORE_PW))
{
clientEncOptions = clientEncOptions.withEnabled(true);
clientEncOptionsBuilder.withEnabled(true);
}
if (cmd.hasOption(SSL_TRUSTSTORE))
{
clientEncOptions = clientEncOptions.withTrustStore(cmd.getOptionValue(SSL_TRUSTSTORE));
clientEncOptionsBuilder.withTrustStore(cmd.getOptionValue(SSL_TRUSTSTORE));
}
if (cmd.hasOption(SSL_TRUSTSTORE_PW))
{
clientEncOptions = clientEncOptions.withTrustStorePassword(cmd.getOptionValue(SSL_TRUSTSTORE_PW));
clientEncOptionsBuilder.withTrustStorePassword(cmd.getOptionValue(SSL_TRUSTSTORE_PW));
}
if (cmd.hasOption(SSL_KEYSTORE))
{
// if a keystore was provided, lets assume we'll need to use
clientEncOptions = clientEncOptions.withKeyStore(cmd.getOptionValue(SSL_KEYSTORE))
clientEncOptionsBuilder.withKeyStore(cmd.getOptionValue(SSL_KEYSTORE))
.withRequireClientAuth(REQUIRED);
}
if (cmd.hasOption(SSL_KEYSTORE_PW))
{
clientEncOptions = clientEncOptions.withKeyStorePassword(cmd.getOptionValue(SSL_KEYSTORE_PW));
clientEncOptionsBuilder.withKeyStorePassword(cmd.getOptionValue(SSL_KEYSTORE_PW));
}
if (cmd.hasOption(SSL_PROTOCOL))
{
clientEncOptions = clientEncOptions.withProtocol(cmd.getOptionValue(SSL_PROTOCOL));
clientEncOptionsBuilder.withProtocol(cmd.getOptionValue(SSL_PROTOCOL));
}
if (cmd.hasOption(SSL_ALGORITHM))
{
clientEncOptions = clientEncOptions.withAlgorithm(cmd.getOptionValue(SSL_ALGORITHM));
clientEncOptionsBuilder.withAlgorithm(cmd.getOptionValue(SSL_ALGORITHM));
}
if (cmd.hasOption(SSL_STORE_TYPE))
{
clientEncOptions = clientEncOptions.withStoreType(cmd.getOptionValue(SSL_STORE_TYPE));
clientEncOptionsBuilder.withStoreType(cmd.getOptionValue(SSL_STORE_TYPE));
}
if (cmd.hasOption(SSL_CIPHER_SUITES))
{
clientEncOptions = clientEncOptions.withCipherSuites(cmd.getOptionValue(SSL_CIPHER_SUITES).split(","));
clientEncOptionsBuilder.withCipherSuites(cmd.getOptionValue(SSL_CIPHER_SUITES).split(","));
}
clientEncOptions = clientEncOptionsBuilder.build();
if (cmd.hasOption(TARGET_KEYSPACE))
{
targetKeyspace = cmd.getOptionValue(TARGET_KEYSPACE);

View File

@ -45,9 +45,9 @@ public class Client extends SimpleClient
{
private final SimpleEventHandler eventHandler = new SimpleEventHandler();
public Client(String host, int port, ProtocolVersion version, EncryptionOptions encryptionOptions)
public Client(String host, int port, ProtocolVersion version, EncryptionOptions.ClientEncryptionOptions encryptionOptions)
{
super(host, port, version, version.isBeta(), new EncryptionOptions(encryptionOptions).applyConfig());
super(host, port, version, version.isBeta(), encryptionOptions.applyConfig());
setEventHandler(eventHandler);
}
@ -260,7 +260,7 @@ public class Client extends SimpleClient
int port = Integer.parseInt(args[1]);
ProtocolVersion version = args.length == 3 ? ProtocolVersion.decode(Integer.parseInt(args[2]), DatabaseDescriptor.getNativeTransportAllowOlderProtocols()) : ProtocolVersion.CURRENT;
EncryptionOptions encryptionOptions = new EncryptionOptions().applyConfig();
EncryptionOptions.ClientEncryptionOptions encryptionOptions = new EncryptionOptions.ClientEncryptionOptions().applyConfig();
System.out.println("CQL binary protocol console " + host + "@" + port + " using native protocol version " + version);
try (Client client = new Client(host, port, version, encryptionOptions))

View File

@ -74,7 +74,7 @@ public class SimpleClient implements Closeable
public final String host;
public final int port;
private final EncryptionOptions encryptionOptions;
private final EncryptionOptions.ClientEncryptionOptions encryptionOptions;
private final int largeMessageThreshold;
protected final ResponseHandler responseHandler = new ResponseHandler();
@ -92,7 +92,7 @@ public class SimpleClient implements Closeable
{
private final String host;
private final int port;
private EncryptionOptions encryptionOptions = new EncryptionOptions();
private EncryptionOptions.ClientEncryptionOptions encryptionOptions = new EncryptionOptions.ClientEncryptionOptions();
private ProtocolVersion version = ProtocolVersion.CURRENT;
private boolean useBeta = false;
private int largeMessageThreshold = FrameEncoder.Payload.MAX_SIZE;
@ -103,7 +103,7 @@ public class SimpleClient implements Closeable
this.port = port;
}
public Builder encryption(EncryptionOptions options)
public Builder encryption(EncryptionOptions.ClientEncryptionOptions options)
{
this.encryptionOptions = options;
return this;
@ -149,22 +149,22 @@ public class SimpleClient implements Closeable
this.largeMessageThreshold = builder.largeMessageThreshold;
}
public SimpleClient(String host, int port, ProtocolVersion version, EncryptionOptions encryptionOptions)
public SimpleClient(String host, int port, ProtocolVersion version, EncryptionOptions.ClientEncryptionOptions encryptionOptions)
{
this(host, port, version, false, encryptionOptions);
}
public SimpleClient(String host, int port, EncryptionOptions encryptionOptions)
public SimpleClient(String host, int port, EncryptionOptions.ClientEncryptionOptions encryptionOptions)
{
this(host, port, ProtocolVersion.CURRENT, encryptionOptions);
}
public SimpleClient(String host, int port, ProtocolVersion version)
{
this(host, port, version, new EncryptionOptions());
this(host, port, version, new EncryptionOptions.ClientEncryptionOptions());
}
public SimpleClient(String host, int port, ProtocolVersion version, boolean useBeta, EncryptionOptions encryptionOptions)
public SimpleClient(String host, int port, ProtocolVersion version, boolean useBeta, EncryptionOptions.ClientEncryptionOptions encryptionOptions)
{
this.host = host;
this.port = port;
@ -172,7 +172,7 @@ public class SimpleClient implements Closeable
throw new IllegalArgumentException(String.format("Beta version of server used (%s), but USE_BETA flag is not set", version));
this.version = version;
this.encryptionOptions = new EncryptionOptions(encryptionOptions).applyConfig();
this.encryptionOptions = encryptionOptions.applyConfig();
this.largeMessageThreshold = FrameEncoder.Payload.MAX_SIZE -
Math.max(FrameEncoderCrc.HEADER_AND_TRAILER_LENGTH,
FrameEncoderLZ4.HEADER_AND_TRAILER_LENGTH);
@ -180,7 +180,7 @@ public class SimpleClient implements Closeable
public SimpleClient(String host, int port)
{
this(host, port, new EncryptionOptions());
this(host, port, new EncryptionOptions.ClientEncryptionOptions());
}
public SimpleClient connect(boolean useCompression) throws IOException

View File

@ -82,7 +82,7 @@ abstract public class AbstractJmxSocketFactory
JMXServerOptions.setJmxSystemProperties(jmxEncryptionOptions.getAcceptedProtocols(), jmxEncryptionOptions.getCipherSuites());
logger.info("Enabling JMX SSL using jmx_encryption_options");
boolean requireClientAuth = jmxEncryptionOptions.getClientAuth() == EncryptionOptions.ClientAuth.REQUIRED;
boolean requireClientAuth = jmxEncryptionOptions.getClientAuth() == EncryptionOptions.ClientEncryptionOptions.ClientAuth.REQUIRED;
String[] ciphers = jmxEncryptionOptions.cipherSuitesArray();
String[] protocols = jmxEncryptionOptions.acceptedProtocolsArray();
SSLContext sslContext = jmxEncryptionOptions.sslContextFactoryInstance.createJSSESslContext(jmxEncryptionOptions.getClientAuth());

View File

@ -138,11 +138,11 @@ public class SimpleClientBurnTest
Arrays.asList(
() -> new SimpleClient(address.getHostAddress(),
port, ProtocolVersion.V5, true,
new EncryptionOptions())
new EncryptionOptions.ClientEncryptionOptions())
.connect(false),
() -> new SimpleClient(address.getHostAddress(),
port, ProtocolVersion.V4, false,
new EncryptionOptions())
new EncryptionOptions.ClientEncryptionOptions())
.connect(false)
);

View File

@ -102,7 +102,7 @@ public class SimpleClientPerfTest
new SizeCaps(10, 20, 5, 10),
() -> new SimpleClient(address.getHostAddress(),
port, version, true,
new EncryptionOptions())
new EncryptionOptions.ClientEncryptionOptions())
.connect(false),
version);
}
@ -114,7 +114,7 @@ public class SimpleClientPerfTest
new SizeCaps(10, 20, 5, 10),
() -> new SimpleClient(address.getHostAddress(),
port, version, true,
new EncryptionOptions())
new EncryptionOptions.ClientEncryptionOptions())
.connect(true),
version);
}
@ -126,7 +126,7 @@ public class SimpleClientPerfTest
new SizeCaps(1000, 2000, 5, 150),
() -> new SimpleClient(address.getHostAddress(),
port, version, true,
new EncryptionOptions())
new EncryptionOptions.ClientEncryptionOptions())
.connect(false),
version);
}
@ -138,7 +138,7 @@ public class SimpleClientPerfTest
new SizeCaps(1000, 2000, 5, 150),
() -> new SimpleClient(address.getHostAddress(),
port, version, true,
new EncryptionOptions())
new EncryptionOptions.ClientEncryptionOptions())
.connect(true),
version);
}

View File

@ -94,7 +94,7 @@ public class IsolatedJmx
// CASSANDRA-18508: Sensitive JMX SSL configuration options can be easily exposed
Map<String, Object> jmxServerOptionsMap = (Map<String, Object>) config.getParams().get("jmx_server_options");
EncryptionOptions jmxEncryptionOptions;
EncryptionOptions.ClientEncryptionOptions jmxEncryptionOptions;
if (jmxServerOptionsMap == null)
{
JMXServerOptions parsingSystemProperties = JMXServerOptions.createParsingSystemProperties();
@ -175,7 +175,7 @@ public class IsolatedJmx
* @return EncryptionOptions built object
*/
@SuppressWarnings("unchecked")
private EncryptionOptions getJmxEncryptionOptions(Map<String, Object> jmxServerOptionsMap)
private EncryptionOptions.ClientEncryptionOptions getJmxEncryptionOptions(Map<String, Object> jmxServerOptionsMap)
{
if (jmxServerOptionsMap == null)
return null;
@ -186,34 +186,34 @@ public class IsolatedJmx
{
return null;
}
EncryptionOptions jmxEncryptionOptions = new EncryptionOptions();
EncryptionOptions.ClientEncryptionOptions.Builder jmxEncryptionOptionsBuilder = new EncryptionOptions.ClientEncryptionOptions.Builder();
String[] cipherSuitesArray = (String[]) encryptionOptionsMap.get(EncryptionOptions.ConfigKey.CIPHER_SUITES.toString());
if (cipherSuitesArray != null)
{
jmxEncryptionOptions = jmxEncryptionOptions.withCipherSuites(cipherSuitesArray);
jmxEncryptionOptionsBuilder.withCipherSuites(cipherSuitesArray);
}
List<String> acceptedProtocols = (List<String>) encryptionOptionsMap.get(EncryptionOptions.ConfigKey.ACCEPTED_PROTOCOLS.toString());
if (acceptedProtocols != null)
{
jmxEncryptionOptions = jmxEncryptionOptions.withAcceptedProtocols(acceptedProtocols);
jmxEncryptionOptionsBuilder.withAcceptedProtocols(acceptedProtocols);
}
Boolean requireClientAuthValue = (Boolean) encryptionOptionsMap.get(EncryptionOptions.ConfigKey.REQUIRE_CLIENT_AUTH.toString());
EncryptionOptions.ClientAuth requireClientAuth = requireClientAuthValue == null ?
EncryptionOptions.ClientAuth.NOT_REQUIRED :
EncryptionOptions.ClientAuth.from(String.valueOf(requireClientAuthValue));
EncryptionOptions.ClientEncryptionOptions.ClientAuth requireClientAuth = requireClientAuthValue == null ?
EncryptionOptions.ClientEncryptionOptions.ClientAuth.NOT_REQUIRED :
EncryptionOptions.ClientEncryptionOptions.ClientAuth.from(String.valueOf(requireClientAuthValue));
Object enabledOption = encryptionOptionsMap.get(EncryptionOptions.ConfigKey.ENABLED.toString());
boolean enabled = enabledOption != null ? (Boolean) encryptionOptionsMap.get(EncryptionOptions.ConfigKey.ENABLED.toString()) : false;
//CASSANDRA-18508 NOTE - We do not populate sslContextFactory configuration here for tests, it could be enhanced
jmxEncryptionOptions = jmxEncryptionOptions
.withKeyStore((String) encryptionOptionsMap.get(EncryptionOptions.ConfigKey.KEYSTORE.toString()))
.withKeyStorePassword((String) encryptionOptionsMap.get(EncryptionOptions.ConfigKey.KEYSTORE_PASSWORD.toString()))
.withTrustStore((String) encryptionOptionsMap.get(EncryptionOptions.ConfigKey.TRUSTSTORE.toString()))
.withTrustStorePassword((String) encryptionOptionsMap.get(EncryptionOptions.ConfigKey.TRUSTSTORE_PASSWORD.toString()))
.withRequireClientAuth(requireClientAuth)
.withEnabled(enabled);
return jmxEncryptionOptions;
return jmxEncryptionOptionsBuilder
.withKeyStore((String) encryptionOptionsMap.get(EncryptionOptions.ConfigKey.KEYSTORE.toString()))
.withKeyStorePassword((String) encryptionOptionsMap.get(EncryptionOptions.ConfigKey.KEYSTORE_PASSWORD.toString()))
.withTrustStore((String) encryptionOptionsMap.get(EncryptionOptions.ConfigKey.TRUSTSTORE.toString()))
.withTrustStorePassword((String) encryptionOptionsMap.get(EncryptionOptions.ConfigKey.TRUSTSTORE_PASSWORD.toString()))
.withRequireClientAuth(requireClientAuth)
.withEnabled(enabled)
.build();
}
private void waitForJmxAvailability(Map<String, ?> env)

View File

@ -56,7 +56,7 @@ import org.apache.cassandra.security.ISslContextFactory;
import org.apache.cassandra.security.SSLFactory;
import static java.util.concurrent.TimeUnit.SECONDS;
import static org.apache.cassandra.config.EncryptionOptions.ClientAuth.REQUIRED;
import static org.apache.cassandra.config.EncryptionOptions.ClientEncryptionOptions.ClientAuth.REQUIRED;
import static org.apache.cassandra.distributed.test.AbstractEncryptionOptionsImpl.ConnectResult.CONNECTING;
import static org.apache.cassandra.distributed.test.AbstractEncryptionOptionsImpl.ConnectResult.UNINITIALIZED;
import static org.apache.cassandra.utils.concurrent.Condition.newOneTimeCondition;
@ -118,10 +118,13 @@ public class AbstractEncryptionOptionsImpl extends TestBaseImpl
final int port;
final List<String> acceptedProtocols;
final List<String> cipherSuites;
final EncryptionOptions encryptionOptions = new EncryptionOptions()
.withEnabled(true)
.withKeyStore(validKeyStorePath).withKeyStorePassword(validKeyStorePassword)
.withTrustStore(validTrustStorePath).withTrustStorePassword(validTrustStorePassword);
final EncryptionOptions.ClientEncryptionOptions encryptionOptions = new EncryptionOptions.ClientEncryptionOptions.Builder()
.withEnabled(true)
.withKeyStore(validKeyStorePath)
.withKeyStorePassword(validKeyStorePassword)
.withTrustStore(validTrustStorePath)
.withTrustStorePassword(validTrustStorePassword)
.build();
private Throwable lastThrowable;
private String lastProtocol;
private String lastCipher;
@ -202,7 +205,7 @@ public class AbstractEncryptionOptionsImpl extends TestBaseImpl
setProtocolAndCipher(null, null);
SslContext sslContext = SSLFactory.getOrCreateSslContext(
encryptionOptions.withAcceptedProtocols(acceptedProtocols).withCipherSuites(cipherSuites),
new EncryptionOptions.ClientEncryptionOptions.Builder(encryptionOptions).withAcceptedProtocols(acceptedProtocols).withCipherSuites(cipherSuites).build(),
REQUIRED, ISslContextFactory.SocketType.CLIENT, "test");
EventLoopGroup workerGroup = new NioEventLoopGroup();

View File

@ -30,6 +30,7 @@ import org.junit.rules.ExpectedException;
import org.apache.cassandra.config.Config;
import org.apache.cassandra.config.DatabaseDescriptor;
import org.apache.cassandra.config.EncryptionOptions.ServerEncryptionOptions.Builder;
import org.apache.cassandra.config.ParameterizedClass;
import org.apache.cassandra.locator.InetAddressAndPort;
import org.apache.cassandra.utils.MBeanWrapper;
@ -52,8 +53,10 @@ public class AuthConfigTest
Config config = load("cassandra-mtls.yaml");
config.internode_authenticator.class_name = "org.apache.cassandra.auth.MutualTlsInternodeAuthenticator";
config.internode_authenticator.parameters = Collections.singletonMap("validator_class_name", "org.apache.cassandra.auth.SpiffeCertificateValidator");
config.server_encryption_options = config.server_encryption_options.withOutboundKeystore("test/conf/cassandra_ssl_test_outbound.keystore")
.withOutboundKeystorePassword("cassandra");
config.server_encryption_options = new Builder(config.server_encryption_options)
.withOutboundKeystore("test/conf/cassandra_ssl_test_outbound.keystore")
.withOutboundKeystorePassword("cassandra")
.build();
DatabaseDescriptor.setConfig(config);
MutualTlsInternodeAuthenticator authenticator = ParameterizedClass.newInstance(config.internode_authenticator,
Arrays.asList("", "org.apache.cassandra.auth."));

View File

@ -48,7 +48,7 @@ import org.apache.cassandra.utils.MBeanWrapper;
import static org.apache.cassandra.auth.AuthTestUtils.getMockInetAddress;
import static org.apache.cassandra.auth.AuthTestUtils.initializeIdentityRolesTable;
import static org.apache.cassandra.auth.AuthTestUtils.loadCertificateChain;
import static org.apache.cassandra.config.EncryptionOptions.ClientAuth.REQUIRED;
import static org.apache.cassandra.config.EncryptionOptions.ClientEncryptionOptions.ClientAuth.REQUIRED;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
@ -79,8 +79,10 @@ public class MutualTlsAuthenticatorTest
StorageService.instance.initServer();
((CassandraRoleManager)DatabaseDescriptor.getRoleManager()).loadIdentityStatement();
final Config config = DatabaseDescriptor.getRawConfig();
config.client_encryption_options = config.client_encryption_options.withEnabled(true)
.withRequireClientAuth(REQUIRED);
config.client_encryption_options = new EncryptionOptions.ClientEncryptionOptions.Builder(config.client_encryption_options)
.withEnabled(true)
.withRequireClientAuth(REQUIRED)
.build();
}
@After
@ -183,8 +185,10 @@ public class MutualTlsAuthenticatorTest
" & client_encryption_options.require_client_auth to be true";
MutualTlsAuthenticator mutualTlsAuthenticator = createAndInitializeMtlsAuthenticator();
config.client_encryption_options = config.client_encryption_options.withEnabled(true)
.withRequireClientAuth(EncryptionOptions.ClientAuth.NOT_REQUIRED);
config.client_encryption_options = new EncryptionOptions.ClientEncryptionOptions.Builder(config.client_encryption_options)
.withEnabled(true)
.withRequireClientAuth(EncryptionOptions.ClientEncryptionOptions.ClientAuth.NOT_REQUIRED)
.build();
expectedException.expect(ConfigurationException.class);
expectedException.expectMessage(msg);
mutualTlsAuthenticator.validateConfiguration();

View File

@ -39,6 +39,7 @@ import org.junit.runners.Parameterized;
import org.apache.cassandra.SchemaLoader;
import org.apache.cassandra.config.Config;
import org.apache.cassandra.config.DatabaseDescriptor;
import org.apache.cassandra.config.EncryptionOptions.ServerEncryptionOptions.Builder;
import org.apache.cassandra.exceptions.ConfigurationException;
import org.apache.cassandra.locator.InetAddressAndPort;
import org.apache.cassandra.transport.TlsTestUtils;
@ -81,8 +82,10 @@ public class MutualTlsInternodeAuthenticatorTest
public void before()
{
Config config = DatabaseDescriptor.getRawConfig();
config.server_encryption_options = config.server_encryption_options.withOutboundKeystore("test/conf/cassandra_ssl_test_outbound.keystore")
.withOutboundKeystorePassword("cassandra");
config.server_encryption_options = new Builder(config.server_encryption_options)
.withOutboundKeystore("test/conf/cassandra_ssl_test_outbound.keystore")
.withOutboundKeystorePassword("cassandra")
.build();
}
String getValidatorClass()
@ -164,8 +167,10 @@ public class MutualTlsInternodeAuthenticatorTest
public void testNoIdentitiesInKeystore()
{
Config config = DatabaseDescriptor.getRawConfig();
config.server_encryption_options = config.server_encryption_options.withOutboundKeystore(TlsTestUtils.SERVER_KEYSTORE_PATH)
.withOutboundKeystorePassword(TlsTestUtils.SERVER_KEYSTORE_PASSWORD);
config.server_encryption_options = new Builder(config.server_encryption_options)
.withOutboundKeystore(TlsTestUtils.SERVER_KEYSTORE_PATH)
.withOutboundKeystorePassword(TlsTestUtils.SERVER_KEYSTORE_PASSWORD)
.build();
expectedException.expect(ConfigurationException.class);
expectedException.expectMessage(String.format("No identity was extracted from the outbound keystore '%s'", TlsTestUtils.SERVER_KEYSTORE_PATH));
new MutualTlsInternodeAuthenticator(getParams());

View File

@ -50,8 +50,10 @@ public class MutualTlsWithPasswordFallbackAuthenticatorTest
DatabaseDescriptor.daemonInitialization();
SchemaLoader.loadSchema();
Config config = DatabaseDescriptor.getRawConfig();
config.client_encryption_options = config.client_encryption_options.withEnabled(true)
.withRequireClientAuth(EncryptionOptions.ClientAuth.OPTIONAL);
config.client_encryption_options = new EncryptionOptions.ClientEncryptionOptions.Builder(config.client_encryption_options)
.withEnabled(true)
.withRequireClientAuth(EncryptionOptions.ClientEncryptionOptions.ClientAuth.OPTIONAL)
.build();
Map<String, String> parameters = Collections.singletonMap("validator_class_name", "org.apache.cassandra.auth.SpiffeCertificateValidator");
fallbackAuthenticator = new MutualTlsWithPasswordFallbackAuthenticator(parameters);
fallbackAuthenticator.setup();

View File

@ -42,7 +42,7 @@ public class JMXAuthJMXServerOptionsTest extends AbstractJMXAuthTest
String config = Paths.get(ClassLoader.getSystemResource("auth/cassandra-test-jaas.conf").toURI()).toString();
return new JMXServerOptions(true, false, 9999, 0, true,
new EncryptionOptions(), "TestLogin", config, null, null,
new EncryptionOptions.ClientEncryptionOptions(), "TestLogin", config, null, null,
NoSuperUserAuthorizationProxy.class.getName());
}
}

View File

@ -27,8 +27,8 @@ import org.apache.cassandra.security.DefaultSslContextFactory;
import org.apache.cassandra.security.DummySslContextFactoryImpl;
import org.apache.cassandra.transport.TlsTestUtils;
import static org.apache.cassandra.config.EncryptionOptions.ClientAuth.NOT_REQUIRED;
import static org.apache.cassandra.config.EncryptionOptions.ClientAuth.REQUIRED;
import static org.apache.cassandra.config.EncryptionOptions.ClientEncryptionOptions.ClientAuth.NOT_REQUIRED;
import static org.apache.cassandra.config.EncryptionOptions.ClientEncryptionOptions.ClientAuth.REQUIRED;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotEquals;
@ -40,23 +40,25 @@ public class EncryptionOptionsEqualityTest
{
private EncryptionOptions.ServerEncryptionOptions createServerEncryptionOptions()
{
return new EncryptionOptions.ServerEncryptionOptions()
EncryptionOptions.ServerEncryptionOptions.Builder serverEncryptionOptionsBuilder = new EncryptionOptions.ServerEncryptionOptions.Builder();
return serverEncryptionOptionsBuilder
.withOutboundKeystore(TlsTestUtils.SERVER_OUTBOUND_KEYSTORE_PATH)
.withOutboundKeystorePassword(TlsTestUtils.SERVER_OUTBOUND_KEYSTORE_PASSWORD)
.withStoreType("JKS")
.withKeyStore(TlsTestUtils.SERVER_KEYSTORE_PATH)
.withKeyStorePassword(TlsTestUtils.SERVER_KEYSTORE_PASSWORD)
.withTrustStore(TlsTestUtils.SERVER_TRUSTSTORE_PATH)
.withTrustStorePassword(TlsTestUtils.SERVER_TRUSTSTORE_PASSWORD)
.withOutboundKeystore(TlsTestUtils.SERVER_OUTBOUND_KEYSTORE_PATH)
.withOutboundKeystorePassword(TlsTestUtils.SERVER_OUTBOUND_KEYSTORE_PASSWORD)
.withProtocol("TLSv1.1")
.withRequireClientAuth(REQUIRED)
.withRequireEndpointVerification(false);
.withRequireEndpointVerification(false)
.build();
}
@Test
public void testKeystoreOptions() {
EncryptionOptions encryptionOptions1 =
new EncryptionOptions()
EncryptionOptions.ServerEncryptionOptions encryptionOptions1 =
new EncryptionOptions.ServerEncryptionOptions.Builder()
.withStoreType("JKS")
.withKeyStore(TlsTestUtils.SERVER_KEYSTORE_PATH)
.withKeyStorePassword(TlsTestUtils.SERVER_KEYSTORE_PASSWORD)
@ -64,10 +66,11 @@ public class EncryptionOptionsEqualityTest
.withTrustStorePassword(TlsTestUtils.SERVER_TRUSTSTORE_PASSWORD)
.withProtocol("TLSv1.1")
.withRequireClientAuth(REQUIRED)
.withRequireEndpointVerification(false);
.withRequireEndpointVerification(false)
.build();
EncryptionOptions encryptionOptions2 =
new EncryptionOptions()
EncryptionOptions.ServerEncryptionOptions encryptionOptions2 =
new EncryptionOptions.ServerEncryptionOptions.Builder()
.withStoreType("JKS")
.withKeyStore(TlsTestUtils.SERVER_KEYSTORE_PATH)
.withKeyStorePassword(TlsTestUtils.SERVER_KEYSTORE_PASSWORD)
@ -75,7 +78,8 @@ public class EncryptionOptionsEqualityTest
.withTrustStorePassword(TlsTestUtils.SERVER_TRUSTSTORE_PASSWORD)
.withProtocol("TLSv1.1")
.withRequireClientAuth(REQUIRED)
.withRequireEndpointVerification(false);
.withRequireEndpointVerification(false)
.build();
assertEquals(encryptionOptions1, encryptionOptions2);
assertEquals(encryptionOptions1.hashCode(), encryptionOptions2.hashCode());
@ -83,8 +87,8 @@ public class EncryptionOptionsEqualityTest
@Test
public void testKeystoreOptionsWithPasswordFile() {
EncryptionOptions encryptionOptions1 =
new EncryptionOptions()
EncryptionOptions.ServerEncryptionOptions encryptionOptions1 =
new EncryptionOptions.ServerEncryptionOptions.Builder()
.withStoreType("JKS")
.withKeyStore(TlsTestUtils.SERVER_KEYSTORE_PATH)
.withKeyStorePasswordFile(TlsTestUtils.SERVER_KEYSTORE_PASSWORD_FILE)
@ -92,10 +96,11 @@ public class EncryptionOptionsEqualityTest
.withTrustStorePasswordFile(TlsTestUtils.SERVER_TRUSTSTORE_PASSWORD_FILE)
.withProtocol("TLSv1.1")
.withRequireClientAuth(REQUIRED)
.withRequireEndpointVerification(false);
.withRequireEndpointVerification(false)
.build();
EncryptionOptions encryptionOptions2 =
new EncryptionOptions()
EncryptionOptions.ServerEncryptionOptions encryptionOptions2 =
new EncryptionOptions.ServerEncryptionOptions.Builder()
.withStoreType("JKS")
.withKeyStore(TlsTestUtils.SERVER_KEYSTORE_PATH)
.withKeyStorePasswordFile(TlsTestUtils.SERVER_KEYSTORE_PASSWORD_FILE)
@ -103,7 +108,8 @@ public class EncryptionOptionsEqualityTest
.withTrustStorePasswordFile(TlsTestUtils.SERVER_TRUSTSTORE_PASSWORD_FILE)
.withProtocol("TLSv1.1")
.withRequireClientAuth(REQUIRED)
.withRequireEndpointVerification(false);
.withRequireEndpointVerification(false)
.build();
assertEquals(encryptionOptions1, encryptionOptions2);
assertEquals(encryptionOptions1.hashCode(), encryptionOptions2.hashCode());
@ -115,15 +121,17 @@ public class EncryptionOptionsEqualityTest
EncryptionOptions.ServerEncryptionOptions encryptionOptions1 = createServerEncryptionOptions();
EncryptionOptions.ServerEncryptionOptions encryptionOptions2 = createServerEncryptionOptions();
encryptionOptions1 = encryptionOptions1
encryptionOptions1 = new EncryptionOptions.ServerEncryptionOptions.Builder(encryptionOptions1)
.withKeyStore(TlsTestUtils.SERVER_KEYSTORE_PATH)
.withKeyStorePassword(null)
.withKeyStorePasswordFile(TlsTestUtils.SERVER_KEYSTORE_PASSWORD_FILE);
.withKeyStorePasswordFile(TlsTestUtils.SERVER_KEYSTORE_PASSWORD_FILE)
.build();
encryptionOptions2 = encryptionOptions2
encryptionOptions2 = new EncryptionOptions.ServerEncryptionOptions.Builder(encryptionOptions2)
.withKeyStore(TlsTestUtils.SERVER_KEYSTORE_PATH)
.withKeyStorePassword(null)
.withKeyStorePasswordFile(TlsTestUtils.SERVER_TRUSTSTORE_PASSWORD_FILE);
.withKeyStorePasswordFile(TlsTestUtils.SERVER_TRUSTSTORE_PASSWORD_FILE)
.build();
assertNotEquals(encryptionOptions1, encryptionOptions2);
assertNotEquals(encryptionOptions1.hashCode(), encryptionOptions2.hashCode());
@ -135,22 +143,24 @@ public class EncryptionOptionsEqualityTest
Map<String,String> parameters1 = new HashMap<>();
parameters1.put("key1", "value1");
parameters1.put("key2", "value2");
EncryptionOptions encryptionOptions1 =
new EncryptionOptions()
EncryptionOptions.ClientEncryptionOptions encryptionOptions1 =
new EncryptionOptions.ClientEncryptionOptions.Builder()
.withSslContextFactory(new ParameterizedClass(DummySslContextFactoryImpl.class.getName(), parameters1))
.withProtocol("TLSv1.1")
.withRequireClientAuth(REQUIRED)
.withRequireEndpointVerification(false);
.withRequireEndpointVerification(false)
.build();
Map<String,String> parameters2 = new HashMap<>();
parameters2.put("key1", "value1");
parameters2.put("key2", "value2");
EncryptionOptions encryptionOptions2 =
new EncryptionOptions()
EncryptionOptions.ClientEncryptionOptions encryptionOptions2 =
new EncryptionOptions.ClientEncryptionOptions.Builder()
.withSslContextFactory(new ParameterizedClass(DummySslContextFactoryImpl.class.getName(), parameters2))
.withProtocol("TLSv1.1")
.withRequireClientAuth(REQUIRED)
.withRequireEndpointVerification(false);
.withRequireEndpointVerification(false)
.build();
assertEquals(encryptionOptions1, encryptionOptions2);
assertEquals(encryptionOptions1.hashCode(), encryptionOptions2.hashCode());
@ -162,22 +172,24 @@ public class EncryptionOptionsEqualityTest
Map<String,String> parameters1 = new HashMap<>();
parameters1.put("key1", "value1");
parameters1.put("key2", "value2");
EncryptionOptions encryptionOptions1 =
new EncryptionOptions()
EncryptionOptions.ClientEncryptionOptions encryptionOptions1 =
new EncryptionOptions.ClientEncryptionOptions.Builder()
.withSslContextFactory(new ParameterizedClass(DummySslContextFactoryImpl.class.getName(), parameters1))
.withProtocol("TLSv1.1")
.withRequireClientAuth(NOT_REQUIRED)
.withRequireEndpointVerification(true);
.withRequireEndpointVerification(true)
.build();
Map<String,String> parameters2 = new HashMap<>();
parameters2.put("key1", "value1");
parameters2.put("key2", "value2");
EncryptionOptions encryptionOptions2 =
new EncryptionOptions()
EncryptionOptions.ClientEncryptionOptions encryptionOptions2 =
new EncryptionOptions.ClientEncryptionOptions.Builder()
.withSslContextFactory(new ParameterizedClass(DefaultSslContextFactory.class.getName(), parameters2))
.withProtocol("TLSv1.1")
.withRequireClientAuth(NOT_REQUIRED)
.withRequireEndpointVerification(true);
.withRequireEndpointVerification(true)
.build();
assertNotEquals(encryptionOptions1, encryptionOptions2);
assertNotEquals(encryptionOptions1.hashCode(), encryptionOptions2.hashCode());
@ -189,18 +201,20 @@ public class EncryptionOptionsEqualityTest
Map<String,String> parameters1 = new HashMap<>();
parameters1.put("key1", "value11");
parameters1.put("key2", "value12");
EncryptionOptions encryptionOptions1 =
new EncryptionOptions()
EncryptionOptions.ClientEncryptionOptions encryptionOptions1 =
new EncryptionOptions.ClientEncryptionOptions.Builder()
.withSslContextFactory(new ParameterizedClass(DummySslContextFactoryImpl.class.getName(), parameters1))
.withProtocol("TLSv1.1");
.withProtocol("TLSv1.1")
.build();
Map<String,String> parameters2 = new HashMap<>();
parameters2.put("key1", "value21");
parameters2.put("key2", "value22");
EncryptionOptions encryptionOptions2 =
new EncryptionOptions()
EncryptionOptions.ClientEncryptionOptions encryptionOptions2 =
new EncryptionOptions.ClientEncryptionOptions.Builder()
.withSslContextFactory(new ParameterizedClass(DummySslContextFactoryImpl.class.getName(), parameters2))
.withProtocol("TLSv1.1");
.withProtocol("TLSv1.1")
.build();
assertNotEquals(encryptionOptions1, encryptionOptions2);
assertNotEquals(encryptionOptions1.hashCode(), encryptionOptions2.hashCode());
@ -222,13 +236,15 @@ public class EncryptionOptionsEqualityTest
EncryptionOptions.ServerEncryptionOptions encryptionOptions1 = createServerEncryptionOptions();
EncryptionOptions.ServerEncryptionOptions encryptionOptions2 = createServerEncryptionOptions();
encryptionOptions1 = encryptionOptions1
encryptionOptions1 = new EncryptionOptions.ServerEncryptionOptions.Builder(encryptionOptions1)
.withOutboundKeystore("test/conf/cassandra_outbound1.keystore")
.withOutboundKeystorePassword("cassandra1");
.withOutboundKeystorePassword("cassandra1")
.build();
encryptionOptions2 = encryptionOptions2
encryptionOptions2 = new EncryptionOptions.ServerEncryptionOptions.Builder(encryptionOptions2)
.withOutboundKeystore("test/conf/cassandra_outbound2.keystore")
.withOutboundKeystorePassword("cassandra2");
.withOutboundKeystorePassword("cassandra2")
.build();
assertNotEquals(encryptionOptions1, encryptionOptions2);
assertNotEquals(encryptionOptions1.hashCode(), encryptionOptions2.hashCode());
@ -240,13 +256,15 @@ public class EncryptionOptionsEqualityTest
EncryptionOptions.ServerEncryptionOptions encryptionOptions1 = createServerEncryptionOptions();
EncryptionOptions.ServerEncryptionOptions encryptionOptions2 = createServerEncryptionOptions();
encryptionOptions1 = encryptionOptions1
encryptionOptions1 = new EncryptionOptions.ServerEncryptionOptions.Builder(encryptionOptions1)
.withKeyStore("test/conf/cassandra1.keystore")
.withKeyStorePassword("cassandra1");
.withKeyStorePassword("cassandra1")
.build();
encryptionOptions2 = encryptionOptions2
encryptionOptions2 = new EncryptionOptions.ServerEncryptionOptions.Builder(encryptionOptions2)
.withKeyStore("test/conf/cassandra2.keystore")
.withKeyStorePassword("cassandra2");
.withKeyStorePassword("cassandra2")
.build();
assertNotEquals(encryptionOptions1, encryptionOptions2);
assertNotEquals(encryptionOptions1.hashCode(), encryptionOptions2.hashCode());

View File

@ -23,11 +23,11 @@ import java.util.HashMap;
import java.util.Map;
import com.google.common.collect.ImmutableMap;
import org.apache.cassandra.io.util.File;
import org.junit.Assert;
import org.junit.Test;
import org.apache.cassandra.exceptions.ConfigurationException;
import org.apache.cassandra.io.util.File;
import org.assertj.core.api.Assertions;
import org.yaml.snakeyaml.constructor.ConstructorException;
@ -46,11 +46,11 @@ public class EncryptionOptionsTest
{
static class EncryptionOptionsTestCase
{
final EncryptionOptions encryptionOptions;
final EncryptionOptions.ClientEncryptionOptions encryptionOptions;
final EncryptionOptions.TlsEncryptionPolicy expected;
final String description;
public EncryptionOptionsTestCase(EncryptionOptions encryptionOptions, EncryptionOptions.TlsEncryptionPolicy expected, String description)
public EncryptionOptionsTestCase(EncryptionOptions.ClientEncryptionOptions encryptionOptions, EncryptionOptions.TlsEncryptionPolicy expected, String description)
{
this.encryptionOptions = encryptionOptions;
this.expected = expected;
@ -59,25 +59,25 @@ public class EncryptionOptionsTest
public static EncryptionOptionsTestCase of(Boolean optional, String keystorePath, Boolean enabled, EncryptionOptions.TlsEncryptionPolicy expected)
{
return new EncryptionOptionsTestCase(new EncryptionOptions(new ParameterizedClass("org.apache.cassandra.security.DefaultSslContextFactory",
new HashMap<>()),
keystorePath, "dummypass", null,
"dummytruststore", "dummypass", null,
Collections.emptyList(), null, null, null, "JKS", "false", false, enabled, optional, null, null)
return new EncryptionOptionsTestCase(new EncryptionOptions.ClientEncryptionOptions(new ParameterizedClass("org.apache.cassandra.security.DefaultSslContextFactory",
new HashMap<>()),
keystorePath, "dummypass", null,
"dummytruststore", "dummypass", null,
Collections.emptyList(), null, null, null, "JKS", "false", false, enabled, optional, null, null)
.applyConfig(),
expected,
String.format("optional=%s keystore=%s enabled=%s", optional, keystorePath, enabled));
}
public static EncryptionOptionsTestCase of(Boolean optional, String keystorePath, Boolean enabled,
Map<String,String> customSslContextFactoryParams,
Map<String, String> customSslContextFactoryParams,
EncryptionOptions.TlsEncryptionPolicy expected)
{
return new EncryptionOptionsTestCase(new EncryptionOptions(new ParameterizedClass("org.apache.cassandra.security.DefaultSslContextFactory",
customSslContextFactoryParams),
keystorePath, "dummypass", null,
"dummytruststore", "dummypass", null,
Collections.emptyList(), null, null, null, "JKS", "false", false, enabled, optional, null, null)
return new EncryptionOptionsTestCase(new EncryptionOptions.ClientEncryptionOptions(new ParameterizedClass("org.apache.cassandra.security.DefaultSslContextFactory",
customSslContextFactoryParams),
keystorePath, "dummypass", null,
"dummytruststore", "dummypass", null,
Collections.emptyList(), null, null, null, "JKS", "false", false, enabled, optional, null, null)
.applyConfig(),
expected,
String.format("optional=%s keystore=%s enabled=%s", optional, keystorePath, enabled));
@ -87,15 +87,15 @@ public class EncryptionOptionsTest
static final String absentKeystore = "test/conf/missing-keystore-is-not-here";
static final String presentKeystore = "test/conf/keystore.jks";
final EncryptionOptionsTestCase[] encryptionOptionTestCases = {
// Optional Keystore Enabled Expected
EncryptionOptionsTestCase.of(null, absentKeystore, false, UNENCRYPTED),
EncryptionOptionsTestCase.of(null, absentKeystore, true, ENCRYPTED),
EncryptionOptionsTestCase.of(null, presentKeystore, false, OPTIONAL),
EncryptionOptionsTestCase.of(null, presentKeystore, true, ENCRYPTED),
EncryptionOptionsTestCase.of(false, absentKeystore, false, UNENCRYPTED),
EncryptionOptionsTestCase.of(false, absentKeystore, true, ENCRYPTED),
EncryptionOptionsTestCase.of(true, presentKeystore, false, OPTIONAL),
EncryptionOptionsTestCase.of(true, presentKeystore, true, OPTIONAL)
// Optional Keystore Enabled Expected
EncryptionOptionsTestCase.of(null, absentKeystore, false, UNENCRYPTED),
EncryptionOptionsTestCase.of(null, absentKeystore, true, ENCRYPTED),
EncryptionOptionsTestCase.of(null, presentKeystore, false, OPTIONAL),
EncryptionOptionsTestCase.of(null, presentKeystore, true, ENCRYPTED),
EncryptionOptionsTestCase.of(false, absentKeystore, false, UNENCRYPTED),
EncryptionOptionsTestCase.of(false, absentKeystore, true, ENCRYPTED),
EncryptionOptionsTestCase.of(true, presentKeystore, false, OPTIONAL),
EncryptionOptionsTestCase.of(true, presentKeystore, true, OPTIONAL)
};
@Test
@ -111,11 +111,11 @@ public class EncryptionOptionsTest
static class ServerEncryptionOptionsTestCase
{
final EncryptionOptions encryptionOptions;
final EncryptionOptions.ServerEncryptionOptions encryptionOptions;
final EncryptionOptions.TlsEncryptionPolicy expected;
final String description;
public ServerEncryptionOptionsTestCase(EncryptionOptions encryptionOptions, EncryptionOptions.TlsEncryptionPolicy expected, String description)
public ServerEncryptionOptionsTestCase(EncryptionOptions.ServerEncryptionOptions encryptionOptions, EncryptionOptions.TlsEncryptionPolicy expected, String description)
{
this.encryptionOptions = encryptionOptions;
this.expected = expected;
@ -131,10 +131,10 @@ public class EncryptionOptionsTest
keystorePath, "dummypass", null,
keystorePath, "dummypass", null,
"dummytruststore", "dummypass", null,
Collections.emptyList(), null, null, null, "JKS", "false", false, optional, internodeEncryption, false, null, null)
Collections.emptyList(), null, null, null, "JKS", "false", false, optional, internodeEncryption, false, null, null)
.applyConfig(),
expected,
String.format("optional=%s keystore=%s internode=%s", optional, keystorePath, internodeEncryption));
expected,
String.format("optional=%s keystore=%s internode=%s", optional, keystorePath, internodeEncryption));
}
}
@ -143,8 +143,8 @@ public class EncryptionOptionsTest
{
Map<String, Object> yaml = ImmutableMap.of(
"server_encryption_options", ImmutableMap.of(
"isEnabled", false
)
"isEnabled", false
)
);
Assertions.assertThatThrownBy(() -> YamlConfigurationLoader.fromMap(yaml, Config.class))
@ -157,8 +157,8 @@ public class EncryptionOptionsTest
{
Map<String, Object> yaml = ImmutableMap.of(
"server_encryption_options", ImmutableMap.of(
"isOptional", false
)
"isOptional", false
)
);
Assertions.assertThatThrownBy(() -> YamlConfigurationLoader.fromMap(yaml, Config.class))
@ -171,11 +171,11 @@ public class EncryptionOptionsTest
{
Map<String, Object> yaml = ImmutableMap.of(
"server_encryption_options", ImmutableMap.of(
"max_certificate_validity_period", "2d"
),
"max_certificate_validity_period", "2d"
),
"client_encryption_options", ImmutableMap.of(
"max_certificate_validity_period", "10d"
)
"max_certificate_validity_period", "10d"
)
);
Config config = YamlConfigurationLoader.fromMap(yaml, Config.class);
@ -188,8 +188,8 @@ public class EncryptionOptionsTest
{
Map<String, Object> yaml = ImmutableMap.of(
"server_encryption_options", ImmutableMap.of(
"max_certificate_validity_period", "not-a-valid-input"
)
"max_certificate_validity_period", "not-a-valid-input"
)
);
Assertions.assertThatThrownBy(() -> YamlConfigurationLoader.fromMap(yaml, Config.class))
@ -202,8 +202,8 @@ public class EncryptionOptionsTest
{
Map<String, Object> yaml = ImmutableMap.of(
"server_encryption_options", ImmutableMap.of(
"max_certificate_validity_period", "-2d"
)
"max_certificate_validity_period", "-2d"
)
);
Assertions.assertThatThrownBy(() -> YamlConfigurationLoader.fromMap(yaml, Config.class))
@ -213,26 +213,26 @@ public class EncryptionOptionsTest
final ServerEncryptionOptionsTestCase[] serverEncryptionOptionTestCases = {
// Optional Keystore Internode Expected
ServerEncryptionOptionsTestCase.of(null, absentKeystore, none, UNENCRYPTED),
ServerEncryptionOptionsTestCase.of(null, absentKeystore, rack, OPTIONAL),
ServerEncryptionOptionsTestCase.of(null, absentKeystore, dc, OPTIONAL),
ServerEncryptionOptionsTestCase.of(null, absentKeystore, all, ENCRYPTED),
// Optional Keystore Internode Expected
ServerEncryptionOptionsTestCase.of(null, absentKeystore, none, UNENCRYPTED),
ServerEncryptionOptionsTestCase.of(null, absentKeystore, rack, OPTIONAL),
ServerEncryptionOptionsTestCase.of(null, absentKeystore, dc, OPTIONAL),
ServerEncryptionOptionsTestCase.of(null, absentKeystore, all, ENCRYPTED),
ServerEncryptionOptionsTestCase.of(null, presentKeystore, none, OPTIONAL),
ServerEncryptionOptionsTestCase.of(null, presentKeystore, rack, OPTIONAL),
ServerEncryptionOptionsTestCase.of(null, absentKeystore, dc, OPTIONAL),
ServerEncryptionOptionsTestCase.of(null, absentKeystore, all, ENCRYPTED),
ServerEncryptionOptionsTestCase.of(null, presentKeystore, none, OPTIONAL),
ServerEncryptionOptionsTestCase.of(null, presentKeystore, rack, OPTIONAL),
ServerEncryptionOptionsTestCase.of(null, absentKeystore, dc, OPTIONAL),
ServerEncryptionOptionsTestCase.of(null, absentKeystore, all, ENCRYPTED),
ServerEncryptionOptionsTestCase.of(false, absentKeystore, none, UNENCRYPTED),
ServerEncryptionOptionsTestCase.of(false, absentKeystore, rack, OPTIONAL),
ServerEncryptionOptionsTestCase.of(false, absentKeystore, dc, OPTIONAL),
ServerEncryptionOptionsTestCase.of(false, absentKeystore, all, ENCRYPTED),
ServerEncryptionOptionsTestCase.of(false, absentKeystore, none, UNENCRYPTED),
ServerEncryptionOptionsTestCase.of(false, absentKeystore, rack, OPTIONAL),
ServerEncryptionOptionsTestCase.of(false, absentKeystore, dc, OPTIONAL),
ServerEncryptionOptionsTestCase.of(false, absentKeystore, all, ENCRYPTED),
ServerEncryptionOptionsTestCase.of(true, presentKeystore, none, OPTIONAL),
ServerEncryptionOptionsTestCase.of(true, presentKeystore, rack, OPTIONAL),
ServerEncryptionOptionsTestCase.of(true, absentKeystore, dc, OPTIONAL),
ServerEncryptionOptionsTestCase.of(true, absentKeystore, all, OPTIONAL),
ServerEncryptionOptionsTestCase.of(true, presentKeystore, none, OPTIONAL),
ServerEncryptionOptionsTestCase.of(true, presentKeystore, rack, OPTIONAL),
ServerEncryptionOptionsTestCase.of(true, absentKeystore, dc, OPTIONAL),
ServerEncryptionOptionsTestCase.of(true, absentKeystore, all, OPTIONAL),
};
@Test
@ -246,12 +246,12 @@ public class EncryptionOptionsTest
}
}
@Test(expected = IllegalArgumentException.class)
@Test(expected = IllegalArgumentException.class)
public void testMisplacedConfigKey()
{
Map<String, String> customSslContextFactoryParams = new HashMap<>();
for(EncryptionOptions.ConfigKey configKey: EncryptionOptions.ConfigKey.values())
for (EncryptionOptions.ConfigKey configKey : EncryptionOptions.ConfigKey.values())
{
customSslContextFactoryParams.put(configKey.toString(), "my-custom-value");
}

View File

@ -663,13 +663,15 @@ public abstract class CQLTester
public static void requireNativeProtocolClientEncryption()
{
DatabaseDescriptor.updateNativeProtocolEncryptionOptions((encryptionOptions) ->
encryptionOptions.withEnabled(true)
.withKeyStore(TlsTestUtils.SERVER_KEYSTORE_PATH)
.withKeyStorePassword(TlsTestUtils.SERVER_KEYSTORE_PASSWORD)
.withTrustStore(TlsTestUtils.SERVER_TRUSTSTORE_PATH)
.withTrustStorePassword(TlsTestUtils.SERVER_TRUSTSTORE_PASSWORD)
.withRequireEndpointVerification(false)
.withRequireClientAuth(EncryptionOptions.ClientAuth.OPTIONAL));
new EncryptionOptions.ClientEncryptionOptions.Builder(encryptionOptions)
.withEnabled(true)
.withKeyStore(TlsTestUtils.SERVER_KEYSTORE_PATH)
.withKeyStorePassword(TlsTestUtils.SERVER_KEYSTORE_PASSWORD)
.withTrustStore(TlsTestUtils.SERVER_TRUSTSTORE_PATH)
.withTrustStorePassword(TlsTestUtils.SERVER_TRUSTSTORE_PASSWORD)
.withRequireEndpointVerification(false)
.withRequireClientAuth(EncryptionOptions.ClientEncryptionOptions.ClientAuth.OPTIONAL)
.build());
}
/**
@ -1691,7 +1693,7 @@ public abstract class CQLTester
protected SimpleClient newSimpleClient(ProtocolVersion version) throws IOException
{
return new SimpleClient(nativeAddr.getHostAddress(), nativePort, version, version.isBeta(), new EncryptionOptions().applyConfig())
return new SimpleClient(nativeAddr.getHostAddress(), nativePort, version, version.isBeta(), new EncryptionOptions.ClientEncryptionOptions())
.connect(false, false);
}

View File

@ -31,6 +31,7 @@ import com.datastax.driver.core.ResultSet;
import com.datastax.driver.core.Row;
import org.apache.cassandra.config.Config;
import org.apache.cassandra.config.DurationSpec;
import org.apache.cassandra.config.EncryptionOptions.ServerEncryptionOptions.Builder;
import org.apache.cassandra.config.EncryptionOptions.ServerEncryptionOptions.InternodeEncryption;
import org.apache.cassandra.config.JMXServerOptions;
import org.apache.cassandra.config.ParameterizedClass;
@ -38,7 +39,7 @@ import org.apache.cassandra.cql3.CQLTester;
import org.apache.cassandra.security.SSLFactory;
import org.yaml.snakeyaml.introspector.Property;
import static org.apache.cassandra.config.EncryptionOptions.ClientAuth.REQUIRED;
import static org.apache.cassandra.config.EncryptionOptions.ClientEncryptionOptions.ClientAuth.REQUIRED;
public class SettingsTableTest extends CQLTester
{
@ -176,52 +177,53 @@ public class SettingsTableTest extends CQLTester
List<String> expectedNames = SettingsTable.PROPERTIES.keySet().stream().filter(n -> n.startsWith("server_encryption")).collect(Collectors.toList());
Assert.assertEquals(expectedNames.size(), executeNet(all).all().size());
Builder serverEncryptionOptionsBuilder = new Builder(config.server_encryption_options);
check(pre + "algorithm", null);
config.server_encryption_options = config.server_encryption_options.withAlgorithm("SUPERSSL");
config.server_encryption_options = serverEncryptionOptionsBuilder.withAlgorithm("SUPERSSL").build();
check(pre + "algorithm", "SUPERSSL");
check(pre + "cipher_suites", null);
config.server_encryption_options = config.server_encryption_options.withCipherSuites("c1", "c2");
config.server_encryption_options = serverEncryptionOptionsBuilder.withCipherSuites("c1", "c2").build();
check(pre + "cipher_suites", "[c1, c2]");
// name doesn't match yaml
check(pre + "protocol", null);
config.server_encryption_options = config.server_encryption_options.withProtocol("TLSv5");
config.server_encryption_options = serverEncryptionOptionsBuilder.withProtocol("TLSv5").build();
check(pre + "protocol", "[TLSv5]");
config.server_encryption_options = config.server_encryption_options.withProtocol("TLS");
config.server_encryption_options = serverEncryptionOptionsBuilder.withProtocol("TLS").build();
check(pre + "protocol", SSLFactory.tlsInstanceProtocolSubstitution().toString());
config.server_encryption_options = config.server_encryption_options.withProtocol("TLS");
config.server_encryption_options = config.server_encryption_options.withAcceptedProtocols(ImmutableList.of("TLSv1.2","TLSv1.1"));
config.server_encryption_options = serverEncryptionOptionsBuilder.withProtocol("TLS").build();
config.server_encryption_options = serverEncryptionOptionsBuilder.withAcceptedProtocols(ImmutableList.of("TLSv1.2","TLSv1.1")).build();
check(pre + "protocol", "[TLSv1.2, TLSv1.1]");
config.server_encryption_options = config.server_encryption_options.withProtocol("TLSv2");
config.server_encryption_options = config.server_encryption_options.withAcceptedProtocols(ImmutableList.of("TLSv1.2","TLSv1.1"));
config.server_encryption_options = serverEncryptionOptionsBuilder.withProtocol("TLSv2").build();
config.server_encryption_options = serverEncryptionOptionsBuilder.withAcceptedProtocols(ImmutableList.of("TLSv1.2","TLSv1.1")).build();
check(pre + "protocol", "[TLSv1.2, TLSv1.1, TLSv2]"); // protocol goes after the explicit accept list if non-TLS
check(pre + "optional", "false");
config.server_encryption_options = config.server_encryption_options.withOptional(true);
config.server_encryption_options = serverEncryptionOptionsBuilder.withOptional(true).build();
check(pre + "optional", "true");
// name doesn't match yaml
check(pre + "client_auth", "false");
config.server_encryption_options = config.server_encryption_options.withRequireClientAuth(REQUIRED);
config.server_encryption_options = serverEncryptionOptionsBuilder.withRequireClientAuth(REQUIRED).build();
check(pre + "client_auth", "true");
// name doesn't match yaml
check(pre + "endpoint_verification", "false");
config.server_encryption_options = config.server_encryption_options.withRequireEndpointVerification(true);
config.server_encryption_options = serverEncryptionOptionsBuilder.withRequireEndpointVerification(true).build();
check(pre + "endpoint_verification", "true");
check(pre + "internode_encryption", "none");
config.server_encryption_options = config.server_encryption_options.withInternodeEncryption(InternodeEncryption.all);
config.server_encryption_options = serverEncryptionOptionsBuilder.withInternodeEncryption(InternodeEncryption.all).build();
check(pre + "internode_encryption", "all");
check(pre + "enabled", "true");
// name doesn't match yaml
check(pre + "legacy_ssl_storage_port", "false");
config.server_encryption_options = config.server_encryption_options.withLegacySslStoragePort(true);
config.server_encryption_options = serverEncryptionOptionsBuilder.withLegacySslStoragePort(true).build();
check(pre + "legacy_ssl_storage_port", "true");
}

View File

@ -57,6 +57,7 @@ import io.netty.channel.ChannelOutboundHandlerAdapter;
import io.netty.channel.ChannelPromise;
import org.apache.cassandra.config.DatabaseDescriptor;
import org.apache.cassandra.config.EncryptionOptions;
import org.apache.cassandra.config.EncryptionOptions.ServerEncryptionOptions.Builder;
import org.apache.cassandra.db.commitlog.CommitLog;
import org.apache.cassandra.distributed.test.log.ClusterMetadataTestHelper;
import org.apache.cassandra.exceptions.RequestFailure;
@ -72,7 +73,7 @@ import org.apache.cassandra.utils.FBUtilities;
import static java.util.concurrent.TimeUnit.MILLISECONDS;
import static java.util.concurrent.TimeUnit.MINUTES;
import static java.util.concurrent.TimeUnit.SECONDS;
import static org.apache.cassandra.config.EncryptionOptions.ClientAuth.NOT_REQUIRED;
import static org.apache.cassandra.config.EncryptionOptions.ClientEncryptionOptions.ClientAuth.NOT_REQUIRED;
import static org.apache.cassandra.net.MessagingService.VERSION_40;
import static org.apache.cassandra.net.NoPayload.noPayload;
import static org.apache.cassandra.net.MessagingService.current_version;
@ -176,17 +177,18 @@ public class ConnectionTest
}
}
static final EncryptionOptions.ServerEncryptionOptions encryptionOptions =
new EncryptionOptions.ServerEncryptionOptions()
static final EncryptionOptions.Builder<EncryptionOptions.ServerEncryptionOptions> encryptionOptionsBuilder =
new Builder()
.withLegacySslStoragePort(true)
.withOptional(true)
.withInternodeEncryption(EncryptionOptions.ServerEncryptionOptions.InternodeEncryption.all)
.withOptional(true)
.withKeyStore(TlsTestUtils.SERVER_KEYSTORE_PATH)
.withKeyStorePassword(TlsTestUtils.SERVER_KEYSTORE_PASSWORD)
.withTrustStore(TlsTestUtils.SERVER_TRUSTSTORE_PATH)
.withTrustStorePassword(TlsTestUtils.SERVER_TRUSTSTORE_PASSWORD)
.withRequireClientAuth(NOT_REQUIRED)
.withCipherSuites("TLS_RSA_WITH_AES_128_CBC_SHA");
static final EncryptionOptions.ServerEncryptionOptions encryptionOptions = encryptionOptionsBuilder.build();
static final List<Function<Settings, Settings>> MODIFIERS = ImmutableList.of(
settings -> settings.outbound(outbound -> outbound.withEncryption(encryptionOptions))

View File

@ -39,6 +39,7 @@ import io.netty.channel.EventLoop;
import io.netty.util.concurrent.Future;
import org.apache.cassandra.config.DatabaseDescriptor;
import org.apache.cassandra.config.EncryptionOptions.ServerEncryptionOptions;
import org.apache.cassandra.config.EncryptionOptions.ServerEncryptionOptions.Builder;
import org.apache.cassandra.config.ParameterizedClass;
import org.apache.cassandra.db.commitlog.CommitLog;
import org.apache.cassandra.distributed.test.log.ClusterMetadataTestHelper;
@ -49,9 +50,9 @@ import org.apache.cassandra.security.DefaultSslContextFactory;
import org.apache.cassandra.transport.TlsTestUtils;
import org.apache.cassandra.utils.concurrent.AsyncPromise;
import static org.apache.cassandra.config.EncryptionOptions.ClientEncryptionOptions.ClientAuth.NOT_REQUIRED;
import static org.apache.cassandra.config.EncryptionOptions.ClientEncryptionOptions.ClientAuth.REQUIRED;
import static org.apache.cassandra.net.ConnectionType.SMALL_MESSAGES;
import static org.apache.cassandra.config.EncryptionOptions.ClientAuth.NOT_REQUIRED;
import static org.apache.cassandra.config.EncryptionOptions.ClientAuth.REQUIRED;
import static org.apache.cassandra.net.MessagingService.current_version;
import static org.apache.cassandra.net.MessagingService.minimum_version;
import static org.apache.cassandra.net.OutboundConnectionInitiator.Result;
@ -279,26 +280,28 @@ public class HandshakeTest
private ServerEncryptionOptions getServerEncryptionOptions(SslFallbackConnectionType sslConnectionType, boolean optional)
{
ServerEncryptionOptions serverEncryptionOptions = new ServerEncryptionOptions().withOptional(optional)
.withKeyStore(TlsTestUtils.SERVER_KEYSTORE_PATH)
.withKeyStorePassword(TlsTestUtils.SERVER_KEYSTORE_PASSWORD)
.withOutboundKeystore(TlsTestUtils.SERVER_OUTBOUND_KEYSTORE_PATH)
.withOutboundKeystorePassword(TlsTestUtils.SERVER_OUTBOUND_KEYSTORE_PASSWORD)
.withTrustStore(TlsTestUtils.SERVER_TRUSTSTORE_PATH)
.withTrustStorePassword(TlsTestUtils.SERVER_TRUSTSTORE_PASSWORD)
.withSslContextFactory((new ParameterizedClass(DefaultSslContextFactory.class.getName(),
new HashMap<>())));
Builder serverEncryptionOptionsBuilder = new Builder();
serverEncryptionOptionsBuilder.withOutboundKeystore(TlsTestUtils.SERVER_OUTBOUND_KEYSTORE_PATH)
.withOutboundKeystorePassword(TlsTestUtils.SERVER_OUTBOUND_KEYSTORE_PASSWORD)
.withOptional(optional)
.withKeyStore(TlsTestUtils.SERVER_KEYSTORE_PATH)
.withKeyStorePassword(TlsTestUtils.SERVER_KEYSTORE_PASSWORD)
.withTrustStore(TlsTestUtils.SERVER_TRUSTSTORE_PATH).withTrustStorePassword(TlsTestUtils.SERVER_TRUSTSTORE_PASSWORD)
.withSslContextFactory((new ParameterizedClass(DefaultSslContextFactory.class.getName(),
new HashMap<>())));
if (sslConnectionType == SslFallbackConnectionType.MTLS)
{
serverEncryptionOptions = serverEncryptionOptions.withInternodeEncryption(ServerEncryptionOptions.InternodeEncryption.all)
.withRequireClientAuth(REQUIRED);
serverEncryptionOptionsBuilder.withInternodeEncryption(ServerEncryptionOptions.InternodeEncryption.all)
.withRequireClientAuth(REQUIRED);
}
else if (sslConnectionType == SslFallbackConnectionType.SSL)
{
serverEncryptionOptions = serverEncryptionOptions.withInternodeEncryption(ServerEncryptionOptions.InternodeEncryption.all)
.withRequireClientAuth(NOT_REQUIRED);
serverEncryptionOptionsBuilder.withInternodeEncryption(ServerEncryptionOptions.InternodeEncryption.all)
.withRequireClientAuth(NOT_REQUIRED);
}
return serverEncryptionOptions;
return serverEncryptionOptionsBuilder.build();
}
private InboundSockets getInboundSocket(ServerEncryptionOptions serverEncryptionOptions)

View File

@ -50,6 +50,7 @@ import com.codahale.metrics.Timer;
import org.apache.cassandra.auth.IInternodeAuthenticator;
import org.apache.cassandra.config.DatabaseDescriptor;
import org.apache.cassandra.config.EncryptionOptions.ServerEncryptionOptions;
import org.apache.cassandra.config.EncryptionOptions.ServerEncryptionOptions.Builder;
import org.apache.cassandra.db.commitlog.CommitLog;
import org.apache.cassandra.distributed.test.log.ClusterMetadataTestHelper;
import org.apache.cassandra.exceptions.ConfigurationException;
@ -257,8 +258,7 @@ public class MessagingServiceTest
public void testFailedOutboundInternodeAuth() throws Exception
{
// Listen on serverside for connections
ServerEncryptionOptions serverEncryptionOptions = new ServerEncryptionOptions()
.withInternodeEncryption(ServerEncryptionOptions.InternodeEncryption.none);
ServerEncryptionOptions serverEncryptionOptions = new Builder().withInternodeEncryption(ServerEncryptionOptions.InternodeEncryption.none).build();
DatabaseDescriptor.setInternodeAuthenticator(REJECT_OUTBOUND_AUTHENTICATOR);
InetAddress listenAddress = FBUtilities.getJustLocalAddress();
@ -293,8 +293,7 @@ public class MessagingServiceTest
@Test
public void testFailedInboundInternodeAuth() throws IOException, InterruptedException
{
ServerEncryptionOptions serverEncryptionOptions = new ServerEncryptionOptions()
.withInternodeEncryption(ServerEncryptionOptions.InternodeEncryption.none);
ServerEncryptionOptions serverEncryptionOptions = new Builder().withInternodeEncryption(ServerEncryptionOptions.InternodeEncryption.none).build();
DatabaseDescriptor.setInternodeAuthenticator(ALLOW_NOTHING_AUTHENTICATOR);
InetAddress listenAddress = FBUtilities.getJustLocalAddress();
@ -348,56 +347,54 @@ public class MessagingServiceTest
@Test
public void listenPlainConnection() throws InterruptedException
{
ServerEncryptionOptions serverEncryptionOptions = new ServerEncryptionOptions()
.withInternodeEncryption(ServerEncryptionOptions.InternodeEncryption.none);
ServerEncryptionOptions serverEncryptionOptions = new Builder().withInternodeEncryption(ServerEncryptionOptions.InternodeEncryption.none).build();
listen(serverEncryptionOptions, false);
}
@Test
public void listenPlainConnectionWithBroadcastAddr() throws InterruptedException
{
ServerEncryptionOptions serverEncryptionOptions = new ServerEncryptionOptions()
.withInternodeEncryption(ServerEncryptionOptions.InternodeEncryption.none);
ServerEncryptionOptions serverEncryptionOptions = new Builder().withInternodeEncryption(ServerEncryptionOptions.InternodeEncryption.none).build();
listen(serverEncryptionOptions, true);
}
@Test
public void listenRequiredSecureConnection() throws InterruptedException
{
ServerEncryptionOptions serverEncryptionOptions = new ServerEncryptionOptions()
.withOptional(false)
.withInternodeEncryption(ServerEncryptionOptions.InternodeEncryption.all)
.withLegacySslStoragePort(false);
ServerEncryptionOptions serverEncryptionOptions = new Builder().withInternodeEncryption(ServerEncryptionOptions.InternodeEncryption.all)
.withLegacySslStoragePort(false)
.withOptional(false)
.build();
listen(serverEncryptionOptions, false);
}
@Test
public void listenRequiredSecureConnectionWithBroadcastAddr() throws InterruptedException
{
ServerEncryptionOptions serverEncryptionOptions = new ServerEncryptionOptions()
.withOptional(false)
.withInternodeEncryption(ServerEncryptionOptions.InternodeEncryption.all)
.withLegacySslStoragePort(false);
ServerEncryptionOptions serverEncryptionOptions = new Builder().withInternodeEncryption(ServerEncryptionOptions.InternodeEncryption.all)
.withLegacySslStoragePort(false)
.withOptional(false)
.build();
listen(serverEncryptionOptions, true);
}
@Test
public void listenRequiredSecureConnectionWithLegacyPort() throws InterruptedException
{
ServerEncryptionOptions serverEncryptionOptions = new ServerEncryptionOptions()
.withInternodeEncryption(ServerEncryptionOptions.InternodeEncryption.all)
.withOptional(false)
.withLegacySslStoragePort(true);
ServerEncryptionOptions serverEncryptionOptions = new Builder().withInternodeEncryption(ServerEncryptionOptions.InternodeEncryption.all)
.withLegacySslStoragePort(true)
.withOptional(false)
.build();
listen(serverEncryptionOptions, false);
}
@Test
public void listenRequiredSecureConnectionWithBroadcastAddrAndLegacyPort() throws InterruptedException
{
ServerEncryptionOptions serverEncryptionOptions = new ServerEncryptionOptions()
.withInternodeEncryption(ServerEncryptionOptions.InternodeEncryption.all)
.withOptional(false)
.withLegacySslStoragePort(true);
ServerEncryptionOptions serverEncryptionOptions = new Builder().withInternodeEncryption(ServerEncryptionOptions.InternodeEncryption.all)
.withLegacySslStoragePort(true)
.withOptional(false)
.build();
listen(serverEncryptionOptions, true);
}
@ -406,8 +403,7 @@ public class MessagingServiceTest
{
for (int i = 0; i < 500; i++) // test used to be flaky, so run in a loop to make sure stable (see CASSANDRA-17033)
{
ServerEncryptionOptions serverEncryptionOptions = new ServerEncryptionOptions()
.withOptional(true);
ServerEncryptionOptions serverEncryptionOptions = new Builder().withOptional(true).build();
listen(serverEncryptionOptions, false);
}
}
@ -415,8 +411,7 @@ public class MessagingServiceTest
@Test
public void listenOptionalSecureConnectionWithBroadcastAddr() throws InterruptedException
{
ServerEncryptionOptions serverEncryptionOptions = new ServerEncryptionOptions()
.withOptional(true);
ServerEncryptionOptions serverEncryptionOptions = new Builder().withOptional(true).build();
listen(serverEncryptionOptions, true);
}

View File

@ -33,17 +33,17 @@ import io.netty.handler.ssl.OpenSslContext;
import io.netty.handler.ssl.SslContext;
import io.netty.handler.ssl.SslProvider;
import org.apache.cassandra.config.EncryptionOptions;
import org.apache.cassandra.config.EncryptionOptions.ServerEncryptionOptions.Builder;
import org.apache.cassandra.distributed.shared.WithProperties;
import org.apache.cassandra.transport.TlsTestUtils;
import static org.apache.cassandra.config.CassandraRelevantProperties.DISABLE_TCACTIVE_OPENSSL;
import static org.apache.cassandra.config.EncryptionOptions.ClientAuth.NOT_REQUIRED;
import static org.apache.cassandra.config.EncryptionOptions.ClientAuth.REQUIRED;
import static org.apache.cassandra.config.EncryptionOptions.ClientEncryptionOptions.ClientAuth.NOT_REQUIRED;
import static org.apache.cassandra.config.EncryptionOptions.ClientEncryptionOptions.ClientAuth.REQUIRED;
public class DefaultSslContextFactoryTest
{
private Map<String,Object> commonConfig = new HashMap<>();
private Map<String, Object> commonConfig = new HashMap<>();
@Before
public void setup()
@ -54,7 +54,7 @@ public class DefaultSslContextFactoryTest
commonConfig.put("cipher_suites", Arrays.asList("TLS_RSA_WITH_AES_128_CBC_SHA"));
}
private void addKeystoreOptions(Map<String,Object> config)
private void addKeystoreOptions(Map<String, Object> config)
{
config.put("keystore", TlsTestUtils.SERVER_KEYSTORE_PATH);
config.put("keystore_password", TlsTestUtils.SERVER_KEYSTORE_PASSWORD);
@ -69,14 +69,18 @@ public class DefaultSslContextFactoryTest
@Test
public void getSslContextOpenSSL() throws IOException
{
EncryptionOptions.ServerEncryptionOptions options = new EncryptionOptions.ServerEncryptionOptions().withTrustStore(TlsTestUtils.SERVER_TRUSTSTORE_PATH)
.withTrustStorePassword(TlsTestUtils.SERVER_TRUSTSTORE_PASSWORD)
.withKeyStore(TlsTestUtils.SERVER_KEYSTORE_PATH)
.withKeyStorePassword(TlsTestUtils.SERVER_KEYSTORE_PASSWORD)
.withOutboundKeystore(TlsTestUtils.SERVER_OUTBOUND_KEYSTORE_PATH)
.withOutboundKeystorePassword(TlsTestUtils.SERVER_OUTBOUND_KEYSTORE_PASSWORD)
.withRequireClientAuth(NOT_REQUIRED)
.withCipherSuites("TLS_RSA_WITH_AES_128_CBC_SHA");
EncryptionOptions.ServerEncryptionOptions.Builder builder = new Builder();
EncryptionOptions.ServerEncryptionOptions options = builder
.withOutboundKeystore(TlsTestUtils.SERVER_OUTBOUND_KEYSTORE_PATH)
.withOutboundKeystorePassword(TlsTestUtils.SERVER_OUTBOUND_KEYSTORE_PASSWORD)
.withTrustStore(TlsTestUtils.SERVER_TRUSTSTORE_PATH)
.withTrustStorePassword(TlsTestUtils.SERVER_TRUSTSTORE_PASSWORD)
.withKeyStore(TlsTestUtils.SERVER_KEYSTORE_PATH)
.withKeyStorePassword(TlsTestUtils.SERVER_KEYSTORE_PASSWORD)
.withRequireClientAuth(NOT_REQUIRED)
.withCipherSuites("TLS_RSA_WITH_AES_128_CBC_SHA")
.build();
SslContext sslContext = SSLFactory.getOrCreateSslContext(options, REQUIRED, ISslContextFactory.SocketType.CLIENT, "test");
Assert.assertNotNull(sslContext);
if (OpenSsl.isAvailable())
@ -88,7 +92,7 @@ public class DefaultSslContextFactoryTest
@Test(expected = IOException.class)
public void buildTrustManagerFactoryWithInvalidTruststoreFile() throws IOException
{
Map<String,Object> config = new HashMap<>();
Map<String, Object> config = new HashMap<>();
config.putAll(commonConfig);
config.put("truststore", "/this/is/probably/not/a/file/on/your/test/machine");
@ -100,7 +104,7 @@ public class DefaultSslContextFactoryTest
@Test(expected = IOException.class)
public void buildTrustManagerFactoryWithBadPassword() throws IOException
{
Map<String,Object> config = new HashMap<>();
Map<String, Object> config = new HashMap<>();
config.putAll(commonConfig);
config.put("truststore_password", "HomeOfBadPasswords");
@ -112,7 +116,7 @@ public class DefaultSslContextFactoryTest
@Test
public void buildTrustManagerFactoryHappyPath() throws IOException
{
Map<String,Object> config = new HashMap<>();
Map<String, Object> config = new HashMap<>();
config.putAll(commonConfig);
DefaultSslContextFactory defaultSslContextFactoryImpl = new DefaultSslContextFactory(config);
@ -124,7 +128,7 @@ public class DefaultSslContextFactoryTest
@Test(expected = IOException.class)
public void buildKeyManagerFactoryWithInvalidKeystoreFile() throws IOException
{
Map<String,Object> config = new HashMap<>();
Map<String, Object> config = new HashMap<>();
config.putAll(commonConfig);
config.put("keystore", "/this/is/probably/not/a/file/on/your/test/machine");
config.put("keystore_password", "ThisWontMatter");
@ -137,7 +141,7 @@ public class DefaultSslContextFactoryTest
@Test(expected = IOException.class)
public void buildKeyManagerFactoryWithBadPassword() throws IOException
{
Map<String,Object> config = new HashMap<>();
Map<String, Object> config = new HashMap<>();
config.putAll(commonConfig);
addKeystoreOptions(config);
config.put("keystore_password", "HomeOfBadPasswords");
@ -149,7 +153,7 @@ public class DefaultSslContextFactoryTest
@Test
public void buildKeyManagerFactoryHappyPath() throws IOException
{
Map<String,Object> config = new HashMap<>();
Map<String, Object> config = new HashMap<>();
config.putAll(commonConfig);
DefaultSslContextFactory defaultSslContextFactoryImpl = new DefaultSslContextFactory(config);
@ -222,12 +226,13 @@ public class DefaultSslContextFactoryTest
}
@Test
public void testDisableOpenSslForInJvmDtests() {
public void testDisableOpenSslForInJvmDtests()
{
// The configuration name below is hard-coded intentionally to make sure we don't break the contract without
// changing the documentation appropriately
try (WithProperties properties = new WithProperties().set(DISABLE_TCACTIVE_OPENSSL, true))
{
Map<String,Object> config = new HashMap<>();
Map<String, Object> config = new HashMap<>();
config.putAll(commonConfig);
DefaultSslContextFactory defaultSslContextFactoryImpl = new DefaultSslContextFactory(config);

View File

@ -44,7 +44,7 @@ public class DummySslContextFactoryImpl implements ISslContextFactory
}
@Override
public SSLContext createJSSESslContext(EncryptionOptions.ClientAuth clientAuth) throws SSLException
public SSLContext createJSSESslContext(EncryptionOptions.ClientEncryptionOptions.ClientAuth clientAuth) throws SSLException
{
return null;
}
@ -56,7 +56,7 @@ public class DummySslContextFactoryImpl implements ISslContextFactory
}
@Override
public SslContext createNettySslContext(EncryptionOptions.ClientAuth clientAuth, SocketType socketType,
public SslContext createNettySslContext(EncryptionOptions.ClientEncryptionOptions.ClientAuth clientAuth, SocketType socketType,
CipherSuiteFilter cipherFilter) throws SSLException
{
return null;

View File

@ -36,11 +36,12 @@ import org.apache.cassandra.transport.TlsTestUtils;
import static org.apache.cassandra.config.CassandraRelevantProperties.CASSANDRA_CONFIG;
import static org.apache.cassandra.config.EncryptionOptions.ClientAuth.NOT_REQUIRED;
import static org.apache.cassandra.config.EncryptionOptions.ClientEncryptionOptions.ClientAuth.NOT_REQUIRED;
public class FileBasedSslContextFactoryTest
{
private EncryptionOptions.ServerEncryptionOptions encryptionOptions;
private EncryptionOptions.ServerEncryptionOptions.Builder encryptionOptionsBuilder;
static WithProperties properties;
@ -60,7 +61,10 @@ public class FileBasedSslContextFactoryTest
@Before
public void setup()
{
encryptionOptions = new EncryptionOptions.ServerEncryptionOptions()
encryptionOptionsBuilder = new EncryptionOptions.ServerEncryptionOptions.Builder();
encryptionOptions = encryptionOptionsBuilder
.withOutboundKeystore(TlsTestUtils.SERVER_OUTBOUND_KEYSTORE_PATH)
.withOutboundKeystorePassword(TlsTestUtils.SERVER_OUTBOUND_KEYSTORE_PASSWORD)
.withSslContextFactory(new ParameterizedClass(TestFileBasedSSLContextFactory.class.getName(),
new HashMap<>()))
.withTrustStore(TlsTestUtils.SERVER_TRUSTSTORE_PATH)
@ -69,8 +73,7 @@ public class FileBasedSslContextFactoryTest
.withCipherSuites("TLS_RSA_WITH_AES_128_CBC_SHA")
.withKeyStore(TlsTestUtils.SERVER_KEYSTORE_PATH)
.withKeyStorePassword(TlsTestUtils.SERVER_KEYSTORE_PASSWORD)
.withOutboundKeystore(TlsTestUtils.SERVER_OUTBOUND_KEYSTORE_PATH)
.withOutboundKeystorePassword(TlsTestUtils.SERVER_OUTBOUND_KEYSTORE_PASSWORD);
.build();
}
@Test
@ -95,11 +98,12 @@ public class FileBasedSslContextFactoryTest
@Test
public void testEmptyKeystorePasswords() throws SSLException
{
EncryptionOptions.ServerEncryptionOptions localEncryptionOptions = encryptionOptions
EncryptionOptions.ServerEncryptionOptions localEncryptionOptions = encryptionOptionsBuilder
.withOutboundKeystorePassword("")
.withOutboundKeystore("test/conf/cassandra_ssl_test_nopassword.keystore")
.withKeyStorePassword("")
.withKeyStore("test/conf/cassandra_ssl_test_nopassword.keystore")
.withOutboundKeystorePassword("")
.withOutboundKeystore("test/conf/cassandra_ssl_test_nopassword.keystore");
.build();
Assert.assertEquals("org.apache.cassandra.security.FileBasedSslContextFactoryTest$TestFileBasedSSLContextFactory",
localEncryptionOptions.ssl_context_factory.class_name);
@ -118,13 +122,14 @@ public class FileBasedSslContextFactoryTest
{
// Here we only override password configuration and specify password_file configuration since keystore paths
// are already loaded in the `encryptionOptions`
EncryptionOptions.ServerEncryptionOptions localEncryptionOptions = encryptionOptions
.withKeyStorePassword(null)
.withKeyStorePasswordFile(TlsTestUtils.SERVER_KEYSTORE_PASSWORD_FILE)
EncryptionOptions.ServerEncryptionOptions localEncryptionOptions = encryptionOptionsBuilder
.withOutboundKeystorePassword(null)
.withOutboundKeystorePasswordFile(TlsTestUtils.SERVER_OUTBOUND_KEYSTORE_PASSWORD_FILE)
.withKeyStorePassword(null)
.withKeyStorePasswordFile(TlsTestUtils.SERVER_KEYSTORE_PASSWORD_FILE)
.withTrustStorePassword(null)
.withTrustStorePasswordFile(TlsTestUtils.SERVER_TRUSTSTORE_PASSWORD_FILE);
.withTrustStorePasswordFile(TlsTestUtils.SERVER_TRUSTSTORE_PASSWORD_FILE)
.build();
Assert.assertEquals("org.apache.cassandra.security.FileBasedSslContextFactoryTest$TestFileBasedSSLContextFactory",
localEncryptionOptions.ssl_context_factory.class_name);
@ -144,13 +149,14 @@ public class FileBasedSslContextFactoryTest
{
// Here we only override password configuration and specify password_file configuration since keystore paths
// are already loaded in the `encryptionOptions`
encryptionOptions
.withKeyStorePassword(null)
.withKeyStorePasswordFile("/path/to/non-existance-password-file")
encryptionOptionsBuilder
.withOutboundKeystorePassword(null)
.withOutboundKeystorePasswordFile("/path/to/non-existance-password-file")
.withKeyStorePassword(null)
.withKeyStorePasswordFile("/path/to/non-existance-password-file")
.withTrustStorePassword(null)
.withTrustStorePasswordFile("/path/to/non-existance-password-file");
.withTrustStorePasswordFile("/path/to/non-existance-password-file")
.build();
}
/**
@ -159,7 +165,9 @@ public class FileBasedSslContextFactoryTest
@Test(expected = IllegalArgumentException.class)
public void testNullKeystorePasswordDisallowed() throws SSLException
{
EncryptionOptions.ServerEncryptionOptions localEncryptionOptions = encryptionOptions.withKeyStorePassword(null);
EncryptionOptions.ServerEncryptionOptions localEncryptionOptions = encryptionOptionsBuilder
.withKeyStorePassword(null)
.build();
Assert.assertEquals("org.apache.cassandra.security.FileBasedSslContextFactoryTest$TestFileBasedSSLContextFactory",
localEncryptionOptions.ssl_context_factory.class_name);
@ -187,7 +195,9 @@ public class FileBasedSslContextFactoryTest
@Test
public void testOnlyEmptyOutboundKeystorePassword() throws SSLException
{
EncryptionOptions.ServerEncryptionOptions localEncryptionOptions = encryptionOptions.withOutboundKeystorePassword(null);
EncryptionOptions.ServerEncryptionOptions localEncryptionOptions = encryptionOptionsBuilder
.withOutboundKeystorePassword(null)
.build();
Assert.assertEquals("org.apache.cassandra.security.FileBasedSslContextFactoryTest$TestFileBasedSSLContextFactory",
localEncryptionOptions.ssl_context_factory.class_name);
@ -203,7 +213,9 @@ public class FileBasedSslContextFactoryTest
@Test
public void testEmptyTruststorePassword() throws SSLException
{
EncryptionOptions.ServerEncryptionOptions localEncryptionOptions = encryptionOptions.withTrustStorePassword(null);
EncryptionOptions.ServerEncryptionOptions localEncryptionOptions = encryptionOptionsBuilder
.withTrustStorePassword(null)
.build();
Assert.assertEquals("org.apache.cassandra.security.FileBasedSslContextFactoryTest$TestFileBasedSSLContextFactory",
localEncryptionOptions.ssl_context_factory.class_name);
Assert.assertNotNull("keystore_password must not be null", localEncryptionOptions.keystore_password);

View File

@ -39,8 +39,8 @@ import org.apache.cassandra.distributed.shared.WithProperties;
import org.apache.cassandra.transport.TlsTestUtils;
import static org.apache.cassandra.config.CassandraRelevantProperties.DISABLE_TCACTIVE_OPENSSL;
import static org.apache.cassandra.config.EncryptionOptions.ClientAuth.NOT_REQUIRED;
import static org.apache.cassandra.config.EncryptionOptions.ClientAuth.REQUIRED;
import static org.apache.cassandra.config.EncryptionOptions.ClientEncryptionOptions.ClientAuth.NOT_REQUIRED;
import static org.apache.cassandra.config.EncryptionOptions.ClientEncryptionOptions.ClientAuth.REQUIRED;
import static org.apache.cassandra.security.PEMBasedSslContextFactory.ConfigKey.ENCODED_CERTIFICATES;
import static org.apache.cassandra.security.PEMBasedSslContextFactory.ConfigKey.ENCODED_KEY;
import static org.apache.cassandra.security.PEMBasedSslContextFactory.ConfigKey.KEY_PASSWORD;
@ -215,12 +215,14 @@ public class PEMBasedSslContextFactoryTest
{
ParameterizedClass sslContextFactory = new ParameterizedClass(PEMBasedSslContextFactory.class.getSimpleName()
, new HashMap<>());
EncryptionOptions options = new EncryptionOptions().withTrustStore(TlsTestUtils.SERVER_TRUSTSTORE_PEM_PATH)
.withKeyStore(TlsTestUtils.SERVER_KEYSTORE_PATH_PEM)
.withKeyStorePassword(TlsTestUtils.SERVER_KEYSTORE_PASSWORD)
.withRequireClientAuth(NOT_REQUIRED)
.withCipherSuites("TLS_RSA_WITH_AES_128_CBC_SHA")
.withSslContextFactory(sslContextFactory);
EncryptionOptions.ClientEncryptionOptions options = new EncryptionOptions.ClientEncryptionOptions.Builder()
.withTrustStore(TlsTestUtils.SERVER_TRUSTSTORE_PEM_PATH)
.withKeyStore(TlsTestUtils.SERVER_KEYSTORE_PATH_PEM)
.withKeyStorePassword(TlsTestUtils.SERVER_KEYSTORE_PASSWORD)
.withRequireClientAuth(NOT_REQUIRED)
.withCipherSuites("TLS_RSA_WITH_AES_128_CBC_SHA")
.withSslContextFactory(sslContextFactory)
.build();
SslContext sslContext = SSLFactory.getOrCreateSslContext(options, REQUIRED, ISslContextFactory.SocketType.SERVER, "test");
Assert.assertNotNull(sslContext);
if (OpenSsl.isAvailable())
@ -234,14 +236,16 @@ public class PEMBasedSslContextFactoryTest
{
ParameterizedClass sslContextFactory = new ParameterizedClass(PEMBasedSslContextFactory.class.getSimpleName()
, new HashMap<>());
EncryptionOptions.ServerEncryptionOptions options = new EncryptionOptions.ServerEncryptionOptions().withTrustStore(TlsTestUtils.SERVER_TRUSTSTORE_PEM_PATH)
.withKeyStore(TlsTestUtils.SERVER_KEYSTORE_PATH_PEM)
.withKeyStorePassword(TlsTestUtils.SERVER_KEYSTORE_PASSWORD)
.withOutboundKeystore(TlsTestUtils.SERVER_KEYSTORE_PATH_PEM)
.withOutboundKeystorePassword(TlsTestUtils.SERVER_KEYSTORE_PASSWORD)
.withRequireClientAuth(NOT_REQUIRED)
.withCipherSuites("TLS_RSA_WITH_AES_128_CBC_SHA")
.withSslContextFactory(sslContextFactory);
EncryptionOptions.ServerEncryptionOptions options =
new EncryptionOptions.ServerEncryptionOptions.Builder().withOutboundKeystore(TlsTestUtils.SERVER_KEYSTORE_PATH_PEM)
.withOutboundKeystorePassword(TlsTestUtils.SERVER_KEYSTORE_PASSWORD)
.withTrustStore(TlsTestUtils.SERVER_TRUSTSTORE_PEM_PATH)
.withKeyStore(TlsTestUtils.SERVER_KEYSTORE_PATH_PEM)
.withKeyStorePassword(TlsTestUtils.SERVER_KEYSTORE_PASSWORD)
.withRequireClientAuth(NOT_REQUIRED)
.withCipherSuites("TLS_RSA_WITH_AES_128_CBC_SHA")
.withSslContextFactory(sslContextFactory)
.build();
SslContext sslContext = SSLFactory.getOrCreateSslContext(options, REQUIRED, ISslContextFactory.SocketType.CLIENT, "test");
Assert.assertNotNull(sslContext);
if (OpenSsl.isAvailable())

View File

@ -1,21 +1,21 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.cassandra.security;
import java.io.FileInputStream;
@ -46,18 +46,20 @@ import io.netty.handler.ssl.util.SelfSignedCertificate;
import org.apache.cassandra.config.DatabaseDescriptor;
import org.apache.cassandra.config.EncryptionOptions;
import org.apache.cassandra.config.EncryptionOptions.ServerEncryptionOptions;
import org.apache.cassandra.config.EncryptionOptions.ServerEncryptionOptions.Builder;
import org.apache.cassandra.config.ParameterizedClass;
import org.apache.cassandra.io.util.File;
import org.apache.cassandra.transport.TlsTestUtils;
import static org.apache.cassandra.config.EncryptionOptions.ClientAuth.NOT_REQUIRED;
import static org.apache.cassandra.config.EncryptionOptions.ClientAuth.REQUIRED;
import static org.apache.cassandra.config.EncryptionOptions.ClientEncryptionOptions.ClientAuth.NOT_REQUIRED;
import static org.apache.cassandra.config.EncryptionOptions.ClientEncryptionOptions.ClientAuth.REQUIRED;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
public class SSLFactoryTest
{
static final SelfSignedCertificate ssc;
static
{
DatabaseDescriptor.daemonInitialization();
@ -77,33 +79,41 @@ public class SSLFactoryTest
public void setup()
{
SSLFactory.clearSslContextCache();
encryptionOptions = new ServerEncryptionOptions()
.withTrustStore(TlsTestUtils.SERVER_TRUSTSTORE_PATH)
.withTrustStorePassword(TlsTestUtils.SERVER_TRUSTSTORE_PASSWORD)
.withRequireClientAuth(NOT_REQUIRED)
.withCipherSuites("TLS_RSA_WITH_AES_128_CBC_SHA")
.withSslContextFactory(new ParameterizedClass(TestFileBasedSSLContextFactory.class.getName(),
new HashMap<>()));
encryptionOptions = new Builder().withTrustStore(TlsTestUtils.SERVER_TRUSTSTORE_PATH)
.withTrustStorePassword(TlsTestUtils.SERVER_TRUSTSTORE_PASSWORD)
.withRequireClientAuth(NOT_REQUIRED)
.withCipherSuites("TLS_RSA_WITH_AES_128_CBC_SHA")
.withSslContextFactory(new ParameterizedClass(TestFileBasedSSLContextFactory.class.getName(),
new HashMap<>()))
.build();
}
private ServerEncryptionOptions addKeystoreOptions(ServerEncryptionOptions options)
private Builder addKeystoreOptions(ServerEncryptionOptions options)
{
return options.withKeyStore(TlsTestUtils.SERVER_KEYSTORE_PATH)
.withKeyStorePassword(TlsTestUtils.SERVER_KEYSTORE_PASSWORD)
.withOutboundKeystore(TlsTestUtils.SERVER_OUTBOUND_KEYSTORE_PATH)
.withOutboundKeystorePassword(TlsTestUtils.SERVER_OUTBOUND_KEYSTORE_PASSWORD);
EncryptionOptions.ServerEncryptionOptions.Builder builder = new EncryptionOptions.ServerEncryptionOptions.Builder(options);
builder.withOutboundKeystorePassword(TlsTestUtils.SERVER_OUTBOUND_KEYSTORE_PASSWORD)
.withOutboundKeystore(TlsTestUtils.SERVER_OUTBOUND_KEYSTORE_PATH)
.withKeyStorePassword(TlsTestUtils.SERVER_KEYSTORE_PASSWORD)
.withKeyStore(TlsTestUtils.SERVER_KEYSTORE_PATH);
return builder;
}
private ServerEncryptionOptions addPEMKeystoreOptions(ServerEncryptionOptions options)
private Builder addPEMKeystoreOptions(ServerEncryptionOptions options)
{
ParameterizedClass sslContextFactoryClass = new ParameterizedClass("org.apache.cassandra.security.PEMBasedSslContextFactory",
new HashMap<>());
return options.withSslContextFactory(sslContextFactoryClass)
.withKeyStore(TlsTestUtils.SERVER_KEYSTORE_PATH_PEM)
.withKeyStorePassword(TlsTestUtils.SERVER_KEYSTORE_PASSWORD)
.withOutboundKeystore(TlsTestUtils.SERVER_KEYSTORE_PATH_PEM)
.withOutboundKeystorePassword(TlsTestUtils.SERVER_KEYSTORE_PASSWORD)
.withTrustStore(TlsTestUtils.SERVER_TRUSTSTORE_PEM_PATH);
EncryptionOptions.ServerEncryptionOptions.Builder builder = new EncryptionOptions.ServerEncryptionOptions.Builder(options);
builder.withOutboundKeystore(TlsTestUtils.SERVER_KEYSTORE_PATH_PEM)
.withOutboundKeystorePassword(TlsTestUtils.SERVER_KEYSTORE_PASSWORD)
.withSslContextFactory(sslContextFactoryClass)
.withKeyStore(TlsTestUtils.SERVER_KEYSTORE_PATH_PEM)
.withKeyStorePassword(TlsTestUtils.SERVER_KEYSTORE_PASSWORD)
.withTrustStore(TlsTestUtils.SERVER_TRUSTSTORE_PEM_PATH);
return builder;
}
@Test
@ -111,9 +121,13 @@ public class SSLFactoryTest
{
try
{
ServerEncryptionOptions options = addKeystoreOptions(encryptionOptions)
.withInternodeEncryption(ServerEncryptionOptions.InternodeEncryption.all);
ServerEncryptionOptions legacyOptions = options.withOptional(false).withInternodeEncryption(ServerEncryptionOptions.InternodeEncryption.all);
Builder optionsBuilder = addKeystoreOptions(encryptionOptions)
.withInternodeEncryption(ServerEncryptionOptions.InternodeEncryption.all);
ServerEncryptionOptions options = optionsBuilder.build();
ServerEncryptionOptions legacyOptions = optionsBuilder
.withInternodeEncryption(ServerEncryptionOptions.InternodeEncryption.all)
.withOptional(false)
.build();
options.sslContextFactoryInstance.initHotReloading();
legacyOptions.sslContextFactoryInstance.initHotReloading();
@ -146,8 +160,9 @@ public class SSLFactoryTest
public void testServerSocketShouldUseKeystore() throws IOException, CertificateException, KeyStoreException, NoSuchAlgorithmException, NoSuchFieldException, IllegalAccessException, ClassNotFoundException, NoSuchMethodException, InvocationTargetException
{
ServerEncryptionOptions options = addKeystoreOptions(encryptionOptions)
.withOutboundKeystore("dummyKeystore")
.withOutboundKeystorePassword("dummyPassword");
.withOutboundKeystore("dummyKeystore")
.withOutboundKeystorePassword("dummyPassword")
.build();
// Server socket type should create a keystore with keystore & keystore password
final OpenSslServerContext context = (OpenSslServerContext) SSLFactory.createNettySslContext(options, REQUIRED, ISslContextFactory.SocketType.SERVER);
@ -163,8 +178,9 @@ public class SSLFactoryTest
public void testClientSocketShouldUseOutboundKeystore() throws IOException, CertificateException, KeyStoreException, NoSuchAlgorithmException, NoSuchFieldException, ClassNotFoundException, InvocationTargetException, IllegalAccessException, NoSuchMethodException
{
ServerEncryptionOptions options = addKeystoreOptions(encryptionOptions)
.withKeyStore("dummyKeystore")
.withKeyStorePassword("dummyPassword");
.withKeyStore("dummyKeystore")
.withKeyStorePassword("dummyPassword")
.build();
// Client socket type should create a keystore with outbound Keystore & outbound password
final OpenSslClientContext context = (OpenSslClientContext) SSLFactory.createNettySslContext(options, REQUIRED, ISslContextFactory.SocketType.CLIENT);
@ -181,10 +197,14 @@ public class SSLFactoryTest
{
try
{
ServerEncryptionOptions options = addPEMKeystoreOptions(encryptionOptions)
.withInternodeEncryption(ServerEncryptionOptions.InternodeEncryption.dc);
Builder optionsBuilder = addPEMKeystoreOptions(encryptionOptions);
ServerEncryptionOptions options = optionsBuilder.withInternodeEncryption(ServerEncryptionOptions.InternodeEncryption.dc)
.build();
// emulate InboundSockets and share the cert but with different options, no extra hot reloading init
ServerEncryptionOptions legacyOptions = options.withOptional(false).withInternodeEncryption(ServerEncryptionOptions.InternodeEncryption.all);
ServerEncryptionOptions legacyOptions = optionsBuilder
.withInternodeEncryption(ServerEncryptionOptions.InternodeEncryption.all)
.withOptional(false)
.build();
options.sslContextFactoryInstance.initHotReloading();
legacyOptions.sslContextFactoryInstance.initHotReloading();
@ -217,8 +237,9 @@ public class SSLFactoryTest
public void testSslFactorySslInit_BadPassword_ThrowsException() throws IOException
{
ServerEncryptionOptions options = addKeystoreOptions(encryptionOptions)
.withKeyStorePassword("bad password")
.withInternodeEncryption(ServerEncryptionOptions.InternodeEncryption.all);
.withInternodeEncryption(ServerEncryptionOptions.InternodeEncryption.all)
.withKeyStorePassword("bad password")
.build();
SSLFactory.validateSslContext("testSslFactorySslInit_BadPassword_ThrowsException", options, NOT_REQUIRED, true);
}
@ -228,13 +249,17 @@ public class SSLFactoryTest
{
try
{
ServerEncryptionOptions options = addKeystoreOptions(encryptionOptions);
Builder optionsBuilder = addKeystoreOptions(encryptionOptions);
ServerEncryptionOptions options = optionsBuilder.build();
// emulate InboundSockets and share the cert but with different options, no extra hot reloading init
ServerEncryptionOptions legacyOptions = options.withOptional(false).withInternodeEncryption(ServerEncryptionOptions.InternodeEncryption.all);
ServerEncryptionOptions legacyOptions = optionsBuilder
.withInternodeEncryption(ServerEncryptionOptions.InternodeEncryption.all)
.withOptional(false)
.build();
File testKeystoreFile = new File(options.keystore + ".test");
FileUtils.copyFile(new File(options.keystore).toJavaIOFile(), testKeystoreFile.toJavaIOFile());
options = options.withKeyStore(testKeystoreFile.path());
options = new Builder(options).withKeyStore(testKeystoreFile.path()).build();
SSLFactory.initHotReloading(options, options, true); // deliberately not initializing with legacyOptions to match InboundSockets.addBindings
@ -261,11 +286,12 @@ public class SSLFactoryTest
{
try
{
ServerEncryptionOptions options = addKeystoreOptions(encryptionOptions);
Builder optionsBuilder = addKeystoreOptions(encryptionOptions);
ServerEncryptionOptions options = optionsBuilder.build();
File testKeystoreFile = new File(options.keystore + ".test");
FileUtils.copyFile(new File(options.keystore).toJavaIOFile(), testKeystoreFile.toJavaIOFile());
options = options.withKeyStore(testKeystoreFile.path());
options = optionsBuilder.withKeyStore(testKeystoreFile.path()).build();
SSLFactory.initHotReloading(options, options, true);
@ -294,8 +320,10 @@ public class SSLFactoryTest
@Test
public void getSslContext_ParamChanges() throws IOException
{
ServerEncryptionOptions options = addKeystoreOptions(encryptionOptions)
.withCipherSuites("TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256");
Builder optionsBuilder = addKeystoreOptions(encryptionOptions);
ServerEncryptionOptions options = optionsBuilder
.withCipherSuites("TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256")
.build();
SslContext ctx1 = SSLFactory.getOrCreateSslContext(options, REQUIRED,
ISslContextFactory.SocketType.SERVER, "test");
@ -303,7 +331,7 @@ public class SSLFactoryTest
Assert.assertTrue(ctx1.isServer());
Assert.assertEquals(ctx1.cipherSuites(), options.cipher_suites);
options = options.withCipherSuites("TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256");
options = optionsBuilder.withCipherSuites("TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256").build();
SslContext ctx2 = SSLFactory.getOrCreateSslContext(options, REQUIRED,
ISslContextFactory.SocketType.CLIENT, "test");
@ -313,30 +341,33 @@ public class SSLFactoryTest
}
@Test
public void testCacheKeyEqualityForCustomSslContextFactory() {
public void testCacheKeyEqualityForCustomSslContextFactory()
{
Map<String,String> parameters1 = new HashMap<>();
Map<String, String> parameters1 = new HashMap<>();
parameters1.put("key1", "value1");
parameters1.put("key2", "value2");
EncryptionOptions encryptionOptions1 =
new EncryptionOptions()
EncryptionOptions.ClientEncryptionOptions encryptionOptions1 =
new EncryptionOptions.ClientEncryptionOptions.Builder()
.withSslContextFactory(new ParameterizedClass(DummySslContextFactoryImpl.class.getName(), parameters1))
.withProtocol("TLSv1.1")
.withRequireClientAuth(REQUIRED)
.withRequireEndpointVerification(false);
.withRequireEndpointVerification(false)
.build();
SSLFactory.CacheKey cacheKey1 = new SSLFactory.CacheKey(encryptionOptions1, ISslContextFactory.SocketType.SERVER, "test"
);
Map<String,String> parameters2 = new HashMap<>();
Map<String, String> parameters2 = new HashMap<>();
parameters2.put("key1", "value1");
parameters2.put("key2", "value2");
EncryptionOptions encryptionOptions2 =
new EncryptionOptions()
EncryptionOptions.ClientEncryptionOptions encryptionOptions2 =
new EncryptionOptions.ClientEncryptionOptions.Builder()
.withSslContextFactory(new ParameterizedClass(DummySslContextFactoryImpl.class.getName(), parameters2))
.withProtocol("TLSv1.1")
.withRequireClientAuth(REQUIRED)
.withRequireEndpointVerification(false);
.withRequireEndpointVerification(false)
.build();
SSLFactory.CacheKey cacheKey2 = new SSLFactory.CacheKey(encryptionOptions2, ISslContextFactory.SocketType.SERVER, "test"
);
@ -345,26 +376,29 @@ public class SSLFactoryTest
}
@Test
public void testCacheKeyInequalityForCustomSslContextFactory() {
public void testCacheKeyInequalityForCustomSslContextFactory()
{
Map<String,String> parameters1 = new HashMap<>();
Map<String, String> parameters1 = new HashMap<>();
parameters1.put("key1", "value11");
parameters1.put("key2", "value12");
EncryptionOptions encryptionOptions1 =
new EncryptionOptions()
EncryptionOptions.ClientEncryptionOptions encryptionOptions1 =
new EncryptionOptions.ClientEncryptionOptions.Builder()
.withSslContextFactory(new ParameterizedClass(DummySslContextFactoryImpl.class.getName(), parameters1))
.withProtocol("TLSv1.1");
.withProtocol("TLSv1.1")
.build();
SSLFactory.CacheKey cacheKey1 = new SSLFactory.CacheKey(encryptionOptions1, ISslContextFactory.SocketType.SERVER, "test"
);
Map<String,String> parameters2 = new HashMap<>();
Map<String, String> parameters2 = new HashMap<>();
parameters2.put("key1", "value21");
parameters2.put("key2", "value22");
EncryptionOptions encryptionOptions2 =
new EncryptionOptions()
EncryptionOptions.ClientEncryptionOptions encryptionOptions2 =
new EncryptionOptions.ClientEncryptionOptions.Builder()
.withSslContextFactory(new ParameterizedClass(DummySslContextFactoryImpl.class.getName(), parameters2))
.withProtocol("TLSv1.1");
.withProtocol("TLSv1.1")
.build();
SSLFactory.CacheKey cacheKey2 = new SSLFactory.CacheKey(encryptionOptions2, ISslContextFactory.SocketType.SERVER, "test"
);
@ -372,7 +406,8 @@ public class SSLFactoryTest
Assert.assertNotEquals(cacheKey1, cacheKey2);
}
public static class TestFileBasedSSLContextFactory extends FileBasedSslContextFactory {
public static class TestFileBasedSSLContextFactory extends FileBasedSslContextFactory
{
public TestFileBasedSSLContextFactory(Map<String, Object> parameters)
{
super(parameters);

View File

@ -70,7 +70,7 @@ public class ClientWarningsTest extends CQLTester
createTable("CREATE TABLE %s (pk int PRIMARY KEY, v text)");
// v4 and higher
try (SimpleClient client = new SimpleClient(nativeAddr.getHostAddress(), nativePort, version, true, new EncryptionOptions()))
try (SimpleClient client = new SimpleClient(nativeAddr.getHostAddress(), nativePort, version, true, new EncryptionOptions.ClientEncryptionOptions()))
{
client.connect(false);
@ -90,7 +90,7 @@ public class ClientWarningsTest extends CQLTester
createTable("CREATE TABLE %s (pk int PRIMARY KEY, v text)");
// v4 and higher
try (SimpleClient client = new SimpleClient(nativeAddr.getHostAddress(), nativePort, version, true, new EncryptionOptions()))
try (SimpleClient client = new SimpleClient(nativeAddr.getHostAddress(), nativePort, version, true, new EncryptionOptions.ClientEncryptionOptions()))
{
client.connect(false);
@ -112,7 +112,7 @@ public class ClientWarningsTest extends CQLTester
final int iterations = 10000;
createTable("CREATE TABLE %s (pk int, ck int, v int, PRIMARY KEY (pk, ck))");
try (SimpleClient client = new SimpleClient(nativeAddr.getHostAddress(), nativePort, version, true, new EncryptionOptions()))
try (SimpleClient client = new SimpleClient(nativeAddr.getHostAddress(), nativePort, version, true, new EncryptionOptions.ClientEncryptionOptions()))
{
client.connect(false);

View File

@ -36,7 +36,7 @@ import static org.junit.Assert.assertTrue;
public class NativeTransportServiceTest
{
static EncryptionOptions defaultOptions;
static EncryptionOptions.ClientEncryptionOptions defaultOptions;
@BeforeClass
public static void setupDD()
@ -48,7 +48,7 @@ public class NativeTransportServiceTest
@After
public void resetConfig()
{
DatabaseDescriptor.updateNativeProtocolEncryptionOptions(update -> new EncryptionOptions(defaultOptions).applyConfig());
DatabaseDescriptor.updateNativeProtocolEncryptionOptions(update -> new EncryptionOptions.ClientEncryptionOptions.Builder(defaultOptions).build());
}
@Test
@ -127,8 +127,11 @@ public class NativeTransportServiceTest
public void testSSLOnly()
{
// default ssl settings: client encryption enabled and default native transport port used for ssl only
DatabaseDescriptor.updateNativeProtocolEncryptionOptions(options -> options.withEnabled(true)
.withOptional(false));
DatabaseDescriptor.updateNativeProtocolEncryptionOptions(options ->
new EncryptionOptions.ClientEncryptionOptions.Builder(options)
.withEnabled(true)
.withOptional(false)
.build());
withService((NativeTransportService service) ->
{
@ -144,8 +147,11 @@ public class NativeTransportServiceTest
public void testSSLOptional()
{
// default ssl settings: client encryption enabled and default native transport port used for optional ssl
DatabaseDescriptor.updateNativeProtocolEncryptionOptions(options -> options.withEnabled(true)
.withOptional(true));
DatabaseDescriptor.updateNativeProtocolEncryptionOptions(options ->
new EncryptionOptions.ClientEncryptionOptions.Builder(options)
.withEnabled(true)
.withOptional(true)
.build());
withService((NativeTransportService service) ->
{

View File

@ -68,7 +68,7 @@ public class ProtocolBetaVersionTest extends CQLTester
createTable("CREATE TABLE %s (pk int PRIMARY KEY, v int)");
assertTrue(betaVersion.isBeta()); // change to another beta version or remove test if no beta version
try (SimpleClient client = new SimpleClient(nativeAddr.getHostAddress(), nativePort, betaVersion, true, new EncryptionOptions()))
try (SimpleClient client = new SimpleClient(nativeAddr.getHostAddress(), nativePort, betaVersion, true, new EncryptionOptions.ClientEncryptionOptions()))
{
client.connect(false);
for (int i = 0; i < 10; i++)
@ -103,7 +103,7 @@ public class ProtocolBetaVersionTest extends CQLTester
}
assertTrue(betaVersion.isBeta()); // change to another beta version or remove test if no beta version
try (SimpleClient client = new SimpleClient(nativeAddr.getHostAddress(), nativePort, betaVersion, false, new EncryptionOptions()))
try (SimpleClient client = new SimpleClient(nativeAddr.getHostAddress(), nativePort, betaVersion, false, new EncryptionOptions.ClientEncryptionOptions()))
{
client.connect(false);
fail("Exception should have been thrown");

View File

@ -28,6 +28,7 @@ import com.google.common.net.HostAndPort;
import org.junit.Test;
import org.apache.cassandra.io.util.File;
import org.apache.cassandra.transport.TlsTestUtils;
import static org.apache.cassandra.tools.OfflineToolUtils.sstableDirName;
import static org.junit.Assert.assertEquals;
@ -85,6 +86,35 @@ public class LoaderOptionsTest
assertEquals("test.jks", options.clientEncOptions.keystore);
}
/**
* Tests for client_encryption_options override from the command line.
*/
@Test
public void testEncryptionSettingsOverride() throws Exception
{
// Default Cassandra config
File config = new File(Paths.get(".", "test", "conf", "cassandra-mtls.yaml").normalize());
String[] args = { "-d", "127.9.9.1", "-f", config.absolutePath(),
"-ts", "test.jks", "-tspw", "truststorePass1",
"-ks", "test.jks", "-kspw", "testdata1",
"--ssl-ciphers", "TLS_RSA_WITH_AES_256_CBC_SHA",
"--ssl-alg", "SunX509", "--store-type", "JKS", "--ssl-protocol", "TLS",
sstableDirName("legacy_sstables", "legacy_ma_simple") };
LoaderOptions options = LoaderOptions.builder().parseArgs(args).build();
// Below two lines validating server encryption options is to verify that we are loading config from the yaml
assertEquals(TlsTestUtils.SERVER_KEYSTORE_PATH, options.serverEncOptions.keystore);
assertEquals(TlsTestUtils.SERVER_KEYSTORE_PASSWORD, options.serverEncOptions.keystore_password);
// Below asserts validate the overrides for the client encryption options from the command line
// Since the values are provided by (and local to) this test, they are hardcoded
assertEquals("JKS", options.clientEncOptions.store_type);
assertEquals("test.jks", options.clientEncOptions.truststore);
assertEquals("truststorePass1", options.clientEncOptions.truststore_password);
assertEquals("test.jks", options.clientEncOptions.keystore);
assertEquals("testdata1", options.clientEncOptions.keystore_password);
assertEquals("TLS_RSA_WITH_AES_256_CBC_SHA", options.clientEncOptions.cipherSuitesArray()[0]);
assertEquals("SunX509", options.clientEncOptions.algorithm);
}
@Test
public void testThrottleDefaultSettings()
{

View File

@ -84,23 +84,23 @@ public class EarlyAuthenticationTest extends CQLTester
});
}
private EncryptionOptions clientEncryptionOptions(boolean presentClientCertificate)
private EncryptionOptions.ClientEncryptionOptions clientEncryptionOptions(boolean presentClientCertificate)
{
EncryptionOptions encryptionOptions = new EncryptionOptions()
.withEnabled(true)
.withRequireClientAuth(EncryptionOptions.ClientAuth.OPTIONAL)
.withTrustStore(TlsTestUtils.CLIENT_TRUSTSTORE_PATH)
.withTrustStorePassword(TlsTestUtils.CLIENT_TRUSTSTORE_PASSWORD)
.withSslContextFactory(new ParameterizedClass(SimpleClientSslContextFactory.class.getName()));
EncryptionOptions.ClientEncryptionOptions.Builder builder = new EncryptionOptions.ClientEncryptionOptions.Builder();
builder.withEnabled(true)
.withRequireClientAuth(EncryptionOptions.ClientEncryptionOptions.ClientAuth.OPTIONAL)
.withTrustStore(TlsTestUtils.CLIENT_TRUSTSTORE_PATH)
.withTrustStorePassword(TlsTestUtils.CLIENT_TRUSTSTORE_PASSWORD)
.withSslContextFactory(new ParameterizedClass(SimpleClientSslContextFactory.class.getName()));
if (presentClientCertificate)
{
encryptionOptions = encryptionOptions.withKeyStore(TlsTestUtils.CLIENT_SPIFFE_KEYSTORE_PATH)
.withStoreType("JKS")
.withKeyStorePassword(TlsTestUtils.CLIENT_SPIFFE_KEYSTORE_PASSWORD);
builder.withKeyStore(TlsTestUtils.CLIENT_SPIFFE_KEYSTORE_PATH)
.withStoreType("JKS")
.withKeyStorePassword(TlsTestUtils.CLIENT_SPIFFE_KEYSTORE_PASSWORD);
}
return new EncryptionOptions(encryptionOptions);
return new EncryptionOptions.ClientEncryptionOptions(builder.build());
}
@Test
@ -180,6 +180,5 @@ public class EarlyAuthenticationTest extends CQLTester
}
};
}
}

View File

@ -127,7 +127,7 @@ public class MessagePayloadTest extends CQLTester
nativePort,
ProtocolVersion.V5,
true,
new EncryptionOptions());
new EncryptionOptions.ClientEncryptionOptions());
try
{
client.connect(false);

View File

@ -30,12 +30,12 @@ import io.netty.handler.ssl.SslContextBuilder;
import org.apache.cassandra.config.EncryptionOptions;
import org.apache.cassandra.security.FileBasedSslContextFactory;
import static org.apache.cassandra.config.EncryptionOptions.ClientAuth.NOT_REQUIRED;
import static org.apache.cassandra.config.EncryptionOptions.ClientEncryptionOptions.ClientAuth.NOT_REQUIRED;
/**
* A custom implementation of {@link FileBasedSslContextFactory} to be used by tests utilizing {@link SimpleClient}.
* <p>
* Provides a subtly different implementation of {@link #createNettySslContext(EncryptionOptions.ClientAuth, SocketType, CipherSuiteFilter)}
* Provides a subtly different implementation of {@link #createNettySslContext(EncryptionOptions.ClientEncryptionOptions.ClientAuth, SocketType, CipherSuiteFilter)}
* that only configures an {@link SslContext} for clients and most importantly only configures a key manager if an
* outbound keystore is configured, where the existing implementation always does this. This is useful for tests
* that try to create a client that uses encryption but does not provide a certificate.
@ -49,7 +49,7 @@ public class SimpleClientSslContextFactory extends FileBasedSslContextFactory
}
@Override
public SSLContext createJSSESslContext(EncryptionOptions.ClientAuth clientAuth) throws SSLException
public SSLContext createJSSESslContext(EncryptionOptions.ClientEncryptionOptions.ClientAuth clientAuth) throws SSLException
{
TrustManager[] trustManagers = null;
if (clientAuth != NOT_REQUIRED)
@ -76,7 +76,7 @@ public class SimpleClientSslContextFactory extends FileBasedSslContextFactory
}
@Override
public SslContext createNettySslContext(EncryptionOptions.ClientAuth clientAuth, SocketType socketType,
public SslContext createNettySslContext(EncryptionOptions.ClientEncryptionOptions.ClientAuth clientAuth, SocketType socketType,
CipherSuiteFilter cipherFilter) throws SSLException
{
SslContextBuilder builder = SslContextBuilder.forClient();

View File

@ -86,17 +86,18 @@ public class TlsTestUtils
public static String CLIENT_TRUSTSTORE_PATH = "test/conf/cassandra_ssl_test.truststore";
public static String CLIENT_TRUSTSTORE_PASSWORD = "cassandra";
public static EncryptionOptions getClientEncryptionOptions()
public static EncryptionOptions.ClientEncryptionOptions getClientEncryptionOptions()
{
return new EncryptionOptions(new EncryptionOptions()
return new EncryptionOptions.ClientEncryptionOptions(new EncryptionOptions.ClientEncryptionOptions.Builder()
.withEnabled(true)
.withRequireClientAuth(EncryptionOptions.ClientAuth.OPTIONAL)
.withRequireClientAuth(EncryptionOptions.ClientEncryptionOptions.ClientAuth.OPTIONAL)
.withOptional(true)
.withKeyStore(SERVER_KEYSTORE_PATH)
.withKeyStorePassword(SERVER_KEYSTORE_PASSWORD)
.withTrustStore(SERVER_TRUSTSTORE_PATH)
.withTrustStorePassword(SERVER_TRUSTSTORE_PASSWORD)
.withRequireEndpointVerification(false));
.withRequireEndpointVerification(false)
.build());
}
public static void configureWithMutualTlsWithPasswordFallbackAuthenticator(Config config)
@ -129,7 +130,7 @@ public class TlsTestUtils
{
return RemoteEndpointAwareJdkSSLOptions.builder()
.withSSLContext(getClientSslContextFactory(provideClientCert)
.createJSSESslContext(EncryptionOptions.ClientAuth.OPTIONAL))
.createJSSESslContext(EncryptionOptions.ClientEncryptionOptions.ClientAuth.OPTIONAL))
.build();
}
@ -139,7 +140,7 @@ public class TlsTestUtils
{
return RemoteEndpointAwareJdkSSLOptions.builder()
.withSSLContext(getClientSslContextFactory(keystorePath, truststorePath)
.createJSSESslContext(EncryptionOptions.ClientAuth.OPTIONAL))
.createJSSESslContext(EncryptionOptions.ClientEncryptionOptions.ClientAuth.OPTIONAL))
.build();
}
catch (SSLException e)

View File

@ -44,31 +44,32 @@ public class SettingsTransport implements Serializable
this.credentials = credentials;
}
public EncryptionOptions getEncryptionOptions()
public EncryptionOptions.ClientEncryptionOptions getEncryptionOptions()
{
EncryptionOptions encOptions = new EncryptionOptions().applyConfig();
EncryptionOptions.ClientEncryptionOptions encOptions = new EncryptionOptions.ClientEncryptionOptions().applyConfig();
if (options.trustStore.present())
{
encOptions = encOptions
.withEnabled(true)
.withTrustStore(options.trustStore.value())
.withTrustStorePassword(options.trustStorePw.setByUser() ? options.trustStorePw.value() : credentials.transportTruststorePassword)
.withAlgorithm(options.alg.value())
.withProtocol(options.protocol.value())
.withCipherSuites(options.ciphers.value().split(","));
EncryptionOptions.Builder<EncryptionOptions.ClientEncryptionOptions> encOptionsBuilder = new EncryptionOptions.ClientEncryptionOptions.Builder(encOptions)
.withEnabled(true)
.withTrustStore(options.trustStore.value())
.withTrustStorePassword(options.trustStorePw.setByUser() ? options.trustStorePw.value() : credentials.transportTruststorePassword)
.withAlgorithm(options.alg.value())
.withProtocol(options.protocol.value())
.withCipherSuites(options.ciphers.value().split(","));
if (options.keyStore.present())
{
encOptions = encOptions
.withKeyStore(options.keyStore.value())
.withKeyStorePassword(options.keyStorePw.setByUser() ? options.keyStorePw.value() : credentials.transportKeystorePassword);
encOptionsBuilder.withKeyStore(options.keyStore.value())
.withKeyStorePassword(options.keyStorePw.setByUser() ? options.keyStorePw.value() : credentials.transportKeystorePassword);
}
else
{
// mandatory for SSLFactory.createSSLContext(), see CASSANDRA-9325
encOptions = encOptions
.withKeyStore(encOptions.truststore)
.withKeyStorePassword(encOptions.truststore_password != null ? encOptions.truststore_password : credentials.transportTruststorePassword);
encOptionsBuilder.withKeyStore(encOptions.truststore)
.withKeyStorePassword(encOptions.truststore_password != null ? encOptions.truststore_password : credentials.transportTruststorePassword);
}
encOptions = encOptionsBuilder.build();
}
return encOptions;
}

View File

@ -139,7 +139,7 @@ public class StressSettings implements Serializable
if (client != null)
return client;
EncryptionOptions encOptions = transport.getEncryptionOptions();
EncryptionOptions.ClientEncryptionOptions encOptions = transport.getEncryptionOptions();
JavaDriverClient c = new JavaDriverClient(this, node.nodes, port.nativePort, encOptions);
c.connect(mode.compression());
if (keyspace != null)

View File

@ -41,7 +41,7 @@ import org.apache.cassandra.config.EncryptionOptions;
import org.apache.cassandra.security.SSLFactory;
import org.apache.cassandra.stress.settings.StressSettings;
import static org.apache.cassandra.config.EncryptionOptions.ClientAuth.REQUIRED;
import static org.apache.cassandra.config.EncryptionOptions.ClientEncryptionOptions.ClientAuth.REQUIRED;
public class JavaDriverClient
{
@ -60,7 +60,7 @@ public class JavaDriverClient
public final int connectionsPerHost;
private final ProtocolVersion protocolVersion;
private final EncryptionOptions encryptionOptions;
private final EncryptionOptions.ClientEncryptionOptions encryptionOptions;
private Cluster cluster;
private Session session;
private final LoadBalancingPolicy loadBalancingPolicy;
@ -69,15 +69,15 @@ public class JavaDriverClient
public JavaDriverClient(StressSettings settings, String host, int port)
{
this(settings, Collections.singletonList(host), port, new EncryptionOptions());
this(settings, Collections.singletonList(host), port, new EncryptionOptions.ClientEncryptionOptions());
}
public JavaDriverClient(StressSettings settings, List<String> hosts, int port)
{
this(settings, hosts, port, new EncryptionOptions());
this(settings, hosts, port, new EncryptionOptions.ClientEncryptionOptions());
}
public JavaDriverClient(StressSettings settings, List<String> hosts, int port, EncryptionOptions encryptionOptions)
public JavaDriverClient(StressSettings settings, List<String> hosts, int port, EncryptionOptions.ClientEncryptionOptions encryptionOptions)
{
this.protocolVersion = settings.mode.protocolVersion;
this.hosts = hosts;
@ -85,7 +85,7 @@ public class JavaDriverClient
this.username = settings.mode.username;
this.password = settings.mode.password;
this.authProvider = settings.mode.authProvider;
this.encryptionOptions = new EncryptionOptions(encryptionOptions).applyConfig();
this.encryptionOptions = new EncryptionOptions.ClientEncryptionOptions(encryptionOptions).applyConfig();
this.loadBalancingPolicy = loadBalancingPolicy(settings);
this.connectionsPerHost = settings.mode.connectionsPerHost == null ? 8 : settings.mode.connectionsPerHost;