DATAREDIS-1145 - Support Sentinel password for Jedis.

We now support password-protected Sentinel configurations when using Jedis.

Original Pull Request: #558
This commit is contained in:
Mark Paluch
2020-09-01 15:33:22 +02:00
committed by Christoph Strobl
parent d97c5df130
commit 717a196da0
6 changed files with 86 additions and 9 deletions

View File

@@ -93,12 +93,29 @@ work/sentinel-%.conf:
echo save \"\" >> $@
echo sentinel monitor mymaster 127.0.0.1 6379 2 >> $@
# Password-protected Sentinel
work/sentinel-26382.conf:
@mkdir -p $(@D)
echo port 26382 >> $@
echo daemonize yes >> $@
echo protected-mode no >> $@
echo bind 0.0.0.0 >> $@
echo pidfile $(shell pwd)/work/sentinel-26382.pid >> $@
echo logfile $(shell pwd)/work/sentinel-26382.log >> $@
echo save \"\" >> $@
echo "requirepass foobared" >> $@
echo "user default on #1b58ee375b42e41f0e48ef2ff27d10a5b1f6924a9acdcdba7cae868e7adce6bf ~* +@all" >> $@
echo "user spring on #3a6eb0790f39ac87c94f3856b2dd2c5d110e6811602261a9a923d3bb23adc8b7 +@all" >> $@
echo sentinel monitor mymaster 127.0.0.1 6382 2 >> $@
echo sentinel auth-pass mymaster foobared >> $@
work/sentinel-%.pid: work/sentinel-%.conf work/redis-6379.pid work/redis/bin/redis-server
work/redis/bin/redis-server $< --sentinel
sentinel-start: work/sentinel-26379.pid work/sentinel-26380.pid work/sentinel-26381.pid
sentinel-start: work/sentinel-26379.pid work/sentinel-26380.pid work/sentinel-26381.pid work/sentinel-26382.pid
sentinel-stop: stop-26379 stop-26380 stop-26381
sentinel-stop: stop-26379 stop-26380 stop-26381 stop-26382
#########
@@ -171,6 +188,9 @@ stop-%: work/redis/bin/redis-cli
stop-6382: work/redis/bin/redis-cli
-work/redis/bin/redis-cli -a foobared -p 6382 shutdown
stop-26382: work/redis/bin/redis-cli
-work/redis/bin/redis-cli -a foobared -p 26382 shutdown
stop: redis-stop sentinel-stop cluster-stop
test:

View File

@@ -8,6 +8,7 @@ This section briefly covers items that are new and noteworthy in the latest rele
* `RedisCache` now exposes `CacheStatistics`.
* ACL authentication support for Redis Standalone, Redis Cluster and Master/Replica.
* Password support for Redis Sentinel using Jedis.
[[new-in-2.3.0]]
== New in Spring Data Redis 2.3

View File

