From 23ef9c3040cd7e283b92e7f5d2bde9ecfe8c7a66 Mon Sep 17 00:00:00 2001 From: M Sazzadul Hoque <7600764+sazzad16@users.noreply.github.com> Date: Fri, 27 Sep 2024 01:03:26 +0600 Subject: [PATCH 01/34] Add SslOptions from Lettuce library --- .../java/redis/clients/jedis/SslOptions.java | 389 ++++++++++++++++++ 1 file changed, 389 insertions(+) create mode 100644 src/main/java/redis/clients/jedis/SslOptions.java diff --git a/src/main/java/redis/clients/jedis/SslOptions.java b/src/main/java/redis/clients/jedis/SslOptions.java new file mode 100644 index 0000000000..b1f3ef97b4 --- /dev/null +++ b/src/main/java/redis/clients/jedis/SslOptions.java @@ -0,0 +1,389 @@ +/* + * Copyright 2011-Present, Redis Ltd. and Contributors + * All rights reserved. + * + * Licensed under the MIT License. + * + * This file contains contributions from third-party contributors + * 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 + * + * https://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 redis.clients.jedis; + +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.net.URL; +import java.security.GeneralSecurityException; +import java.security.KeyStore; +import java.util.Arrays; +import java.util.Objects; +import javax.net.ssl.KeyManagerFactory; +import javax.net.ssl.SSLContext; +import javax.net.ssl.TrustManagerFactory; + +/** + * Options to configure SSL options for the connections kept to Redis servers. + * + * @author Mark Paluch + */ +public class SslOptions { + + private final String keyManagerAlgorithm; + + private final String trustManagerAlgorithm; + + private final String keyStoreType; + + private final String trustStoreType; + + private final Resource keystoreResource; + + private final char[] keystorePassword; + + private final Resource truststoreResource; + + private final char[] truststorePassword; + + private SslOptions(Builder builder) { + this.keyManagerAlgorithm = builder.keyManagerAlgorithm; + this.trustManagerAlgorithm = builder.trustManagerAlgorithm; + this.keyStoreType = builder.keyStoreType; + this.trustStoreType = builder.trustStoreType; + this.keystoreResource = builder.keystoreResource; + this.keystorePassword = builder.keystorePassword; + this.truststoreResource = builder.truststoreResource; + this.truststorePassword = builder.truststorePassword; + } + + /** + * Returns a new {@link SslOptions.Builder} to construct {@link SslOptions}. + * + * @return a new {@link SslOptions.Builder} to construct {@link SslOptions}. + */ + public static SslOptions.Builder builder() { + return new SslOptions.Builder(); + } + + /** + * Builder for {@link SslOptions}. + */ + public static class Builder { + + private String keyManagerAlgorithm = KeyManagerFactory.getDefaultAlgorithm(); + //private String keyManagerAlgorithm = TrustManagerFactory.getDefaultAlgorithm(); // Lettuce + + private String trustManagerAlgorithm = TrustManagerFactory.getDefaultAlgorithm(); + + private String keyStoreType; + + private String trustStoreType; + + private Resource keystoreResource; + + private char[] keystorePassword = new char[0]; + + private Resource truststoreResource; + + private char[] truststorePassword = new char[0]; + + private Builder() { + } + + public Builder keyManagerAlgorithm(String keyManagerAlgorithm) { + this.keyManagerAlgorithm = Objects.requireNonNull(keyManagerAlgorithm, "KeyManagerAlgorithm must not be null"); + return this; + } + + public Builder trustManagerAlgorithm(String trustManagerAlgorithm) { + this.trustManagerAlgorithm = Objects.requireNonNull(trustManagerAlgorithm, "TrustManagerAlgorithm must not be null"); + return this; + } + + /** + * Sets the KeyStore type. Defaults to {@link KeyStore#getDefaultType()} if not set. + * + * @param keyStoreType the keystore type to use, must not be {@code null}. + * @return {@code this} + */ + public Builder keyStoreType(String keyStoreType) { + this.keyStoreType = Objects.requireNonNull(keyStoreType, "KeyStoreType must not be null"); + return this; + } + + /** + * Sets the KeyStore type. Defaults to {@link KeyStore#getDefaultType()} if not set. + * + * @param trustStoreType the keystore type to use, must not be {@code null}. + * @return {@code this} + */ + public Builder trustStoreType(String trustStoreType) { + this.trustStoreType = Objects.requireNonNull(trustStoreType, "TrustStoreType must not be null"); + return this; + } + + /** + * Sets the Keystore file to load client certificates. The key store file must be supported by + * {@link java.security.KeyStore} which is {@link KeyStore#getDefaultType()} by default. The keystore is reloaded on + * each connection attempt that allows to replace certificates during runtime. + * + * @param keystore the keystore file, must not be {@code null}. + * @return {@code this} + */ + public Builder keystore(File keystore) { + return keystore(keystore, null); + //return keystore(keystore, new char[0]); // Lettuce + } + + /** + * Sets the Keystore file to load client certificates. The keystore file must be supported by + * {@link java.security.KeyStore} which is {@link KeyStore#getDefaultType()} by default. The keystore is reloaded on + * each connection attempt that allows to replace certificates during runtime. + * + * @param keystore the keystore file, must not be {@code null}. + * @param keystorePassword the keystore password. May be empty to omit password and the keystore integrity check. + * @return {@code this} + */ + public Builder keystore(File keystore, char[] keystorePassword) { + + Objects.requireNonNull(keystore, "Keystore must not be null"); +// LettuceAssert.isTrue(keystore.exists(), () -> String.format("Keystore file %s does not exist", truststore)); +// LettuceAssert.isTrue(keystore.isFile(), () -> String.format("Keystore %s is not a file", truststore)); + + return keystore(Resource.from(keystore), keystorePassword); + } + + /** + * Sets the Keystore resource to load client certificates. The keystore file must be supported by + * {@link java.security.KeyStore} which is {@link KeyStore#getDefaultType()} by default. The keystore is reloaded on + * each connection attempt that allows to replace certificates during runtime. + * + * @param keystore the keystore URL, must not be {@code null}. + * @return {@code this} + */ + public Builder keystore(URL keystore) { + return keystore(keystore, null); + } + + /** + * Sets the Keystore resource to load client certificates. The keystore file must be supported by + * {@link java.security.KeyStore} which is {@link KeyStore#getDefaultType()} by default. The keystore is reloaded on + * each connection attempt that allows to replace certificates during runtime. + * + * @param keystore the keystore file, must not be {@code null}. + * @param keystorePassword + * @return {@code this + */ + public Builder keystore(URL keystore, char[] keystorePassword) { + + Objects.requireNonNull(keystore, "Keystore must not be null"); + + return keystore(Resource.from(keystore), keystorePassword); + } + + /** + * Sets the Java Keystore resource to load client certificates. The keystore file must be supported by + * {@link java.security.KeyStore} which is {@link KeyStore#getDefaultType()} by default. The keystore is reloaded on + * each connection attempt that allows to replace certificates during runtime. + * + * @param resource the provider that opens a {@link InputStream} to the keystore file, must not be {@code null}. + * @param keystorePassword the keystore password. May be empty to omit password and the keystore integrity check. + * @return {@code this} + */ + public Builder keystore(Resource resource, char[] keystorePassword) { + + Objects.requireNonNull(resource, "Keystore InputStreamProvider must not be null"); + + this.keystorePassword = getPassword(keystorePassword); + this.keystoreResource = resource; + + return this; + } + + /** + * Sets the Truststore file to load trusted certificates. The truststore file must be supported by + * {@link java.security.KeyStore} which is {@link KeyStore#getDefaultType()} by default. The truststore is reloaded on + * each connection attempt that allows to replace certificates during runtime. + * + * @param truststore the truststore file, must not be {@code null}. + * @return {@code this} + */ + public Builder truststore(File truststore) { + return truststore(truststore, null); + } + + /** + * Sets the Truststore file to load trusted certificates. The truststore file must be supported by + * {@link java.security.KeyStore} which is {@link KeyStore#getDefaultType()} by default. The truststore is reloaded on + * each connection attempt that allows to replace certificates during runtime. + * + * @param truststore the truststore file, must not be {@code null}. + * @param truststorePassword the truststore password. May be empty to omit password and the truststore integrity check. + * @return {@code this} + */ + public Builder truststore(File truststore, String truststorePassword) { + + Objects.requireNonNull(truststore, "Truststore must not be null"); +// LettuceAssert.isTrue(truststore.exists(), () -> String.format("Truststore file %s does not exist", truststore)); +// LettuceAssert.isTrue(truststore.isFile(), () -> String.format("Truststore file %s is not a file", truststore)); + + return truststore(Resource.from(truststore), getPassword(truststorePassword)); + } + + /** + * Sets the Truststore resource to load trusted certificates. The truststore resource must be supported by + * {@link java.security.KeyStore} which is {@link KeyStore#getDefaultType()} by default. The truststore is reloaded on + * each connection attempt that allows to replace certificates during runtime. + * + * @param truststore the truststore file, must not be {@code null}. + * @return {@code this} + */ + public Builder truststore(URL truststore) { + return truststore(truststore, null); + } + + /** + * Sets the Truststore resource to load trusted certificates. The truststore resource must be supported by + * {@link java.security.KeyStore} which is {@link KeyStore#getDefaultType()} by default. The truststore is reloaded on + * each connection attempt that allows to replace certificates during runtime. + * + * @param truststore the truststore file, must not be {@code null}. + * @param truststorePassword the truststore password. May be empty to omit password and the truststore integrity check. + * @return {@code this} + */ + public Builder truststore(URL truststore, String truststorePassword) { + + Objects.requireNonNull(truststore, "Truststore must not be null"); + + return truststore(Resource.from(truststore), getPassword(truststorePassword)); + } + + /** + * Sets the Truststore resource to load trusted certificates. The truststore resource must be supported by + * {@link java.security.KeyStore} which is {@link KeyStore#getDefaultType()} by default. The truststore is reloaded on + * each connection attempt that allows to replace certificates during runtime. + * + * @param resource the provider that opens a {@link InputStream} to the keystore file, must not be {@code null}. + * @param truststorePassword the truststore password. May be empty to omit password and the truststore integrity check. + * @return {@code this} + */ + private Builder truststore(Resource resource, char[] truststorePassword) { + + Objects.requireNonNull(resource, "Truststore InputStreamProvider must not be null"); + + this.truststorePassword = getPassword(truststorePassword); + this.truststoreResource = resource; + + return this; + } + + /** + * Create a new instance of {@link SslOptions} + * + * @return new instance of {@link SslOptions} + */ + public SslOptions build() { + return new SslOptions(this); + } + + } + + /** + * A {@link SSLContext} object that is configured with values from this {@link SslOptions} object. + * + * @return a {@link SSLContext}. + * @throws IOException thrown when loading the keystore or the truststore fails. + * @throws GeneralSecurityException thrown when loading the keystore or the truststore fails. + */ + public SSLContext createSslContext() throws IOException, GeneralSecurityException { + + KeyStore keyStore = KeyStore.getInstance(keyStoreType); + try (InputStream keystoreStream = keystoreResource.get()) { + keyStore.load(keystoreStream, keystorePassword); + } + + KeyStore trustStore = KeyStore.getInstance(trustStoreType); + try (InputStream truststoreStream = truststoreResource.get()) { + trustStore.load(truststoreStream, truststorePassword); + } + + TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(trustManagerAlgorithm); + trustManagerFactory.init(trustStore); + + KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(keyManagerAlgorithm); + keyManagerFactory.init(keyStore, keystorePassword); + + SSLContext sslContext = SSLContext.getDefault(); + //SSLContext sslContext = SSLContext.getInstance("TLS"); // examples + + sslContext.init(keyManagerFactory.getKeyManagers(), trustManagerFactory.getTrustManagers(), null); + + return sslContext; + } + + private static boolean isEmpty(String cs) { + return cs == null || cs.isEmpty(); + } + + private static char[] getPassword(String truststorePassword) { + return !isEmpty(truststorePassword) ? truststorePassword.toCharArray() : null; + } + + private static char[] getPassword(char[] chars) { + return chars != null ? Arrays.copyOf(chars, chars.length) : null; + } + + /** + * Supplier for a {@link InputStream} representing a resource. The resulting {@link InputStream} must be closed by + * the calling code. + */ + @FunctionalInterface + public interface Resource { + + /** + * Create a {@link Resource} that obtains a {@link InputStream} from a {@link URL}. + * + * @param url the URL to obtain the {@link InputStream} from. + * @return a {@link Resource} that opens a connection to the URL and obtains the {@link InputStream} for it. + */ + static Resource from(URL url) { + + Objects.requireNonNull(url, "URL must not be null"); + + return () -> url.openConnection().getInputStream(); + } + + /** + * Create a {@link Resource} that obtains a {@link InputStream} from a {@link File}. + * + * @param file the File to obtain the {@link InputStream} from. + * @return a {@link Resource} that obtains the {@link FileInputStream} for the given {@link File}. + */ + static Resource from(File file) { + + Objects.requireNonNull(file, "File must not be null"); + + return () -> new FileInputStream(file); + } + + /** + * Obtains the {@link InputStream}. + * + * @return the {@link InputStream}. + * @throws IOException + */ + InputStream get() throws IOException; + + } + +} From 375e1ca843e8e0133e789980b48eb01582ab48dc Mon Sep 17 00:00:00 2001 From: M Sazzadul Hoque <7600764+sazzad16@users.noreply.github.com> Date: Fri, 27 Sep 2024 12:34:34 +0600 Subject: [PATCH 02/34] Add InsecureTrustManagerFactory from Netty library --- .../util/InsecureTrustManagerFactory.java | 225 ++++++++++++++++++ 1 file changed, 225 insertions(+) create mode 100644 src/main/java/redis/clients/jedis/util/InsecureTrustManagerFactory.java diff --git a/src/main/java/redis/clients/jedis/util/InsecureTrustManagerFactory.java b/src/main/java/redis/clients/jedis/util/InsecureTrustManagerFactory.java new file mode 100644 index 0000000000..c5e4411340 --- /dev/null +++ b/src/main/java/redis/clients/jedis/util/InsecureTrustManagerFactory.java @@ -0,0 +1,225 @@ +/* + * Copyright 2014 The Netty Project + * + * The Netty Project 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: + * + * https://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 redis.clients.jedis.util; + +import java.net.Socket; +import javax.net.ssl.ManagerFactoryParameters; +import javax.net.ssl.SSLEngine; +import javax.net.ssl.TrustManager; +import javax.net.ssl.TrustManagerFactory; +import javax.net.ssl.TrustManagerFactorySpi; +import javax.net.ssl.X509ExtendedTrustManager; +import javax.net.ssl.X509TrustManager; +import java.security.InvalidAlgorithmParameterException; +import java.security.KeyStore; +import java.security.KeyStoreException; +import java.security.Provider; +import java.security.cert.CertificateException; +import java.security.cert.X509Certificate; + +import java.util.Objects; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * An insecure {@link TrustManagerFactory} that trusts all X.509 certificates without any verification. + *
+ * NOTE: + * Never use this {@link TrustManagerFactory} in production. + * It is purely for testing purposes, and thus it is very insecure. + *
+ */ +public final class InsecureTrustManagerFactory extends TrustManagerFactory { + + private static final Logger logger = LoggerFactory.getLogger(InsecureTrustManagerFactory.class); + + public static final TrustManagerFactory INSTANCE = new InsecureTrustManagerFactory(); + + private static final X509Certificate[] EMPTY_X509_CERTIFICATES = {}; + + private static final Provider PROVIDER = new Provider("", 0.0, "") { + private static final long serialVersionUID = -2680540247105807895L; + }; + + /** + * {@link InsecureTrustManagerFactorySpi} must have a reference to {@link InsecureTrustManagerFactory} + * to delegate its callbacks back to {@link InsecureTrustManagerFactory}. However, it is impossible to do so, + * because {@link TrustManagerFactory} requires {@link TrustManagerFactorySpi} at construction time and + * does not provide a way to access it later. + * + * To work around this issue, we use an ugly hack which uses a {@link ThreadLocal}. + */ + private static final ThreadLocal- * NOTE: - * Never use this {@link TrustManagerFactory} in production. - * It is purely for testing purposes, and thus it is very insecure. - *
- */ -public final class InsecureTrustManagerFactory extends TrustManagerFactory { - - private static final Logger logger = LoggerFactory.getLogger(InsecureTrustManagerFactory.class); - - public static final TrustManagerFactory INSTANCE = new InsecureTrustManagerFactory(); - - private static final X509Certificate[] EMPTY_X509_CERTIFICATES = {}; - - private static final Provider PROVIDER = new Provider("", 0.0, "") { - private static final long serialVersionUID = -2680540247105807895L; - }; - - /** - * {@link InsecureTrustManagerFactorySpi} must have a reference to {@link InsecureTrustManagerFactory} - * to delegate its callbacks back to {@link InsecureTrustManagerFactory}. However, it is impossible to do so, - * because {@link TrustManagerFactory} requires {@link TrustManagerFactorySpi} at construction time and - * does not provide a way to access it later. - * - * To work around this issue, we use an ugly hack which uses a {@link ThreadLocal}. - */ - private static final ThreadLocal
* This test is only executed when the server/cluster is Redis 6. or more.
*/
+@org.junit.Ignore
public class SSLACLJedisTest {
protected static final EndpointConfig endpoint = HostAndPorts.getRedisEndpoint("standalone0-acl-tls");
diff --git a/src/test/java/redis/clients/jedis/SSLJedisClusterTest.java b/src/test/java/redis/clients/jedis/SSLJedisClusterTest.java
index f4763fe875..802b99620b 100644
--- a/src/test/java/redis/clients/jedis/SSLJedisClusterTest.java
+++ b/src/test/java/redis/clients/jedis/SSLJedisClusterTest.java
@@ -17,6 +17,7 @@
import redis.clients.jedis.exceptions.JedisClusterOperationException;
import redis.clients.jedis.SSLJedisTest.BasicHostnameVerifier;
+@org.junit.Ignore
public class SSLJedisClusterTest extends JedisClusterTestBase {
private static final int DEFAULT_REDIRECTIONS = 5;
diff --git a/src/test/java/redis/clients/jedis/SSLJedisSentinelPoolTest.java b/src/test/java/redis/clients/jedis/SSLJedisSentinelPoolTest.java
index 7468c9abfa..7fa8d88ec3 100644
--- a/src/test/java/redis/clients/jedis/SSLJedisSentinelPoolTest.java
+++ b/src/test/java/redis/clients/jedis/SSLJedisSentinelPoolTest.java
@@ -6,6 +6,7 @@
import org.junit.BeforeClass;
import org.junit.Test;
+@org.junit.Ignore
public class SSLJedisSentinelPoolTest {
private static final String MASTER_NAME = "aclmaster";
diff --git a/src/test/java/redis/clients/jedis/SSLJedisTest.java b/src/test/java/redis/clients/jedis/SSLJedisTest.java
index 4ef4f969bb..8aae443fe6 100644
--- a/src/test/java/redis/clients/jedis/SSLJedisTest.java
+++ b/src/test/java/redis/clients/jedis/SSLJedisTest.java
@@ -23,6 +23,7 @@
import org.junit.BeforeClass;
import org.junit.Test;
+@org.junit.Ignore
public class SSLJedisTest {
protected static final EndpointConfig endpoint = HostAndPorts.getRedisEndpoint("standalone0-tls");
@@ -33,15 +34,15 @@ public static void prepare() {
}
public static void setupTrustStore() {
- setJvmTrustStore("src/test/resources/truststore.jceks", "jceks");
+// setJvmTrustStore("src/test/resources/truststore.jceks", "jceks");
}
- private static void setJvmTrustStore(String trustStoreFilePath, String trustStoreType) {
- assertTrue(String.format("Could not find trust store at '%s'.", trustStoreFilePath),
- new File(trustStoreFilePath).exists());
- System.setProperty("javax.net.ssl.trustStore", trustStoreFilePath);
- System.setProperty("javax.net.ssl.trustStoreType", trustStoreType);
- }
+// private static void setJvmTrustStore(String trustStoreFilePath, String trustStoreType) {
+// assertTrue(String.format("Could not find trust store at '%s'.", trustStoreFilePath),
+// new File(trustStoreFilePath).exists());
+// System.setProperty("javax.net.ssl.trustStore", trustStoreFilePath);
+// System.setProperty("javax.net.ssl.trustStoreType", trustStoreType);
+// }
@Test
public void connectWithSsl() {
diff --git a/src/test/java/redis/clients/jedis/csc/SSLJedisPooledClientSideCacheTest.java b/src/test/java/redis/clients/jedis/csc/SSLJedisPooledClientSideCacheTest.java
index b8df3910cd..42c8f29f63 100644
--- a/src/test/java/redis/clients/jedis/csc/SSLJedisPooledClientSideCacheTest.java
+++ b/src/test/java/redis/clients/jedis/csc/SSLJedisPooledClientSideCacheTest.java
@@ -4,6 +4,7 @@
import redis.clients.jedis.HostAndPorts;
import redis.clients.jedis.SSLJedisTest;
+@org.junit.Ignore
public class SSLJedisPooledClientSideCacheTest extends JedisPooledClientSideCacheTestBase {
@BeforeClass
From 1566a2a73cd59764ddaa1784b5d7105caa1e9ea3 Mon Sep 17 00:00:00 2001
From: M Sazzadul Hoque <7600764+sazzad16@users.noreply.github.com>
Date: Mon, 18 Nov 2024 17:57:30 +0600
Subject: [PATCH 14/34] JedisTest with SslOptions
---
.../java/redis/clients/jedis/SslOptions.java | 9 +-
.../clients/jedis/SSLOptionsJedisTest.java | 139 ++++++++++++++++++
2 files changed, 144 insertions(+), 4 deletions(-)
create mode 100644 src/test/java/redis/clients/jedis/SSLOptionsJedisTest.java
diff --git a/src/main/java/redis/clients/jedis/SslOptions.java b/src/main/java/redis/clients/jedis/SslOptions.java
index e5d3c5f059..278ddc3ba5 100644
--- a/src/main/java/redis/clients/jedis/SslOptions.java
+++ b/src/main/java/redis/clients/jedis/SslOptions.java
@@ -366,7 +366,7 @@ public SSLContext createSslContext() throws IOException, GeneralSecurityExceptio
}
KeyManager[] keyManagers = null;
- if (keyManagerAlgorithm != null) {
+ if (keystoreResource != null) {
KeyStore keyStore = KeyStore.getInstance(keyStoreType);
try (InputStream keystoreStream = keystoreResource.get()) {
@@ -380,7 +380,7 @@ public SSLContext createSslContext() throws IOException, GeneralSecurityExceptio
if (trustManagers != null) {
// skip
- } else if (trustManagerAlgorithm == null) {
+ } else if (truststoreResource != null) {
KeyStore trustStore = KeyStore.getInstance(trustStoreType);
try (InputStream truststoreStream = truststoreResource.get()) {
@@ -392,8 +392,9 @@ public SSLContext createSslContext() throws IOException, GeneralSecurityExceptio
trustManagers = trustManagerFactory.getTrustManagers();
}
- SSLContext sslContext = SSLContext.getDefault();
- //SSLContext sslContext = SSLContext.getInstance("TLS"); // examples
+ //SSLContext sslContext = SSLContext.getDefault(); // throws exception
+ //SSLContext sslContext = SSLContext.getInstance("TLS"); // in redis.io examples, works
+ SSLContext sslContext = SSLContext.getInstance("SSL"); // also works
sslContext.init(keyManagers, trustManagers, null);
diff --git a/src/test/java/redis/clients/jedis/SSLOptionsJedisTest.java b/src/test/java/redis/clients/jedis/SSLOptionsJedisTest.java
new file mode 100644
index 0000000000..15a6010326
--- /dev/null
+++ b/src/test/java/redis/clients/jedis/SSLOptionsJedisTest.java
@@ -0,0 +1,139 @@
+package redis.clients.jedis;
+
+import static org.junit.Assert.assertEquals;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.InputStream;
+import java.security.InvalidAlgorithmParameterException;
+import java.security.KeyStore;
+import java.security.SecureRandom;
+import java.security.cert.X509Certificate;
+
+import javax.net.ssl.HostnameVerifier;
+import javax.net.ssl.SSLContext;
+import javax.net.ssl.SSLPeerUnverifiedException;
+import javax.net.ssl.SSLSession;
+import javax.net.ssl.SSLSocketFactory;
+import javax.net.ssl.TrustManager;
+import javax.net.ssl.TrustManagerFactory;
+import javax.net.ssl.X509TrustManager;
+
+import org.junit.Test;
+
+public class SSLOptionsJedisTest {
+
+ protected static final EndpointConfig endpoint = HostAndPorts.getRedisEndpoint("standalone0-tls");
+
+ @Test
+ public void connectWithSsl() {
+ try (Jedis jedis = new Jedis(endpoint.getHostAndPort(),
+ DefaultJedisClientConfig.builder()
+ .sslOptions(SslOptions.builder()
+ .truststore(new File("src/test/resources/truststore.jceks"))
+ .trustStoreType("jceks")
+ .build()).build())) {
+ jedis.auth(endpoint.getPassword());
+ assertEquals("PONG", jedis.ping());
+ }
+ }
+
+ @Test
+ public void connectWithSslConfig() {
+ try (Jedis jedis = new Jedis(endpoint.getHostAndPort(),
+ endpoint.getClientConfigBuilder()
+ .sslOptions(SslOptions.builder()
+ .truststore(new File("src/test/resources/truststore.jceks"))
+ .trustStoreType("jceks")
+ .build()).build())) {
+ jedis.auth(endpoint.getPassword());
+ assertEquals("PONG", jedis.ping());
+ }
+ }
+
+ @Test
+ public void connectWithSslInsecure() {
+ try (Jedis jedis = new Jedis(endpoint.getHostAndPort(),
+ endpoint.getClientConfigBuilder()
+ .sslOptions(SslOptions.builder()
+ .sslVerifyMode(SslVerifyMode.INSECURE)
+ .build()).build())) {
+ jedis.auth(endpoint.getPassword());
+ assertEquals("PONG", jedis.ping());
+ }
+ }
+
+ /**
+ * Creates an SSLSocketFactory that trusts all certificates in truststore.jceks.
+ */
+ static SSLSocketFactory createTrustStoreSslSocketFactory() throws Exception {
+
+ KeyStore trustStore = KeyStore.getInstance("jceks");
+
+ try (InputStream inputStream = new FileInputStream("src/test/resources/truststore.jceks")) {
+ trustStore.load(inputStream, null);
+ }
+
+ TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance("PKIX");
+ trustManagerFactory.init(trustStore);
+ TrustManager[] trustManagers = trustManagerFactory.getTrustManagers();
+
+ SSLContext sslContext = SSLContext.getInstance("TLS");
+ sslContext.init(null, trustManagers, new SecureRandom());
+ return sslContext.getSocketFactory();
+ }
+
+ /**
+ * Creates an SSLSocketFactory with a trust manager that does not trust any certificates.
+ */
+ static SSLSocketFactory createTrustNoOneSslSocketFactory() throws Exception {
+ TrustManager[] unTrustManagers = new TrustManager[] { new X509TrustManager() {
+ public X509Certificate[] getAcceptedIssuers() {
+ return new X509Certificate[0];
+ }
+
+ public void checkClientTrusted(X509Certificate[] chain, String authType) {
+ throw new RuntimeException(new InvalidAlgorithmParameterException());
+ }
+
+ public void checkServerTrusted(X509Certificate[] chain, String authType) {
+ throw new RuntimeException(new InvalidAlgorithmParameterException());
+ }
+ } };
+ SSLContext sslContext = SSLContext.getInstance("TLS");
+ sslContext.init(null, unTrustManagers, new SecureRandom());
+ return sslContext.getSocketFactory();
+ }
+
+ /**
+ * Very basic hostname verifier implementation for testing. NOT recommended for production.
+ */
+ static class BasicHostnameVerifier implements HostnameVerifier {
+
+ private static final String COMMON_NAME_RDN_PREFIX = "CN=";
+
+ @Override
+ public boolean verify(String hostname, SSLSession session) {
+ X509Certificate peerCertificate;
+ try {
+ peerCertificate = (X509Certificate) session.getPeerCertificates()[0];
+ } catch (SSLPeerUnverifiedException e) {
+ throw new IllegalStateException("The session does not contain a peer X.509 certificate.", e);
+ }
+ String peerCertificateCN = getCommonName(peerCertificate);
+ return hostname.equals(peerCertificateCN);
+ }
+
+ private String getCommonName(X509Certificate peerCertificate) {
+ String subjectDN = peerCertificate.getSubjectDN().getName();
+ String[] dnComponents = subjectDN.split(",");
+ for (String dnComponent : dnComponents) {
+ dnComponent = dnComponent.trim();
+ if (dnComponent.startsWith(COMMON_NAME_RDN_PREFIX)) {
+ return dnComponent.substring(COMMON_NAME_RDN_PREFIX.length());
+ }
+ }
+ throw new IllegalArgumentException("The certificate has no common name.");
+ }
+ }
+}
From 06e258724ba19225760431dca665d9c8c2358ac8 Mon Sep 17 00:00:00 2001
From: M Sazzadul Hoque <7600764+sazzad16@users.noreply.github.com>
Date: Mon, 18 Nov 2024 18:16:35 +0600
Subject: [PATCH 15/34] SSLACLJedisTest with SslOptions
---
.../redis/clients/jedis/SSLACLJedisTest.java | 81 -------------------
.../clients/jedis/SSLOptionsJedisTest.java | 18 ++++-
2 files changed, 15 insertions(+), 84 deletions(-)
diff --git a/src/test/java/redis/clients/jedis/SSLACLJedisTest.java b/src/test/java/redis/clients/jedis/SSLACLJedisTest.java
index df0f89acbd..027c0055d4 100644
--- a/src/test/java/redis/clients/jedis/SSLACLJedisTest.java
+++ b/src/test/java/redis/clients/jedis/SSLACLJedisTest.java
@@ -2,14 +2,6 @@
import static org.junit.Assert.*;
-import java.io.FileInputStream;
-import java.io.InputStream;
-import java.security.InvalidAlgorithmParameterException;
-import java.security.KeyStore;
-import java.security.SecureRandom;
-import java.security.cert.X509Certificate;
-import javax.net.ssl.*;
-
import org.junit.BeforeClass;
import org.junit.Test;
@@ -77,77 +69,4 @@ public void connectWithUri() {
assertEquals("PONG", jedis.ping());
}
}
-
- /**
- * Creates an SSLSocketFactory that trusts all certificates in truststore.jceks.
- */
- static SSLSocketFactory createTrustStoreSslSocketFactory() throws Exception {
-
- KeyStore trustStore = KeyStore.getInstance("jceks");
- try (InputStream inputStream = new FileInputStream("src/test/resources/truststore.jceks")) {
- trustStore.load(inputStream, null);
- }
-
- TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance("PKIX");
- trustManagerFactory.init(trustStore);
- TrustManager[] trustManagers = trustManagerFactory.getTrustManagers();
-
- SSLContext sslContext = SSLContext.getInstance("TLS");
- sslContext.init(null, trustManagers, new SecureRandom());
- return sslContext.getSocketFactory();
- }
-
- /**
- * Creates an SSLSocketFactory with a trust manager that does not trust any certificates.
- */
- static SSLSocketFactory createTrustNoOneSslSocketFactory() throws Exception {
- TrustManager[] unTrustManagers = new TrustManager[] { new X509TrustManager() {
- public X509Certificate[] getAcceptedIssuers() {
- return new X509Certificate[0];
- }
-
- public void checkClientTrusted(X509Certificate[] chain, String authType) {
- throw new RuntimeException(new InvalidAlgorithmParameterException());
- }
-
- public void checkServerTrusted(X509Certificate[] chain, String authType) {
- throw new RuntimeException(new InvalidAlgorithmParameterException());
- }
- } };
- SSLContext sslContext = SSLContext.getInstance("TLS");
- sslContext.init(null, unTrustManagers, new SecureRandom());
- return sslContext.getSocketFactory();
- }
-
- /**
- * Very basic hostname verifier implementation for testing. NOT recommended for production.
- */
- static class BasicHostnameVerifier implements HostnameVerifier {
-
- private static final String COMMON_NAME_RDN_PREFIX = "CN=";
-
- @Override
- public boolean verify(String hostname, SSLSession session) {
- X509Certificate peerCertificate;
- try {
- peerCertificate = (X509Certificate) session.getPeerCertificates()[0];
- } catch (SSLPeerUnverifiedException e) {
- throw new IllegalStateException("The session does not contain a peer X.509 certificate.", e);
- }
- String peerCertificateCN = getCommonName(peerCertificate);
- return hostname.equals(peerCertificateCN);
- }
-
- private String getCommonName(X509Certificate peerCertificate) {
- String subjectDN = peerCertificate.getSubjectDN().getName();
- String[] dnComponents = subjectDN.split(",");
- for (String dnComponent : dnComponents) {
- dnComponent = dnComponent.trim();
- if (dnComponent.startsWith(COMMON_NAME_RDN_PREFIX)) {
- return dnComponent.substring(COMMON_NAME_RDN_PREFIX.length());
- }
- }
- throw new IllegalArgumentException("The certificate has no common name.");
- }
- }
}
diff --git a/src/test/java/redis/clients/jedis/SSLOptionsJedisTest.java b/src/test/java/redis/clients/jedis/SSLOptionsJedisTest.java
index 15a6010326..719b51b6ba 100644
--- a/src/test/java/redis/clients/jedis/SSLOptionsJedisTest.java
+++ b/src/test/java/redis/clients/jedis/SSLOptionsJedisTest.java
@@ -25,6 +25,8 @@ public class SSLOptionsJedisTest {
protected static final EndpointConfig endpoint = HostAndPorts.getRedisEndpoint("standalone0-tls");
+ protected static final EndpointConfig aclEndpoint = HostAndPorts.getRedisEndpoint("standalone0-acl-tls");
+
@Test
public void connectWithSsl() {
try (Jedis jedis = new Jedis(endpoint.getHostAndPort(),
@@ -39,14 +41,13 @@ public void connectWithSsl() {
}
@Test
- public void connectWithSslConfig() {
+ public void connectWithConfig() {
try (Jedis jedis = new Jedis(endpoint.getHostAndPort(),
endpoint.getClientConfigBuilder()
.sslOptions(SslOptions.builder()
.truststore(new File("src/test/resources/truststore.jceks"))
.trustStoreType("jceks")
.build()).build())) {
- jedis.auth(endpoint.getPassword());
assertEquals("PONG", jedis.ping());
}
}
@@ -58,7 +59,18 @@ public void connectWithSslInsecure() {
.sslOptions(SslOptions.builder()
.sslVerifyMode(SslVerifyMode.INSECURE)
.build()).build())) {
- jedis.auth(endpoint.getPassword());
+ assertEquals("PONG", jedis.ping());
+ }
+ }
+
+ @Test
+ public void connectWithAcl() {
+ try (Jedis jedis = new Jedis(aclEndpoint.getHostAndPort(),
+ aclEndpoint.getClientConfigBuilder()
+ .sslOptions(SslOptions.builder()
+ .truststore(new File("src/test/resources/truststore.jceks"))
+ .trustStoreType("jceks")
+ .build()).build())) {
assertEquals("PONG", jedis.ping());
}
}
From 4b27241e466022d457233081f6f5ba3ef0ab5662 Mon Sep 17 00:00:00 2001
From: M Sazzadul Hoque <7600764+sazzad16@users.noreply.github.com>
Date: Mon, 18 Nov 2024 19:34:54 +0600
Subject: [PATCH 16/34] SSLOptionsJedisSentinelPoolTest with SslOptions
---
.../SSLOptionsJedisSentinelPoolTest.java | 100 ++++++++++++++++++
1 file changed, 100 insertions(+)
create mode 100644 src/test/java/redis/clients/jedis/SSLOptionsJedisSentinelPoolTest.java
diff --git a/src/test/java/redis/clients/jedis/SSLOptionsJedisSentinelPoolTest.java b/src/test/java/redis/clients/jedis/SSLOptionsJedisSentinelPoolTest.java
new file mode 100644
index 0000000000..062ef49052
--- /dev/null
+++ b/src/test/java/redis/clients/jedis/SSLOptionsJedisSentinelPoolTest.java
@@ -0,0 +1,100 @@
+package redis.clients.jedis;
+
+import java.io.File;
+import java.util.HashSet;
+import java.util.Set;
+import org.apache.commons.pool2.impl.GenericObjectPoolConfig;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+public class SSLOptionsJedisSentinelPoolTest {
+
+ private static final String MASTER_NAME = "aclmaster";
+
+ private static Set
* This test is only executed when the server/cluster is Redis 6. or more.
*/
-@org.junit.Ignore
+@org.junit.Ignore // TODO: enable -- (in a different way?)
public class SSLACLJedisTest {
protected static final EndpointConfig endpoint = HostAndPorts.getRedisEndpoint("standalone0-acl-tls");
diff --git a/src/test/java/redis/clients/jedis/SSLJedisClusterTest.java b/src/test/java/redis/clients/jedis/SSLJedisClusterTest.java
index 802b99620b..f46cd45db7 100644
--- a/src/test/java/redis/clients/jedis/SSLJedisClusterTest.java
+++ b/src/test/java/redis/clients/jedis/SSLJedisClusterTest.java
@@ -17,7 +17,7 @@
import redis.clients.jedis.exceptions.JedisClusterOperationException;
import redis.clients.jedis.SSLJedisTest.BasicHostnameVerifier;
-@org.junit.Ignore
+@org.junit.Ignore // TODO: enable -- (in a different way?)
public class SSLJedisClusterTest extends JedisClusterTestBase {
private static final int DEFAULT_REDIRECTIONS = 5;
diff --git a/src/test/java/redis/clients/jedis/SSLJedisSentinelPoolTest.java b/src/test/java/redis/clients/jedis/SSLJedisSentinelPoolTest.java
index 7fa8d88ec3..3f576956d8 100644
--- a/src/test/java/redis/clients/jedis/SSLJedisSentinelPoolTest.java
+++ b/src/test/java/redis/clients/jedis/SSLJedisSentinelPoolTest.java
@@ -6,7 +6,7 @@
import org.junit.BeforeClass;
import org.junit.Test;
-@org.junit.Ignore
+@org.junit.Ignore // TODO: enable -- (in a different way?)
public class SSLJedisSentinelPoolTest {
private static final String MASTER_NAME = "aclmaster";
diff --git a/src/test/java/redis/clients/jedis/SSLJedisTest.java b/src/test/java/redis/clients/jedis/SSLJedisTest.java
index 8aae443fe6..0d3c1e01d6 100644
--- a/src/test/java/redis/clients/jedis/SSLJedisTest.java
+++ b/src/test/java/redis/clients/jedis/SSLJedisTest.java
@@ -23,7 +23,7 @@
import org.junit.BeforeClass;
import org.junit.Test;
-@org.junit.Ignore
+@org.junit.Ignore // TODO: enable -- (in a different way?)
public class SSLJedisTest {
protected static final EndpointConfig endpoint = HostAndPorts.getRedisEndpoint("standalone0-tls");
From ff88451400df82e7e38a9a984f6523660df12152 Mon Sep 17 00:00:00 2001
From: M Sazzadul Hoque <7600764+sazzad16@users.noreply.github.com>
Date: Mon, 18 Nov 2024 22:24:58 +0600
Subject: [PATCH 19/34] TODO command to enable existing SSL tests in csc
package
---
.../clients/jedis/csc/SSLJedisPooledClientSideCacheTest.java | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/test/java/redis/clients/jedis/csc/SSLJedisPooledClientSideCacheTest.java b/src/test/java/redis/clients/jedis/csc/SSLJedisPooledClientSideCacheTest.java
index 42c8f29f63..c62a4460ee 100644
--- a/src/test/java/redis/clients/jedis/csc/SSLJedisPooledClientSideCacheTest.java
+++ b/src/test/java/redis/clients/jedis/csc/SSLJedisPooledClientSideCacheTest.java
@@ -4,7 +4,7 @@
import redis.clients.jedis.HostAndPorts;
import redis.clients.jedis.SSLJedisTest;
-@org.junit.Ignore
+@org.junit.Ignore // TODO: enable
public class SSLJedisPooledClientSideCacheTest extends JedisPooledClientSideCacheTestBase {
@BeforeClass
From 315d73d5f8382a8c606a38858537a5485587fa28 Mon Sep 17 00:00:00 2001
From: M Sazzadul Hoque <7600764+sazzad16@users.noreply.github.com>
Date: Mon, 18 Nov 2024 22:59:20 +0600
Subject: [PATCH 20/34] Enable existing SSL tests without impacting new ones
---
.../clients/jedis/SSLACLJedisClusterTest.java | 13 ++++---
.../redis/clients/jedis/SSLACLJedisTest.java | 6 ++++
.../clients/jedis/SSLJedisClusterTest.java | 7 +++-
.../jedis/SSLJedisSentinelPoolTest.java | 7 +++-
.../redis/clients/jedis/SSLJedisTest.java | 34 +++++++++++++------
.../SSLJedisPooledClientSideCacheTest.java | 7 +++-
6 files changed, 57 insertions(+), 17 deletions(-)
diff --git a/src/test/java/redis/clients/jedis/SSLACLJedisClusterTest.java b/src/test/java/redis/clients/jedis/SSLACLJedisClusterTest.java
index 2dfaf9e43d..fbe57f66f7 100644
--- a/src/test/java/redis/clients/jedis/SSLACLJedisClusterTest.java
+++ b/src/test/java/redis/clients/jedis/SSLACLJedisClusterTest.java
@@ -10,6 +10,7 @@
import javax.net.ssl.SSLSession;
import javax.net.ssl.SSLSocketFactory;
+import org.junit.AfterClass;
import org.junit.Assert;
import org.junit.BeforeClass;
import org.junit.Test;
@@ -18,7 +19,6 @@
import redis.clients.jedis.SSLJedisTest.BasicHostnameVerifier;
import redis.clients.jedis.util.RedisVersionUtil;
-@org.junit.Ignore // TODO: enable -- (in a different way?)
public class SSLACLJedisClusterTest extends JedisClusterTestBase {
private static final int DEFAULT_REDIRECTIONS = 5;
@@ -44,15 +44,20 @@ public class SSLACLJedisClusterTest extends JedisClusterTestBase {
@BeforeClass
public static void prepare() {
- // We need to set up certificates first before connecting to the endpoint with enabled TLS
- SSLJedisTest.setupTrustStore();
-
// TODO(imalinovskyi): Remove hardcoded connection settings
// once this test is refactored to support RE
org.junit.Assume.assumeTrue("Not running ACL test on this version of Redis",
RedisVersionUtil.checkRedisMajorVersionNumber(6,
new EndpointConfig(new HostAndPort("localhost", 8379),
"default", "cluster", true)));
+
+ // We need to set up certificates first before connecting to the endpoint with enabled TLS
+ SSLJedisTest.setupTrustStore();
+ }
+
+ @AfterClass
+ public static void unprepare() {
+ SSLJedisTest.cleanupTrustStore();
}
@Test
diff --git a/src/test/java/redis/clients/jedis/SSLACLJedisTest.java b/src/test/java/redis/clients/jedis/SSLACLJedisTest.java
index af7fd49e62..8e39e26b6d 100644
--- a/src/test/java/redis/clients/jedis/SSLACLJedisTest.java
+++ b/src/test/java/redis/clients/jedis/SSLACLJedisTest.java
@@ -2,6 +2,7 @@
import static org.junit.Assert.*;
+import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Test;
@@ -28,6 +29,11 @@ public static void prepare() {
RedisVersionUtil.checkRedisMajorVersionNumber(6, endpoint));
}
+ @AfterClass
+ public static void unprepare() {
+ SSLJedisTest.cleanupTrustStore();
+ }
+
@Test
public void connectWithSsl() {
try (Jedis jedis = new Jedis(endpoint.getHost(), endpoint.getPort(), true)) {
diff --git a/src/test/java/redis/clients/jedis/SSLJedisClusterTest.java b/src/test/java/redis/clients/jedis/SSLJedisClusterTest.java
index f46cd45db7..805783601c 100644
--- a/src/test/java/redis/clients/jedis/SSLJedisClusterTest.java
+++ b/src/test/java/redis/clients/jedis/SSLJedisClusterTest.java
@@ -10,6 +10,7 @@
import javax.net.ssl.SSLSession;
import javax.net.ssl.SSLSocketFactory;
+import org.junit.AfterClass;
import org.junit.Assert;
import org.junit.BeforeClass;
import org.junit.Test;
@@ -17,7 +18,6 @@
import redis.clients.jedis.exceptions.JedisClusterOperationException;
import redis.clients.jedis.SSLJedisTest.BasicHostnameVerifier;
-@org.junit.Ignore // TODO: enable -- (in a different way?)
public class SSLJedisClusterTest extends JedisClusterTestBase {
private static final int DEFAULT_REDIRECTIONS = 5;
@@ -46,6 +46,11 @@ public static void prepare() {
SSLJedisTest.setupTrustStore(); // set up trust store for SSL tests
}
+ @AfterClass
+ public static void unprepare() {
+ SSLJedisTest.cleanupTrustStore();
+ }
+
@Test
public void testSSLDiscoverNodesAutomatically() {
try (JedisCluster jc = new JedisCluster(Collections.singleton(new HostAndPort("localhost", 8379)),
diff --git a/src/test/java/redis/clients/jedis/SSLJedisSentinelPoolTest.java b/src/test/java/redis/clients/jedis/SSLJedisSentinelPoolTest.java
index 3f576956d8..4fda9646c3 100644
--- a/src/test/java/redis/clients/jedis/SSLJedisSentinelPoolTest.java
+++ b/src/test/java/redis/clients/jedis/SSLJedisSentinelPoolTest.java
@@ -3,10 +3,10 @@
import java.util.HashSet;
import java.util.Set;
import org.apache.commons.pool2.impl.GenericObjectPoolConfig;
+import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Test;
-@org.junit.Ignore // TODO: enable -- (in a different way?)
public class SSLJedisSentinelPoolTest {
private static final String MASTER_NAME = "aclmaster";
@@ -25,6 +25,11 @@ public static void prepare() {
sentinels.add(HostAndPorts.getSentinelServers().get(4));
}
+ @AfterClass
+ public static void unprepare() {
+ SSLJedisTest.cleanupTrustStore();
+ }
+
@Test
public void sentinelWithoutSslConnectsToRedisWithSsl() {
diff --git a/src/test/java/redis/clients/jedis/SSLJedisTest.java b/src/test/java/redis/clients/jedis/SSLJedisTest.java
index 0d3c1e01d6..a26fc4a9ae 100644
--- a/src/test/java/redis/clients/jedis/SSLJedisTest.java
+++ b/src/test/java/redis/clients/jedis/SSLJedisTest.java
@@ -20,30 +20,44 @@
import javax.net.ssl.TrustManagerFactory;
import javax.net.ssl.X509TrustManager;
+import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Test;
-@org.junit.Ignore // TODO: enable -- (in a different way?)
public class SSLJedisTest {
protected static final EndpointConfig endpoint = HostAndPorts.getRedisEndpoint("standalone0-tls");
+ public static void setupTrustStore() {
+ setJvmTrustStore("src/test/resources/truststore.jceks", "jceks");
+ }
+
+ private static void setJvmTrustStore(String trustStoreFilePath, String trustStoreType) {
+ assertTrue(String.format("Could not find trust store at '%s'.", trustStoreFilePath),
+ new File(trustStoreFilePath).exists());
+ System.setProperty("javax.net.ssl.trustStore", trustStoreFilePath);
+ System.setProperty("javax.net.ssl.trustStoreType", trustStoreType);
+ }
+
+ public static void cleanupTrustStore() {
+ clearJvmTrustStore();
+ }
+
+ private static void clearJvmTrustStore() {
+ System.clearProperty("javax.net.ssl.trustStore");
+ System.clearProperty("javax.net.ssl.trustStoreType");
+ }
+
@BeforeClass
public static void prepare() {
setupTrustStore();
}
- public static void setupTrustStore() {
-// setJvmTrustStore("src/test/resources/truststore.jceks", "jceks");
+ @AfterClass
+ public static void unprepare() {
+ cleanupTrustStore();
}
-// private static void setJvmTrustStore(String trustStoreFilePath, String trustStoreType) {
-// assertTrue(String.format("Could not find trust store at '%s'.", trustStoreFilePath),
-// new File(trustStoreFilePath).exists());
-// System.setProperty("javax.net.ssl.trustStore", trustStoreFilePath);
-// System.setProperty("javax.net.ssl.trustStoreType", trustStoreType);
-// }
-
@Test
public void connectWithSsl() {
try (Jedis jedis = new Jedis(endpoint.getHost(), endpoint.getPort(), true)) {
diff --git a/src/test/java/redis/clients/jedis/csc/SSLJedisPooledClientSideCacheTest.java b/src/test/java/redis/clients/jedis/csc/SSLJedisPooledClientSideCacheTest.java
index c62a4460ee..f59f248b7a 100644
--- a/src/test/java/redis/clients/jedis/csc/SSLJedisPooledClientSideCacheTest.java
+++ b/src/test/java/redis/clients/jedis/csc/SSLJedisPooledClientSideCacheTest.java
@@ -1,10 +1,10 @@
package redis.clients.jedis.csc;
+import org.junit.AfterClass;
import org.junit.BeforeClass;
import redis.clients.jedis.HostAndPorts;
import redis.clients.jedis.SSLJedisTest;
-@org.junit.Ignore // TODO: enable
public class SSLJedisPooledClientSideCacheTest extends JedisPooledClientSideCacheTestBase {
@BeforeClass
@@ -14,4 +14,9 @@ public static void prepare() {
endpoint = HostAndPorts.getRedisEndpoint("standalone0-tls");
}
+ @AfterClass
+ public static void unprepare() {
+ SSLJedisTest.cleanupTrustStore();
+ }
+
}
From 00d6dcece33851bf4f71a3e8183b9a202fedc8e6 Mon Sep 17 00:00:00 2001
From: M Sazzadul Hoque <7600764+sazzad16@users.noreply.github.com>
Date: Mon, 18 Nov 2024 23:03:41 +0600
Subject: [PATCH 21/34] Missing enable existing SSL tests without impacting new
ones
---
src/test/java/redis/clients/jedis/SSLACLJedisTest.java | 1 -
1 file changed, 1 deletion(-)
diff --git a/src/test/java/redis/clients/jedis/SSLACLJedisTest.java b/src/test/java/redis/clients/jedis/SSLACLJedisTest.java
index 8e39e26b6d..a6b2d4c059 100644
--- a/src/test/java/redis/clients/jedis/SSLACLJedisTest.java
+++ b/src/test/java/redis/clients/jedis/SSLACLJedisTest.java
@@ -13,7 +13,6 @@
*
* This test is only executed when the server/cluster is Redis 6. or more.
*/
-@org.junit.Ignore // TODO: enable -- (in a different way?)
public class SSLACLJedisTest {
protected static final EndpointConfig endpoint = HostAndPorts.getRedisEndpoint("standalone0-acl-tls");
From f56aec33bd4cf451f249fd66d71b02a092f2e938 Mon Sep 17 00:00:00 2001
From: M Sazzadul Hoque <7600764+sazzad16@users.noreply.github.com>
Date: Sun, 24 Nov 2024 17:47:31 +0600
Subject: [PATCH 22/34] Keep only Builder pattern constructor for
DefaultJedisClientConfig
---
.../jedis/DefaultJedisClientConfig.java | 75 ++++++++++---------
.../clients/jedis/JedisClientConfig.java | 1 +
2 files changed, 40 insertions(+), 36 deletions(-)
diff --git a/src/main/java/redis/clients/jedis/DefaultJedisClientConfig.java b/src/main/java/redis/clients/jedis/DefaultJedisClientConfig.java
index b4ab76064b..7ae0746b82 100644
--- a/src/main/java/redis/clients/jedis/DefaultJedisClientConfig.java
+++ b/src/main/java/redis/clients/jedis/DefaultJedisClientConfig.java
@@ -29,29 +29,6 @@ public final class DefaultJedisClientConfig implements JedisClientConfig {
private final boolean readOnlyForRedisClusterReplicas;
- // TODO: how many constructors should we have? 1) all params, 2) builder 3) another config
- private DefaultJedisClientConfig(RedisProtocol protocol, int connectionTimeoutMillis, int soTimeoutMillis,
- int blockingSocketTimeoutMillis, Supplier