Skip to content

Commit d411b02

Browse files
authored
RATIS-2331. Reuse SslContext in gRPC. (#1288)
1 parent c5a89d8 commit d411b02

File tree

9 files changed

+134
-250
lines changed

9 files changed

+134
-250
lines changed

ratis-common/src/main/java/org/apache/ratis/util/LifeCycle.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,9 @@ static void validate(Object name, State from, State to) {
117117
if (LOG.isTraceEnabled()) {
118118
LOG.trace("TRACE", new Throwable());
119119
}
120+
if (to == EXCEPTION) {
121+
LOG.error("{} has failed ({} -> {})", name, from, to, new Throwable("TRACE"));
122+
}
120123

121124
Preconditions.assertTrue(isValid(from, to),
122125
"ILLEGAL TRANSITION: In %s, %s -> %s", name, from, to);

ratis-grpc/src/main/java/org/apache/ratis/grpc/GrpcFactory.java

Lines changed: 40 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -32,11 +32,15 @@
3232
import org.apache.ratis.server.leader.FollowerInfo;
3333
import org.apache.ratis.server.leader.LeaderState;
3434
import org.apache.ratis.thirdparty.io.netty.buffer.PooledByteBufAllocator;
35+
import org.apache.ratis.thirdparty.io.netty.handler.ssl.SslContext;
3536
import org.apache.ratis.util.JavaUtils;
37+
import org.apache.ratis.util.MemoizedSupplier;
3638
import org.slf4j.Logger;
3739
import org.slf4j.LoggerFactory;
3840

41+
import java.util.function.BiFunction;
3942
import java.util.function.Consumer;
43+
import java.util.function.Supplier;
4044

4145
public class GrpcFactory implements ServerFactory, ClientFactory {
4246

@@ -65,19 +69,32 @@ static boolean checkPooledByteBufAllocatorUseCacheForAllThreads(Consumer<String>
6569
return value;
6670
}
6771

68-
private final GrpcServices.Customizer servicesCustomizer;
72+
static final BiFunction<GrpcTlsConfig, SslContext, SslContext> BUILD_SSL_CONTEXT_FOR_SERVER
73+
= (tlsConf, defaultContext) -> tlsConf == null ? defaultContext : GrpcUtil.buildSslContextForServer(tlsConf);
74+
75+
static final BiFunction<GrpcTlsConfig, SslContext, SslContext> BUILD_SSL_CONTEXT_FOR_CLIENT
76+
= (tlsConf, defaultContext) -> tlsConf == null ? defaultContext : GrpcUtil.buildSslContextForClient(tlsConf);
6977

70-
private final GrpcTlsConfig tlsConfig;
71-
private final GrpcTlsConfig adminTlsConfig;
72-
private final GrpcTlsConfig clientTlsConfig;
73-
private final GrpcTlsConfig serverTlsConfig;
78+
static final class SslContexts {
79+
private final SslContext adminSslContext;
80+
private final SslContext clientSslContext;
81+
private final SslContext serverSslContext;
7482

75-
public static Parameters newRaftParameters(GrpcTlsConfig conf) {
76-
final Parameters p = new Parameters();
77-
GrpcConfigKeys.TLS.setConf(p, conf);
78-
return p;
83+
private SslContexts(GrpcTlsConfig tlsConfig, GrpcTlsConfig adminTlsConfig,
84+
GrpcTlsConfig clientTlsConfig, GrpcTlsConfig serverTlsConfig,
85+
BiFunction<GrpcTlsConfig, SslContext, SslContext> buildMethod) {
86+
final SslContext defaultSslContext = buildMethod.apply(tlsConfig, null);
87+
this.adminSslContext = buildMethod.apply(adminTlsConfig, defaultSslContext);
88+
this.clientSslContext = buildMethod.apply(clientTlsConfig, defaultSslContext);
89+
this.serverSslContext = buildMethod.apply(serverTlsConfig, defaultSslContext);
90+
}
7991
}
8092

93+
private final GrpcServices.Customizer servicesCustomizer;
94+
95+
private final Supplier<SslContexts> forServerSupplier;
96+
private final Supplier<SslContexts> forClientSupplier;
97+
8198
public GrpcFactory(Parameters parameters) {
8299
this(GrpcConfigKeys.Server.servicesCustomizer(parameters),
83100
GrpcConfigKeys.TLS.conf(parameters),
@@ -87,35 +104,15 @@ public GrpcFactory(Parameters parameters) {
87104
);
88105
}
89106

90-
public GrpcFactory(GrpcTlsConfig tlsConfig) {
91-
this(null, tlsConfig, null, null, null);
92-
}
93-
94107
private GrpcFactory(GrpcServices.Customizer servicesCustomizer,
95108
GrpcTlsConfig tlsConfig, GrpcTlsConfig adminTlsConfig,
96109
GrpcTlsConfig clientTlsConfig, GrpcTlsConfig serverTlsConfig) {
97110
this.servicesCustomizer = servicesCustomizer;
98111

99-
this.tlsConfig = tlsConfig;
100-
this.adminTlsConfig = adminTlsConfig;
101-
this.clientTlsConfig = clientTlsConfig;
102-
this.serverTlsConfig = serverTlsConfig;
103-
}
104-
105-
public GrpcTlsConfig getTlsConfig() {
106-
return tlsConfig;
107-
}
108-
109-
public GrpcTlsConfig getAdminTlsConfig() {
110-
return adminTlsConfig != null ? adminTlsConfig : tlsConfig;
111-
}
112-
113-
public GrpcTlsConfig getClientTlsConfig() {
114-
return clientTlsConfig != null ? clientTlsConfig : tlsConfig;
115-
}
116-
117-
public GrpcTlsConfig getServerTlsConfig() {
118-
return serverTlsConfig != null ? serverTlsConfig : tlsConfig;
112+
this.forServerSupplier = MemoizedSupplier.valueOf(() -> new SslContexts(
113+
tlsConfig, adminTlsConfig, clientTlsConfig, serverTlsConfig, BUILD_SSL_CONTEXT_FOR_SERVER));
114+
this.forClientSupplier = MemoizedSupplier.valueOf(() -> new SslContexts(
115+
tlsConfig, adminTlsConfig, clientTlsConfig, serverTlsConfig, BUILD_SSL_CONTEXT_FOR_CLIENT));
119116
}
120117

121118
@Override
@@ -131,19 +128,24 @@ public LogAppender newLogAppender(RaftServer.Division server, LeaderState state,
131128
@Override
132129
public GrpcServices newRaftServerRpc(RaftServer server) {
133130
checkPooledByteBufAllocatorUseCacheForAllThreads(LOG::info);
131+
132+
final SslContexts forServer = forServerSupplier.get();
133+
final SslContexts forClient = forClientSupplier.get();
134134
return GrpcServicesImpl.newBuilder()
135135
.setServer(server)
136136
.setCustomizer(servicesCustomizer)
137-
.setAdminTlsConfig(getAdminTlsConfig())
138-
.setServerTlsConfig(getServerTlsConfig())
139-
.setClientTlsConfig(getClientTlsConfig())
137+
.setAdminSslContext(forServer.adminSslContext)
138+
.setServerSslContextForServer(forServer.serverSslContext)
139+
.setServerSslContextForClient(forClient.serverSslContext)
140+
.setClientSslContext(forServer.clientSslContext)
140141
.build();
141142
}
142143

143144
@Override
144145
public GrpcClientRpc newRaftClientRpc(ClientId clientId, RaftProperties properties) {
145146
checkPooledByteBufAllocatorUseCacheForAllThreads(LOG::debug);
146-
return new GrpcClientRpc(clientId, properties,
147-
getAdminTlsConfig(), getClientTlsConfig());
147+
148+
final SslContexts forClient = forClientSupplier.get();
149+
return new GrpcClientRpc(clientId, properties, forClient.adminSslContext, forClient.clientSslContext);
148150
}
149151
}

ratis-grpc/src/main/java/org/apache/ratis/grpc/GrpcUtil.java

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,10 @@
2828
import org.apache.ratis.thirdparty.io.grpc.Metadata;
2929
import org.apache.ratis.thirdparty.io.grpc.Status;
3030
import org.apache.ratis.thirdparty.io.grpc.StatusRuntimeException;
31+
import org.apache.ratis.thirdparty.io.grpc.netty.GrpcSslContexts;
3132
import org.apache.ratis.thirdparty.io.grpc.stub.StreamObserver;
33+
import org.apache.ratis.thirdparty.io.netty.handler.ssl.ClientAuth;
34+
import org.apache.ratis.thirdparty.io.netty.handler.ssl.SslContext;
3235
import org.apache.ratis.thirdparty.io.netty.handler.ssl.SslContextBuilder;
3336
import org.apache.ratis.util.IOUtils;
3437
import org.apache.ratis.util.JavaUtils;
@@ -39,13 +42,16 @@
3942
import org.slf4j.LoggerFactory;
4043

4144
import javax.net.ssl.KeyManager;
45+
import javax.net.ssl.SSLException;
4246
import javax.net.ssl.TrustManager;
4347
import java.io.IOException;
4448
import java.util.concurrent.CompletableFuture;
4549
import java.util.concurrent.TimeUnit;
4650
import java.util.function.Function;
4751
import java.util.function.Supplier;
4852

53+
import static org.apache.ratis.thirdparty.io.netty.handler.ssl.SslProvider.OPENSSL;
54+
4955
public interface GrpcUtil {
5056
Logger LOG = LoggerFactory.getLogger(GrpcUtil.class);
5157

@@ -299,4 +305,38 @@ static void setKeyManager(SslContextBuilder b, KeyManagerConf keyManagerConfig)
299305
b.keyManager(privateKey.get(), certificates.get());
300306
}
301307
}
308+
309+
static SslContext buildSslContextForServer(GrpcTlsConfig tlsConf) {
310+
if (tlsConf == null) {
311+
return null;
312+
}
313+
SslContextBuilder b = initSslContextBuilderForServer(tlsConf.getKeyManager());
314+
if (tlsConf.getMtlsEnabled()) {
315+
b.clientAuth(ClientAuth.REQUIRE);
316+
setTrustManager(b, tlsConf.getTrustManager());
317+
}
318+
b = GrpcSslContexts.configure(b, OPENSSL);
319+
try {
320+
return b.build();
321+
} catch (Exception e) {
322+
throw new IllegalArgumentException("Failed to buildSslContextForServer from tlsConfig " + tlsConf, e);
323+
}
324+
}
325+
326+
static SslContext buildSslContextForClient(GrpcTlsConfig tlsConf) {
327+
if (tlsConf == null) {
328+
return null;
329+
}
330+
331+
final SslContextBuilder b = GrpcSslContexts.forClient();
332+
setTrustManager(b, tlsConf.getTrustManager());
333+
if (tlsConf.getMtlsEnabled()) {
334+
setKeyManager(b, tlsConf.getKeyManager());
335+
}
336+
try {
337+
return b.build();
338+
} catch (SSLException e) {
339+
throw new IllegalArgumentException("Failed to buildSslContextForClient from tlsConfig " + tlsConf, e);
340+
}
341+
}
302342
}

ratis-grpc/src/main/java/org/apache/ratis/grpc/client/GrpcClientProtocolClient.java

Lines changed: 7 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@
2121
import org.apache.ratis.client.impl.ClientProtoUtils;
2222
import org.apache.ratis.conf.RaftProperties;
2323
import org.apache.ratis.grpc.GrpcConfigKeys;
24-
import org.apache.ratis.grpc.GrpcTlsConfig;
2524
import org.apache.ratis.grpc.GrpcUtil;
2625
import org.apache.ratis.grpc.metrics.intercept.client.MetricClientInterceptor;
2726
import org.apache.ratis.proto.RaftProtos.GroupInfoReplyProto;
@@ -49,11 +48,10 @@
4948
import org.apache.ratis.protocol.exceptions.TimeoutIOException;
5049
import org.apache.ratis.thirdparty.io.grpc.ManagedChannel;
5150
import org.apache.ratis.thirdparty.io.grpc.StatusRuntimeException;
52-
import org.apache.ratis.thirdparty.io.grpc.netty.GrpcSslContexts;
5351
import org.apache.ratis.thirdparty.io.grpc.netty.NegotiationType;
5452
import org.apache.ratis.thirdparty.io.grpc.netty.NettyChannelBuilder;
5553
import org.apache.ratis.thirdparty.io.grpc.stub.StreamObserver;
56-
import org.apache.ratis.thirdparty.io.netty.handler.ssl.SslContextBuilder;
54+
import org.apache.ratis.thirdparty.io.netty.handler.ssl.SslContext;
5755
import org.apache.ratis.util.CollectionUtils;
5856
import org.apache.ratis.util.JavaUtils;
5957
import org.apache.ratis.util.SizeInBytes;
@@ -97,7 +95,7 @@ public class GrpcClientProtocolClient implements Closeable {
9795
private final MetricClientInterceptor metricClientInterceptor;
9896

9997
GrpcClientProtocolClient(ClientId id, RaftPeer target, RaftProperties properties,
100-
GrpcTlsConfig adminTlsConfig, GrpcTlsConfig clientTlsConfig) {
98+
SslContext adminSslContext, SslContext clientSslContext) {
10199
this.name = JavaUtils.memoize(() -> id + "->" + target.getId());
102100
this.target = target;
103101
final SizeInBytes flowControlWindow = GrpcConfigKeys.flowControlWindow(properties, LOG::debug);
@@ -110,11 +108,9 @@ public class GrpcClientProtocolClient implements Closeable {
110108
.filter(x -> !x.isEmpty()).orElse(target.getAddress());
111109
final boolean separateAdminChannel = !Objects.equals(clientAddress, adminAddress);
112110

113-
clientChannel = buildChannel(clientAddress, clientTlsConfig,
114-
flowControlWindow, maxMessageSize);
111+
clientChannel = buildChannel(clientAddress, clientSslContext, flowControlWindow, maxMessageSize);
115112
adminChannel = separateAdminChannel
116-
? buildChannel(adminAddress, adminTlsConfig,
117-
flowControlWindow, maxMessageSize)
113+
? buildChannel(adminAddress, adminSslContext, flowControlWindow, maxMessageSize)
118114
: clientChannel;
119115

120116
asyncStub = RaftClientProtocolServiceGrpc.newStub(clientChannel);
@@ -124,26 +120,16 @@ public class GrpcClientProtocolClient implements Closeable {
124120
RaftClientConfigKeys.Rpc.watchRequestTimeout(properties);
125121
}
126122

127-
private ManagedChannel buildChannel(String address, GrpcTlsConfig tlsConf,
123+
private ManagedChannel buildChannel(String address, SslContext sslContext,
128124
SizeInBytes flowControlWindow, SizeInBytes maxMessageSize) {
129125
NettyChannelBuilder channelBuilder =
130126
NettyChannelBuilder.forTarget(address);
131127
// ignore any http proxy for grpc
132128
channelBuilder.proxyDetector(uri -> null);
133129

134-
if (tlsConf != null) {
130+
if (sslContext != null) {
135131
LOG.debug("Setting TLS for {}", address);
136-
SslContextBuilder sslContextBuilder = GrpcSslContexts.forClient();
137-
GrpcUtil.setTrustManager(sslContextBuilder, tlsConf.getTrustManager());
138-
if (tlsConf.getMtlsEnabled()) {
139-
GrpcUtil.setKeyManager(sslContextBuilder, tlsConf.getKeyManager());
140-
}
141-
try {
142-
channelBuilder.useTransportSecurity().sslContext(
143-
sslContextBuilder.build());
144-
} catch (Exception ex) {
145-
throw new RuntimeException(ex);
146-
}
132+
channelBuilder.useTransportSecurity().sslContext(sslContext);
147133
} else {
148134
channelBuilder.negotiationType(NegotiationType.PLAINTEXT);
149135
}

ratis-grpc/src/main/java/org/apache/ratis/grpc/client/GrpcClientProtocolProxy.java

Lines changed: 0 additions & 108 deletions
This file was deleted.

0 commit comments

Comments
 (0)