@@ -324,11 +324,6 @@ public RedisConnectionFactory lettuceConnectionFactory() {
Sometimes, direct interaction with one of the Sentinels is required. Using `RedisConnectionFactory.getSentinelConnection()` or `RedisConnection.getSentinelCommands()` gives you access to the first active Sentinel configured.
[NOTE]
====
Sentinel authentication is only available using https://lettuce.io/[Lettuce].
====
[[redis:template]]
== Working with Objects through RedisTemplate

View File

@@ -371,10 +371,12 @@ public class JedisConnectionFactory implements InitializingBean, DisposableBean,
protected Pool<Jedis> createRedisSentinelPool(RedisSentinelConfiguration config) {
GenericObjectPoolConfig<?> poolConfig = getPoolConfig() != null ? getPoolConfig() : new JedisPoolConfig();
String sentinelUser = null;
String sentinelPassword = config.getSentinelPassword().toOptional().map(String::new).orElse(null);
return new JedisSentinelPool(config.getMaster().getName(), convertToJedisSentinelSet(config.getSentinels()),
poolConfig, getConnectTimeout(), getReadTimeout(), getUsername(), getPassword(), getDatabase(),
getClientName());
getClientName(), getConnectTimeout(), getReadTimeout(), sentinelUser, sentinelPassword, getClientName());
}
/**
@@ -868,10 +870,12 @@ public class JedisConnectionFactory implements InitializingBean, DisposableBean,
private Jedis getActiveSentinel() {
Assert.isTrue(RedisConfiguration.isSentinelConfiguration(configuration), "SentinelConfig must not be null!");
SentinelConfiguration sentinelConfiguration = (SentinelConfiguration) configuration;
for (RedisNode node : ((SentinelConfiguration) configuration).getSentinels()) {
for (RedisNode node : sentinelConfiguration.getSentinels()) {
Jedis jedis = new Jedis(node.getHost(), node.getPort(), getConnectTimeout(), getReadTimeout());
sentinelConfiguration.getSentinelPassword().toOptional().map(String::new).ifPresent(jedis::auth);
try {
if (jedis.ping().equalsIgnoreCase("pong")) {

View File

@@ -18,11 +18,16 @@ package org.springframework.data.redis.connection.jedis;
import static org.assertj.core.api.Assertions.*;
import static org.junit.Assume.*;
import java.io.IOException;
import java.util.Collections;
import org.junit.Before;
import org.junit.Test;
import org.springframework.data.redis.RedisTestProfileValueSource;
import org.springframework.data.redis.connection.RedisConnection;
import org.springframework.data.redis.connection.RedisSentinelConfiguration;
import org.springframework.data.redis.connection.RedisSentinelConnection;
import org.springframework.data.redis.connection.RedisStandaloneConfiguration;
/**
@@ -72,6 +77,26 @@ public class JedisAclIntegrationTests {
connectionFactory.destroy();
}
@Test // DATAREDIS-1145
public void shouldConnectSentinelWithAclAuthentication() throws IOException {
// Note: As per https://github.com/redis/redis/issues/7708, Sentinel does not support ACL authentication yet.
RedisSentinelConfiguration sentinelConfiguration = new RedisSentinelConfiguration("mymaster",
Collections.singleton("localhost:26382"));
sentinelConfiguration.setSentinelPassword("foobared");
JedisConnectionFactory connectionFactory = new JedisConnectionFactory(sentinelConfiguration);
connectionFactory.afterPropertiesSet();
RedisSentinelConnection connection = connectionFactory.getSentinelConnection();
assertThat(connection.masters()).isNotEmpty();
connection.close();
connectionFactory.destroy();
}
@Test // DATAREDIS-1046
public void shouldConnectStandaloneWithAclAuthenticationAndPooling() {

View File

@@ -18,12 +18,20 @@ package org.springframework.data.redis.connection.lettuce;
import static org.assertj.core.api.Assertions.*;
import static org.junit.Assume.*;
import io.lettuce.core.ClientOptions;
import io.lettuce.core.protocol.ProtocolVersion;
import java.io.IOException;
import java.util.Collections;
import org.junit.Before;
import org.junit.Ignore;
import org.junit.Test;
import org.springframework.data.redis.RedisTestProfileValueSource;
import org.springframework.data.redis.connection.RedisConnection;
import org.springframework.data.redis.connection.RedisSentinelConfiguration;
import org.springframework.data.redis.connection.RedisSentinelConnection;
import org.springframework.data.redis.connection.RedisStandaloneConfiguration;
import org.springframework.data.redis.connection.RedisStaticMasterReplicaConfiguration;
@@ -76,6 +84,30 @@ public class LettuceAclIntegrationTests {
connectionFactory.destroy();
}
@Test // DATAREDIS-1145
public void shouldConnectSentinelWithAuthentication() throws IOException {
// Note: As per https://github.com/redis/redis/issues/7708, Sentinel does not support ACL authentication yet.
LettuceClientConfiguration configuration = LettuceClientConfiguration.builder()
.clientResources(LettuceTestClientResources.getSharedClientResources())
.clientOptions(ClientOptions.builder().protocolVersion(ProtocolVersion.RESP2).build()).build();
RedisSentinelConfiguration sentinelConfiguration = new RedisSentinelConfiguration("mymaster",
Collections.singleton("localhost:26382"));
sentinelConfiguration.setSentinelPassword("foobared");
LettuceConnectionFactory connectionFactory = new LettuceConnectionFactory(sentinelConfiguration, configuration);
connectionFactory.afterPropertiesSet();
RedisSentinelConnection connection = connectionFactory.getSentinelConnection();
assertThat(connection.masters()).isNotEmpty();
connection.close();
connectionFactory.destroy();
}
@Test // DATAREDIS-1046
@Ignore("https://github.com/lettuce-io/lettuce-core/issues/1406")
public void shouldConnectMasterReplicaWithAclAuthentication() {