DATAREDIS-1046 - Use ACL authentication when username is configured.

Upgrade to Redis 6 for tests. Introduce support for username in configurations that support authentication.

Original Pull Request: #558
This commit is contained in:
Mark Paluch
2020-09-01 15:04:33 +02:00
committed by Christoph Strobl
parent da5bab1fb2
commit d97c5df130
16 changed files with 437 additions and 51 deletions

View File

@@ -12,7 +12,7 @@
# See the License for the specific language governing permissions and
# limitations under the License.
REDIS_VERSION:=5.0.5
REDIS_VERSION:=6.0.7
SPRING_PROFILE?=ci
SHELL=/bin/bash -euo pipefail
@@ -36,6 +36,24 @@ work/redis-%.conf:
echo save \"\" >> $@
echo slaveof 127.0.0.1 6379 >> $@
# Handled separately because it's a node with authentication. User: spring, password: data. Default password: foobared
work/redis-6382.conf:
@mkdir -p $(@D)
echo port 6382 >> $@
echo daemonize yes >> $@
echo protected-mode no >> $@
echo bind 0.0.0.0 >> $@
echo notify-keyspace-events Ex >> $@
echo pidfile $(shell pwd)/work/redis-6382.pid >> $@
echo logfile $(shell pwd)/work/redis-6382.log >> $@
echo unixsocket $(shell pwd)/work/redis-6382.sock >> $@
echo unixsocketperm 755 >> $@
echo "requirepass foobared" >> $@
echo "user default on #1b58ee375b42e41f0e48ef2ff27d10a5b1f6924a9acdcdba7cae868e7adce6bf ~* +@all" >> $@
echo "user spring on #3a6eb0790f39ac87c94f3856b2dd2c5d110e6811602261a9a923d3bb23adc8b7 +@all" >> $@
echo save \"\" >> $@
# Handled separately because it's the master and all others are slaves
work/redis-6379.conf:
@mkdir -p $(@D)
@@ -54,9 +72,9 @@ work/redis-6379.conf:
work/redis-%.pid: work/redis-%.conf work/redis/bin/redis-server
work/redis/bin/redis-server $<
redis-start: work/redis-6379.pid work/redis-6380.pid work/redis-6381.pid
redis-start: work/redis-6379.pid work/redis-6380.pid work/redis-6381.pid work/redis-6382.pid
redis-stop: stop-6379 stop-6380 stop-6381
redis-stop: stop-6379 stop-6380 stop-6381 stop-6382
##########
# Sentinel
@@ -150,6 +168,9 @@ start: redis-start sentinel-start cluster-init
stop-%: work/redis/bin/redis-cli
-work/redis/bin/redis-cli -p $* shutdown
stop-6382: work/redis/bin/redis-cli
-work/redis/bin/redis-cli -a foobared -p 6382 shutdown
stop: redis-stop sentinel-stop cluster-stop
test:

View File

@@ -7,9 +7,9 @@ This section briefly covers items that are new and noteworthy in the latest rele
== New in Spring Data Redis 2.4
* `RedisCache` now exposes `CacheStatistics`.
* ACL authentication support for Redis Standalone, Redis Cluster and Master/Replica.
[[new-in-2.3.0]]
== New in Spring Data Redis 2.3
* Template API Method Refinements for `Duration` and `Instant`.

View File

