Skip to content

Handle "hot reloaded" SslBundles with Lettuce #3270

@lvogt

Description

@lvogt

Hello,

our SpringBoot (3.5.7) application uses Redis (via Lettuce) as session cache, and the connection is secured using mTLS.

The necessary certificates are loaded as a spring managed SslBundle with reload-on-update: true, because the application is deployed in a kubernetes cluster and the used certificates can be renewed in the background by cert-manager.

Redis is able to handle "live" certificate updates during runtime, so we would like our application to handle that as well.

As long as there is an existing connection everything is fine, because Redis does not break existing connections on certificate updates. However a new connection cannot be established since the certificates will not match.

It seems all attempts to get various components of the Redis integration like the LettuceConnectionFactory to read the changed SslBundle by a "simple reset" do not work, as the ClientConfiguration is "cached forever" after the first initialization.

The only solution we found so far is to create a LettuceClientOptionsBuilderCustomizer bean to fetch the "current" sslBundle from the SslBundles bean inside the customizer when setting the sslContext (see below).

However, it feels like writing this boiler plate code should not be necessary and might break easily when the library is updated. Additionally, it is unclear to us, if this has a performance impact on the Redis connection / transactions.

What is intended approach to our problem?

  @Bean
  public LettuceClientOptionsBuilderCustomizer customizer(
      SslBundles sslBundles, RedisProperties redisProperties) {

    if (!redisProperties.getSsl().isEnabled()) {
      return ClientOptions.Builder::build;
    }

    final String bundleName = redisProperties.getSsl().getBundle();

    return builder ->
        builder.sslOptions(
            SslOptions.builder()
                .sslContext(
                    sslContextBuilder -> {
                      try {
                        log.info("Configuring redis SSL connection with SslBundle {}", bundleName);
                        SslManagerBundle managers = sslBundles.getBundle(bundleName).getManagers();
                        sslContextBuilder
                            .keyManager(managers.getKeyManagerFactory())
                            .trustManager(managers.getTrustManagerFactory())
                            .build();
                      } catch (SSLException e) {
                        throw new IllegalStateException("Cannot create SSL context", e);
                      }
                    })
                .build());
  }

Some general remark: We are aware that there are solutions for this problem "outside the spring boot application" and we are also evaluating these, but this is issue is intended to clarify if there is a (better) "Spring Boot solution".

Metadata

Metadata

Assignees

No one assigned

    Labels

    for: external-projectFor an external project and not something we can fix

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions