redis / lettuce

Advanced Java Redis client for thread-safe sync, async, and reactive usage. Supports Cluster, Sentinel, Pipelining, and codecs.
https://lettuce.io
MIT License
5.41k stars 975 forks source link

Add support for Redis Sentinel authentication #1002

Closed ssouris closed 5 years ago

ssouris commented 5 years ago

Bug Report

Current Behavior

I am trying to connect to the sentinel node of a Redis setup in AWS, and I am getting the message:

NOAUTH Authentication required.

Input Code

Just used a template for Spring Boot from start.spring.io with redis my properties are

spring:
  redis:
    password: ***********
    sentinel:
      master: redis-master
      nodes:
        - redis-sentinel.host

Expected behavior/code

It should connect without a problem.

Environment

Possible Solution

I think the problem is that from 5.0.1 and on they added authentication on the Sentinel and that's why it's failing. For more info check Redis 5 Release Notes

mp911de commented 5 years ago

Thanks a lot for the ticket. I wasn't aware of the sentinel change and TBH, I'm not quite sure how to deal with that. Previously, a URL with authentication affected on the Redis connection, not the Sentinel one. Servers can be configured with different passwords and we need to consider backward compatibility in which Sentinel did not support authentication.

ssouris commented 5 years ago

Thanks for the fast response. Just wanted to let you know that the password that the client will use to authenticate with the sentinels, can be different from the one that it will use to connect to the masters.

mp911de commented 5 years ago

Thanks for the heads up. I took a look and the connectSentinel() method is highly optimized for multiple attempts and fallbacks. The only type of failure we could experience there was connection refused. We need to deal with authentication failures and issue authentication in there so the entire sentinel connect process requires a rewrite.

mp911de commented 5 years ago

That is now in place.

cdekker commented 5 years ago

@mp911de How is this to be used with Spring Boot? I am running into the same issue where I have a password on both my Sentinel and Redis node (same password), but upgrading to lettuce-core 5.2.0.RELEASE does not solve the issue.

I have this in my gradle file:

implementation 'org.springframework.boot:spring-boot-starter-data-redis'
compile 'org.springframework.session:spring-session-data-redis:2.1.8.RELEASE'
compile group: 'io.lettuce', name: 'lettuce-core', version: '5.2.0.RELEASE'

When running gradle dependencies, I see that lettuce-core version is successfully overridden from 5.1.8. to 5.2.0:

+--- org.springframework.boot:spring-boot-starter-data-redis -> 2.1.8.RELEASE
|    +--- org.springframework.boot:spring-boot-starter:2.1.8.RELEASE (*)
|    +--- org.springframework.data:spring-data-redis:2.1.10.RELEASE (*)
|    \--- io.lettuce:lettuce-core:5.1.8.RELEASE -> 5.2.0.RELEASE (*)

My application properties has this:

spring.session.store-type=redis

spring.redis.password=mypassword
spring.redis.sentinel.master=mymaster
spring.redis.sentinel.nodes=redis-sentinel-hostname:26379

Yet, when starting up, I still get the same exception: io.lettuce.core.RedisCommandExecutionException: NOAUTH Authentication required.

mp911de commented 5 years ago

Please upgrade to Spring Data Redis 2.2. Earlier Spring Data Redis versions do not set the password on RedisURI when using Sentinel.

cdekker commented 5 years ago

Upgraded Spring Data Redis to 2.2.0:

    compile "org.springframework.session:spring-session-data-redis:2.1.8.RELEASE"
    compile group: 'org.springframework.data', name: 'spring-data-redis', version: '2.2.0.RELEASE'
    compile group: 'io.lettuce', name: 'lettuce-core', version: '5.2.0.RELEASE'
+--- org.springframework.boot:spring-boot-starter-data-redis -> 2.1.8.RELEASE
|    +--- org.springframework.boot:spring-boot-starter:2.1.8.RELEASE (*)
|    +--- org.springframework.data:spring-data-redis:2.1.10.RELEASE -> 2.2.0.RELEASE (*)
|    \--- io.lettuce:lettuce-core:5.1.8.RELEASE -> 5.2.0.RELEASE (*)

Still same issue.

mp911de commented 5 years ago

I took a look, LettuceConnectionFactory sets only the password on the RedisURI but not the Sentinel URI's. The bug should probably be fixed there. @cdekker Can you file a ticket at https://jira.spring.io?

cdekker commented 5 years ago

You're saying this is an issue with spring-data-redis? Can open a ticket, yeah.

kshchepanovskyi commented 4 years ago

Upgraded to latest Spring Boot - 2.2.5, spring-data-redis supports sentinel password with lettuce, however it looks like https://github.com/spring-projects/spring-boot/blob/master/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/data/redis/RedisConnectionConfiguration.java does not have property for dedicated sentinel password.

andrew-landsverk-win commented 4 years ago

Regrading the previous off-topic comment, I had to disable the sentinel password on my cluster to get spring-data-redis to connect. I am using the latest Spring Boot 2.2.6.

huyto000 commented 4 years ago

@andrew-landsverk-win i've just connected to Redis sentinel from springboot-2.2.6 successful. In configuration bean, you have to set both "setPassword" and "setSentinelPassword"

andrew-landsverk-win commented 4 years ago

@huyto000 thanks for the reply, do you know of a way to set sentinelPassword via Spring Boot properties at this time?

caplike commented 4 years ago

Same problems here, sprng-boot-starter-data-redis:2.2.1:RELEASE

UPDATED: Got to set requirepass which is the same as the password in Redis instance's redis.conf in sentinel.conf.

Pramit2512 commented 2 years ago

I recently noticed in lettuce docs that below usage is deprecated

sentinel(String host, int port, String masterId, CharSequence password) Deprecated. since 6.0, use sentinel(String, int, String) and withAuthentication(String, CharSequence) instead.

and when i check public RedisURI.Builder withAuthentication(String username, CharSequence password)

I have checked the implementation of withAuthentication method and it is as below:

       /**
         * Configures authentication.
         *
         * @param username the user name
         * @param password the **password name**
         * @return the builder
         * @since 6.0
         */

        public Builder withAuthentication(String username, CharSequence password) {

            LettuceAssert.notNull(username, "User name must not be null");
            LettuceAssert.notNull(password, "Password must not be null");

            this.username = username;
            return withPassword(password);
        }

I am not able to understand the String username in parameter list for method withAuthentication . What is it ,and how can we get this/configure this .Is this any random string or sentinel username .if so how can we set/get the sentinel username from config file. I have never seen username usage before.Can anyone please explain?

Also is passwordname different from password? In specification they have given it as passwordname

Pramit2512 commented 2 years ago

After some help i was able to connect to redis as :

        RedisClient redisClient = RedisClient.create();

        LOG.info("created the redis client");

        RedisURI source = RedisURI.Builder
                .sentinel(getSentinelHost_1(), getSentinelPort_1())
                .withSentinel(getSentinelHost_2(), getSentinelPort_2())
                .withSentinel(getSentinelHost_3(), getSentinelPort_3())
                .withSentinelMasterId(getMasterName()).withPassword(getMasterPassword())
                .build();

        for (RedisURI sentinel : source.getSentinels()) {
            sentinel.setPassword(getSentinelPassword());
        }

        StatefulRedisMasterReplicaConnection<String, String> connection = MasterReplica.connect(redisClient, StringCodec.UTF8,
                source);

        connection.setReadFrom(ReadFrom.REPLICA_PREFERRED);

        LOG.info("created the redis connection");