Skip to content

Secure connections to Sentinel cannot be established #3125

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
tishun opened this issue Mar 27, 2025 · 2 comments
Closed

Secure connections to Sentinel cannot be established #3125

tishun opened this issue Mar 27, 2025 · 2 comments
Labels
status: waiting-for-triage An issue we've not yet triaged

Comments

@tishun
Copy link
Contributor

tishun commented Mar 27, 2025

Steps to reproduce:

  • deploy a Sentinel environment with TLS on both Sentinel and Redis instance
  • attempt to connect to said environment by providing the address and port of the Sentinel

Expected behavior:

  • Successfully resolve the Redis master address and port and connect to them

Actual behavior:

  • Address is resolved, but the connection could not be established
12:15:40.105 [lettuce-nioEventLoop-4-2] DEBUG i.l.core.protocol.CommandHandler - [channel=0x2930af4e, /192.168.100.47:59502 -> /my-server:15571, epid=0x1, chid=0x2] channelUnregistered()
Exception in thread "main" java.lang.AssertionError: expectation "expectComplete" failed (expected: onComplete(); actual: onError(org.springframework.data.redis.RedisConnectionFailureException: Unable to connect to Redis))
	at reactor.test.MessageFormatter.assertionError(MessageFormatter.java:115)
	at reactor.test.MessageFormatter.failPrefix(MessageFormatter.java:104)
	at reactor.test.MessageFormatter.fail(MessageFormatter.java:73)
	at reactor.test.MessageFormatter.failOptional(MessageFormatter.java:88)
	at reactor.test.DefaultStepVerifierBuilder.lambda$expectComplete$4(DefaultStepVerifierBuilder.java:344)
	at reactor.test.DefaultStepVerifierBuilder$SignalEvent.test(DefaultStepVerifierBuilder.java:2289)
	at reactor.test.DefaultStepVerifierBuilder$DefaultVerifySubscriber.onSignal(DefaultStepVerifierBuilder.java:1529)
	at reactor.test.DefaultStepVerifierBuilder$DefaultVerifySubscriber.onExpectation(DefaultStepVerifierBuilder.java:1477)
	at reactor.test.DefaultStepVerifierBuilder$DefaultVerifySubscriber.onError(DefaultStepVerifierBuilder.java:1129)
	at reactor.core.publisher.MonoNext$NextSubscriber.onError(MonoNext.java:93)
	at reactor.core.publisher.Operators.error(Operators.java:198)
	at reactor.core.publisher.FluxUsingWhen.subscribe(FluxUsingWhen.java:98)
	at reactor.core.publisher.Mono.subscribe(Mono.java:4568)
	at reactor.test.DefaultStepVerifierBuilder$DefaultStepVerifier.toVerifierAndSubscribe(DefaultStepVerifierBuilder.java:891)
	at reactor.test.DefaultStepVerifierBuilder$DefaultStepVerifier.verify(DefaultStepVerifierBuilder.java:831)
	at reactor.test.DefaultStepVerifierBuilder$DefaultStepVerifier.verify(DefaultStepVerifierBuilder.java:823)
	at com.acme.spring.sandbox.SDRStuff.storaromus(SDRStuff.java:42)
	at com.acme.spring.sandbox.SDRStuff.main(SDRStuff.java:18)
	Suppressed: org.springframework.data.redis.RedisConnectionFailureException: Unable to connect to Redis
		at org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory$ExceptionTranslatingConnectionProvider.translateException(LettuceConnectionFactory.java:1795)
		at org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory$ExceptionTranslatingConnectionProvider.getConnection(LettuceConnectionFactory.java:1726)
		at org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory$SharedConnection.getNativeConnection(LettuceConnectionFactory.java:1528)
		at org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory$SharedConnection.lambda$getConnection$0(LettuceConnectionFactory.java:1508)
		at org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory.doInLock(LettuceConnectionFactory.java:1469)
		at org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory$SharedConnection.getConnection(LettuceConnectionFactory.java:1505)
		at org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory.getSharedReactiveConnection(LettuceConnectionFactory.java:1216)
		at org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory.getReactiveConnection(LettuceConnectionFactory.java:1091)
		at org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory.getReactiveConnection(LettuceConnectionFactory.java:118)
		at org.springframework.data.redis.core.ReactiveRedisTemplate.lambda$getConnection$2(ReactiveRedisTemplate.java:267)
		at reactor.core.publisher.MonoSupplier.call(MonoSupplier.java:67)
		at reactor.core.publisher.FluxUsingWhen.subscribe(FluxUsingWhen.java:80)
		... 6 more
	Caused by: io.lettuce.core.RedisConnectionException: Unable to connect to my-server/<unresolved>:15571
		at io.lettuce.core.RedisConnectionException.create(RedisConnectionException.java:63)
		at io.lettuce.core.RedisConnectionException.create(RedisConnectionException.java:41)
		at io.lettuce.core.AbstractRedisClient.getConnection(AbstractRedisClient.java:354)
		at io.lettuce.core.RedisClient.connect(RedisClient.java:219)
		at org.springframework.data.redis.connection.lettuce.StandaloneConnectionProvider.lambda$getConnection$1(StandaloneConnectionProvider.java:112)
		at java.base/java.util.Optional.orElseGet(Optional.java:364)
		at org.springframework.data.redis.connection.lettuce.StandaloneConnectionProvider.getConnection(StandaloneConnectionProvider.java:112)
		at org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory$ExceptionTranslatingConnectionProvider.getConnection(LettuceConnectionFactory.java:1724)
		... 16 more
	Caused by: java.net.SocketException: Connection reset
		at java.base/sun.nio.ch.SocketChannelImpl.throwConnectionReset(SocketChannelImpl.java:401)
		at java.base/sun.nio.ch.SocketChannelImpl.read(SocketChannelImpl.java:434)
		at io.netty.buffer.PooledByteBuf.setBytes(PooledByteBuf.java:255)
		at io.netty.buffer.AbstractByteBuf.writeBytes(AbstractByteBuf.java:1132)
		at io.netty.channel.socket.nio.NioSocketChannel.doReadBytes(NioSocketChannel.java:357)
		at io.netty.channel.nio.AbstractNioByteChannel$NioByteUnsafe.read(AbstractNioByteChannel.java:151)
		at io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:788)
		at io.netty.channel.nio.NioEventLoop.processSelectedKeysOptimized(NioEventLoop.java:724)
		at io.netty.channel.nio.NioEventLoop.processSelectedKeys(NioEventLoop.java:650)
		at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:562)
		at io.netty.util.concurrent.SingleThreadEventExecutor$4.run(SingleThreadEventExecutor.java:997)
		at io.netty.util.internal.ThreadExecutorMap$2.run(ThreadExecutorMap.java:74)
		at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30)
		at java.base/java.lang.Thread.run(Thread.java:1583)

