diff --git a/driver-cql/src/main/java/io/nosqlbench/activitytype/cql/statements/core/CQLSessionCache.java b/driver-cql/src/main/java/io/nosqlbench/activitytype/cql/statements/core/CQLSessionCache.java index dc92a23ad..c2de632c2 100644 --- a/driver-cql/src/main/java/io/nosqlbench/activitytype/cql/statements/core/CQLSessionCache.java +++ b/driver-cql/src/main/java/io/nosqlbench/activitytype/cql/statements/core/CQLSessionCache.java @@ -1,25 +1,43 @@ package io.nosqlbench.activitytype.cql.statements.core; -import com.datastax.driver.core.*; -import com.datastax.driver.core.policies.*; -import com.datastax.driver.dse.DseCluster; -import io.nosqlbench.activitytype.cql.core.CQLOptions; -import io.nosqlbench.activitytype.cql.core.ProxyTranslator; -import io.nosqlbench.engine.api.activityapi.core.Shutdownable; -import io.nosqlbench.engine.api.activityimpl.ActivityDef; -import io.nosqlbench.engine.api.metrics.ActivityMetrics; -import io.nosqlbench.engine.api.scripting.NashornEvaluator; -import io.nosqlbench.engine.api.util.SSLKsFactory; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - import java.io.File; import java.io.IOException; import java.net.InetSocketAddress; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; -import java.util.*; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import javax.net.ssl.SSLContext; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.datastax.driver.core.Cluster; +import com.datastax.driver.core.ProtocolOptions; +import com.datastax.driver.core.RemoteEndpointAwareJdkSSLOptions; +import com.datastax.driver.core.RemoteEndpointAwareNettySSLOptions; +import com.datastax.driver.core.SSLOptions; +import com.datastax.driver.core.Session; +import com.datastax.driver.core.policies.DefaultRetryPolicy; +import com.datastax.driver.core.policies.LoadBalancingPolicy; +import com.datastax.driver.core.policies.LoggingRetryPolicy; +import com.datastax.driver.core.policies.RetryPolicy; +import com.datastax.driver.core.policies.RoundRobinPolicy; +import com.datastax.driver.core.policies.SpeculativeExecutionPolicy; +import com.datastax.driver.core.policies.WhiteListPolicy; +import com.datastax.driver.dse.DseCluster; +import io.netty.handler.ssl.SslContext; +import io.nosqlbench.activitytype.cql.core.CQLOptions; +import io.nosqlbench.activitytype.cql.core.ProxyTranslator; +import io.nosqlbench.engine.api.activityapi.core.Shutdownable; +import io.nosqlbench.engine.api.activityimpl.ActivityDef; +import io.nosqlbench.engine.api.metrics.ActivityMetrics; +import io.nosqlbench.engine.api.scripting.NashornEvaluator; +import io.nosqlbench.engine.api.util.SSLKsFactory; public class CQLSessionCache implements Shutdownable { @@ -202,99 +220,12 @@ public class CQLSessionCache implements Shutdownable { .map(CQLOptions::withCompression) .ifPresent(builder::withCompression); - if (activityDef.getParams().getOptionalString("ssl").isPresent()) { - logger.info("Cluster builder proceeding with SSL but no Client Auth"); - Object context = SSLKsFactory.get().getContext(activityDef); - SSLOptions sslOptions; - if (context instanceof javax.net.ssl.SSLContext) { - sslOptions = RemoteEndpointAwareJdkSSLOptions.builder() - .withSSLContext((javax.net.ssl.SSLContext) context).build(); - builder.withSSL(sslOptions); - } else if (context instanceof io.netty.handler.ssl.SslContext) { - sslOptions = - new RemoteEndpointAwareNettySSLOptions((io.netty.handler.ssl.SslContext) context); - } else { - throw new RuntimeException("Unrecognized ssl context object type: " + context.getClass().getCanonicalName()); - } + SslContext context = SSLKsFactory.get().getContext(activityDef); + if (context != null) { + SSLOptions sslOptions = new RemoteEndpointAwareNettySSLOptions(context); builder.withSSL(sslOptions); } -// JdkSSLOptions sslOptions = RemoteEndpointAwareJdkSSLOptions -// .builder() -// .withSSLContext(context) -// .build(); -// builder.withSSL(sslOptions); -// -// } -// -// boolean sslEnabled = activityDef.getParams().getOptionalBoolean("ssl").orElse(false); -// boolean jdkSslEnabled = activityDef.getParams().getOptionalBoolean("jdkssl").orElse(false); -// if (jdkSslEnabled){ -// sslEnabled = true; -// } -// -// // used for OpenSSL -// boolean openSslEnabled = activityDef.getParams().getOptionalBoolean("openssl").orElse(false); -// -// if (sslEnabled && openSslEnabled) { -// logger.error("You cannot enable both OpenSSL and JDKSSL, please pick one and try again!"); -// System.exit(2); -// } -// -// if (sslEnabled) { -// logger.info("Cluster builder proceeding with SSL but no Client Auth"); -// SSLContext context = SSLKsFactory.get().getContext(activityDef); -// JdkSSLOptions sslOptions = RemoteEndpointAwareJdkSSLOptions -// .builder() -// .withSSLContext(context) -// .build(); -// builder.withSSL(sslOptions); -// } -// else if (openSslEnabled) { -// logger.info("Cluster builder proceeding with SSL and Client Auth"); -// String keyPassword = activityDef.getParams().getOptionalString("keyPassword").orElse(null); -// String caCertFileLocation = activityDef.getParams().getOptionalString("caCertFilePath").orElse(null); -// String certFileLocation = activityDef.getParams().getOptionalString("certFilePath").orElse(null); -// String keyFileLocation = activityDef.getParams().getOptionalString("keyFilePath").orElse(null); -// -// -// try { -// -// KeyStore ks = KeyStore.getInstance("JKS", "SUN"); -// ks.load(null, keyPassword.toCharArray()); -// -// X509Certificate cert = (X509Certificate) CertificateFactory. -// getInstance("X509"). -// generateCertificate(new FileInputStream(caCertFileLocation)); -// -// //set alias to cert -// ks.setCertificateEntry(cert.getSubjectX500Principal().getName(), cert); -// -// TrustManagerFactory tMF = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm()); -// tMF.init(ks); -// -// -// SslContext sslContext = SslContextBuilder -// .forClient() -// /* configured with the TrustManagerFactory that has the cert from the ca.cert -// * This tells the driver to trust the server during the SSL handshake */ -// .trustManager(tMF) -// /* These are needed because the server is configured with require_client_auth -// * In this case the client's public key must be in the truststore on each DSE -// * server node and the CA configured */ -// .keyManager(new File(certFileLocation), new File(keyFileLocation)) -// .build(); -// -// RemoteEndpointAwareNettySSLOptions sslOptions = new RemoteEndpointAwareNettySSLOptions(sslContext); -// -// // Cluster builder with sslOptions -// builder.withSSL(sslOptions); -// -// } catch (Exception e) { -// throw new RuntimeException(e); -// } -// } - RetryPolicy retryPolicy = activityDef.getParams() .getOptionalString("retrypolicy") .map(CQLOptions::retryPolicyFor).orElse(DefaultRetryPolicy.INSTANCE); diff --git a/driver-cql/src/main/resources/cql.md b/driver-cql/src/main/resources/cql.md index 94f6ad7bb..8aeaf78d0 100644 --- a/driver-cql/src/main/resources/cql.md +++ b/driver-cql/src/main/resources/cql.md @@ -1,6 +1,6 @@ # cql driver -This is an driver which allows for the execution of CQL statements. This driver supports both sync and async modes, with +This is a driver which allows for the execution of CQL statements. This driver supports both sync and async modes, with detailed metrics provided for both. ### Example activity definitions @@ -38,7 +38,7 @@ activity types. with no spaces. Examples: - `host=192.168.1.25` - - `host=`192.168.1.25,testhost42` + - `host=192.168.1.25,testhost42` - **workload** - The workload definition which holds the schema and statement defs. see workload yaml location for additional details (no default, required) @@ -59,8 +59,8 @@ activity types. policy in the driver. If used, a WhitelistPolicy(RoundRobinPolicy()) will be created and added to the cluster builder on startup. Examples: - - whitelist=127.0.0.1 - - whitelist=127.0.0.1:9042,127.0.0.2:1234 + - `whitelist=127.0.0.1` + - `whitelist=127.0.0.1:9042,127.0.0.2:1234` - **retrypolicy** default: none - Applies a retry policy in the driver The only option supported for this version is `retrypolicy=logging`, which uses the default retry policy, but with logging added. @@ -107,7 +107,7 @@ activity types. Examples: - `socketoptions=read_timeout_ms=23423,connect_timeout_ms=4444` - - `socketoptions=tcp_no_delay=true + - `socketoptions=tcp_no_delay=true` - **tokens** default: unset - Only executes statements that fall within any of the specified token ranges. Others are counted in metrics @@ -133,36 +133,12 @@ activity types. ignored if passfile is also present. - **passfile** - the file to read the password from. The first line of this file is used as the password. + - **ssl** - specifies the type of the SSL implementation. - Disabled by default, possible values are `jdk`, and `openssl`. - Depending on type, additional parameters need to be provided. -- **tlsversion** - specify the TLS version to use for SSL. - Examples: - - `tlsversion=TLSv1.2` (the default) -- **truststore** (`jdk`, `openssl`) - specify the path to the SSL truststore. - Examples: - - `truststore=file.truststore` -- **tspass** (`jdk`, `openssl`) - specify the password for the SSL truststore. - Examples: - - `tspass=mypass` -- **keystore** (`jdk`) - specify the path to the SSL keystore. - Examples: - - `keystore=file.keystore` -- **kspass** (`jdk`) - specify the password for the SSL keystore. - Examples: - - `kspass=mypass` -- **keyFilePath** (`openssl`) - path to the OpenSSL key file. - Examples: - - `keyFilePath=file.key` -- **keyPassword** (`openssl`) - key password; - Examples: - - `keyPassword=password` -- **caCertFilePath** (`openssl`) - path to the X509 CA certificate file. - Examples: - - `caCertFilePath=cacert.pem` -- **certFilePath** (`openssl`) - path to the X509 certificate file. - Examples: - - `certFilePath=ca.pem` + Disabled by default, possible values are `jdk` and `openssl`. + + [Additional parameters may need to be provided](ssl.md). + - **jmxreporting** - enable JMX reporting if needed. Examples: - `jmxreporting=true` diff --git a/driver-cql/src/main/resources/ssl.md b/driver-cql/src/main/resources/ssl.md new file mode 100644 index 000000000..b6b4ece26 --- /dev/null +++ b/driver-cql/src/main/resources/ssl.md @@ -0,0 +1,56 @@ +# SSL + +Supported options: + +- **ssl** - specifies the type of the SSL implementation. + Disabled by default, possible values are `jdk`, and `openssl`. + +- **tlsversion** - specify the TLS version to use for SSL. + + Examples: + - `tlsversion=TLSv1.2` (the default) + +For `jdk` type, the following options are available: + +- **truststore** - specify the path to the SSL truststore. + + Examples: + - `truststore=file.truststore` + +- **tspass** - specify the password for the SSL truststore. + + Examples: + - `tspass=truststore_pass` + +- **keystore** - specify the path to the SSL keystore. + + Examples: + - `keystore=file.keystore` + +- **kspass** - specify the password for the SSL keystore. + + Examples: + - `kspass=keystore_pass` + +- **keyPassword** - specify the password for the key. + + Examples: + - `keyPassword=password` + + +For `openssl` type, the following options are available: + +- **caCertFilePath** - path to the X509 CA certificate file. + + Examples: + - `caCertFilePath=cacert.crt` + +- **certFilePath** - path to the X509 certificate file. + + Examples: + - `certFilePath=ca.pem` + +- **keyFilePath** - path to the OpenSSL key file. + + Examples: + - `keyFilePath=file.key` diff --git a/driver-tcp/src/main/resources/tcpclient.md b/driver-tcp/src/main/resources/tcpclient.md index 3d71bab0e..82ca1f4c6 100644 --- a/driver-tcp/src/main/resources/tcpclient.md +++ b/driver-tcp/src/main/resources/tcpclient.md @@ -37,6 +37,11 @@ Run a stdout activity named 'stdout-test', with definitions from activities/stdo - **ssl** - boolean to enable or disable ssl - default: false - dynamic: false + + To enable, specifies the type of the SSL implementation with either `jdk` or `openssl`. + + [Additional parameters may need to be provided](../../../../driver-cql/src/main/resources/ssl.md). + - **host** - this is the name to connect to (remote server IP address) - default: localhost - dynamic: false @@ -50,5 +55,4 @@ Run a stdout activity named 'stdout-test', with definitions from activities/stdo ## Statement Format -Refer to the help for the stdout driver for for details. - +Refer to the help for the stdout driver for details. diff --git a/driver-tcp/src/main/resources/tcpserver.md b/driver-tcp/src/main/resources/tcpserver.md index f21a4cc68..f3f679bd2 100644 --- a/driver-tcp/src/main/resources/tcpserver.md +++ b/driver-tcp/src/main/resources/tcpserver.md @@ -36,9 +36,15 @@ Run a stdout activity named 'stdout-test', with definitions from activities/stdo failed. - default: 3 - dynamic: false + - **ssl** - boolean to enable or disable ssl - default: false - dynamic: false + + To enable, specifies the type of the SSL implementation with either `jdk` or `openssl`. + + [Additional parameters may need to be provided](../../../../driver-cql/src/main/resources/ssl.md). + - **host** - this is the name to bind to (local interface address) - default: localhost - dynamic: false @@ -52,5 +58,4 @@ Run a stdout activity named 'stdout-test', with definitions from activities/stdo ## Statement Format -Refer to the help for the stdout driver for for details. - +Refer to the help for the stdout driver for details. diff --git a/engine-api/src/main/java/io/nosqlbench/engine/api/util/SSLKsFactory.java b/engine-api/src/main/java/io/nosqlbench/engine/api/util/SSLKsFactory.java index b3537f345..82f26f88f 100644 --- a/engine-api/src/main/java/io/nosqlbench/engine/api/util/SSLKsFactory.java +++ b/engine-api/src/main/java/io/nosqlbench/engine/api/util/SSLKsFactory.java @@ -17,29 +17,26 @@ package io.nosqlbench.engine.api.util; -import io.nosqlbench.engine.api.activityimpl.ActivityDef; -import io.netty.handler.ssl.SslContext; -import io.netty.handler.ssl.SslContextBuilder; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - +import java.io.File; +import java.security.KeyStore; +import java.util.Optional; import javax.net.ServerSocketFactory; import javax.net.SocketFactory; import javax.net.ssl.KeyManagerFactory; -import javax.net.ssl.SSLContext; import javax.net.ssl.TrustManagerFactory; -import java.io.File; -import java.io.FileInputStream; -import java.io.InputStream; -import java.security.KeyStore; -import java.security.cert.CertificateFactory; -import java.security.cert.X509Certificate; -import java.util.Optional; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import io.netty.handler.ssl.JdkSslContext; +import io.netty.handler.ssl.SslContext; +import io.netty.handler.ssl.SslContextBuilder; +import io.nosqlbench.engine.api.activityimpl.ActivityDef; public class SSLKsFactory { private final static Logger logger = LoggerFactory.getLogger(SSLKsFactory.class); - private static SSLKsFactory instance = new SSLKsFactory(); + private static final SSLKsFactory instance = new SSLKsFactory(); /** * Consider: https://gist.github.com/artem-smotrakov/bd14e4bde4d7238f7e5ab12c697a86a3 @@ -52,16 +49,28 @@ public class SSLKsFactory { } public ServerSocketFactory createSSLServerSocketFactory(ActivityDef def) { - return ((SSLContext) getContext(def)).getServerSocketFactory(); + SslContext context = getContext(def); + if (context == null) { + throw new IllegalArgumentException("SSL is not enabled."); + } + // FIXME: potential incompatibility issue + return ((JdkSslContext) context).context().getServerSocketFactory(); } public SocketFactory createSocketFactory(ActivityDef def) { - return ((SSLContext) getContext(def)).getSocketFactory(); + SslContext context = getContext(def); + if (context == null) { + throw new IllegalArgumentException("SSL is not enabled."); + } + // FIXME: potential incompatibility issue + return ((JdkSslContext) context).context().getSocketFactory(); } - public Object getContext(ActivityDef def) { + public SslContext getContext(ActivityDef def) { Optional sslParam = def.getParams().getOptionalString("ssl"); if (sslParam.isPresent()) { + String tlsVersion = def.getParams().getOptionalString("tlsversion").orElse("TLSv1.2"); + if (sslParam.get().equals("jdk") || sslParam.get().equals("true")) { if (sslParam.get().equals("true")) { logger.warn("Please update your 'ssl=true' parameter to 'ssl=jdk'"); @@ -69,104 +78,71 @@ public class SSLKsFactory { Optional keystorePath = def.getParams().getOptionalString("keystore"); Optional keystorePass = def.getParams().getOptionalString("kspass"); + char[] keyPassword = def.getParams().getOptionalString("keyPassword") + .map(String::toCharArray) + .orElse(null); Optional truststorePath = def.getParams().getOptionalString("truststore"); Optional truststorePass = def.getParams().getOptionalString("tspass"); - String tlsVersion = def.getParams().getOptionalString("tlsversion").orElse("TLSv1.2"); - if (keystorePath.isPresent() && keystorePass.isPresent() && truststorePath.isPresent() && truststorePass.isPresent()) { + KeyStore ks = keystorePath.map(ksPath -> { try { - KeyStore ks = KeyStore.getInstance("JKS"); - ks.load(new FileInputStream(keystorePath.get()), keystorePass.get().toCharArray()); - - KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm()); - kmf.init(ks, keystorePass.get().toCharArray()); - - TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm()); - if (!truststorePath.get().isEmpty()) { - KeyStore ts = KeyStore.getInstance("JKS"); - InputStream trustStore = new FileInputStream(truststorePath.get()); - - String truststorePassword = truststorePass.get(); - ts.load(trustStore, truststorePassword.toCharArray()); - tmf.init(ts); - } else { - tmf.init(ks); - } - - SSLContext sc = SSLContext.getInstance(tlsVersion); - sc.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null); - - return sc; + return KeyStore.getInstance(new File(ksPath), + keystorePass.map(String::toCharArray).orElse(null)); } catch (Exception e) { - throw new RuntimeException(e); + throw new RuntimeException("Unable to load the keystore. Please check.", e); } + }).orElse(null); - } else if (keystorePath.isEmpty() && keystorePass.isEmpty() && truststorePath.isPresent() && truststorePass.isPresent()) { - try { - TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm()); - KeyStore ts = KeyStore.getInstance("JKS"); - InputStream trustStore = new FileInputStream(truststorePath.get()); - String truststorePassword = truststorePass.get(); - ts.load(trustStore, truststorePassword.toCharArray()); - tmf.init(ts); - SSLContext sc = SSLContext.getInstance(tlsVersion); - sc.init(null, tmf.getTrustManagers(), null); - return sc; - } catch (Exception e) { - throw new RuntimeException(e); - } - } else { - throw new RuntimeException("SSL arguments are incorrectly configured. Please Check."); + KeyManagerFactory kmf; + try { + kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm()); + kmf.init(ks, keyPassword); + } catch (Exception e) { + throw new RuntimeException("Unable to init KeyManagerFactory. Please check.", e); } + KeyStore ts = truststorePath.map(tsPath -> { + try { + return KeyStore.getInstance(new File(tsPath), + truststorePass.map(String::toCharArray).orElse(null)); + } catch (Exception e) { + throw new RuntimeException("Unable to load the truststore. Please check.", e); + } + }).orElse(null); - } else if (sslParam.get().equals("openssl")) { - - logger.info("Cluster builder proceeding with SSL and Client Auth"); - String keyPassword = def.getParams().getOptionalString("keyPassword").orElse(null); - String caCertFileLocation = def.getParams().getOptionalString("caCertFilePath").orElse(null); - String certFileLocation = def.getParams().getOptionalString("certFilePath").orElse(null); - String keyFileLocation = def.getParams().getOptionalString("keyFilePath").orElse(null); - String truststorePath = def.getParams().getOptionalString("truststore").orElse(null); - String truststorePass = def.getParams().getOptionalString("tspass").orElse(null); + TrustManagerFactory tmf; + try { + tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm()); + tmf.init(ts != null ? ts : ks); + } catch (Exception e) { + throw new RuntimeException("Unable to init TrustManagerFactory. Please check.", e); + } try { - KeyStore ks = KeyStore.getInstance("JKS", "SUN"); - char[] pass = keyPassword==null? null : keyPassword.toCharArray(); - ks.load(null, pass); - - X509Certificate cert = (X509Certificate) CertificateFactory. - getInstance("X509"). - generateCertificate(new FileInputStream(caCertFileLocation)); - - //set alias to cert - ks.setCertificateEntry(cert.getSubjectX500Principal().getName(), cert); - - TrustManagerFactory tMF = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm()); - //String truststorePath = System.getProperty("javax.net.ssl.trustStore"); - - if (truststorePath != null && !truststorePath.isEmpty() && truststorePass != null) { - KeyStore ts = KeyStore.getInstance("JKS"); - InputStream trustStore = new FileInputStream(truststorePath); - ts.load(trustStore, truststorePass.toCharArray()); - tMF.init(ts); - } else { - tMF.init(ks); - } - - SslContext sslContext = SslContextBuilder - .forClient() - /* configured with the TrustManagerFactory that has the cert from the ca.cert - * This tells the driver to trust the server during the SSL handshake */ - .trustManager(tMF) - /* These are needed because the server is configured with require_client_auth - * In this case the client's public key must be in the truststore on each DSE - * server node and the CA configured */ - .keyManager(new File(certFileLocation), new File(keyFileLocation)) - .build(); - - return sslContext; + return SslContextBuilder.forClient() + .protocols(tlsVersion) + .trustManager(tmf) + .keyManager(kmf) + .build(); + } catch (Exception e) { + throw new RuntimeException(e); + } + } else if (sslParam.get().equals("openssl")) { + File caCertFileLocation = def.getParams().getOptionalString("caCertFilePath").map(File::new).orElse(null); + File certFileLocation = def.getParams().getOptionalString("certFilePath").map(File::new).orElse(null); + File keyFileLocation = def.getParams().getOptionalString("keyFilePath").map(File::new).orElse(null); + try { + return SslContextBuilder.forClient() + .protocols(tlsVersion) + /* configured with the TrustManagerFactory that has the cert from the ca.cert + * This tells the driver to trust the server during the SSL handshake */ + .trustManager(caCertFileLocation) + /* These are needed if the server is configured with require_client_auth + * In this case the client's public key must be in the truststore on each DSE + * server node and the CA configured */ + .keyManager(certFileLocation, keyFileLocation) + .build(); } catch (Exception e) { throw new RuntimeException(e); } diff --git a/engine-api/src/test/java/io/nosqlbench/engine/api/util/SSLKsFactoryTest.java b/engine-api/src/test/java/io/nosqlbench/engine/api/util/SSLKsFactoryTest.java new file mode 100644 index 000000000..c225c4e8d --- /dev/null +++ b/engine-api/src/test/java/io/nosqlbench/engine/api/util/SSLKsFactoryTest.java @@ -0,0 +1,187 @@ +/* + * + * Copyright 2020 jshook + * Licensed 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 io.nosqlbench.engine.api.util; + +import org.junit.Test; + +import io.nosqlbench.engine.api.activityimpl.ActivityDef; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatExceptionOfType; + +public class SSLKsFactoryTest +{ + @Test + public void testJdkGetContextWithTruststoreAndKeystore() { + String[] params = { + "ssl=jdk", + "truststore=src/test/resources/ssl/server_truststore.p12", + "tspass=nosqlbench_server", + "keystore=src/test/resources/ssl/client.p12", + "kspass=nosqlbench_client", + "keyPassword=nosqlbench_client" + }; + ActivityDef activityDef = ActivityDef.parseActivityDef(String.join(";", params)); + assertThat(SSLKsFactory.get().getContext(activityDef)).isNotNull(); + } + + @Test + public void testJdkGetContextWithTruststore() { + String[] params = { + "ssl=jdk", + "truststore=src/test/resources/ssl/server_truststore.p12", + "tspass=nosqlbench_server" + }; + ActivityDef activityDef = ActivityDef.parseActivityDef(String.join(";", params)); + assertThat(SSLKsFactory.get().getContext(activityDef)).isNotNull(); + } + + @Test + public void testJdkGetContextWithKeystore() { + String[] params = { + "ssl=jdk", + "keystore=src/test/resources/ssl/client.p12", + "kspass=nosqlbench_client", + "keyPassword=nosqlbench_client" + }; + ActivityDef activityDef = ActivityDef.parseActivityDef(String.join(";", params)); + assertThat(SSLKsFactory.get().getContext(activityDef)).isNotNull(); + } + + @Test + public void testOpenSSLGetContextWithCaCertAndClientCert() { + String[] params = { + "ssl=openssl", + "caCertFilePath=src/test/resources/ssl/cacert.crt", + "certFilePath=src/test/resources/ssl/client_cert.pem", + "keyFilePath=src/test/resources/ssl/client.key" + }; + ActivityDef activityDef = ActivityDef.parseActivityDef(String.join(";", params)); + assertThat(SSLKsFactory.get().getContext(activityDef)).isNotNull(); + } + + @Test + public void testOpenSSLGetContextWithCaCert() { + String[] params = { + "ssl=openssl", + "caCertFilePath=src/test/resources/ssl/cacert.crt" + }; + ActivityDef activityDef = ActivityDef.parseActivityDef(String.join(";", params)); + assertThat(SSLKsFactory.get().getContext(activityDef)).isNotNull(); + } + + @Test + public void testJdkGetContext() { + String[] params = { + "ssl=jdk", + "tlsversion=TLSv1.2", + }; + ActivityDef activityDef = ActivityDef.parseActivityDef(String.join(";", params)); + assertThat(SSLKsFactory.get().getContext(activityDef)).isNotNull(); + } + + @Test + public void testOpenSSLGetContext() { + String[] params = { + "ssl=openssl", + "tlsversion=TLSv1.2", + }; + ActivityDef activityDef = ActivityDef.parseActivityDef(String.join(";", params)); + assertThat(SSLKsFactory.get().getContext(activityDef)).isNotNull(); + } + + @Test + public void testLoadKeystoreError() { + String[] params = { + "ssl=jdk", + "keystore=src/test/resources/ssl/non_existing.p12", + "kspass=nosqlbench_client", + "keyPassword=nosqlbench_client" + }; + ActivityDef activityDef = ActivityDef.parseActivityDef(String.join(";", params)); + assertThatExceptionOfType(RuntimeException.class) + .isThrownBy(() -> SSLKsFactory.get().getContext(activityDef)) + .withMessageMatching("Unable to load the keystore. Please check."); + } + + @Test + public void testInitKeyManagerFactoryError() { + String[] params = { + "ssl=jdk", + "keystore=src/test/resources/ssl/client.p12", + "kspass=nosqlbench_client", + "keyPassword=incorrect_password" + }; + ActivityDef activityDef = ActivityDef.parseActivityDef(String.join(";", params)); + assertThatExceptionOfType(RuntimeException.class) + .isThrownBy(() -> SSLKsFactory.get().getContext(activityDef)) + .withMessageMatching("Unable to init KeyManagerFactory. Please check."); + } + + @Test + public void testLoadTruststoreError() { + String[] params = { + "ssl=jdk", + "truststore=src/test/resources/ssl/non_existing.p12", + "tspass=nosqlbench_server" + }; + ActivityDef activityDef = ActivityDef.parseActivityDef(String.join(";", params)); + assertThatExceptionOfType(RuntimeException.class) + .isThrownBy(() -> SSLKsFactory.get().getContext(activityDef)) + .withMessageMatching("Unable to load the truststore. Please check."); + } + + @Test + public void testOpenSSLGetContextWithCaCertError() { + String[] params = { + "ssl=openssl", + "caCertFilePath=src/test/resources/ssl/non_existing.pem" + }; + ActivityDef activityDef = ActivityDef.parseActivityDef(String.join(";", params)); + assertThatExceptionOfType(RuntimeException.class) + .isThrownBy(() -> SSLKsFactory.get().getContext(activityDef)) + .withMessageContaining("File does not contain valid certificates") + .withCauseInstanceOf(IllegalArgumentException.class); + } + + @Test + public void testOpenSSLGetContextWithCertError() { + String[] params = { + "ssl=openssl", + "certFilePath=src/test/resources/ssl/non_existing.pem" + }; + ActivityDef activityDef = ActivityDef.parseActivityDef(String.join(";", params)); + assertThatExceptionOfType(RuntimeException.class) + .isThrownBy(() -> SSLKsFactory.get().getContext(activityDef)) + .withMessageContaining("File does not contain valid certificates") + .withCauseInstanceOf(IllegalArgumentException.class); + } + + @Test + public void testOpenSSLGetContextWithKeyError() { + String[] params = { + "ssl=openssl", + "keyFilePath=src/test/resources/ssl/non_existing.pem" + }; + ActivityDef activityDef = ActivityDef.parseActivityDef(String.join(";", params)); + assertThatExceptionOfType(RuntimeException.class) + .isThrownBy(() -> SSLKsFactory.get().getContext(activityDef)) + .withMessageContaining("File does not contain valid private key") + .withCauseInstanceOf(IllegalArgumentException.class); + } +} \ No newline at end of file diff --git a/engine-api/src/test/resources/ssl/cacert.crt b/engine-api/src/test/resources/ssl/cacert.crt new file mode 100644 index 000000000..b7f20bf0d --- /dev/null +++ b/engine-api/src/test/resources/ssl/cacert.crt @@ -0,0 +1,19 @@ +-----BEGIN CERTIFICATE----- +MIIDEzCCAfsCFA3o5Ne8hiqC9/d5sJzmHg3t3iD8MA0GCSqGSIb3DQEBCwUAMEYx +DzANBgNVBAMMBnJvb3RDYTETMBEGA1UECwwKbm9zcWxiZW5jaDERMA8GA1UECgwI +RGF0YVN0YXgxCzAJBgNVBAYTAlVTMB4XDTIwMDUwNDIyMTcyOFoXDTMwMDUwMjIy +MTcyOFowRjEPMA0GA1UEAwwGcm9vdENhMRMwEQYDVQQLDApub3NxbGJlbmNoMREw +DwYDVQQKDAhEYXRhU3RheDELMAkGA1UEBhMCVVMwggEiMA0GCSqGSIb3DQEBAQUA +A4IBDwAwggEKAoIBAQC5LFz/eR3k8d8F3cB6jnpsnOVIPonHwthcWKOXEy9Z8f31 +s70QhF7tkep3ExqUGhQJyjz4Cdk4cFvElMob9WuaoM5Qp4scKW5rQ47WCV660Ok1 +skKJXE/wLFc8edEn6vyvyUTpAce+B8HlY7cONiwA8mGALnYoPlsn2wFbTYIEGVVv +My01990zgkMYwZErEYe2XXvc3gZEC7An16xzYrfYmYFfs0CsH2GUuDQtcFSmyTKH +nYA+kn92JWEx1WMSsC07B8A0qwxdLJy6/d3VLHshbd3Aimf0Jhkg0mLHC5XlkVxr +3pVYrdVEMuBee6A8v4BG8pG42Fjb1xSYwGM9GelvAgMBAAEwDQYJKoZIhvcNAQEL +BQADggEBADz9MhhOA0/RF6iqW7gfWXlSpU2ks696IEhVRi+F9/y8jbKcwKHFchkN +FRc1W6Xyx6LVunOw3zlbeMh+E0DzNTWMF+njcBQH7S5A8TcumU2CDgGNBdl1692x +/z6nGhYIv4IBxaYEd30HPuRz3MXeVyfbGEnIU8jU0vsbfdtZqPdyEk3PNZoFvosk +WhE0Z4KhYoPjwJLhpAnQgW3/RRSNJySReen5YTWJ0qQGYt1HO0Oqz+YgTsthofWc +g/JbmCAD6L1YiCb6WCbDG5qrjwlzhw8bjiT3vw+y10ZIk07Vwbm4QlHSCoe0ayI4 +Pckz9yE0knBOV+Y1kV2DITKV6kYkWBw= +-----END CERTIFICATE----- diff --git a/engine-api/src/test/resources/ssl/client.key b/engine-api/src/test/resources/ssl/client.key new file mode 100644 index 000000000..c07dba0f9 --- /dev/null +++ b/engine-api/src/test/resources/ssl/client.key @@ -0,0 +1,28 @@ +-----BEGIN PRIVATE KEY----- +MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQC8NqAtNjapKtai +hauevzX64ikBE0vugZLbXjlqfHYMoPqYBcP+Qj7JM1QnRbU0p15NCi/eUuNbzuGQ +IzQFIo/IF3F3ivohOrTsunpFYdZlNCx3ixr4mJr4q5G/HbqGHPRSBGgyB/Sye550 +N819RiZh7d71dkSvig3CTnCK/d4NckSJ2dzYYEE/8ue+gfUsQZJrCPJcp2GTCEsq +kq+3FMyVyZHC0V/BiCO9RouC1P5uE70CHKedpPUdZBJU8vRUMM7y75TqzKIT9/xI +fZ0azUDWO89v/n99+O71M8uYhf4MMvS60DMgW8TfWqrToK+jYwnx4zVVburqu6b/ +JSsvODWvAgMBAAECggEANu+W1zuAvuXjGjL8Aez724vRvh+cxTQK4n7hMWS8rDj8 +jAz6xSce3mleAcyF9KV5j/EOQc1d0XlUO1cbIviQkS3Oj77//Vz+XC6d68x/4LBW +3lm6+J7KdRTXCLqrq+OdqKbipt/Nm58bg/6ZuxwTrffZYToxGC+qjnGIxfkNrEyS +jrTJRBOW7MlUhTjlnSYInsBZljRS7V2Zte3F53PCS8p2dbGRLu224bow/5oE5lt6 +x92cpjt+f/+a7Je+K2KoT/KAfG/SeGKzEQaYrqw1+WMEu4xwCvO+atJQDE0cShzl +4vYwUp3GEmMhwdML817MyxxBKpcz+inqvCatZWgrOQKBgQDtVMLvgFPLnpmKJ1g9 +TGZE5a7FeZQVdF/ALnxko4pvw0ZyqPStlklfkyVvzPZYa99CP5p8oFNyVMONsLVk +U57Y1pmU5Dm0e9E1Zqk4fMPL5h8FOv5F8g6vfg3ZEe2C0FvV7CekxchgcJKTmat6 +fzbwXPK+rW0Ld7etCiPAT+o/jQKBgQDLBMJ0gySusIkBG5gCHymAcgchYj16bbC0 +lbckxYzGXYJoqg/HpEfh7Auh6ofoXnYKRcZ696Rk7vQ6jTaNl3NOLMkxkdhHdQvK +gze1+zWmzsakntfk+auf70M+feh2bSPe7tRoY6y+WYpTuxCGYgEV2WRNL1syEeXW +8lmoDrLtKwKBgQC/MRWJU9wtoSsX/PI9D5sjzdSqCXOehQ3OCKT1fjo8JxhNrobO +gM/DSwtRsdCTEvPcrtiJpa8T3+1Z7A11MVg6X0eChwlluImld3rDot8pF83NrOTC +/GmQPwBw6txoEeqpv4GAYEU4S/gJKDbYjDt6D6cOrS+3mU5C/HQorTiM0QKBgFu0 +1rIS22sdy4V4lX2/3dtrptTpr6OyEPRB/OzbX+/rJZFp4J7qEp53JfoKG0JYCTIy +uqmpW9VMK36Xc2EaXLefe3Ks0unUcXMVOwE1bNLg7NJH/nYsYd5pEhMUhQGZ4248 +rC5LeCi0Acw44AoUEzFvdeN31NYVR6GE8AL+QMzpAoGAJYdZbz/i+EoV23TiWnEE +q0vBZ9dCKhYA3SaV/cwesFANGLOtFhhiUDA9/Jkw8P9eHoWfsqY4ud/nGGWeXvUu +Ox576QcrYoIW6g0Gk7bwS2tSC943LAxS2YkAdMM27BhCZw7jAkmoxbQhf9t2IBMc +ixHr+et58pQWFjF73/Ex16k= +-----END PRIVATE KEY----- diff --git a/engine-api/src/test/resources/ssl/client.p12 b/engine-api/src/test/resources/ssl/client.p12 new file mode 100644 index 000000000..78ea24e6c Binary files /dev/null and b/engine-api/src/test/resources/ssl/client.p12 differ diff --git a/engine-api/src/test/resources/ssl/client_cert.pem b/engine-api/src/test/resources/ssl/client_cert.pem new file mode 100644 index 000000000..70a4e7bf1 --- /dev/null +++ b/engine-api/src/test/resources/ssl/client_cert.pem @@ -0,0 +1,19 @@ +-----BEGIN CERTIFICATE----- +MIIDEzCCAfsCFBuaP3upDuMBExO4l649oUURC/SkMA0GCSqGSIb3DQEBCwUAMEYx +DzANBgNVBAMMBnJvb3RDYTETMBEGA1UECwwKbm9zcWxiZW5jaDERMA8GA1UECgwI +RGF0YVN0YXgxCzAJBgNVBAYTAlVTMB4XDTIwMDUwNDIzMTQ1MloXDTMwMDUwMjIz +MTQ1MlowRjEPMA0GA1UEAwwGY2xpZW50MRMwEQYDVQQLDApub3NxbGJlbmNoMREw +DwYDVQQKDAhEYXRhU3RheDELMAkGA1UEBhMCVVMwggEiMA0GCSqGSIb3DQEBAQUA +A4IBDwAwggEKAoIBAQC8NqAtNjapKtaihauevzX64ikBE0vugZLbXjlqfHYMoPqY +BcP+Qj7JM1QnRbU0p15NCi/eUuNbzuGQIzQFIo/IF3F3ivohOrTsunpFYdZlNCx3 +ixr4mJr4q5G/HbqGHPRSBGgyB/Sye550N819RiZh7d71dkSvig3CTnCK/d4NckSJ +2dzYYEE/8ue+gfUsQZJrCPJcp2GTCEsqkq+3FMyVyZHC0V/BiCO9RouC1P5uE70C +HKedpPUdZBJU8vRUMM7y75TqzKIT9/xIfZ0azUDWO89v/n99+O71M8uYhf4MMvS6 +0DMgW8TfWqrToK+jYwnx4zVVburqu6b/JSsvODWvAgMBAAEwDQYJKoZIhvcNAQEL +BQADggEBAFx3oSbS/6PfEYQjfesUMdHIPHGosrLfjzk0KUtSwRbmIJLIzujaUz4s +UEyuxQhA6ERFNN8AUaighAO6IScYgVlxTeykeE3nGP+tZ+EuIxo6wXoo8WI85ivk +OGspI+2Ne/mo45xSNdvnALnsPLEZM870LBe0UvHcSnDYR0V0d28BzzuAZfMRyT4z +DkBSdouxahzzXIMi/TR0DDu4VMsVl55MNACgV+JDRAAwdYjN6kwJrtfVrsYBrIew +TMUFXuEa1vDcsvAoALDN4+wGa/8TdPnAJuRirHVVfxoKb1XlcDCy/79pCOirUmbn +ib/nCyq+MlFFYrE1YQSVZ2IM8x8n5d4= +-----END CERTIFICATE----- diff --git a/engine-api/src/test/resources/ssl/server_truststore.p12 b/engine-api/src/test/resources/ssl/server_truststore.p12 new file mode 100644 index 000000000..0cfe4a010 Binary files /dev/null and b/engine-api/src/test/resources/ssl/server_truststore.p12 differ