diff --git a/extensions/redis-client/runtime/src/main/java/io/quarkus/redis/client/runtime/RedisClientUtil.java b/extensions/redis-client/runtime/src/main/java/io/quarkus/redis/client/runtime/RedisClientUtil.java index b376fb6d2200f..f1030014b42d2 100644 --- a/extensions/redis-client/runtime/src/main/java/io/quarkus/redis/client/runtime/RedisClientUtil.java +++ b/extensions/redis-client/runtime/src/main/java/io/quarkus/redis/client/runtime/RedisClientUtil.java @@ -1,5 +1,12 @@ package io.quarkus.redis.client.runtime; +import static io.quarkus.vertx.core.runtime.SSLConfigHelper.configureJksKeyCertOptions; +import static io.quarkus.vertx.core.runtime.SSLConfigHelper.configureJksTrustOptions; +import static io.quarkus.vertx.core.runtime.SSLConfigHelper.configurePemKeyCertOptions; +import static io.quarkus.vertx.core.runtime.SSLConfigHelper.configurePemTrustOptions; +import static io.quarkus.vertx.core.runtime.SSLConfigHelper.configurePfxKeyCertOptions; +import static io.quarkus.vertx.core.runtime.SSLConfigHelper.configurePfxTrustOptions; + import java.net.URI; import java.util.Collections; import java.util.Set; @@ -9,6 +16,7 @@ import io.quarkus.redis.client.RedisHostsProvider; import io.quarkus.redis.client.runtime.RedisConfig.RedisConfiguration; import io.quarkus.runtime.configuration.ConfigurationException; +import io.vertx.core.net.NetClientOptions; import io.vertx.redis.client.RedisClientType; import io.vertx.redis.client.RedisOptions; @@ -59,9 +67,49 @@ public static RedisOptions buildOptions(RedisConfiguration redisConfig) { options.setUseReplicas(redisConfig.replicas.get()); } + if (redisConfig.password.isPresent()) { + options.setPassword(redisConfig.password.get()); + } + + options.setNetClientOptions(toNetClientOptions(redisConfig)); + return options; } + private static NetClientOptions toNetClientOptions(RedisConfiguration redisConfig) { + NetClientOptions netClientOptions = new NetClientOptions() + .setTcpKeepAlive(redisConfig.tcpKeepAlive) + .setTcpNoDelay(redisConfig.tcpNoDelay); + + SslConfig sslConfig = redisConfig.ssl; + + netClientOptions + .setSsl(sslConfig.enabled) + .setTrustAll(sslConfig.trustAll); + + configurePemTrustOptions(netClientOptions, sslConfig.trustCertificatePem); + configureJksTrustOptions(netClientOptions, sslConfig.trustCertificateJks); + configurePfxTrustOptions(netClientOptions, sslConfig.trustCertificatePfx); + + configurePemKeyCertOptions(netClientOptions, sslConfig.keyCertificatePem); + configureJksKeyCertOptions(netClientOptions, sslConfig.keyCertificateJks); + configurePfxKeyCertOptions(netClientOptions, sslConfig.keyCertificatePfx); + + netClientOptions.setReconnectAttempts(redisConfig.reconnectAttempts); + netClientOptions.setReconnectInterval(redisConfig.reconnectInterval.toMillis()); + + if (redisConfig.idleTimeout.isPresent()) { + netClientOptions.setIdleTimeout(redisConfig.idleTimeout.get()); + } + + if (sslConfig.hostnameVerificationAlgorithm.isPresent()) { + netClientOptions.setHostnameVerificationAlgorithm( + sslConfig.hostnameVerificationAlgorithm.get()); + } + + return netClientOptions; + } + public static boolean isDefault(String clientName) { return DEFAULT_CLIENT.equals(clientName); } diff --git a/extensions/redis-client/runtime/src/main/java/io/quarkus/redis/client/runtime/RedisConfig.java b/extensions/redis-client/runtime/src/main/java/io/quarkus/redis/client/runtime/RedisConfig.java index ae593e4ddaeb3..3841ab3fbfd42 100644 --- a/extensions/redis-client/runtime/src/main/java/io/quarkus/redis/client/runtime/RedisConfig.java +++ b/extensions/redis-client/runtime/src/main/java/io/quarkus/redis/client/runtime/RedisConfig.java @@ -8,6 +8,7 @@ import io.quarkus.redis.client.RedisClient; import io.quarkus.redis.client.RedisClientName; +import io.quarkus.runtime.annotations.ConfigDocSection; import io.quarkus.runtime.annotations.ConfigGroup; import io.quarkus.runtime.annotations.ConfigItem; import io.quarkus.runtime.annotations.ConfigPhase; @@ -110,6 +111,14 @@ public static class RedisConfiguration { @ConfigItem(defaultValueDocumentation = "never") public Optional replicas; + /** + * The default password for cluster/sentinel connections. + *

+ * If not set it will try to extract the value from the current default {@code #hosts}. + */ + @ConfigItem + public Optional password; + /** * The maximum size of the connection pool. When working with cluster or sentinel. *

@@ -150,5 +159,43 @@ public static class RedisConfiguration { */ @ConfigItem(defaultValue = "32") public int maxNestedArrays; + + /** + * The number of reconnection attempts when a pooled connection cannot be established on first try. + */ + @ConfigItem(defaultValue = "0") + public int reconnectAttempts; + + /** + * The interval between reconnection attempts when a pooled connection cannot be established on first try. + */ + @ConfigItem(defaultValue = "1") + public Duration reconnectInterval; + + /** + * The maximum time a connection remains unused in the pool before it is closed. + */ + @ConfigItem(defaultValueDocumentation = "no timeout") + public Optional idleTimeout; + + /** + * Whether TCP keep alive is enabled + */ + @ConfigItem(defaultValue = "true") + public boolean tcpKeepAlive; + + /** + * Whether TCP no delay is enabled + */ + @ConfigItem(defaultValue = "true") + public boolean tcpNoDelay; + + /** + * SSL/TLS config. + */ + @ConfigItem + @ConfigDocSection + public SslConfig ssl; + } } diff --git a/extensions/redis-client/runtime/src/main/java/io/quarkus/redis/client/runtime/SslConfig.java b/extensions/redis-client/runtime/src/main/java/io/quarkus/redis/client/runtime/SslConfig.java new file mode 100644 index 0000000000000..58d86b2e25e1d --- /dev/null +++ b/extensions/redis-client/runtime/src/main/java/io/quarkus/redis/client/runtime/SslConfig.java @@ -0,0 +1,82 @@ +package io.quarkus.redis.client.runtime; + +import java.util.Optional; + +import io.quarkus.runtime.annotations.ConfigGroup; +import io.quarkus.runtime.annotations.ConfigItem; +import io.quarkus.vertx.core.runtime.config.JksConfiguration; +import io.quarkus.vertx.core.runtime.config.PemKeyCertConfiguration; +import io.quarkus.vertx.core.runtime.config.PemTrustCertConfiguration; +import io.quarkus.vertx.core.runtime.config.PfxConfiguration; + +@ConfigGroup +public class SslConfig { + + /** + * Whether SSL/TLS is enabled. + */ + @ConfigItem(defaultValue = "false") + public boolean enabled; + + /** + * Enable trusting all certificates. Disabled by default. + */ + @ConfigItem(defaultValue = "false") + public boolean trustAll; + + /** + * Trust configuration in the PEM format. + *

+ * When enabled, {@code #trust-certificate-jks} and {@code #trust-certificate-pfx} must be disabled. + */ + @ConfigItem + public PemTrustCertConfiguration trustCertificatePem; + + /** + * Trust configuration in the JKS format. + *

+ * When enabled, {@code #trust-certificate-pem} and {@code #trust-certificate-pfx} must be disabled. + */ + @ConfigItem + public JksConfiguration trustCertificateJks; + + /** + * Trust configuration in the PFX format. + *

+ * When enabled, {@code #trust-certificate-jks} and {@code #trust-certificate-pem} must be disabled. + */ + @ConfigItem + public PfxConfiguration trustCertificatePfx; + + /** + * Key/cert configuration in the PEM format. + *

+ * When enabled, {@code key-certificate-jks} and {@code #key-certificate-pfx} must be disabled. + */ + @ConfigItem + public PemKeyCertConfiguration keyCertificatePem; + + /** + * Key/cert configuration in the JKS format. + *

+ * When enabled, {@code #key-certificate-pem} and {@code #key-certificate-pfx} must be disabled. + */ + @ConfigItem + public JksConfiguration keyCertificateJks; + + /** + * Key/cert configuration in the PFX format. + *

+ * When enabled, {@code key-certificate-jks} and {@code #key-certificate-pem} must be disabled. + */ + @ConfigItem + public PfxConfiguration keyCertificatePfx; + + /** + * The hostname verification algorithm to use in case the server's identity should be checked. + * Should be HTTPS, LDAPS or an empty string. + */ + @ConfigItem + public Optional hostnameVerificationAlgorithm; + +}