Code used:

    RedisURI sentinelUri = RedisURI.Builder
        .sentinel("my-server", 8001, "my-db")
        .withSsl(true).withVerifyPeer(false)
        .withAuthentication("default", "redis")
        .build();

    RedisConfiguration redisConfiguration =
        LettuceConnectionFactory.createRedisConfiguration(sentinelUri);
    LettuceConnectionFactory factory = new LettuceConnectionFactory(redisConfiguration);


    ReactiveRedisTemplate<Object, Object> operations = new ReactiveRedisTemplate<>(factory, RedisSerializationContext.java());
    factory.afterPropertiesSet();

    operations
        .opsForValue().get("test")
        .as(StepVerifier::create)
        .expectComplete()
        .verify();

Using Lettuce however this seems to work out fine:

        RedisURI sentinelUri = RedisURI.Builder
                .sentinel("my-server", 8001, "my-db")
                .withSsl(true).withVerifyPeer(false)
                .withAuthentication("default", "redis")
                .build();
        RedisClient client = RedisClient.create();

        StatefulRedisConnection<String, String> connection = client.connect(sentinelUri);

        logger.info("Connected to Redis using Redis Sentinel");
        logger.info(connection.sync().get("key"));

        connection.close();
        client.shutdown();

Seems to me that during processing of the RedisUri the SSL setting is lost for the Redis server.

Is there any workaround we can use?

@spring-projects-issues spring-projects-issues added the status: waiting-for-triage An issue we've not yet triaged label Mar 27, 2025
@tishun
Copy link
Contributor Author

tishun commented Mar 27, 2025

Scratch that, adding a LettuceClientConfiguration to the mix solved the problem:

LettuceClientConfiguration clientConfiguration = LettuceClientConfiguration.builder()
	.useSsl().verifyPeer(SslVerifyMode.NONE)
	.build();

LettuceConnectionFactory connectionFactory = 
        new LettuceConnectionFactory(redisConfiguration, clientConfiguration);

@tishun tishun closed this as completed Mar 27, 2025
@tishun
Copy link
Contributor Author

tishun commented Mar 27, 2025

Folks,

I still think there is an issue, or at least it should not take a user so much time to configure the connection.
We have the option to specify .useSSL() in the RedisURI, but we then completely ignore it in the logic.

Would it make sense to have this parsed from the RedisURI and added as LettuceConfiguration?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
status: waiting-for-triage An issue we've not yet triaged
Projects
None yet
Development

No branches or pull requests

2 participants