From d839cc64933fb05dbe4ebf981355bf79dbfdc0c3 Mon Sep 17 00:00:00 2001 From: Ben Date: Wed, 26 Aug 2026 17:03:10 -0600 Subject: [PATCH] Add SSL support for Redis transports --- .../transport/RedisBackendProxyTransport.java | 3 +- .../votingplugin/config/BungeeSettings.java | 4 +++ .../votingplugin/proxy/VotingPluginProxy.java | 32 ++++++++++++----- .../proxy/VotingPluginProxyConfig.java | 18 ++++++++++ .../proxy/bungee/BungeeConfig.java | 10 ++++++ .../proxy/multiproxy/MultiProxyHandler.java | 10 +++++- .../proxy/velocity/VelocityConfig.java | 10 ++++++ .../src/main/resources/BungeeSettings.yml | 2 ++ .../src/main/resources/bungeeconfig.yml | 4 +++ .../proxy/RedisClientConfigTest.java | 34 +++++++++++++++++++ 10 files changed, 116 insertions(+), 11 deletions(-) create mode 100644 VotingPlugin/src/test/java/com/bencodez/votingplugin/proxy/RedisClientConfigTest.java diff --git a/VotingPlugin/src/main/java/com/bencodez/votingplugin/backendproxy/transport/RedisBackendProxyTransport.java b/VotingPlugin/src/main/java/com/bencodez/votingplugin/backendproxy/transport/RedisBackendProxyTransport.java index 34873e528..de8d68817 100644 --- a/VotingPlugin/src/main/java/com/bencodez/votingplugin/backendproxy/transport/RedisBackendProxyTransport.java +++ b/VotingPlugin/src/main/java/com/bencodez/votingplugin/backendproxy/transport/RedisBackendProxyTransport.java @@ -23,7 +23,8 @@ public RedisBackendProxyTransport(VotingPluginMain plugin) { public void start(GlobalMessageHandler messageHandler) { redisHandler = new RedisHandler(plugin.getBungeeSettings().getRedisHost(), plugin.getBungeeSettings().getRedisPort(), plugin.getBungeeSettings().getRedisUsername(), - plugin.getBungeeSettings().getRedisPassword(), plugin.getBungeeSettings().getRedisdbindex()) { + plugin.getBungeeSettings().getRedisPassword(), plugin.getBungeeSettings().getRedisdbindex(), + plugin.getBungeeSettings().isRedisSsl()) { @Override public void debug(String message) { if (plugin.getBungeeSettings().isBungeeDebug()) { diff --git a/VotingPlugin/src/main/java/com/bencodez/votingplugin/config/BungeeSettings.java b/VotingPlugin/src/main/java/com/bencodez/votingplugin/config/BungeeSettings.java index 34c308b05..b9f8b1afc 100644 --- a/VotingPlugin/src/main/java/com/bencodez/votingplugin/config/BungeeSettings.java +++ b/VotingPlugin/src/main/java/com/bencodez/votingplugin/config/BungeeSettings.java @@ -58,6 +58,10 @@ public class BungeeSettings extends YMLFile { @Getter private int redisPort = 6379; + @ConfigDataBoolean(path = "Redis.SSL") + @Getter + private boolean redisSsl = false; + @ConfigDataString(path = "MQTT.ClientID") @Getter private String mqttClientID = ""; diff --git a/VotingPlugin/src/main/java/com/bencodez/votingplugin/proxy/VotingPluginProxy.java b/VotingPlugin/src/main/java/com/bencodez/votingplugin/proxy/VotingPluginProxy.java index 0a2fd7fdf..5dd4a1409 100644 --- a/VotingPlugin/src/main/java/com/bencodez/votingplugin/proxy/VotingPluginProxy.java +++ b/VotingPlugin/src/main/java/com/bencodez/votingplugin/proxy/VotingPluginProxy.java @@ -30,6 +30,8 @@ import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; +import javax.net.ssl.SSLParameters; + import org.eclipse.paho.client.mqttv3.MqttException; import com.bencodez.advancedcore.api.time.TimeType; @@ -1331,7 +1333,8 @@ public void onReceiveEnvelope(JsonEnvelope envelope) { } } else if (method.equals(BungeeMethod.REDIS)) { redisHandler = new RedisHandler(getConfig().getRedisHost(), getConfig().getRedisPort(), - getConfig().getRedisUsername(), getConfig().getRedisPassword(), getConfig().getRedisDbIndex()) { + getConfig().getRedisUsername(), getConfig().getRedisPassword(), getConfig().getRedisDbIndex(), + getConfig().getRedisSsl()) { @Override public void debug(String message) { @@ -1339,7 +1342,7 @@ public void debug(String message) { } }; redisPublisherPool = new JedisPool(new HostAndPort(getConfig().getRedisHost(), getConfig().getRedisPort()), - buildRedisClientConfig()); + buildRedisClientConfig(getConfig())); runAsync(() -> { RedisListener listener = redisHandler.createEnvelopeListener( @@ -1784,6 +1787,11 @@ public int getMultiProxyRedisPort() { return getConfig().getMultiProxyRedisPort(); } + @Override + public boolean getMultiProxyRedisSsl() { + return getConfig().getMultiProxyRedisSsl(); + } + @Override public int getMultiProxyRedisDbIndex() { return getConfig().getMultiProxyRedisDbIndex(); @@ -2498,14 +2506,20 @@ protected boolean sendPluginMessageServerNow(String server, JsonEnvelope envelop } } - private DefaultJedisClientConfig buildRedisClientConfig() { + static DefaultJedisClientConfig buildRedisClientConfig(VotingPluginProxyConfig configSource) { DefaultJedisClientConfig.Builder config = DefaultJedisClientConfig.builder() - .database(getConfig().getRedisDbIndex()).connectionTimeoutMillis(2000).socketTimeoutMillis(2000); - if (getConfig().getRedisUsername() != null && !getConfig().getRedisUsername().isEmpty()) { - config.user(getConfig().getRedisUsername()); - } - if (getConfig().getRedisPassword() != null && !getConfig().getRedisPassword().isEmpty()) { - config.password(getConfig().getRedisPassword()); + .database(configSource.getRedisDbIndex()).ssl(configSource.getRedisSsl()).connectionTimeoutMillis(2000) + .socketTimeoutMillis(2000); + if (configSource.getRedisSsl()) { + SSLParameters sslParameters = new SSLParameters(); + sslParameters.setEndpointIdentificationAlgorithm("HTTPS"); + config.sslParameters(sslParameters); + } + if (configSource.getRedisUsername() != null && !configSource.getRedisUsername().isEmpty()) { + config.user(configSource.getRedisUsername()); + } + if (configSource.getRedisPassword() != null && !configSource.getRedisPassword().isEmpty()) { + config.password(configSource.getRedisPassword()); } return config.build(); } diff --git a/VotingPlugin/src/main/java/com/bencodez/votingplugin/proxy/VotingPluginProxyConfig.java b/VotingPlugin/src/main/java/com/bencodez/votingplugin/proxy/VotingPluginProxyConfig.java index 27e631d85..c2d2bcad4 100644 --- a/VotingPlugin/src/main/java/com/bencodez/votingplugin/proxy/VotingPluginProxyConfig.java +++ b/VotingPlugin/src/main/java/com/bencodez/votingplugin/proxy/VotingPluginProxyConfig.java @@ -265,6 +265,15 @@ default List getProxyBroadcastOfflineForwardServers() { */ public int getMultiProxyRedisPort(); + /** + * Gets whether the multi-proxy Redis connection uses SSL/TLS. + * + * @return true if SSL/TLS is enabled + */ + default boolean getMultiProxyRedisSsl() { + return false; + } + /** * Gets whether multi-proxy Redis uses existing connection. * @@ -371,6 +380,15 @@ default List getProxyBroadcastOfflineForwardServers() { */ public int getRedisPort(); + /** + * Gets whether the Redis connection uses SSL/TLS. + * + * @return true if SSL/TLS is enabled + */ + default boolean getRedisSsl() { + return false; + } + /** * Gets the Redis database index. * diff --git a/VotingPlugin/src/main/java/com/bencodez/votingplugin/proxy/bungee/BungeeConfig.java b/VotingPlugin/src/main/java/com/bencodez/votingplugin/proxy/bungee/BungeeConfig.java index 4a74ae58f..ab98b05bd 100644 --- a/VotingPlugin/src/main/java/com/bencodez/votingplugin/proxy/bungee/BungeeConfig.java +++ b/VotingPlugin/src/main/java/com/bencodez/votingplugin/proxy/bungee/BungeeConfig.java @@ -166,6 +166,11 @@ public int getMultiProxyRedisPort() { return getData().getInt("MultiProxyRedis.Port", 6379); } + @Override + public boolean getMultiProxyRedisSsl() { + return getData().getBoolean("MultiProxyRedis.SSL", false); + } + @Override public int getMultiProxyRedisDbIndex() { return getData().getInt("MultiProxyRedis.Db-Index", 0); @@ -246,6 +251,11 @@ public int getRedisPort() { return getData().getInt("Redis.Port", 6379); } + @Override + public boolean getRedisSsl() { + return getData().getBoolean("Redis.SSL", false); + } + @Override public int getRedisDbIndex() { return getData().getInt("Redis.Db-Index", 0); diff --git a/VotingPlugin/src/main/java/com/bencodez/votingplugin/proxy/multiproxy/MultiProxyHandler.java b/VotingPlugin/src/main/java/com/bencodez/votingplugin/proxy/multiproxy/MultiProxyHandler.java index 752b20ebf..933b28a65 100644 --- a/VotingPlugin/src/main/java/com/bencodez/votingplugin/proxy/multiproxy/MultiProxyHandler.java +++ b/VotingPlugin/src/main/java/com/bencodez/votingplugin/proxy/multiproxy/MultiProxyHandler.java @@ -105,6 +105,13 @@ public void close() { */ public abstract int getMultiProxyRedisPort(); + /** + * Gets whether the multi-proxy Redis connection uses SSL/TLS. + * + * @return true if SSL/TLS is enabled + */ + public abstract boolean getMultiProxyRedisSsl(); + /** * Gets the multi-proxy Redis database index. * @@ -286,7 +293,8 @@ public void onReceiveEnvelope(JsonEnvelope envelope) { multiProxyRedis = getRedisHandler(); } else { multiProxyRedis = new RedisHandler(getMultiProxyRedisHost(), getMultiProxyRedisPort(), - getMultiProxyUsername(), getMultiProxyPassword(), getMultiProxyRedisDbIndex()) { + getMultiProxyUsername(), getMultiProxyPassword(), getMultiProxyRedisDbIndex(), + getMultiProxyRedisSsl()) { @Override public void debug(String message) { if (getDebug()) { diff --git a/VotingPlugin/src/main/java/com/bencodez/votingplugin/proxy/velocity/VelocityConfig.java b/VotingPlugin/src/main/java/com/bencodez/votingplugin/proxy/velocity/VelocityConfig.java index ca745b995..b6d28e214 100644 --- a/VotingPlugin/src/main/java/com/bencodez/votingplugin/proxy/velocity/VelocityConfig.java +++ b/VotingPlugin/src/main/java/com/bencodez/votingplugin/proxy/velocity/VelocityConfig.java @@ -146,6 +146,11 @@ public int getMultiProxyRedisPort() { return getInt(getNode("MultiProxyRedis", "Port"), 6379); } + @Override + public boolean getMultiProxyRedisSsl() { + return getBoolean(getNode("MultiProxyRedis", "SSL"), false); + } + @Override public int getMultiProxyRedisDbIndex() { return getInt(getNode("MultiProxyRedis", "Db-Index"), 0); @@ -249,6 +254,11 @@ public int getRedisPort() { return getInt(getNode("Redis", "Port"), 6379); } + @Override + public boolean getRedisSsl() { + return getBoolean(getNode("Redis", "SSL"), false); + } + @Override public int getRedisDbIndex() { return getInt(getNode("Redis", "Db-Index"), 0); diff --git a/VotingPlugin/src/main/resources/BungeeSettings.yml b/VotingPlugin/src/main/resources/BungeeSettings.yml index a6e970209..036566edc 100644 --- a/VotingPlugin/src/main/resources/BungeeSettings.yml +++ b/VotingPlugin/src/main/resources/BungeeSettings.yml @@ -72,6 +72,8 @@ BungeeMethod: PLUGINMESSAGING Redis: Host: localhost Port: 6379 + # Enable SSL/TLS. The Redis certificate must be trusted by the Java runtime. + SSL: false # To get the user name, run redis-cli # If you set a password, run "auth " # If the output is "OK" run "ACL USERS" diff --git a/VotingPlugin/src/main/resources/bungeeconfig.yml b/VotingPlugin/src/main/resources/bungeeconfig.yml index 321d835f6..99a7f6149 100644 --- a/VotingPlugin/src/main/resources/bungeeconfig.yml +++ b/VotingPlugin/src/main/resources/bungeeconfig.yml @@ -284,6 +284,8 @@ PluginMessageEncryption: false Redis: Host: localhost Port: 6379 + # Enable SSL/TLS. The Redis certificate must be trusted by the Java runtime. + SSL: false Username: '' Password: '' # Set a prefix from an entire proxy network if using multi-proxy setup below @@ -448,6 +450,8 @@ MultiProxyRedis: UseExistingConnection: false Host: localhost Port: 6379 + # Ignored when UseExistingConnection is true; the Redis.SSL setting is used instead. + SSL: false Username: '' Password: '' diff --git a/VotingPlugin/src/test/java/com/bencodez/votingplugin/proxy/RedisClientConfigTest.java b/VotingPlugin/src/test/java/com/bencodez/votingplugin/proxy/RedisClientConfigTest.java new file mode 100644 index 000000000..66688f26c --- /dev/null +++ b/VotingPlugin/src/test/java/com/bencodez/votingplugin/proxy/RedisClientConfigTest.java @@ -0,0 +1,34 @@ +package com.bencodez.votingplugin.proxy; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +import org.junit.jupiter.api.Test; + +import redis.clients.jedis.DefaultJedisClientConfig; + +class RedisClientConfigTest { + + @Test + void tlsCanBeEnabledForProxyPublisherConnections() { + VotingPluginProxyConfig config = mock(VotingPluginProxyConfig.class); + when(config.getRedisDbIndex()).thenReturn(2); + when(config.getRedisSsl()).thenReturn(true); + + DefaultJedisClientConfig clientConfig = VotingPluginProxy.buildRedisClientConfig(config); + + assertTrue(clientConfig.isSsl()); + assertEquals(2, clientConfig.getDatabase()); + assertEquals("HTTPS", clientConfig.getSslParameters().getEndpointIdentificationAlgorithm()); + } + + @Test + void tlsRemainsDisabledByDefault() { + VotingPluginProxyConfig config = mock(VotingPluginProxyConfig.class); + + assertFalse(VotingPluginProxy.buildRedisClientConfig(config).isSsl()); + } +}