@@ -23,6 +23,7 @@ import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedHashSet;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import org.springframework.core.env.MapPropertySource;
@@ -49,6 +50,7 @@ public class RedisClusterConfiguration implements RedisConfiguration, ClusterCon
private Set<RedisNode> clusterNodes;
private @Nullable Integer maxRedirects;
private Optional<String> username = Optional.empty();
private RedisPassword password = RedisPassword.none();
/**
@@ -182,6 +184,24 @@ public class RedisClusterConfiguration implements RedisConfiguration, ClusterCon
}
}
/*
* (non-Javadoc)
* @see org.springframework.data.redis.connection.RedisConfiguration.WithAuthentication#setUsername(String)
*/
@Override
public void setUsername(String username) {
this.username = Optional.of(username);
}
/*
* (non-Javadoc)
* @see org.springframework.data.redis.connection.RedisConfiguration.WithAuthentication#getUsername()
*/
@Override
public Optional<String> getUsername() {
return this.username;
}
/*
* (non-Javadoc)
* @see org.springframework.data.redis.connection.RedisConfiguration.WithPassword#getPassword()

View File

@@ -17,6 +17,7 @@ package org.springframework.data.redis.connection;
import java.util.Collections;
import java.util.List;
import java.util.Optional;
import java.util.Set;
import java.util.function.IntSupplier;
import java.util.function.Supplier;
@@ -51,11 +52,11 @@ public interface RedisConfiguration {
/**
* Get the configured {@link RedisPassword} if the current {@link RedisConfiguration} is
* {@link #isPasswordAware(RedisConfiguration) password aware} or evaluate and return the value of the given
* {@link #isAuthenticationAware(RedisConfiguration) password aware} or evaluate and return the value of the given
* {@link Supplier}.
*
* @param other a {@code Supplier} whose result is returned if given {@link RedisConfiguration} is not
* {@link #isPasswordAware(RedisConfiguration) password aware}.
* {@link #isAuthenticationAware(RedisConfiguration) password aware}.
* @return never {@literal null}.
* @throws IllegalArgumentException if {@code other} is {@literal null}.
*/
@@ -67,8 +68,8 @@ public interface RedisConfiguration {
* @param configuration can be {@literal null}.
* @return {@code true} if given {@link RedisConfiguration} is instance of {@link WithPassword}.
*/
static boolean isPasswordAware(@Nullable RedisConfiguration configuration) {
return configuration instanceof WithPassword;
static boolean isAuthenticationAware(@Nullable RedisConfiguration configuration) {
return configuration instanceof WithAuthentication;
}
/**
@@ -136,14 +137,28 @@ public interface RedisConfiguration {
/**
* @param configuration can be {@literal null}.
* @param other a {@code Supplier} whose result is returned if given {@link RedisConfiguration} is not
* {@link #isPasswordAware(RedisConfiguration) password aware}.
* {@link #isAuthenticationAware(RedisConfiguration) password aware}.
* @return never {@literal null}.
* @throws IllegalArgumentException if {@code other} is {@literal null}.
*/
static Optional<String> getUsernameOrElse(@Nullable RedisConfiguration configuration,
Supplier<Optional<String>> other) {
Assert.notNull(other, "Other must not be null!");
return isAuthenticationAware(configuration) ? ((WithAuthentication) configuration).getUsername() : other.get();
}
/**
* @param configuration can be {@literal null}.
* @param other a {@code Supplier} whose result is returned if given {@link RedisConfiguration} is not
* {@link #isAuthenticationAware(RedisConfiguration) password aware}.
* @return never {@literal null}.
* @throws IllegalArgumentException if {@code other} is {@literal null}.
*/
static RedisPassword getPasswordOrElse(@Nullable RedisConfiguration configuration, Supplier<RedisPassword> other) {
Assert.notNull(other, "Other must not be null!");
return isPasswordAware(configuration) ? ((WithPassword) configuration).getPassword() : other.get();
return isAuthenticationAware(configuration) ? ((WithAuthentication) configuration).getPassword() : other.get();
}
/**
@@ -178,9 +193,17 @@ public interface RedisConfiguration {
* {@link RedisConfiguration} part suitable for configurations that may use authentication when connecting.
*
* @author Christoph Strobl
* @since 2.1
* @author Mark Paluch
* @since 2.4
*/
interface WithPassword {
interface WithAuthentication {
/**
* Create and set a username with the given {@link String}. Requires Redis 6 or newer.
*
* @param username the username.
*/
void setUsername(String username);
/**
* Create and set a {@link RedisPassword} for given {@link String}.
@@ -207,6 +230,13 @@ public interface RedisConfiguration {
*/
void setPassword(RedisPassword password);
/**
* Get the username to use when connecting.
*
* @return {@link Optional#empty()} if none set.
*/
Optional<String> getUsername();
/**
* Get the RedisPassword to use when connecting.
*
@@ -215,6 +245,16 @@ public interface RedisConfiguration {
RedisPassword getPassword();
}
/**
* {@link RedisConfiguration} part suitable for configurations that may use authentication when connecting.
*
* @author Christoph Strobl
* @since 2.1
*/
interface WithPassword extends WithAuthentication {
}
/**
* {@link RedisConfiguration} part suitable for configurations that use a specific database.
*
@@ -339,7 +379,17 @@ public interface RedisConfiguration {
Set<RedisNode> getSentinels();
/**
* Get the {@link RedisPassword} used when authenticating with a Redis Server..
* Get the username used when authenticating with a Redis Server.
*
* @return never {@literal null}.
* @since 2.4
*/
default Optional<String> getDataNodeUsername() {
return getUsername();
}
/**
* Get the {@link RedisPassword} used when authenticating with a Redis Server.
*
* @return never {@literal null}.
* @since 2.2.2

View File

@@ -21,6 +21,7 @@ import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedHashSet;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import org.springframework.core.env.MapPropertySource;
@@ -50,6 +51,7 @@ public class RedisSentinelConfiguration implements RedisConfiguration, SentinelC
private Set<RedisNode> sentinels;
private int database;
private Optional<String> dataNodeUsername = Optional.empty();
private RedisPassword dataNodePassword = RedisPassword.none();
private RedisPassword sentinelPassword = RedisPassword.none();
@@ -229,6 +231,24 @@ public class RedisSentinelConfiguration implements RedisConfiguration, SentinelC
this.database = index;
}
/*
* (non-Javadoc)
* @see org.springframework.data.redis.connection.RedisConfiguration.WithAuthentication#setUsername(String)
*/
@Override
public void setUsername(String username) {
this.dataNodeUsername = Optional.of(username);
}
/*
* (non-Javadoc)
* @see org.springframework.data.redis.connection.RedisConfiguration.WithAuthentication#getUsername()
*/
@Override
public Optional<String> getUsername() {
return this.dataNodeUsername;
}
/*
* (non-Javadoc)
* @see org.springframework.data.redis.connection.RedisConfiguration.WithPassword#getPassword()

View File

@@ -15,6 +15,8 @@
*/
package org.springframework.data.redis.connection;
import java.util.Optional;
import org.springframework.data.redis.connection.RedisConfiguration.DomainSocketConfiguration;
import org.springframework.util.Assert;
@@ -32,6 +34,7 @@ public class RedisSocketConfiguration implements RedisConfiguration, DomainSocke
private String socket = DEFAULT_SOCKET;
private int database;
private Optional<String> username = Optional.empty();
private RedisPassword password = RedisPassword.none();
/**
@@ -92,6 +95,24 @@ public class RedisSocketConfiguration implements RedisConfiguration, DomainSocke
this.database = index;
}
/*
* (non-Javadoc)
* @see org.springframework.data.redis.connection.RedisConfiguration.WithAuthentication#setUsername(String)
*/
@Override
public void setUsername(String username) {
this.username = Optional.of(username);
}
/*
* (non-Javadoc)
* @see org.springframework.data.redis.connection.RedisConfiguration.WithAuthentication#getUsername()
*/
@Override
public Optional<String> getUsername() {
return this.username;
}
/*
* (non-Javadoc)
* @see org.springframework.data.redis.connection.RedisConfiguration.WithPassword#getPassword()

View File

@@ -15,6 +15,8 @@
*/
package org.springframework.data.redis.connection;
import java.util.Optional;
import org.springframework.data.redis.connection.RedisConfiguration.WithDatabaseIndex;
import org.springframework.data.redis.connection.RedisConfiguration.WithHostAndPort;
import org.springframework.data.redis.connection.RedisConfiguration.WithPassword;
@@ -37,6 +39,7 @@ public class RedisStandaloneConfiguration
private String hostName = DEFAULT_HOST;
private int port = DEFAULT_PORT;
private int database;
private Optional<String> username = Optional.empty();
private RedisPassword password = RedisPassword.none();
/**
@@ -125,6 +128,24 @@ public class RedisStandaloneConfiguration
this.database = index;
}
/*
* (non-Javadoc)
* @see org.springframework.data.redis.connection.RedisConfiguration.WithAuthentication#setUsername(String)
*/
@Override
public void setUsername(String username) {
this.username = Optional.of(username);
}
/*
* (non-Javadoc)
* @see org.springframework.data.redis.connection.RedisConfiguration.WithAuthentication#getUsername()
*/
@Override
public Optional<String> getUsername() {
return this.username;
}
/*
* (non-Javadoc)
* @see org.springframework.data.redis.connection.RedisConfiguration.WithPassword#getPassword()

View File

@@ -18,6 +18,7 @@ package org.springframework.data.redis.connection;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Optional;
import org.springframework.data.redis.connection.RedisConfiguration.StaticMasterReplicaConfiguration;
import org.springframework.util.Assert;
@@ -40,6 +41,7 @@ public class RedisStaticMasterReplicaConfiguration implements RedisConfiguration
private List<RedisStandaloneConfiguration> nodes = new ArrayList<>();
private int database;
private Optional<String> username = Optional.empty();
private RedisPassword password = RedisPassword.none();
/**
@@ -130,6 +132,24 @@ public class RedisStaticMasterReplicaConfiguration implements RedisConfiguration
this.nodes.forEach(it -> it.setDatabase(database));
}
/*
* (non-Javadoc)
* @see org.springframework.data.redis.connection.RedisConfiguration.WithAuthentication#setUsername(String)
*/
@Override
public void setUsername(String username) {
this.username = Optional.of(username);
}
/*
* (non-Javadoc)
* @see org.springframework.data.redis.connection.RedisConfiguration.WithAuthentication#getUsername()
*/
@Override
public Optional<String> getUsername() {
return this.username;
}
/*
* (non-Javadoc)
* @see org.springframework.data.redis.connection.RedisConfiguration.WithPassword#getPassword()

View File

@@ -328,6 +328,7 @@ public class JedisConnectionFactory implements InitializingBean, DisposableBean,
clientConfiguration.getHostnameVerifier().orElse(null));
getRedisPassword().map(String::new).ifPresent(shardInfo::setPassword);
getRedisUsername().ifPresent(shardInfo::setUser);
int readTimeout = getReadTimeout();
@@ -369,9 +370,11 @@ public class JedisConnectionFactory implements InitializingBean, DisposableBean,
*/
protected Pool<Jedis> createRedisSentinelPool(RedisSentinelConfiguration config) {
GenericObjectPoolConfig poolConfig = getPoolConfig() != null ? getPoolConfig() : new JedisPoolConfig();
GenericObjectPoolConfig<?> poolConfig = getPoolConfig() != null ? getPoolConfig() : new JedisPoolConfig();
return new JedisSentinelPool(config.getMaster().getName(), convertToJedisSentinelSet(config.getSentinels()),
poolConfig, getConnectTimeout(), getReadTimeout(), getPassword(), getDatabase(), getClientName());
poolConfig, getConnectTimeout(), getReadTimeout(), getUsername(), getPassword(), getDatabase(),
getClientName());
}
/**
@@ -383,7 +386,7 @@ public class JedisConnectionFactory implements InitializingBean, DisposableBean,
protected Pool<Jedis> createRedisPool() {
return new JedisPool(getPoolConfig(), getHostName(), getPort(), getConnectTimeout(), getReadTimeout(),
getPassword(), getDatabase(), getClientName(), isUseSsl(),
getUsername(), getPassword(), getDatabase(), getClientName(), isUseSsl(),
clientConfiguration.getSslSocketFactory().orElse(null), //
clientConfiguration.getSslParameters().orElse(null), //
clientConfiguration.getHostnameVerifier().orElse(null));
@@ -414,7 +417,7 @@ public class JedisConnectionFactory implements InitializingBean, DisposableBean,
* @return the actual {@link JedisCluster}.
* @since 1.7
*/
protected JedisCluster createCluster(RedisClusterConfiguration clusterConfig, GenericObjectPoolConfig poolConfig) {
protected JedisCluster createCluster(RedisClusterConfiguration clusterConfig, GenericObjectPoolConfig<?> poolConfig) {
Assert.notNull(clusterConfig, "Cluster configuration must not be null!");
@@ -425,7 +428,7 @@ public class JedisConnectionFactory implements InitializingBean, DisposableBean,
int redirects = clusterConfig.getMaxRedirects() != null ? clusterConfig.getMaxRedirects() : 5;
return new JedisCluster(hostAndPort, getConnectTimeout(), getReadTimeout(), redirects, getPassword(),
return new JedisCluster(hostAndPort, getConnectTimeout(), getReadTimeout(), redirects, getUsername(), getPassword(),
getClientName(), poolConfig, isUseSsl(), clientConfiguration.getSslSocketFactory().orElse(null),
clientConfiguration.getSslParameters().orElse(null), clientConfiguration.getHostnameVerifier().orElse(null),
null);
@@ -544,6 +547,16 @@ public class JedisConnectionFactory implements InitializingBean, DisposableBean,
getMutableConfiguration().setUseSsl(useSsl);
}
/**
* Returns the username used for authenticating with the Redis server.
*
* @return username for authentication.
*/
@Nullable
private String getUsername() {
return getRedisUsername().orElse(null);
}
/**
* Returns the password used for authenticating with the Redis server.
*
@@ -554,6 +567,10 @@ public class JedisConnectionFactory implements InitializingBean, DisposableBean,
return getRedisPassword().map(String::new).orElse(null);
}
private Optional<String> getRedisUsername() {
return RedisConfiguration.getUsernameOrElse(this.configuration, standaloneConfig::getUsername);
}
private RedisPassword getRedisPassword() {
return RedisConfiguration.getPasswordOrElse(this.configuration, standaloneConfig::getPassword);
}
@@ -568,7 +585,7 @@ public class JedisConnectionFactory implements InitializingBean, DisposableBean,
@Deprecated
public void setPassword(String password) {
if (RedisConfiguration.isPasswordAware(configuration)) {
if (RedisConfiguration.isAuthenticationAware(configuration)) {
((WithPassword) configuration).setPassword(password);
return;

View File

@@ -788,6 +788,9 @@ public class LettuceConnectionFactory
this.getMutableConfiguration().setClientName(clientName);
}
private Optional<String> getRedisUsername() {
return RedisConfiguration.getUsernameOrElse(configuration, standaloneConfig::getUsername);
}
/**
* Returns the password used for authenticating with the Redis server.
*
@@ -812,7 +815,7 @@ public class LettuceConnectionFactory
@Deprecated
public void setPassword(String password) {
if (RedisConfiguration.isPasswordAware(configuration)) {
if (RedisConfiguration.isAuthenticationAware(configuration)) {
((WithPassword) configuration).setPassword(password);
return;
@@ -1135,7 +1138,8 @@ public class LettuceConnectionFactory
RedisURI.Builder builder = RedisURI.Builder.redis(host, port);
getRedisPassword().toOptional().ifPresent(builder::withPassword);
applyAuthentication(builder);
clientConfiguration.getClientName().ifPresent(builder::withClientName);
builder.withDatabase(getDatabase());
@@ -1151,13 +1155,25 @@ public class LettuceConnectionFactory
RedisURI.Builder builder = RedisURI.Builder.socket(socketPath);
getRedisPassword().toOptional().ifPresent(builder::withPassword);
applyAuthentication(builder);
builder.withDatabase(getDatabase());
builder.withTimeout(clientConfiguration.getCommandTimeout());
return builder.build();
}
private void applyAuthentication(RedisURI.Builder builder) {
Optional<String> username = getRedisUsername();
if (username.isPresent()) {
// See https://github.com/lettuce-io/lettuce-core/issues/1404
username.ifPresent(
it -> builder.withAuthentication(it, new String(getRedisPassword().toOptional().orElse(new char[0]))));
} else {
getRedisPassword().toOptional().ifPresent(builder::withPassword);
}
}
@Override
public RedisSentinelConnection getSentinelConnection() {
return new LettuceSentinelConnection(connectionProvider);

View File

@@ -18,16 +18,11 @@ package org.springframework.data.redis.connection.lettuce;
import io.lettuce.core.*;
import io.lettuce.core.cluster.models.partitions.Partitions;
import io.lettuce.core.cluster.models.partitions.RedisClusterNode.NodeFlag;
import io.lettuce.core.models.stream.PendingMessage;
import io.lettuce.core.models.stream.PendingMessages;
import io.lettuce.core.models.stream.PendingParser;
import java.nio.ByteBuffer;
import java.nio.charset.StandardCharsets;
import java.time.Duration;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.function.BiFunction;
import java.util.stream.Collectors;
import org.springframework.core.convert.converter.Converter;
@@ -69,9 +64,6 @@ import org.springframework.data.redis.connection.convert.Converters;
import org.springframework.data.redis.connection.convert.ListConverter;
import org.springframework.data.redis.connection.convert.LongToBooleanConverter;
import org.springframework.data.redis.connection.convert.StringToRedisClientInfoConverter;
import org.springframework.data.redis.connection.stream.Consumer;
import org.springframework.data.redis.connection.stream.PendingMessagesSummary;
import org.springframework.data.redis.connection.stream.RecordId;
import org.springframework.data.redis.core.ScanOptions;
import org.springframework.data.redis.core.types.Expiration;
import org.springframework.data.redis.core.types.RedisClientInfo;
@@ -79,7 +71,6 @@ import org.springframework.data.redis.util.ByteUtils;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils;
import org.springframework.util.NumberUtils;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;
@@ -657,15 +648,19 @@ abstract public class LettuceConverters extends Converters {
RedisURI.Builder sentinelBuilder = RedisURI.Builder.redis(sentinel.getHost(), sentinel.getPort());
if (sentinelPassword.isPresent()) {
sentinelBuilder.withPassword(sentinelPassword.get());
}
sentinelPassword.toOptional().ifPresent(sentinelBuilder::withPassword);
builder.withSentinel(sentinelBuilder.build());
}
Optional<String> username = sentinelConfiguration.getUsername();
RedisPassword password = sentinelConfiguration.getPassword();
if (password.isPresent()) {
builder.withPassword(password.get());
if (username.isPresent()) {
// See https://github.com/lettuce-io/lettuce-core/issues/1404
builder.withAuthentication(username.get(), new String(password.toOptional().orElse(new char[0])));
} else {
password.toOptional().ifPresent(builder::withPassword);
}
builder.withSentinelMasterId(sentinelConfiguration.getMaster().getName());

View File

@@ -41,6 +41,7 @@ public class RedisTestProfileValueSource implements ProfileValueSource {
private static final String REDIS_30 = "3.0";
private static final String REDIS_32 = "3.2";
private static final String REDIS_50 = "5.0";
private static final String REDIS_60 = "6.0";
private static final String REDIS_VERSION_KEY = "redisVersion";
private static RedisTestProfileValueSource INSTANCE;
@@ -97,6 +98,10 @@ public class RedisTestProfileValueSource implements ProfileValueSource {
return System.getProperty(key);
}
if (redisVersion.compareTo(RedisVersionUtils.parseVersion(REDIS_60)) >= 0) {
return REDIS_60;
}
if (redisVersion.compareTo(RedisVersionUtils.parseVersion(REDIS_50)) >= 0) {
return REDIS_50;
}

View File

@@ -0,0 +1,93 @@
/*
* Copyright 2020 the original author or authors.
*
* 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 org.springframework.data.redis.connection.jedis;
import static org.assertj.core.api.Assertions.*;
import static org.junit.Assume.*;
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.RedisStandaloneConfiguration;
/**
* Integration tests for Redis 6 ACL.
*
* @author Mark Paluch
*/
public class JedisAclIntegrationTests {
@Before
public void before() {
assumeTrue(RedisTestProfileValueSource.atLeast("redisVersion", "6.0"));
}
@Test
public void shouldConnectWithDefaultAuthentication() {
RedisStandaloneConfiguration standaloneConfiguration = new RedisStandaloneConfiguration("localhost", 6382);
standaloneConfiguration.setPassword("foobared");
JedisConnectionFactory connectionFactory = new JedisConnectionFactory(standaloneConfiguration);
connectionFactory.afterPropertiesSet();
RedisConnection connection = connectionFactory.getConnection();
assertThat(connection.ping()).isEqualTo("PONG");
connection.close();
connectionFactory.destroy();
}
@Test // DATAREDIS-1046
public void shouldConnectStandaloneWithAclAuthentication() {
RedisStandaloneConfiguration standaloneConfiguration = new RedisStandaloneConfiguration("localhost", 6382);
standaloneConfiguration.setUsername("spring");
standaloneConfiguration.setPassword("data");
JedisConnectionFactory connectionFactory = new JedisConnectionFactory(standaloneConfiguration);
connectionFactory.afterPropertiesSet();
RedisConnection connection = connectionFactory.getConnection();
assertThat(connection.ping()).isEqualTo("PONG");
connection.close();
connectionFactory.destroy();
}
@Test // DATAREDIS-1046
public void shouldConnectStandaloneWithAclAuthenticationAndPooling() {
RedisStandaloneConfiguration standaloneConfiguration = new RedisStandaloneConfiguration("localhost", 6382);
standaloneConfiguration.setUsername("spring");
standaloneConfiguration.setPassword("data");
JedisConnectionFactory connectionFactory = new JedisConnectionFactory(standaloneConfiguration);
connectionFactory.setUsePool(true);
connectionFactory.afterPropertiesSet();
RedisConnection connection = connectionFactory.getConnection();
assertThat(connection.ping()).isEqualTo("PONG");
connection.close();
connectionFactory.destroy();
}
}

View File

@@ -22,24 +22,22 @@ import io.lettuce.core.pubsub.StatefulRedisPubSubConnection;
import org.junit.After;
import org.junit.Before;
import org.junit.Ignore;
import org.junit.Test;
/**
* Integration test of {@link AuthenticatingRedisClient}. Enable requirepass and comment out the @Ignore to run.
* Integration test of {@link AuthenticatingRedisClient}.
*
* @author Jennifer Hickey
* @author Thomas Darimont
* @author Christoph Strobl
*/
@Ignore("Redis must have requirepass set to run this test")
public class AuthenticatingRedisClientTests {
private RedisClient client;
@Before
public void setUp() {
client = new AuthenticatingRedisClient("localhost", "foo");
client = new AuthenticatingRedisClient("localhost", 6382, "foobared");
}
@After
@@ -63,7 +61,7 @@ public class AuthenticatingRedisClientTests {
client.shutdown();
}
RedisClient badClient = new AuthenticatingRedisClient("localhost", "notthepassword");
RedisClient badClient = new AuthenticatingRedisClient("localhost", 6382, "notthepassword");
badClient.connect();
}

View File

@@ -171,16 +171,6 @@ public class DefaultLettucePoolTests {
pool.getResource();
}
@Test(expected = PoolException.class)
public void testCreateWithPasswordNoPassword() {
pool = new DefaultLettucePool(SettingsUtils.getHost(), SettingsUtils.getPort());
pool.setClientResources(LettuceTestClientResources.getSharedClientResources());
pool.setPassword("notthepassword");
pool.afterPropertiesSet();
pool.getResource();
}
@Ignore("Redis must have requirepass set to run this test")
@Test
public void testCreatePassword() {

View File

@@ -0,0 +1,99 @@
/*
* Copyright 2020 the original author or authors.
*
* 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 org.springframework.data.redis.connection.lettuce;
import static org.assertj.core.api.Assertions.*;
import static org.junit.Assume.*;
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.RedisStandaloneConfiguration;
import org.springframework.data.redis.connection.RedisStaticMasterReplicaConfiguration;
/**
* Integration tests for Redis 6 ACL.
*
* @author Mark Paluch
*/
public class LettuceAclIntegrationTests {
@Before
public void before() {
assumeTrue(RedisTestProfileValueSource.atLeast("redisVersion", "6.0"));
}
@Test // DATAREDIS-1046
public void shouldConnectWithDefaultAuthentication() {
RedisStandaloneConfiguration standaloneConfiguration = new RedisStandaloneConfiguration("localhost", 6382);
standaloneConfiguration.setPassword("foobared");
LettuceConnectionFactory connectionFactory = new LettuceConnectionFactory(standaloneConfiguration);
connectionFactory.setClientResources(LettuceTestClientResources.getSharedClientResources());
connectionFactory.afterPropertiesSet();
RedisConnection connection = connectionFactory.getConnection();
assertThat(connection.ping()).isEqualTo("PONG");
connection.close();
connectionFactory.destroy();
}
@Test // DATAREDIS-1046
public void shouldConnectStandaloneWithAclAuthentication() {
RedisStandaloneConfiguration standaloneConfiguration = new RedisStandaloneConfiguration("localhost", 6382);
standaloneConfiguration.setUsername("spring");
standaloneConfiguration.setPassword("data");
LettuceConnectionFactory connectionFactory = new LettuceConnectionFactory(standaloneConfiguration);
connectionFactory.setClientResources(LettuceTestClientResources.getSharedClientResources());
connectionFactory.afterPropertiesSet();
RedisConnection connection = connectionFactory.getConnection();
assertThat(connection.ping()).isEqualTo("PONG");
connection.close();
connectionFactory.destroy();
}
@Test // DATAREDIS-1046
@Ignore("https://github.com/lettuce-io/lettuce-core/issues/1406")
public void shouldConnectMasterReplicaWithAclAuthentication() {
RedisStaticMasterReplicaConfiguration masterReplicaConfiguration = new RedisStaticMasterReplicaConfiguration(
"localhost", 6382);
masterReplicaConfiguration.setUsername("spring");
masterReplicaConfiguration.setPassword("data");
LettuceConnectionFactory connectionFactory = new LettuceConnectionFactory(masterReplicaConfiguration);
connectionFactory.setClientResources(LettuceTestClientResources.getSharedClientResources());
connectionFactory.afterPropertiesSet();
RedisConnection connection = connectionFactory.getConnection();
assertThat(connection.ping()).isEqualTo("PONG");
connection.close();
connectionFactory.destroy();
}
}