Closed chandank-nu closed 1 year ago
What client are you using? Jedis uses a fixed password while Lettuce provides a Credentials Supplier API that you can use without subclassing any Spring Data Redis utilities.
What client are you using? Jedis uses a fixed password while Lettuce provides a Credentials Supplier API that you can use without subclassing any Spring Data Redis utilities.
@mp911de thanks for your response. We're using Lettuce. How can I use credentials supplier API while creating LettuceConnectionFactory? Kindly suggest.
You have to provide a RedisCredentialsProviderFactory
via LettuceClientConfiguration
. That could look like:
class MyCredentialsProviderFactory implements RedisCredentialsProviderFactory {
@Override
public RedisCredentialsProvider createCredentialsProvider(RedisConfiguration redisConfiguration) {
Supplier<RedisCredentials> supplier = …;
return () -> Mono.fromSupplier(supplier);
}
@Override
public RedisCredentialsProvider createSentinelCredentialsProvider(RedisSentinelConfiguration redisConfiguration) {
Supplier<RedisCredentials> supplier = …;
return () -> Mono.fromSupplier(supplier);
}
}
LettuceClientConfiguration clientConfiguration = LettuceClientConfiguration.builder()
.redisCredentialsProviderFactory(new MyCredentialsProviderFactory())
.build();
LettuceConnectionFactory connFactory = new LettuceConnectionFactory(redisConfiguration, clientConfiguration);
@mp911de thanks for sharing the code snippet.. We're currently using springboot 2.7 and RedisCredentialsProviderFactory is not present in 2.7.11
RedisCredentialsProviderFactory
was introduced with version 3 and requires an upgrade to Java 17 and Spring Boot 3.
@mp911de We migrated to Java 17 and Springboot 3.1.5 but still facing the same issue. As per your suggestion I implemented RedisCredentialsProviderFactory but the reconnect attempts are failing. The initial connection is a success but I don't see the LettuceConnectionFactory referring to Custom RedisCredentialProviderFactory while reconnect attempt.
` class IamCredentialsProviderFactory implements RedisCredentialsProviderFactory {
final String replicationGroupId;
final String userId;
final String region;
final char[] password;
private static final Logger LOG = LoggerFactory.getLogger(IamCredentialsProviderFactory.class);
IamCredentialsProviderFactory(String replicationGroupId, String userId, String region, char[] password) {
this.replicationGroupId = replicationGroupId;
this.userId = userId;
this.region = region;
this.password = password;
}
@Override
public RedisCredentialsProvider createCredentialsProvider(RedisConfiguration redisConfiguration) {
LOG.info("Inside createCredentialsProvider");
if (password == null || password.length == 0) {
AwsCredentialsProvider defaultCredentialsProvider =
DefaultCredentialsProvider.create();
String password = ElasticCacheIamAuthUtils
.toSignedRequestUri(defaultCredentialsProvider.resolveCredentials(),
userId, region, replicationGroupId);
LOG.info("Inside createCredentialsProvider, password {}", password);
Supplier<RedisCredentials> supplier = () -> RedisCredentials.just(userId, password);
return () -> Mono.fromSupplier(supplier);
} else {
return redisConfiguration instanceof RedisConfiguration.WithAuthentication &&
((RedisConfiguration.WithAuthentication)redisConfiguration).getPassword().isPresent() ? RedisCredentialsProvider.from(() -> {
RedisConfiguration.WithAuthentication withAuthentication = (RedisConfiguration.WithAuthentication)redisConfiguration;
return RedisCredentials.just(withAuthentication.getUsername(), withAuthentication.getPassword().get());
}) : () -> Mono.just(RedisCredentialsProviderFactory.AbsentRedisCredentials.ANONYMOUS);
}
}`
String password = ElasticCacheIamAuthUtils
.toSignedRequestUri(defaultCredentialsProvider.resolveCredentials(),
userId, region, replicationGroupId);
LOG.info("Inside createCredentialsProvider, password {}", password);
Supplier<RedisCredentials> supplier = () -> RedisCredentials.just(userId, password);
return () -> Mono.fromSupplier(supplier);
This captures the password that has been created and each request to provide new credentials returns the same password.
You need to return the password within the Supplier
, or better, within the Mono
.
Thanks! I'll try this today and confirm
Hi, We recently switched from Password based Auth to IAM auth for our Elasticache cluster enabled Redis. I was able to supply Sig4 signed request as password and connect to Elasticache. This works well for first 12 hours as IAM auth enabled Elasticache disconnects after 12 hours automatically.
As I created a Custom RedisClusterConfiguration while creating RedisConnectionFactory so was expecting Springboot-data-redis and Lettuce to reconnect automatically but it seems like the password / "Sig4 signed request" that was generated for the first time is being cached somewhere.
Here is my code.... I don't see getPassword() being called while trying to reconnect.. I'm getting WRONG username - password error in Logs.
Any thoughts how we can supply new password (generated through code) every time it tries to retry connecting to Redis.
Thanks for taking a look at this.
Thanks, Chandan