From ed8647c2664b9930501bf3ed7d5b75d9ae6951f0 Mon Sep 17 00:00:00 2001 From: HTHou Date: Tue, 19 May 2026 11:03:47 +0800 Subject: [PATCH 1/7] RATIS-2537. Support configurable gRPC TLS options --- ratis-docs/src/site/markdown/security.md | 4 + .../org/apache/ratis/grpc/GrpcConfigKeys.java | 71 +++++++++ .../org/apache/ratis/grpc/GrpcFactory.java | 42 +++-- .../org/apache/ratis/grpc/GrpcTlsConfig.java | 148 +++++++++++++++++- .../java/org/apache/ratis/grpc/GrpcUtil.java | 50 +++++- .../apache/ratis/grpc/TestGrpcTlsConfig.java | 62 ++++++++ 6 files changed, 357 insertions(+), 20 deletions(-) create mode 100644 ratis-grpc/src/test/java/org/apache/ratis/grpc/TestGrpcTlsConfig.java diff --git a/ratis-docs/src/site/markdown/security.md b/ratis-docs/src/site/markdown/security.md index eb233bf932..9045ef52ac 100644 --- a/ratis-docs/src/site/markdown/security.md +++ b/ratis-docs/src/site/markdown/security.md @@ -42,5 +42,9 @@ Applications may use them to build `RaftServer`/`RaftClient` objects for establi | `raft.grpc.server.tls.conf` | gRPC server TLS conf | | `raft.grpc.client.tls.conf` | gRPC client TLS conf | | `raft.grpc.admin.tls.conf` | gRPC admin TLS conf | +| `raft.grpc.tls.ssl.provider` | gRPC TLS Netty SSL provider | +| `raft.grpc.tls.jsse.provider.name` | gRPC TLS JSSE provider name | +| `raft.grpc.tls.protocols` | gRPC TLS protocols | +| `raft.grpc.tls.cipher.suites` | gRPC TLS cipher suites | | `raft.netty.dataStream.server.tls.conf` | Netty data stream server TLS conf | | `raft.netty.dataStream.client.tls.conf` | Netty data stream client TLS conf | diff --git a/ratis-grpc/src/main/java/org/apache/ratis/grpc/GrpcConfigKeys.java b/ratis-grpc/src/main/java/org/apache/ratis/grpc/GrpcConfigKeys.java index f31794ac36..567090f36b 100644 --- a/ratis-grpc/src/main/java/org/apache/ratis/grpc/GrpcConfigKeys.java +++ b/ratis-grpc/src/main/java/org/apache/ratis/grpc/GrpcConfigKeys.java @@ -21,11 +21,15 @@ import org.apache.ratis.conf.RaftProperties; import org.apache.ratis.grpc.server.GrpcServices; import org.apache.ratis.server.RaftServerConfigKeys; +import org.apache.ratis.thirdparty.io.netty.handler.ssl.SslProvider; import org.apache.ratis.util.SizeInBytes; +import org.apache.ratis.util.StringUtils; import org.apache.ratis.util.TimeDuration; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import java.util.Arrays; +import java.util.Objects; import java.util.concurrent.TimeUnit; import java.util.function.Consumer; @@ -87,6 +91,73 @@ static GrpcTlsConfig conf(Parameters parameters) { static void setConf(Parameters parameters, GrpcTlsConfig conf) { parameters.put(CONF_PARAMETER, conf, GrpcTlsConfig.class); } + + String SSL_PROVIDER_KEY = PREFIX + ".ssl.provider"; + SslProvider SSL_PROVIDER_DEFAULT = null; + static SslProvider sslProvider(RaftProperties properties) { + return properties.getEnum(SSL_PROVIDER_KEY, SslProvider.class, SSL_PROVIDER_DEFAULT); + } + static void setSslProvider(RaftProperties properties, SslProvider provider) { + properties.setEnum(SSL_PROVIDER_KEY, provider); + } + + String JSSE_PROVIDER_NAME_KEY = PREFIX + ".jsse.provider.name"; + String JSSE_PROVIDER_NAME_DEFAULT = null; + static String jsseProviderName(RaftProperties properties) { + return properties.get(JSSE_PROVIDER_NAME_KEY, JSSE_PROVIDER_NAME_DEFAULT); + } + static void setJsseProviderName(RaftProperties properties, String name) { + properties.set(JSSE_PROVIDER_NAME_KEY, name); + } + + String PROTOCOLS_KEY = PREFIX + ".protocols"; + String[] PROTOCOLS_DEFAULT = StringUtils.EMPTY_STRING_ARRAY; + static String[] protocols(RaftProperties properties) { + return StringUtils.getTrimmedStrings(properties.get(PROTOCOLS_KEY, null)); + } + static void setProtocols(RaftProperties properties, String... protocols) { + properties.set(PROTOCOLS_KEY, String.join(",", protocols)); + } + + String CIPHER_SUITES_KEY = PREFIX + ".cipher.suites"; + String[] CIPHER_SUITES_DEFAULT = StringUtils.EMPTY_STRING_ARRAY; + static String[] cipherSuites(RaftProperties properties) { + return StringUtils.getTrimmedStrings(properties.get(CIPHER_SUITES_KEY, null)); + } + static void setCipherSuites(RaftProperties properties, String... cipherSuites) { + properties.set(CIPHER_SUITES_KEY, String.join(",", cipherSuites)); + } + + static GrpcTlsConfig apply(RaftProperties properties, GrpcTlsConfig conf) { + if (properties == null || conf == null) { + return conf; + } + final GrpcTlsConfig.Builder b = GrpcTlsConfig.newBuilder(conf); + final SslProvider provider = sslProvider(properties); + if (provider != null) { + b.setSslProvider(provider); + } + final String jsseProvider = jsseProviderName(properties); + if (jsseProvider != null && !jsseProvider.isEmpty()) { + b.setJsseProviderName(jsseProvider); + } + final String[] configuredProtocols = protocols(properties); + if (configuredProtocols.length > 0) { + b.setProtocols(configuredProtocols); + } + final String[] configuredCipherSuites = cipherSuites(properties); + if (configuredCipherSuites.length > 0) { + b.setCipherSuites(configuredCipherSuites); + } + final GrpcTlsConfig updated = b.build(); + if (!Arrays.equals(conf.getProtocols(), updated.getProtocols()) + || !Arrays.equals(conf.getCipherSuites(), updated.getCipherSuites()) + || conf.getSslProvider() != updated.getSslProvider() + || !Objects.equals(conf.getJsseProviderName(), updated.getJsseProviderName())) { + LOG.info("Applied gRPC TLS options from RaftProperties to {}", updated); + } + return updated; + } } interface Admin { diff --git a/ratis-grpc/src/main/java/org/apache/ratis/grpc/GrpcFactory.java b/ratis-grpc/src/main/java/org/apache/ratis/grpc/GrpcFactory.java index 1053cab80e..98f54ff900 100644 --- a/ratis-grpc/src/main/java/org/apache/ratis/grpc/GrpcFactory.java +++ b/ratis-grpc/src/main/java/org/apache/ratis/grpc/GrpcFactory.java @@ -34,13 +34,11 @@ import org.apache.ratis.thirdparty.io.netty.buffer.PooledByteBufAllocator; import org.apache.ratis.thirdparty.io.netty.handler.ssl.SslContext; import org.apache.ratis.util.JavaUtils; -import org.apache.ratis.util.MemoizedSupplier; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.util.function.BiFunction; import java.util.function.Consumer; -import java.util.function.Supplier; public class GrpcFactory implements ServerFactory, ClientFactory { @@ -80,20 +78,25 @@ static final class SslContexts { private final SslContext clientSslContext; private final SslContext serverSslContext; - private SslContexts(GrpcTlsConfig tlsConfig, GrpcTlsConfig adminTlsConfig, + private SslContexts(RaftProperties properties, GrpcTlsConfig tlsConfig, GrpcTlsConfig adminTlsConfig, GrpcTlsConfig clientTlsConfig, GrpcTlsConfig serverTlsConfig, BiFunction buildMethod) { - final SslContext defaultSslContext = buildMethod.apply(tlsConfig, null); - this.adminSslContext = buildMethod.apply(adminTlsConfig, defaultSslContext); - this.clientSslContext = buildMethod.apply(clientTlsConfig, defaultSslContext); - this.serverSslContext = buildMethod.apply(serverTlsConfig, defaultSslContext); + final GrpcTlsConfig defaultTlsConfig = GrpcConfigKeys.TLS.apply(properties, tlsConfig); + final SslContext defaultSslContext = buildMethod.apply(defaultTlsConfig, null); + this.adminSslContext = buildMethod.apply( + GrpcConfigKeys.TLS.apply(properties, adminTlsConfig), defaultSslContext); + this.clientSslContext = buildMethod.apply( + GrpcConfigKeys.TLS.apply(properties, clientTlsConfig), defaultSslContext); + this.serverSslContext = buildMethod.apply( + GrpcConfigKeys.TLS.apply(properties, serverTlsConfig), defaultSslContext); } } private final GrpcServices.Customizer servicesCustomizer; - - private final Supplier forServerSupplier; - private final Supplier forClientSupplier; + private final GrpcTlsConfig tlsConfig; + private final GrpcTlsConfig adminTlsConfig; + private final GrpcTlsConfig clientTlsConfig; + private final GrpcTlsConfig serverTlsConfig; public GrpcFactory(Parameters parameters) { this(GrpcConfigKeys.Server.servicesCustomizer(parameters), @@ -108,11 +111,15 @@ private GrpcFactory(GrpcServices.Customizer servicesCustomizer, GrpcTlsConfig tlsConfig, GrpcTlsConfig adminTlsConfig, GrpcTlsConfig clientTlsConfig, GrpcTlsConfig serverTlsConfig) { this.servicesCustomizer = servicesCustomizer; + this.tlsConfig = tlsConfig; + this.adminTlsConfig = adminTlsConfig; + this.clientTlsConfig = clientTlsConfig; + this.serverTlsConfig = serverTlsConfig; + } - this.forServerSupplier = MemoizedSupplier.valueOf(() -> new SslContexts( - tlsConfig, adminTlsConfig, clientTlsConfig, serverTlsConfig, BUILD_SSL_CONTEXT_FOR_SERVER)); - this.forClientSupplier = MemoizedSupplier.valueOf(() -> new SslContexts( - tlsConfig, adminTlsConfig, clientTlsConfig, serverTlsConfig, BUILD_SSL_CONTEXT_FOR_CLIENT)); + private SslContexts newSslContexts(RaftProperties properties, + BiFunction buildMethod) { + return new SslContexts(properties, tlsConfig, adminTlsConfig, clientTlsConfig, serverTlsConfig, buildMethod); } @Override @@ -129,8 +136,9 @@ public LogAppender newLogAppender(RaftServer.Division server, LeaderState state, public GrpcServices newRaftServerRpc(RaftServer server) { checkPooledByteBufAllocatorUseCacheForAllThreads(LOG::info); - final SslContexts forServer = forServerSupplier.get(); - final SslContexts forClient = forClientSupplier.get(); + final RaftProperties properties = server.getProperties(); + final SslContexts forServer = newSslContexts(properties, BUILD_SSL_CONTEXT_FOR_SERVER); + final SslContexts forClient = newSslContexts(properties, BUILD_SSL_CONTEXT_FOR_CLIENT); return GrpcServicesImpl.newBuilder() .setServer(server) .setCustomizer(servicesCustomizer) @@ -145,7 +153,7 @@ public GrpcServices newRaftServerRpc(RaftServer server) { public GrpcClientRpc newRaftClientRpc(ClientId clientId, RaftProperties properties) { checkPooledByteBufAllocatorUseCacheForAllThreads(LOG::debug); - final SslContexts forClient = forClientSupplier.get(); + final SslContexts forClient = newSslContexts(properties, BUILD_SSL_CONTEXT_FOR_CLIENT); return new GrpcClientRpc(clientId, properties, forClient.adminSslContext, forClient.clientSslContext); } } diff --git a/ratis-grpc/src/main/java/org/apache/ratis/grpc/GrpcTlsConfig.java b/ratis-grpc/src/main/java/org/apache/ratis/grpc/GrpcTlsConfig.java index ff540c3cc2..fb823d7bdd 100644 --- a/ratis-grpc/src/main/java/org/apache/ratis/grpc/GrpcTlsConfig.java +++ b/ratis-grpc/src/main/java/org/apache/ratis/grpc/GrpcTlsConfig.java @@ -18,12 +18,15 @@ package org.apache.ratis.grpc; import org.apache.ratis.security.TlsConf; +import org.apache.ratis.thirdparty.io.netty.handler.ssl.SslProvider; import javax.net.ssl.KeyManager; import javax.net.ssl.TrustManager; import java.io.File; import java.security.PrivateKey; +import java.security.Provider; import java.security.cert.X509Certificate; +import java.util.Arrays; import java.util.Collections; import java.util.Iterator; import java.util.List; @@ -34,6 +37,11 @@ */ public class GrpcTlsConfig extends TlsConf { private final boolean fileBasedConfig; + private final SslProvider sslProvider; + private final Provider jsseProvider; + private final String jsseProviderName; + private final String[] protocols; + private final String[] cipherSuites; public boolean isFileBasedConfig() { return fileBasedConfig; @@ -87,6 +95,26 @@ public boolean getMtlsEnabled() { return isMutualTls(); } + public SslProvider getSslProvider() { + return sslProvider; + } + + public Provider getJsseProvider() { + return jsseProvider; + } + + public String getJsseProviderName() { + return jsseProviderName; + } + + public String[] getProtocols() { + return protocols != null ? Arrays.copyOf(protocols, protocols.length) : null; + } + + public String[] getCipherSuites() { + return cipherSuites != null ? Arrays.copyOf(cipherSuites, cipherSuites.length) : null; + } + public GrpcTlsConfig(PrivateKey privateKey, X509Certificate certChain, List trustStore, boolean mTlsEnabled) { this(newBuilder(privateKey, certChain, trustStore, mTlsEnabled), false); @@ -105,6 +133,11 @@ public GrpcTlsConfig(File privateKeyFile, File certChainFile, private GrpcTlsConfig(Builder builder, boolean fileBasedConfig) { super(builder); this.fileBasedConfig = fileBasedConfig; + this.sslProvider = builder.sslProvider; + this.jsseProvider = builder.jsseProvider; + this.jsseProviderName = builder.jsseProviderName; + this.protocols = copy(builder.protocols); + this.cipherSuites = copy(builder.cipherSuites); } public GrpcTlsConfig(KeyManager keyManager, TrustManager trustManager, boolean mTlsEnabled) { @@ -131,4 +164,117 @@ private static Builder newBuilder(File privateKeyFile, File certChainFile, File private static Builder newBuilder(KeyManager keyManager, TrustManager trustManager, boolean mTlsEnabled) { return newBuilder().setMutualTls(mTlsEnabled).setKeyManager(keyManager).setTrustManager(trustManager); } -} \ No newline at end of file + + public static Builder newBuilder(GrpcTlsConfig conf) { + final Builder b = newBuilder().setMutualTls(conf.isMutualTls()); + Optional.ofNullable(conf.getKeyManager()).ifPresent(keyManager -> { + if (keyManager.getKeyManager() != null) { + b.setKeyManager(keyManager.getKeyManager()); + } else { + b.setPrivateKey(keyManager.getPrivateKey()); + b.setKeyCertificates(keyManager.getKeyCertificates()); + } + }); + Optional.ofNullable(conf.getTrustManager()).ifPresent(trustManager -> { + if (trustManager.getTrustManager() != null) { + b.setTrustManager(trustManager.getTrustManager()); + } else { + b.setTrustCertificates(trustManager.getTrustCertificates()); + } + }); + return b.setSslProvider(conf.getSslProvider()) + .setJsseProvider(conf.getJsseProvider()) + .setJsseProviderName(conf.getJsseProviderName()) + .setProtocols(conf.getProtocols()) + .setCipherSuites(conf.getCipherSuites()); + } + + private static String[] copy(String[] values) { + return values != null ? Arrays.copyOf(values, values.length) : null; + } + + public static Builder newBuilder() { + return new Builder(); + } + + /** For building {@link GrpcTlsConfig}. */ + public static class Builder extends TlsConf.Builder { + private SslProvider sslProvider; + private Provider jsseProvider; + private String jsseProviderName; + private String[] protocols; + private String[] cipherSuites; + + @Override + public Builder setName(String name) { + super.setName(name); + return this; + } + + @Override + public Builder setTrustCertificates(CertificatesConf trustCertificates) { + super.setTrustCertificates(trustCertificates); + return this; + } + + @Override + public Builder setPrivateKey(PrivateKeyConf privateKey) { + super.setPrivateKey(privateKey); + return this; + } + + @Override + public Builder setKeyCertificates(CertificatesConf keyCertificates) { + super.setKeyCertificates(keyCertificates); + return this; + } + + @Override + public Builder setKeyManager(KeyManager keyManager) { + super.setKeyManager(keyManager); + return this; + } + + @Override + public Builder setTrustManager(TrustManager trustManager) { + super.setTrustManager(trustManager); + return this; + } + + @Override + public Builder setMutualTls(boolean mutualTls) { + super.setMutualTls(mutualTls); + return this; + } + + public Builder setSslProvider(SslProvider sslProvider) { + this.sslProvider = sslProvider; + return this; + } + + public Builder setJsseProvider(Provider jsseProvider) { + this.jsseProvider = jsseProvider; + return this; + } + + public Builder setJsseProviderName(String jsseProviderName) { + this.jsseProviderName = jsseProviderName; + return this; + } + + public Builder setProtocols(String... protocols) { + this.protocols = copy(protocols); + return this; + } + + public Builder setCipherSuites(String... cipherSuites) { + this.cipherSuites = copy(cipherSuites); + return this; + } + + @Override + public GrpcTlsConfig build() { + return new GrpcTlsConfig(this, false); + } + } +} diff --git a/ratis-grpc/src/main/java/org/apache/ratis/grpc/GrpcUtil.java b/ratis-grpc/src/main/java/org/apache/ratis/grpc/GrpcUtil.java index df076875bf..ae829eb384 100644 --- a/ratis-grpc/src/main/java/org/apache/ratis/grpc/GrpcUtil.java +++ b/ratis-grpc/src/main/java/org/apache/ratis/grpc/GrpcUtil.java @@ -33,6 +33,8 @@ import org.apache.ratis.thirdparty.io.netty.handler.ssl.ClientAuth; import org.apache.ratis.thirdparty.io.netty.handler.ssl.SslContext; import org.apache.ratis.thirdparty.io.netty.handler.ssl.SslContextBuilder; +import org.apache.ratis.thirdparty.io.netty.handler.ssl.SslProvider; +import org.apache.ratis.thirdparty.io.netty.handler.ssl.SupportedCipherSuiteFilter; import org.apache.ratis.util.IOUtils; import org.apache.ratis.util.JavaUtils; import org.apache.ratis.util.LogUtils; @@ -45,6 +47,9 @@ import javax.net.ssl.SSLException; import javax.net.ssl.TrustManager; import java.io.IOException; +import java.security.Provider; +import java.security.Security; +import java.util.Arrays; import java.util.concurrent.CompletableFuture; import java.util.concurrent.TimeUnit; import java.util.function.Function; @@ -306,6 +311,47 @@ static void setKeyManager(SslContextBuilder b, KeyManagerConf keyManagerConfig) } } + static SslContextBuilder configureSslContextBuilder( + SslContextBuilder b, GrpcTlsConfig tlsConf, SslProvider defaultSslProvider) { + final Provider jsseProvider = getJsseProvider(tlsConf); + if (jsseProvider != null) { + b = GrpcSslContexts.configure(b, jsseProvider); + } else { + final SslProvider sslProvider = tlsConf.getSslProvider() != null + ? tlsConf.getSslProvider() : defaultSslProvider; + if (sslProvider == SslProvider.OPENSSL_REFCNT) { + b = GrpcSslContexts.configure(b, OPENSSL).sslProvider(SslProvider.OPENSSL_REFCNT); + } else { + b = sslProvider != null ? GrpcSslContexts.configure(b, sslProvider) : GrpcSslContexts.configure(b); + } + } + final String[] protocols = tlsConf.getProtocols(); + if (protocols != null && protocols.length > 0) { + b.protocols(protocols); + } + final String[] cipherSuites = tlsConf.getCipherSuites(); + if (cipherSuites != null && cipherSuites.length > 0) { + b.ciphers(Arrays.asList(cipherSuites), SupportedCipherSuiteFilter.INSTANCE); + } + return b; + } + + static Provider getJsseProvider(GrpcTlsConfig tlsConf) { + final Provider provider = tlsConf.getJsseProvider(); + if (provider != null) { + return provider; + } + final String providerName = tlsConf.getJsseProviderName(); + if (providerName == null || providerName.trim().isEmpty()) { + return null; + } + final Provider namedProvider = Security.getProvider(providerName.trim()); + if (namedProvider == null) { + throw new IllegalArgumentException("JSSE provider not found: " + providerName); + } + return namedProvider; + } + static SslContext buildSslContextForServer(GrpcTlsConfig tlsConf) { if (tlsConf == null) { return null; @@ -315,7 +361,7 @@ static SslContext buildSslContextForServer(GrpcTlsConfig tlsConf) { b.clientAuth(ClientAuth.REQUIRE); setTrustManager(b, tlsConf.getTrustManager()); } - b = GrpcSslContexts.configure(b, OPENSSL); + b = configureSslContextBuilder(b, tlsConf, OPENSSL); try { return b.build(); } catch (Exception e) { @@ -328,7 +374,7 @@ static SslContext buildSslContextForClient(GrpcTlsConfig tlsConf) { return null; } - final SslContextBuilder b = GrpcSslContexts.forClient(); + final SslContextBuilder b = configureSslContextBuilder(SslContextBuilder.forClient(), tlsConf, null); setTrustManager(b, tlsConf.getTrustManager()); if (tlsConf.getMtlsEnabled()) { setKeyManager(b, tlsConf.getKeyManager()); diff --git a/ratis-grpc/src/test/java/org/apache/ratis/grpc/TestGrpcTlsConfig.java b/ratis-grpc/src/test/java/org/apache/ratis/grpc/TestGrpcTlsConfig.java new file mode 100644 index 0000000000..93b449d1d9 --- /dev/null +++ b/ratis-grpc/src/test/java/org/apache/ratis/grpc/TestGrpcTlsConfig.java @@ -0,0 +1,62 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.ratis.grpc; + +import org.apache.ratis.conf.RaftProperties; +import org.apache.ratis.thirdparty.io.netty.handler.ssl.SslProvider; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +public class TestGrpcTlsConfig { + @Test + public void testRaftPropertiesOverrideGrpcTlsOptions() { + final GrpcTlsConfig conf = GrpcTlsConfig.newBuilder() + .setSslProvider(SslProvider.OPENSSL) + .setProtocols("TLSv1.2") + .setCipherSuites("TLS_AES_128_GCM_SHA256") + .build(); + + final RaftProperties properties = new RaftProperties(); + GrpcConfigKeys.TLS.setSslProvider(properties, SslProvider.JDK); + GrpcConfigKeys.TLS.setJsseProviderName(properties, "BCJSSE"); + GrpcConfigKeys.TLS.setProtocols(properties, "TLSv1.3"); + GrpcConfigKeys.TLS.setCipherSuites(properties, "TLS_AES_256_GCM_SHA384"); + + final GrpcTlsConfig updated = GrpcConfigKeys.TLS.apply(properties, conf); + Assertions.assertSame(SslProvider.JDK, updated.getSslProvider()); + Assertions.assertEquals("BCJSSE", updated.getJsseProviderName()); + Assertions.assertArrayEquals(new String[] {"TLSv1.3"}, updated.getProtocols()); + Assertions.assertArrayEquals(new String[] {"TLS_AES_256_GCM_SHA384"}, updated.getCipherSuites()); + } + + @Test + public void testRaftPropertiesKeepUnsetGrpcTlsOptions() { + final GrpcTlsConfig conf = GrpcTlsConfig.newBuilder() + .setSslProvider(SslProvider.OPENSSL) + .setJsseProviderName("BCJSSE") + .setProtocols("TLSv1.2") + .setCipherSuites("TLS_AES_128_GCM_SHA256") + .build(); + + final GrpcTlsConfig updated = GrpcConfigKeys.TLS.apply(new RaftProperties(), conf); + Assertions.assertSame(SslProvider.OPENSSL, updated.getSslProvider()); + Assertions.assertEquals("BCJSSE", updated.getJsseProviderName()); + Assertions.assertArrayEquals(new String[] {"TLSv1.2"}, updated.getProtocols()); + Assertions.assertArrayEquals(new String[] {"TLS_AES_128_GCM_SHA256"}, updated.getCipherSuites()); + } +} From d6dfa39cf15f96c75dcc066f32862102f187a89c Mon Sep 17 00:00:00 2001 From: HTHou Date: Tue, 19 May 2026 14:49:13 +0800 Subject: [PATCH 2/7] RATIS-2537. Support generic JSSE providers for gRPC TLS --- .../java/org/apache/ratis/grpc/GrpcUtil.java | 26 ++++++++++++++++--- .../apache/ratis/grpc/TestGrpcTlsConfig.java | 26 ++++++++++++++++--- 2 files changed, 45 insertions(+), 7 deletions(-) diff --git a/ratis-grpc/src/main/java/org/apache/ratis/grpc/GrpcUtil.java b/ratis-grpc/src/main/java/org/apache/ratis/grpc/GrpcUtil.java index ae829eb384..c4f803f6fc 100644 --- a/ratis-grpc/src/main/java/org/apache/ratis/grpc/GrpcUtil.java +++ b/ratis-grpc/src/main/java/org/apache/ratis/grpc/GrpcUtil.java @@ -30,11 +30,12 @@ import org.apache.ratis.thirdparty.io.grpc.StatusRuntimeException; import org.apache.ratis.thirdparty.io.grpc.netty.GrpcSslContexts; import org.apache.ratis.thirdparty.io.grpc.stub.StreamObserver; +import org.apache.ratis.thirdparty.io.netty.handler.ssl.ApplicationProtocolConfig; import org.apache.ratis.thirdparty.io.netty.handler.ssl.ClientAuth; +import org.apache.ratis.thirdparty.io.netty.handler.ssl.IdentityCipherSuiteFilter; import org.apache.ratis.thirdparty.io.netty.handler.ssl.SslContext; import org.apache.ratis.thirdparty.io.netty.handler.ssl.SslContextBuilder; import org.apache.ratis.thirdparty.io.netty.handler.ssl.SslProvider; -import org.apache.ratis.thirdparty.io.netty.handler.ssl.SupportedCipherSuiteFilter; import org.apache.ratis.util.IOUtils; import org.apache.ratis.util.JavaUtils; import org.apache.ratis.util.LogUtils; @@ -69,6 +70,12 @@ public interface GrpcUtil { Metadata.Key HEARTBEAT = Metadata.Key.of("heartbeat", Metadata.ASCII_STRING_MARSHALLER); + ApplicationProtocolConfig ALPN = + new ApplicationProtocolConfig(ApplicationProtocolConfig.Protocol.ALPN, + ApplicationProtocolConfig.SelectorFailureBehavior.NO_ADVERTISE, + ApplicationProtocolConfig.SelectedListenerFailureBehavior.ACCEPT, + "h2"); + static StatusRuntimeException wrapException(Throwable t) { return wrapException(t, -1); } @@ -315,7 +322,7 @@ static SslContextBuilder configureSslContextBuilder( SslContextBuilder b, GrpcTlsConfig tlsConf, SslProvider defaultSslProvider) { final Provider jsseProvider = getJsseProvider(tlsConf); if (jsseProvider != null) { - b = GrpcSslContexts.configure(b, jsseProvider); + b = configureJsseProvider(b, jsseProvider); } else { final SslProvider sslProvider = tlsConf.getSslProvider() != null ? tlsConf.getSslProvider() : defaultSslProvider; @@ -331,11 +338,24 @@ static SslContextBuilder configureSslContextBuilder( } final String[] cipherSuites = tlsConf.getCipherSuites(); if (cipherSuites != null && cipherSuites.length > 0) { - b.ciphers(Arrays.asList(cipherSuites), SupportedCipherSuiteFilter.INSTANCE); + b.ciphers(Arrays.asList(cipherSuites), IdentityCipherSuiteFilter.INSTANCE); } return b; } + static SslContextBuilder configureJsseProvider(SslContextBuilder b, Provider provider) { + try { + return GrpcSslContexts.configure(b, provider); + } catch (IllegalArgumentException e) { + if (!String.valueOf(e.getMessage()).contains("Unknown provider")) { + throw e; + } + return b.sslProvider(SslProvider.JDK) + .applicationProtocolConfig(ALPN) + .sslContextProvider(provider); + } + } + static Provider getJsseProvider(GrpcTlsConfig tlsConf) { final Provider provider = tlsConf.getJsseProvider(); if (provider != null) { diff --git a/ratis-grpc/src/test/java/org/apache/ratis/grpc/TestGrpcTlsConfig.java b/ratis-grpc/src/test/java/org/apache/ratis/grpc/TestGrpcTlsConfig.java index 93b449d1d9..20fad483d1 100644 --- a/ratis-grpc/src/test/java/org/apache/ratis/grpc/TestGrpcTlsConfig.java +++ b/ratis-grpc/src/test/java/org/apache/ratis/grpc/TestGrpcTlsConfig.java @@ -18,10 +18,13 @@ package org.apache.ratis.grpc; import org.apache.ratis.conf.RaftProperties; +import org.apache.ratis.thirdparty.io.netty.handler.ssl.SslContextBuilder; import org.apache.ratis.thirdparty.io.netty.handler.ssl.SslProvider; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; +import java.security.Provider; + public class TestGrpcTlsConfig { @Test public void testRaftPropertiesOverrideGrpcTlsOptions() { @@ -33,13 +36,13 @@ public void testRaftPropertiesOverrideGrpcTlsOptions() { final RaftProperties properties = new RaftProperties(); GrpcConfigKeys.TLS.setSslProvider(properties, SslProvider.JDK); - GrpcConfigKeys.TLS.setJsseProviderName(properties, "BCJSSE"); + GrpcConfigKeys.TLS.setJsseProviderName(properties, "SunJSSE"); GrpcConfigKeys.TLS.setProtocols(properties, "TLSv1.3"); GrpcConfigKeys.TLS.setCipherSuites(properties, "TLS_AES_256_GCM_SHA384"); final GrpcTlsConfig updated = GrpcConfigKeys.TLS.apply(properties, conf); Assertions.assertSame(SslProvider.JDK, updated.getSslProvider()); - Assertions.assertEquals("BCJSSE", updated.getJsseProviderName()); + Assertions.assertEquals("SunJSSE", updated.getJsseProviderName()); Assertions.assertArrayEquals(new String[] {"TLSv1.3"}, updated.getProtocols()); Assertions.assertArrayEquals(new String[] {"TLS_AES_256_GCM_SHA384"}, updated.getCipherSuites()); } @@ -48,15 +51,30 @@ public void testRaftPropertiesOverrideGrpcTlsOptions() { public void testRaftPropertiesKeepUnsetGrpcTlsOptions() { final GrpcTlsConfig conf = GrpcTlsConfig.newBuilder() .setSslProvider(SslProvider.OPENSSL) - .setJsseProviderName("BCJSSE") + .setJsseProviderName("SunJSSE") .setProtocols("TLSv1.2") .setCipherSuites("TLS_AES_128_GCM_SHA256") .build(); final GrpcTlsConfig updated = GrpcConfigKeys.TLS.apply(new RaftProperties(), conf); Assertions.assertSame(SslProvider.OPENSSL, updated.getSslProvider()); - Assertions.assertEquals("BCJSSE", updated.getJsseProviderName()); + Assertions.assertEquals("SunJSSE", updated.getJsseProviderName()); Assertions.assertArrayEquals(new String[] {"TLSv1.2"}, updated.getProtocols()); Assertions.assertArrayEquals(new String[] {"TLS_AES_128_GCM_SHA256"}, updated.getCipherSuites()); } + + @Test + public void testUnknownJsseProviderUsesGenericJdkConfiguration() { + final SslContextBuilder builder = GrpcUtil.configureJsseProvider( + SslContextBuilder.forClient(), new TestProvider()); + Assertions.assertNotNull(builder); + } + + private static class TestProvider extends Provider { + private static final long serialVersionUID = 1L; + + TestProvider() { + super("TestJSSE", 1.0, "Test JSSE provider"); + } + } } From f2202f1746797e75b4bdb24a33feb50386259eda Mon Sep 17 00:00:00 2001 From: HTHou Date: Tue, 19 May 2026 15:20:00 +0800 Subject: [PATCH 3/7] RATIS-2537. Remove direct JSSE provider from TLS config --- .../java/org/apache/ratis/grpc/GrpcTlsConfig.java | 14 -------------- .../main/java/org/apache/ratis/grpc/GrpcUtil.java | 4 ---- 2 files changed, 18 deletions(-) diff --git a/ratis-grpc/src/main/java/org/apache/ratis/grpc/GrpcTlsConfig.java b/ratis-grpc/src/main/java/org/apache/ratis/grpc/GrpcTlsConfig.java index fb823d7bdd..6cd16e40d7 100644 --- a/ratis-grpc/src/main/java/org/apache/ratis/grpc/GrpcTlsConfig.java +++ b/ratis-grpc/src/main/java/org/apache/ratis/grpc/GrpcTlsConfig.java @@ -24,7 +24,6 @@ import javax.net.ssl.TrustManager; import java.io.File; import java.security.PrivateKey; -import java.security.Provider; import java.security.cert.X509Certificate; import java.util.Arrays; import java.util.Collections; @@ -38,7 +37,6 @@ public class GrpcTlsConfig extends TlsConf { private final boolean fileBasedConfig; private final SslProvider sslProvider; - private final Provider jsseProvider; private final String jsseProviderName; private final String[] protocols; private final String[] cipherSuites; @@ -99,10 +97,6 @@ public SslProvider getSslProvider() { return sslProvider; } - public Provider getJsseProvider() { - return jsseProvider; - } - public String getJsseProviderName() { return jsseProviderName; } @@ -134,7 +128,6 @@ private GrpcTlsConfig(Builder builder, boolean fileBasedConfig) { super(builder); this.fileBasedConfig = fileBasedConfig; this.sslProvider = builder.sslProvider; - this.jsseProvider = builder.jsseProvider; this.jsseProviderName = builder.jsseProviderName; this.protocols = copy(builder.protocols); this.cipherSuites = copy(builder.cipherSuites); @@ -183,7 +176,6 @@ public static Builder newBuilder(GrpcTlsConfig conf) { } }); return b.setSslProvider(conf.getSslProvider()) - .setJsseProvider(conf.getJsseProvider()) .setJsseProviderName(conf.getJsseProviderName()) .setProtocols(conf.getProtocols()) .setCipherSuites(conf.getCipherSuites()); @@ -200,7 +192,6 @@ public static Builder newBuilder() { /** For building {@link GrpcTlsConfig}. */ public static class Builder extends TlsConf.Builder { private SslProvider sslProvider; - private Provider jsseProvider; private String jsseProviderName; private String[] protocols; private String[] cipherSuites; @@ -252,11 +243,6 @@ public Builder setSslProvider(SslProvider sslProvider) { return this; } - public Builder setJsseProvider(Provider jsseProvider) { - this.jsseProvider = jsseProvider; - return this; - } - public Builder setJsseProviderName(String jsseProviderName) { this.jsseProviderName = jsseProviderName; return this; diff --git a/ratis-grpc/src/main/java/org/apache/ratis/grpc/GrpcUtil.java b/ratis-grpc/src/main/java/org/apache/ratis/grpc/GrpcUtil.java index c4f803f6fc..6a00d89e6e 100644 --- a/ratis-grpc/src/main/java/org/apache/ratis/grpc/GrpcUtil.java +++ b/ratis-grpc/src/main/java/org/apache/ratis/grpc/GrpcUtil.java @@ -357,10 +357,6 @@ static SslContextBuilder configureJsseProvider(SslContextBuilder b, Provider pro } static Provider getJsseProvider(GrpcTlsConfig tlsConf) { - final Provider provider = tlsConf.getJsseProvider(); - if (provider != null) { - return provider; - } final String providerName = tlsConf.getJsseProviderName(); if (providerName == null || providerName.trim().isEmpty()) { return null; From 900b8776e720ec7235a9aaed57b40db8560c5f28 Mon Sep 17 00:00:00 2001 From: HTHou Date: Thu, 21 May 2026 14:29:02 +0800 Subject: [PATCH 4/7] RATIS-2537. Address gRPC TLS config review comments --- ratis-docs/src/site/markdown/security.md | 4 -- .../org/apache/ratis/grpc/GrpcConfigKeys.java | 71 ------------------- .../org/apache/ratis/grpc/GrpcFactory.java | 26 +++---- .../org/apache/ratis/grpc/GrpcTlsConfig.java | 35 ++++++--- .../java/org/apache/ratis/grpc/GrpcUtil.java | 14 ++-- .../apache/ratis/grpc/TestGrpcTlsConfig.java | 40 ++++++----- 6 files changed, 63 insertions(+), 127 deletions(-) diff --git a/ratis-docs/src/site/markdown/security.md b/ratis-docs/src/site/markdown/security.md index 9045ef52ac..eb233bf932 100644 --- a/ratis-docs/src/site/markdown/security.md +++ b/ratis-docs/src/site/markdown/security.md @@ -42,9 +42,5 @@ Applications may use them to build `RaftServer`/`RaftClient` objects for establi | `raft.grpc.server.tls.conf` | gRPC server TLS conf | | `raft.grpc.client.tls.conf` | gRPC client TLS conf | | `raft.grpc.admin.tls.conf` | gRPC admin TLS conf | -| `raft.grpc.tls.ssl.provider` | gRPC TLS Netty SSL provider | -| `raft.grpc.tls.jsse.provider.name` | gRPC TLS JSSE provider name | -| `raft.grpc.tls.protocols` | gRPC TLS protocols | -| `raft.grpc.tls.cipher.suites` | gRPC TLS cipher suites | | `raft.netty.dataStream.server.tls.conf` | Netty data stream server TLS conf | | `raft.netty.dataStream.client.tls.conf` | Netty data stream client TLS conf | diff --git a/ratis-grpc/src/main/java/org/apache/ratis/grpc/GrpcConfigKeys.java b/ratis-grpc/src/main/java/org/apache/ratis/grpc/GrpcConfigKeys.java index 567090f36b..f31794ac36 100644 --- a/ratis-grpc/src/main/java/org/apache/ratis/grpc/GrpcConfigKeys.java +++ b/ratis-grpc/src/main/java/org/apache/ratis/grpc/GrpcConfigKeys.java @@ -21,15 +21,11 @@ import org.apache.ratis.conf.RaftProperties; import org.apache.ratis.grpc.server.GrpcServices; import org.apache.ratis.server.RaftServerConfigKeys; -import org.apache.ratis.thirdparty.io.netty.handler.ssl.SslProvider; import org.apache.ratis.util.SizeInBytes; -import org.apache.ratis.util.StringUtils; import org.apache.ratis.util.TimeDuration; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import java.util.Arrays; -import java.util.Objects; import java.util.concurrent.TimeUnit; import java.util.function.Consumer; @@ -91,73 +87,6 @@ static GrpcTlsConfig conf(Parameters parameters) { static void setConf(Parameters parameters, GrpcTlsConfig conf) { parameters.put(CONF_PARAMETER, conf, GrpcTlsConfig.class); } - - String SSL_PROVIDER_KEY = PREFIX + ".ssl.provider"; - SslProvider SSL_PROVIDER_DEFAULT = null; - static SslProvider sslProvider(RaftProperties properties) { - return properties.getEnum(SSL_PROVIDER_KEY, SslProvider.class, SSL_PROVIDER_DEFAULT); - } - static void setSslProvider(RaftProperties properties, SslProvider provider) { - properties.setEnum(SSL_PROVIDER_KEY, provider); - } - - String JSSE_PROVIDER_NAME_KEY = PREFIX + ".jsse.provider.name"; - String JSSE_PROVIDER_NAME_DEFAULT = null; - static String jsseProviderName(RaftProperties properties) { - return properties.get(JSSE_PROVIDER_NAME_KEY, JSSE_PROVIDER_NAME_DEFAULT); - } - static void setJsseProviderName(RaftProperties properties, String name) { - properties.set(JSSE_PROVIDER_NAME_KEY, name); - } - - String PROTOCOLS_KEY = PREFIX + ".protocols"; - String[] PROTOCOLS_DEFAULT = StringUtils.EMPTY_STRING_ARRAY; - static String[] protocols(RaftProperties properties) { - return StringUtils.getTrimmedStrings(properties.get(PROTOCOLS_KEY, null)); - } - static void setProtocols(RaftProperties properties, String... protocols) { - properties.set(PROTOCOLS_KEY, String.join(",", protocols)); - } - - String CIPHER_SUITES_KEY = PREFIX + ".cipher.suites"; - String[] CIPHER_SUITES_DEFAULT = StringUtils.EMPTY_STRING_ARRAY; - static String[] cipherSuites(RaftProperties properties) { - return StringUtils.getTrimmedStrings(properties.get(CIPHER_SUITES_KEY, null)); - } - static void setCipherSuites(RaftProperties properties, String... cipherSuites) { - properties.set(CIPHER_SUITES_KEY, String.join(",", cipherSuites)); - } - - static GrpcTlsConfig apply(RaftProperties properties, GrpcTlsConfig conf) { - if (properties == null || conf == null) { - return conf; - } - final GrpcTlsConfig.Builder b = GrpcTlsConfig.newBuilder(conf); - final SslProvider provider = sslProvider(properties); - if (provider != null) { - b.setSslProvider(provider); - } - final String jsseProvider = jsseProviderName(properties); - if (jsseProvider != null && !jsseProvider.isEmpty()) { - b.setJsseProviderName(jsseProvider); - } - final String[] configuredProtocols = protocols(properties); - if (configuredProtocols.length > 0) { - b.setProtocols(configuredProtocols); - } - final String[] configuredCipherSuites = cipherSuites(properties); - if (configuredCipherSuites.length > 0) { - b.setCipherSuites(configuredCipherSuites); - } - final GrpcTlsConfig updated = b.build(); - if (!Arrays.equals(conf.getProtocols(), updated.getProtocols()) - || !Arrays.equals(conf.getCipherSuites(), updated.getCipherSuites()) - || conf.getSslProvider() != updated.getSslProvider() - || !Objects.equals(conf.getJsseProviderName(), updated.getJsseProviderName())) { - LOG.info("Applied gRPC TLS options from RaftProperties to {}", updated); - } - return updated; - } } interface Admin { diff --git a/ratis-grpc/src/main/java/org/apache/ratis/grpc/GrpcFactory.java b/ratis-grpc/src/main/java/org/apache/ratis/grpc/GrpcFactory.java index 98f54ff900..e6220e3306 100644 --- a/ratis-grpc/src/main/java/org/apache/ratis/grpc/GrpcFactory.java +++ b/ratis-grpc/src/main/java/org/apache/ratis/grpc/GrpcFactory.java @@ -78,17 +78,13 @@ static final class SslContexts { private final SslContext clientSslContext; private final SslContext serverSslContext; - private SslContexts(RaftProperties properties, GrpcTlsConfig tlsConfig, GrpcTlsConfig adminTlsConfig, + private SslContexts(GrpcTlsConfig tlsConfig, GrpcTlsConfig adminTlsConfig, GrpcTlsConfig clientTlsConfig, GrpcTlsConfig serverTlsConfig, BiFunction buildMethod) { - final GrpcTlsConfig defaultTlsConfig = GrpcConfigKeys.TLS.apply(properties, tlsConfig); - final SslContext defaultSslContext = buildMethod.apply(defaultTlsConfig, null); - this.adminSslContext = buildMethod.apply( - GrpcConfigKeys.TLS.apply(properties, adminTlsConfig), defaultSslContext); - this.clientSslContext = buildMethod.apply( - GrpcConfigKeys.TLS.apply(properties, clientTlsConfig), defaultSslContext); - this.serverSslContext = buildMethod.apply( - GrpcConfigKeys.TLS.apply(properties, serverTlsConfig), defaultSslContext); + final SslContext defaultSslContext = buildMethod.apply(tlsConfig, null); + this.adminSslContext = buildMethod.apply(adminTlsConfig, defaultSslContext); + this.clientSslContext = buildMethod.apply(clientTlsConfig, defaultSslContext); + this.serverSslContext = buildMethod.apply(serverTlsConfig, defaultSslContext); } } @@ -117,9 +113,8 @@ private GrpcFactory(GrpcServices.Customizer servicesCustomizer, this.serverTlsConfig = serverTlsConfig; } - private SslContexts newSslContexts(RaftProperties properties, - BiFunction buildMethod) { - return new SslContexts(properties, tlsConfig, adminTlsConfig, clientTlsConfig, serverTlsConfig, buildMethod); + private SslContexts newSslContexts(BiFunction buildMethod) { + return new SslContexts(tlsConfig, adminTlsConfig, clientTlsConfig, serverTlsConfig, buildMethod); } @Override @@ -136,9 +131,8 @@ public LogAppender newLogAppender(RaftServer.Division server, LeaderState state, public GrpcServices newRaftServerRpc(RaftServer server) { checkPooledByteBufAllocatorUseCacheForAllThreads(LOG::info); - final RaftProperties properties = server.getProperties(); - final SslContexts forServer = newSslContexts(properties, BUILD_SSL_CONTEXT_FOR_SERVER); - final SslContexts forClient = newSslContexts(properties, BUILD_SSL_CONTEXT_FOR_CLIENT); + final SslContexts forServer = newSslContexts(BUILD_SSL_CONTEXT_FOR_SERVER); + final SslContexts forClient = newSslContexts(BUILD_SSL_CONTEXT_FOR_CLIENT); return GrpcServicesImpl.newBuilder() .setServer(server) .setCustomizer(servicesCustomizer) @@ -153,7 +147,7 @@ public GrpcServices newRaftServerRpc(RaftServer server) { public GrpcClientRpc newRaftClientRpc(ClientId clientId, RaftProperties properties) { checkPooledByteBufAllocatorUseCacheForAllThreads(LOG::debug); - final SslContexts forClient = newSslContexts(properties, BUILD_SSL_CONTEXT_FOR_CLIENT); + final SslContexts forClient = newSslContexts(BUILD_SSL_CONTEXT_FOR_CLIENT); return new GrpcClientRpc(clientId, properties, forClient.adminSslContext, forClient.clientSslContext); } } diff --git a/ratis-grpc/src/main/java/org/apache/ratis/grpc/GrpcTlsConfig.java b/ratis-grpc/src/main/java/org/apache/ratis/grpc/GrpcTlsConfig.java index 6cd16e40d7..52ba762886 100644 --- a/ratis-grpc/src/main/java/org/apache/ratis/grpc/GrpcTlsConfig.java +++ b/ratis-grpc/src/main/java/org/apache/ratis/grpc/GrpcTlsConfig.java @@ -25,6 +25,7 @@ import java.io.File; import java.security.PrivateKey; import java.security.cert.X509Certificate; +import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.Iterator; @@ -38,8 +39,8 @@ public class GrpcTlsConfig extends TlsConf { private final boolean fileBasedConfig; private final SslProvider sslProvider; private final String jsseProviderName; - private final String[] protocols; - private final String[] cipherSuites; + private final List protocols; + private final List cipherSuites; public boolean isFileBasedConfig() { return fileBasedConfig; @@ -101,12 +102,12 @@ public String getJsseProviderName() { return jsseProviderName; } - public String[] getProtocols() { - return protocols != null ? Arrays.copyOf(protocols, protocols.length) : null; + public List getProtocols() { + return protocols; } - public String[] getCipherSuites() { - return cipherSuites != null ? Arrays.copyOf(cipherSuites, cipherSuites.length) : null; + public List getCipherSuites() { + return cipherSuites; } public GrpcTlsConfig(PrivateKey privateKey, X509Certificate certChain, @@ -181,8 +182,12 @@ public static Builder newBuilder(GrpcTlsConfig conf) { .setCipherSuites(conf.getCipherSuites()); } - private static String[] copy(String[] values) { - return values != null ? Arrays.copyOf(values, values.length) : null; + private static List copy(List values) { + return values != null ? Collections.unmodifiableList(new ArrayList<>(values)) : null; + } + + private static List copy(String[] values) { + return values != null ? copy(Arrays.asList(values)) : null; } public static Builder newBuilder() { @@ -193,8 +198,8 @@ public static Builder newBuilder() { public static class Builder extends TlsConf.Builder { private SslProvider sslProvider; private String jsseProviderName; - private String[] protocols; - private String[] cipherSuites; + private List protocols; + private List cipherSuites; @Override public Builder setName(String name) { @@ -253,11 +258,21 @@ public Builder setProtocols(String... protocols) { return this; } + public Builder setProtocols(List protocols) { + this.protocols = copy(protocols); + return this; + } + public Builder setCipherSuites(String... cipherSuites) { this.cipherSuites = copy(cipherSuites); return this; } + public Builder setCipherSuites(List cipherSuites) { + this.cipherSuites = copy(cipherSuites); + return this; + } + @Override public GrpcTlsConfig build() { return new GrpcTlsConfig(this, false); diff --git a/ratis-grpc/src/main/java/org/apache/ratis/grpc/GrpcUtil.java b/ratis-grpc/src/main/java/org/apache/ratis/grpc/GrpcUtil.java index 6a00d89e6e..380260d626 100644 --- a/ratis-grpc/src/main/java/org/apache/ratis/grpc/GrpcUtil.java +++ b/ratis-grpc/src/main/java/org/apache/ratis/grpc/GrpcUtil.java @@ -50,7 +50,7 @@ import java.io.IOException; import java.security.Provider; import java.security.Security; -import java.util.Arrays; +import java.util.List; import java.util.concurrent.CompletableFuture; import java.util.concurrent.TimeUnit; import java.util.function.Function; @@ -332,13 +332,13 @@ static SslContextBuilder configureSslContextBuilder( b = sslProvider != null ? GrpcSslContexts.configure(b, sslProvider) : GrpcSslContexts.configure(b); } } - final String[] protocols = tlsConf.getProtocols(); - if (protocols != null && protocols.length > 0) { - b.protocols(protocols); + final List protocols = tlsConf.getProtocols(); + if (protocols != null && !protocols.isEmpty()) { + b.protocols(protocols.toArray(new String[0])); } - final String[] cipherSuites = tlsConf.getCipherSuites(); - if (cipherSuites != null && cipherSuites.length > 0) { - b.ciphers(Arrays.asList(cipherSuites), IdentityCipherSuiteFilter.INSTANCE); + final List cipherSuites = tlsConf.getCipherSuites(); + if (cipherSuites != null && !cipherSuites.isEmpty()) { + b.ciphers(cipherSuites, IdentityCipherSuiteFilter.INSTANCE); } return b; } diff --git a/ratis-grpc/src/test/java/org/apache/ratis/grpc/TestGrpcTlsConfig.java b/ratis-grpc/src/test/java/org/apache/ratis/grpc/TestGrpcTlsConfig.java index 20fad483d1..a6aa15db53 100644 --- a/ratis-grpc/src/test/java/org/apache/ratis/grpc/TestGrpcTlsConfig.java +++ b/ratis-grpc/src/test/java/org/apache/ratis/grpc/TestGrpcTlsConfig.java @@ -17,38 +17,40 @@ */ package org.apache.ratis.grpc; -import org.apache.ratis.conf.RaftProperties; import org.apache.ratis.thirdparty.io.netty.handler.ssl.SslContextBuilder; import org.apache.ratis.thirdparty.io.netty.handler.ssl.SslProvider; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; import java.security.Provider; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; public class TestGrpcTlsConfig { @Test - public void testRaftPropertiesOverrideGrpcTlsOptions() { + public void testGrpcTlsConfigCopiesLists() { + final List protocols = new ArrayList<>(Collections.singletonList("TLSv1.2")); + final List cipherSuites = new ArrayList<>(Collections.singletonList("TLS_AES_128_GCM_SHA256")); + final GrpcTlsConfig conf = GrpcTlsConfig.newBuilder() - .setSslProvider(SslProvider.OPENSSL) - .setProtocols("TLSv1.2") - .setCipherSuites("TLS_AES_128_GCM_SHA256") + .setProtocols(protocols) + .setCipherSuites(cipherSuites) .build(); - final RaftProperties properties = new RaftProperties(); - GrpcConfigKeys.TLS.setSslProvider(properties, SslProvider.JDK); - GrpcConfigKeys.TLS.setJsseProviderName(properties, "SunJSSE"); - GrpcConfigKeys.TLS.setProtocols(properties, "TLSv1.3"); - GrpcConfigKeys.TLS.setCipherSuites(properties, "TLS_AES_256_GCM_SHA384"); + protocols.add("TLSv1.3"); + cipherSuites.add("TLS_AES_256_GCM_SHA384"); - final GrpcTlsConfig updated = GrpcConfigKeys.TLS.apply(properties, conf); - Assertions.assertSame(SslProvider.JDK, updated.getSslProvider()); - Assertions.assertEquals("SunJSSE", updated.getJsseProviderName()); - Assertions.assertArrayEquals(new String[] {"TLSv1.3"}, updated.getProtocols()); - Assertions.assertArrayEquals(new String[] {"TLS_AES_256_GCM_SHA384"}, updated.getCipherSuites()); + Assertions.assertEquals(Collections.singletonList("TLSv1.2"), conf.getProtocols()); + Assertions.assertEquals(Collections.singletonList("TLS_AES_128_GCM_SHA256"), conf.getCipherSuites()); + Assertions.assertThrows(UnsupportedOperationException.class, () -> conf.getProtocols().add("TLSv1.3")); + Assertions.assertThrows(UnsupportedOperationException.class, + () -> conf.getCipherSuites().add("TLS_AES_256_GCM_SHA384")); } @Test - public void testRaftPropertiesKeepUnsetGrpcTlsOptions() { + public void testNewBuilderCopiesGrpcTlsOptions() { final GrpcTlsConfig conf = GrpcTlsConfig.newBuilder() .setSslProvider(SslProvider.OPENSSL) .setJsseProviderName("SunJSSE") @@ -56,11 +58,11 @@ public void testRaftPropertiesKeepUnsetGrpcTlsOptions() { .setCipherSuites("TLS_AES_128_GCM_SHA256") .build(); - final GrpcTlsConfig updated = GrpcConfigKeys.TLS.apply(new RaftProperties(), conf); + final GrpcTlsConfig updated = GrpcTlsConfig.newBuilder(conf).build(); Assertions.assertSame(SslProvider.OPENSSL, updated.getSslProvider()); Assertions.assertEquals("SunJSSE", updated.getJsseProviderName()); - Assertions.assertArrayEquals(new String[] {"TLSv1.2"}, updated.getProtocols()); - Assertions.assertArrayEquals(new String[] {"TLS_AES_128_GCM_SHA256"}, updated.getCipherSuites()); + Assertions.assertEquals(Collections.singletonList("TLSv1.2"), updated.getProtocols()); + Assertions.assertEquals(Arrays.asList("TLS_AES_128_GCM_SHA256"), updated.getCipherSuites()); } @Test From c6963e657df0256e1ca05781c7c652465349c1b2 Mon Sep 17 00:00:00 2001 From: HTHou Date: Thu, 21 May 2026 14:37:53 +0800 Subject: [PATCH 5/7] RATIS-2537. Avoid exposing TLS option lists --- .../src/main/java/org/apache/ratis/grpc/GrpcTlsConfig.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ratis-grpc/src/main/java/org/apache/ratis/grpc/GrpcTlsConfig.java b/ratis-grpc/src/main/java/org/apache/ratis/grpc/GrpcTlsConfig.java index 52ba762886..39fac65942 100644 --- a/ratis-grpc/src/main/java/org/apache/ratis/grpc/GrpcTlsConfig.java +++ b/ratis-grpc/src/main/java/org/apache/ratis/grpc/GrpcTlsConfig.java @@ -103,11 +103,11 @@ public String getJsseProviderName() { } public List getProtocols() { - return protocols; + return copy(protocols); } public List getCipherSuites() { - return cipherSuites; + return copy(cipherSuites); } public GrpcTlsConfig(PrivateKey privateKey, X509Certificate certChain, From 12dc7472d6fcff25e78fe80ed53b5a7ec10bd311 Mon Sep 17 00:00:00 2001 From: HTHou Date: Fri, 22 May 2026 09:51:07 +0800 Subject: [PATCH 6/7] RATIS-2537. Move TLS options to TlsConf --- .../org/apache/ratis/security/TlsConf.java | 86 +++++++++++++++++-- .../org/apache/ratis/grpc/GrpcFactory.java | 26 +++--- .../org/apache/ratis/grpc/GrpcTlsConfig.java | 80 +++-------------- .../java/org/apache/ratis/grpc/GrpcUtil.java | 5 +- .../apache/ratis/grpc/TestGrpcTlsConfig.java | 21 +---- 5 files changed, 106 insertions(+), 112 deletions(-) diff --git a/ratis-common/src/main/java/org/apache/ratis/security/TlsConf.java b/ratis-common/src/main/java/org/apache/ratis/security/TlsConf.java index 30cf67c83b..b442124596 100644 --- a/ratis-common/src/main/java/org/apache/ratis/security/TlsConf.java +++ b/ratis-common/src/main/java/org/apache/ratis/security/TlsConf.java @@ -17,6 +17,7 @@ */ package org.apache.ratis.security; +import org.apache.ratis.thirdparty.io.netty.handler.ssl.SslProvider; import org.apache.ratis.util.JavaUtils; import org.apache.ratis.util.Preconditions; @@ -25,8 +26,11 @@ import java.io.File; import java.security.PrivateKey; import java.security.cert.X509Certificate; +import java.util.ArrayList; import java.util.Arrays; +import java.util.Collections; import java.util.Iterator; +import java.util.List; import java.util.Objects; import java.util.Optional; import java.util.concurrent.atomic.AtomicInteger; @@ -170,16 +174,22 @@ public KeyManager getKeyManager() { private final KeyManagerConf keyManager; private final TrustManagerConf trustManager; private final boolean mutualTls; - - private TlsConf(String name, KeyManagerConf keyManager, TrustManagerConf trustManager, boolean mutualTls) { - this.name = JavaUtils.getClassSimpleName(getClass()) + COUNT.getAndIncrement() + (name == null? "": "-" + name); - this.keyManager = keyManager; - this.trustManager = trustManager; - this.mutualTls = mutualTls; - } + private final SslProvider sslProvider; + private final String jsseProviderName; + private final List protocols; + private final List cipherSuites; protected TlsConf(Builder b) { - this(b.buildName(), b.buildKeyManagerConf(), b.buildTrustManagerConf(), b.isMutualTls()); + final String buildName = b.buildName(); + this.name = JavaUtils.getClassSimpleName(getClass()) + COUNT.getAndIncrement() + + (buildName == null? "": "-" + buildName); + this.keyManager = b.buildKeyManagerConf(); + this.trustManager = b.buildTrustManagerConf(); + this.mutualTls = b.isMutualTls(); + this.sslProvider = b.sslProvider; + this.jsseProviderName = b.jsseProviderName; + this.protocols = copy(b.protocols); + this.cipherSuites = copy(b.cipherSuites); } /** @return the key manager configuration. */ @@ -197,6 +207,22 @@ public boolean isMutualTls() { return mutualTls; } + public SslProvider getSslProvider() { + return sslProvider; + } + + public String getJsseProviderName() { + return jsseProviderName; + } + + public List getProtocols() { + return copy(protocols); + } + + public List getCipherSuites() { + return copy(cipherSuites); + } + @Override public String toString() { return name; @@ -206,6 +232,14 @@ public static Builder newBuilder() { return new Builder(); } + private static List copy(List values) { + return values != null ? Collections.unmodifiableList(new ArrayList<>(values)) : null; + } + + private static List copy(String[] values) { + return values != null ? copy(Arrays.asList(values)) : null; + } + /** For building {@link TlsConf}. */ public static class Builder { private String name; @@ -215,6 +249,10 @@ public static class Builder { private boolean mutualTls; private KeyManager keyManager; private TrustManager trustManager; + private SslProvider sslProvider; + private String jsseProviderName; + private List protocols; + private List cipherSuites; public Builder setName(String name) { this.name = name; @@ -251,6 +289,36 @@ public Builder setMutualTls(boolean mutualTls) { return this; } + public Builder setSslProvider(SslProvider sslProvider) { + this.sslProvider = sslProvider; + return this; + } + + public Builder setJsseProviderName(String jsseProviderName) { + this.jsseProviderName = jsseProviderName; + return this; + } + + public Builder setProtocols(String... protocols) { + this.protocols = copy(protocols); + return this; + } + + public Builder setProtocols(List protocols) { + this.protocols = copy(protocols); + return this; + } + + public Builder setCipherSuites(String... cipherSuites) { + this.cipherSuites = copy(cipherSuites); + return this; + } + + public Builder setCipherSuites(List cipherSuites) { + this.cipherSuites = copy(cipherSuites); + return this; + } + private boolean isMutualTls() { return mutualTls; } @@ -285,4 +353,4 @@ public TlsConf build() { return new TlsConf(this); } } -} \ No newline at end of file +} diff --git a/ratis-grpc/src/main/java/org/apache/ratis/grpc/GrpcFactory.java b/ratis-grpc/src/main/java/org/apache/ratis/grpc/GrpcFactory.java index e6220e3306..1053cab80e 100644 --- a/ratis-grpc/src/main/java/org/apache/ratis/grpc/GrpcFactory.java +++ b/ratis-grpc/src/main/java/org/apache/ratis/grpc/GrpcFactory.java @@ -34,11 +34,13 @@ import org.apache.ratis.thirdparty.io.netty.buffer.PooledByteBufAllocator; import org.apache.ratis.thirdparty.io.netty.handler.ssl.SslContext; import org.apache.ratis.util.JavaUtils; +import org.apache.ratis.util.MemoizedSupplier; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.util.function.BiFunction; import java.util.function.Consumer; +import java.util.function.Supplier; public class GrpcFactory implements ServerFactory, ClientFactory { @@ -89,10 +91,9 @@ private SslContexts(GrpcTlsConfig tlsConfig, GrpcTlsConfig adminTlsConfig, } private final GrpcServices.Customizer servicesCustomizer; - private final GrpcTlsConfig tlsConfig; - private final GrpcTlsConfig adminTlsConfig; - private final GrpcTlsConfig clientTlsConfig; - private final GrpcTlsConfig serverTlsConfig; + + private final Supplier forServerSupplier; + private final Supplier forClientSupplier; public GrpcFactory(Parameters parameters) { this(GrpcConfigKeys.Server.servicesCustomizer(parameters), @@ -107,14 +108,11 @@ private GrpcFactory(GrpcServices.Customizer servicesCustomizer, GrpcTlsConfig tlsConfig, GrpcTlsConfig adminTlsConfig, GrpcTlsConfig clientTlsConfig, GrpcTlsConfig serverTlsConfig) { this.servicesCustomizer = servicesCustomizer; - this.tlsConfig = tlsConfig; - this.adminTlsConfig = adminTlsConfig; - this.clientTlsConfig = clientTlsConfig; - this.serverTlsConfig = serverTlsConfig; - } - private SslContexts newSslContexts(BiFunction buildMethod) { - return new SslContexts(tlsConfig, adminTlsConfig, clientTlsConfig, serverTlsConfig, buildMethod); + this.forServerSupplier = MemoizedSupplier.valueOf(() -> new SslContexts( + tlsConfig, adminTlsConfig, clientTlsConfig, serverTlsConfig, BUILD_SSL_CONTEXT_FOR_SERVER)); + this.forClientSupplier = MemoizedSupplier.valueOf(() -> new SslContexts( + tlsConfig, adminTlsConfig, clientTlsConfig, serverTlsConfig, BUILD_SSL_CONTEXT_FOR_CLIENT)); } @Override @@ -131,8 +129,8 @@ public LogAppender newLogAppender(RaftServer.Division server, LeaderState state, public GrpcServices newRaftServerRpc(RaftServer server) { checkPooledByteBufAllocatorUseCacheForAllThreads(LOG::info); - final SslContexts forServer = newSslContexts(BUILD_SSL_CONTEXT_FOR_SERVER); - final SslContexts forClient = newSslContexts(BUILD_SSL_CONTEXT_FOR_CLIENT); + final SslContexts forServer = forServerSupplier.get(); + final SslContexts forClient = forClientSupplier.get(); return GrpcServicesImpl.newBuilder() .setServer(server) .setCustomizer(servicesCustomizer) @@ -147,7 +145,7 @@ public GrpcServices newRaftServerRpc(RaftServer server) { public GrpcClientRpc newRaftClientRpc(ClientId clientId, RaftProperties properties) { checkPooledByteBufAllocatorUseCacheForAllThreads(LOG::debug); - final SslContexts forClient = newSslContexts(BUILD_SSL_CONTEXT_FOR_CLIENT); + final SslContexts forClient = forClientSupplier.get(); return new GrpcClientRpc(clientId, properties, forClient.adminSslContext, forClient.clientSslContext); } } diff --git a/ratis-grpc/src/main/java/org/apache/ratis/grpc/GrpcTlsConfig.java b/ratis-grpc/src/main/java/org/apache/ratis/grpc/GrpcTlsConfig.java index 39fac65942..c6b8dce594 100644 --- a/ratis-grpc/src/main/java/org/apache/ratis/grpc/GrpcTlsConfig.java +++ b/ratis-grpc/src/main/java/org/apache/ratis/grpc/GrpcTlsConfig.java @@ -25,8 +25,6 @@ import java.io.File; import java.security.PrivateKey; import java.security.cert.X509Certificate; -import java.util.ArrayList; -import java.util.Arrays; import java.util.Collections; import java.util.Iterator; import java.util.List; @@ -37,10 +35,6 @@ */ public class GrpcTlsConfig extends TlsConf { private final boolean fileBasedConfig; - private final SslProvider sslProvider; - private final String jsseProviderName; - private final List protocols; - private final List cipherSuites; public boolean isFileBasedConfig() { return fileBasedConfig; @@ -94,22 +88,6 @@ public boolean getMtlsEnabled() { return isMutualTls(); } - public SslProvider getSslProvider() { - return sslProvider; - } - - public String getJsseProviderName() { - return jsseProviderName; - } - - public List getProtocols() { - return copy(protocols); - } - - public List getCipherSuites() { - return copy(cipherSuites); - } - public GrpcTlsConfig(PrivateKey privateKey, X509Certificate certChain, List trustStore, boolean mTlsEnabled) { this(newBuilder(privateKey, certChain, trustStore, mTlsEnabled), false); @@ -128,10 +106,6 @@ public GrpcTlsConfig(File privateKeyFile, File certChainFile, private GrpcTlsConfig(Builder builder, boolean fileBasedConfig) { super(builder); this.fileBasedConfig = fileBasedConfig; - this.sslProvider = builder.sslProvider; - this.jsseProviderName = builder.jsseProviderName; - this.protocols = copy(builder.protocols); - this.cipherSuites = copy(builder.cipherSuites); } public GrpcTlsConfig(KeyManager keyManager, TrustManager trustManager, boolean mTlsEnabled) { @@ -159,48 +133,12 @@ private static Builder newBuilder(KeyManager keyManager, TrustManager trustManag return newBuilder().setMutualTls(mTlsEnabled).setKeyManager(keyManager).setTrustManager(trustManager); } - public static Builder newBuilder(GrpcTlsConfig conf) { - final Builder b = newBuilder().setMutualTls(conf.isMutualTls()); - Optional.ofNullable(conf.getKeyManager()).ifPresent(keyManager -> { - if (keyManager.getKeyManager() != null) { - b.setKeyManager(keyManager.getKeyManager()); - } else { - b.setPrivateKey(keyManager.getPrivateKey()); - b.setKeyCertificates(keyManager.getKeyCertificates()); - } - }); - Optional.ofNullable(conf.getTrustManager()).ifPresent(trustManager -> { - if (trustManager.getTrustManager() != null) { - b.setTrustManager(trustManager.getTrustManager()); - } else { - b.setTrustCertificates(trustManager.getTrustCertificates()); - } - }); - return b.setSslProvider(conf.getSslProvider()) - .setJsseProviderName(conf.getJsseProviderName()) - .setProtocols(conf.getProtocols()) - .setCipherSuites(conf.getCipherSuites()); - } - - private static List copy(List values) { - return values != null ? Collections.unmodifiableList(new ArrayList<>(values)) : null; - } - - private static List copy(String[] values) { - return values != null ? copy(Arrays.asList(values)) : null; - } - public static Builder newBuilder() { return new Builder(); } /** For building {@link GrpcTlsConfig}. */ public static class Builder extends TlsConf.Builder { - private SslProvider sslProvider; - private String jsseProviderName; - private List protocols; - private List cipherSuites; - @Override public Builder setName(String name) { super.setName(name); @@ -243,33 +181,39 @@ public Builder setMutualTls(boolean mutualTls) { return this; } + @Override public Builder setSslProvider(SslProvider sslProvider) { - this.sslProvider = sslProvider; + super.setSslProvider(sslProvider); return this; } + @Override public Builder setJsseProviderName(String jsseProviderName) { - this.jsseProviderName = jsseProviderName; + super.setJsseProviderName(jsseProviderName); return this; } + @Override public Builder setProtocols(String... protocols) { - this.protocols = copy(protocols); + super.setProtocols(protocols); return this; } + @Override public Builder setProtocols(List protocols) { - this.protocols = copy(protocols); + super.setProtocols(protocols); return this; } + @Override public Builder setCipherSuites(String... cipherSuites) { - this.cipherSuites = copy(cipherSuites); + super.setCipherSuites(cipherSuites); return this; } + @Override public Builder setCipherSuites(List cipherSuites) { - this.cipherSuites = copy(cipherSuites); + super.setCipherSuites(cipherSuites); return this; } diff --git a/ratis-grpc/src/main/java/org/apache/ratis/grpc/GrpcUtil.java b/ratis-grpc/src/main/java/org/apache/ratis/grpc/GrpcUtil.java index 380260d626..36b8e9d65c 100644 --- a/ratis-grpc/src/main/java/org/apache/ratis/grpc/GrpcUtil.java +++ b/ratis-grpc/src/main/java/org/apache/ratis/grpc/GrpcUtil.java @@ -20,6 +20,7 @@ import java.util.function.Consumer; import org.apache.ratis.protocol.exceptions.ServerNotReadyException; import org.apache.ratis.protocol.exceptions.TimeoutIOException; +import org.apache.ratis.security.TlsConf; import org.apache.ratis.security.TlsConf.TrustManagerConf; import org.apache.ratis.security.TlsConf.CertificatesConf; import org.apache.ratis.security.TlsConf.PrivateKeyConf; @@ -319,7 +320,7 @@ static void setKeyManager(SslContextBuilder b, KeyManagerConf keyManagerConfig) } static SslContextBuilder configureSslContextBuilder( - SslContextBuilder b, GrpcTlsConfig tlsConf, SslProvider defaultSslProvider) { + SslContextBuilder b, TlsConf tlsConf, SslProvider defaultSslProvider) { final Provider jsseProvider = getJsseProvider(tlsConf); if (jsseProvider != null) { b = configureJsseProvider(b, jsseProvider); @@ -356,7 +357,7 @@ static SslContextBuilder configureJsseProvider(SslContextBuilder b, Provider pro } } - static Provider getJsseProvider(GrpcTlsConfig tlsConf) { + static Provider getJsseProvider(TlsConf tlsConf) { final String providerName = tlsConf.getJsseProviderName(); if (providerName == null || providerName.trim().isEmpty()) { return null; diff --git a/ratis-grpc/src/test/java/org/apache/ratis/grpc/TestGrpcTlsConfig.java b/ratis-grpc/src/test/java/org/apache/ratis/grpc/TestGrpcTlsConfig.java index a6aa15db53..d3c6be8e2c 100644 --- a/ratis-grpc/src/test/java/org/apache/ratis/grpc/TestGrpcTlsConfig.java +++ b/ratis-grpc/src/test/java/org/apache/ratis/grpc/TestGrpcTlsConfig.java @@ -18,13 +18,12 @@ package org.apache.ratis.grpc; import org.apache.ratis.thirdparty.io.netty.handler.ssl.SslContextBuilder; -import org.apache.ratis.thirdparty.io.netty.handler.ssl.SslProvider; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; +import javax.net.ssl.SSLException; import java.security.Provider; import java.util.ArrayList; -import java.util.Arrays; import java.util.Collections; import java.util.List; @@ -49,27 +48,11 @@ public void testGrpcTlsConfigCopiesLists() { () -> conf.getCipherSuites().add("TLS_AES_256_GCM_SHA384")); } - @Test - public void testNewBuilderCopiesGrpcTlsOptions() { - final GrpcTlsConfig conf = GrpcTlsConfig.newBuilder() - .setSslProvider(SslProvider.OPENSSL) - .setJsseProviderName("SunJSSE") - .setProtocols("TLSv1.2") - .setCipherSuites("TLS_AES_128_GCM_SHA256") - .build(); - - final GrpcTlsConfig updated = GrpcTlsConfig.newBuilder(conf).build(); - Assertions.assertSame(SslProvider.OPENSSL, updated.getSslProvider()); - Assertions.assertEquals("SunJSSE", updated.getJsseProviderName()); - Assertions.assertEquals(Collections.singletonList("TLSv1.2"), updated.getProtocols()); - Assertions.assertEquals(Arrays.asList("TLS_AES_128_GCM_SHA256"), updated.getCipherSuites()); - } - @Test public void testUnknownJsseProviderUsesGenericJdkConfiguration() { final SslContextBuilder builder = GrpcUtil.configureJsseProvider( SslContextBuilder.forClient(), new TestProvider()); - Assertions.assertNotNull(builder); + Assertions.assertThrows(SSLException.class, builder::build); } private static class TestProvider extends Provider { From 4bd2ce8da7a452be8ab4fd50eab284879fed4e5f Mon Sep 17 00:00:00 2001 From: HTHou Date: Fri, 22 May 2026 10:17:24 +0800 Subject: [PATCH 7/7] RATIS-2537. Trigger CI rerun