Skip to content

Commit 6afbcd4

Browse files
authored
[Streaming Indexing] Ensure support of the new transport by security plugin (opensearch-project#13174)
Signed-off-by: Andriy Redko <andriy.redko@aiven.io>
1 parent a944967 commit 6afbcd4

File tree

14 files changed

+938
-51
lines changed

14 files changed

+938
-51
lines changed

CHANGELOG.md

+1
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
2121
- [Tiered Caching] Add dimension-based stats to ICache implementations. ([#12531](https://github.com/opensearch-project/OpenSearch/pull/12531))
2222
- Add changes for overriding remote store and replication settings during snapshot restore. ([#11868](https://github.com/opensearch-project/OpenSearch/pull/11868))
2323
- Add an individual setting of rate limiter for segment replication ([#12959](https://github.com/opensearch-project/OpenSearch/pull/12959))
24+
- [Streaming Indexing] Ensure support of the new transport by security plugin ([#13174](https://github.com/opensearch-project/OpenSearch/pull/13174))
2425

2526
### Dependencies
2627
- Bump `org.apache.commons:commons-configuration2` from 2.10.0 to 2.10.1 ([#12896](https://github.com/opensearch-project/OpenSearch/pull/12896))

modules/transport-netty4/src/test/java/org/opensearch/http/netty4/Netty4HttpClient.java

+2-2
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,6 @@
3838
import org.opensearch.core.common.unit.ByteSizeValue;
3939
import org.opensearch.tasks.Task;
4040
import org.opensearch.transport.NettyAllocator;
41-
import org.opensearch.transport.netty4.ssl.TrustAllManager;
4241

4342
import java.io.Closeable;
4443
import java.net.SocketAddress;
@@ -90,6 +89,7 @@
9089
import io.netty.handler.ssl.ClientAuth;
9190
import io.netty.handler.ssl.SslContextBuilder;
9291
import io.netty.handler.ssl.SslHandler;
92+
import io.netty.handler.ssl.util.InsecureTrustManagerFactory;
9393
import io.netty.util.AttributeKey;
9494

9595
import static io.netty.handler.codec.http.HttpHeaderNames.HOST;
@@ -270,7 +270,7 @@ protected void initChannel(SocketChannel ch) throws Exception {
270270
final SslHandler sslHandler = new SslHandler(
271271
SslContextBuilder.forClient()
272272
.clientAuth(ClientAuth.NONE)
273-
.trustManager(TrustAllManager.INSTANCE)
273+
.trustManager(InsecureTrustManagerFactory.INSTANCE)
274274
.build()
275275
.newEngine(ch.alloc())
276276
);

modules/transport-netty4/src/test/java/org/opensearch/http/netty4/ssl/SecureNetty4HttpServerTransportTests.java

+2-2
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,6 @@
4141
import org.opensearch.threadpool.ThreadPool;
4242
import org.opensearch.transport.NettyAllocator;
4343
import org.opensearch.transport.SharedGroupFactory;
44-
import org.opensearch.transport.netty4.ssl.TrustAllManager;
4544
import org.junit.After;
4645
import org.junit.Before;
4746

@@ -84,6 +83,7 @@
8483
import io.netty.handler.codec.http.HttpUtil;
8584
import io.netty.handler.codec.http.HttpVersion;
8685
import io.netty.handler.ssl.SslContextBuilder;
86+
import io.netty.handler.ssl.util.InsecureTrustManagerFactory;
8787

8888
import static org.opensearch.core.rest.RestStatus.BAD_REQUEST;
8989
import static org.opensearch.core.rest.RestStatus.OK;
@@ -131,7 +131,7 @@ public Optional<SSLEngine> buildSecureHttpServerEngine(Settings settings, HttpSe
131131
keyManagerFactory.init(keyStore, "password".toCharArray());
132132

133133
SSLEngine engine = SslContextBuilder.forServer(keyManagerFactory)
134-
.trustManager(TrustAllManager.INSTANCE)
134+
.trustManager(InsecureTrustManagerFactory.INSTANCE)
135135
.build()
136136
.newEngine(NettyAllocator.getAllocator());
137137
return Optional.of(engine);

modules/transport-netty4/src/test/java/org/opensearch/transport/netty4/ssl/SimpleSecureNetty4TransportTests.java

+3-2
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@
5555

5656
import io.netty.handler.ssl.ClientAuth;
5757
import io.netty.handler.ssl.SslContextBuilder;
58+
import io.netty.handler.ssl.util.InsecureTrustManagerFactory;
5859

5960
import static java.util.Collections.emptyMap;
6061
import static java.util.Collections.emptySet;
@@ -87,7 +88,7 @@ public Optional<SSLEngine> buildSecureServerTransportEngine(Settings settings, T
8788

8889
SSLEngine engine = SslContextBuilder.forServer(keyManagerFactory)
8990
.clientAuth(ClientAuth.NONE)
90-
.trustManager(TrustAllManager.INSTANCE)
91+
.trustManager(InsecureTrustManagerFactory.INSTANCE)
9192
.build()
9293
.newEngine(NettyAllocator.getAllocator());
9394
return Optional.of(engine);
@@ -103,7 +104,7 @@ public Optional<SSLEngine> buildSecureClientTransportEngine(Settings settings, S
103104
return Optional.of(
104105
SslContextBuilder.forClient()
105106
.clientAuth(ClientAuth.NONE)
106-
.trustManager(TrustAllManager.INSTANCE)
107+
.trustManager(InsecureTrustManagerFactory.INSTANCE)
107108
.build()
108109
.newEngine(NettyAllocator.getAllocator())
109110
);

modules/transport-netty4/src/test/java/org/opensearch/transport/netty4/ssl/TrustAllManager.java

-28
This file was deleted.

plugins/transport-reactor-netty4/src/main/java/org/opensearch/http/reactor/netty4/ReactorNetty4HttpServerTransport.java

+121-4
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88

99
package org.opensearch.http.reactor.netty4;
1010

11+
import org.opensearch.common.Nullable;
1112
import org.opensearch.common.network.NetworkService;
1213
import org.opensearch.common.settings.ClusterSettings;
1314
import org.opensearch.common.settings.Setting;
@@ -23,21 +24,33 @@
2324
import org.opensearch.http.HttpChannel;
2425
import org.opensearch.http.HttpReadTimeoutException;
2526
import org.opensearch.http.HttpServerChannel;
27+
import org.opensearch.http.reactor.netty4.ssl.SslUtils;
28+
import org.opensearch.plugins.SecureHttpTransportSettingsProvider;
2629
import org.opensearch.telemetry.tracing.Tracer;
2730
import org.opensearch.threadpool.ThreadPool;
2831
import org.opensearch.transport.reactor.SharedGroupFactory;
2932
import org.opensearch.transport.reactor.netty4.Netty4Utils;
3033

34+
import javax.net.ssl.SSLEngine;
35+
import javax.net.ssl.SSLException;
36+
import javax.net.ssl.SSLSessionContext;
37+
3138
import java.net.InetSocketAddress;
3239
import java.net.SocketOption;
3340
import java.time.Duration;
41+
import java.util.Arrays;
42+
import java.util.List;
3443

44+
import io.netty.buffer.ByteBufAllocator;
3545
import io.netty.channel.ChannelOption;
3646
import io.netty.channel.socket.nio.NioChannelOption;
3747
import io.netty.handler.codec.http.DefaultLastHttpContent;
3848
import io.netty.handler.codec.http.FullHttpResponse;
3949
import io.netty.handler.codec.http.HttpContent;
50+
import io.netty.handler.ssl.ApplicationProtocolNegotiator;
51+
import io.netty.handler.ssl.SslContext;
4052
import io.netty.handler.timeout.ReadTimeoutException;
53+
import io.netty.util.ReferenceCountUtil;
4154
import org.reactivestreams.Publisher;
4255
import reactor.core.publisher.Mono;
4356
import reactor.core.scheduler.Scheduler;
@@ -116,6 +129,7 @@ public class ReactorNetty4HttpServerTransport extends AbstractHttpServerTranspor
116129
private final ByteSizeValue maxInitialLineLength;
117130
private final ByteSizeValue maxHeaderSize;
118131
private final ByteSizeValue maxChunkSize;
132+
private final SecureHttpTransportSettingsProvider secureHttpTransportSettingsProvider;
119133
private volatile SharedGroupFactory.SharedGroup sharedGroup;
120134
private volatile DisposableServer disposableServer;
121135
private volatile Scheduler scheduler;
@@ -142,6 +156,45 @@ public ReactorNetty4HttpServerTransport(
142156
ClusterSettings clusterSettings,
143157
SharedGroupFactory sharedGroupFactory,
144158
Tracer tracer
159+
) {
160+
this(
161+
settings,
162+
networkService,
163+
bigArrays,
164+
threadPool,
165+
xContentRegistry,
166+
dispatcher,
167+
clusterSettings,
168+
sharedGroupFactory,
169+
null,
170+
tracer
171+
);
172+
}
173+
174+
/**
175+
* Creates new HTTP transport implementations based on Reactor Netty (see please {@link HttpServer}).
176+
* @param settings settings
177+
* @param networkService network service
178+
* @param bigArrays big array allocator
179+
* @param threadPool thread pool instance
180+
* @param xContentRegistry XContent registry instance
181+
* @param dispatcher dispatcher instance
182+
* @param clusterSettings cluster settings
183+
* @param sharedGroupFactory shared group factory
184+
* @param secureHttpTransportSettingsProvider secure HTTP transport settings provider
185+
* @param tracer tracer instance
186+
*/
187+
public ReactorNetty4HttpServerTransport(
188+
Settings settings,
189+
NetworkService networkService,
190+
BigArrays bigArrays,
191+
ThreadPool threadPool,
192+
NamedXContentRegistry xContentRegistry,
193+
Dispatcher dispatcher,
194+
ClusterSettings clusterSettings,
195+
SharedGroupFactory sharedGroupFactory,
196+
@Nullable SecureHttpTransportSettingsProvider secureHttpTransportSettingsProvider,
197+
Tracer tracer
145198
) {
146199
super(settings, networkService, bigArrays, threadPool, xContentRegistry, dispatcher, clusterSettings, tracer);
147200
Netty4Utils.setAvailableProcessors(OpenSearchExecutors.NODE_PROCESSORS_SETTING.get(settings));
@@ -152,6 +205,7 @@ public ReactorNetty4HttpServerTransport(
152205
this.maxChunkSize = SETTING_HTTP_MAX_CHUNK_SIZE.get(settings);
153206
this.maxHeaderSize = SETTING_HTTP_MAX_HEADER_SIZE.get(settings);
154207
this.maxInitialLineLength = SETTING_HTTP_MAX_INITIAL_LINE_LENGTH.get(settings);
208+
this.secureHttpTransportSettingsProvider = secureHttpTransportSettingsProvider;
155209
}
156210

157211
/**
@@ -160,7 +214,7 @@ public ReactorNetty4HttpServerTransport(
160214
*/
161215
@Override
162216
protected HttpServerChannel bind(InetSocketAddress socketAddress) throws Exception {
163-
final HttpServer server = configureChannelOptions(
217+
final HttpServer server = configure(
164218
HttpServer.create()
165219
.httpFormDecoder(builder -> builder.scheduler(scheduler))
166220
.idleTimeout(Duration.ofMillis(connectTimeoutMillis))
@@ -173,16 +227,15 @@ protected HttpServerChannel bind(InetSocketAddress socketAddress) throws Excepti
173227
.maxHeaderSize(maxHeaderSize.bytesAsInt())
174228
.maxInitialLineLength(maxInitialLineLength.bytesAsInt())
175229
)
176-
.protocol(HttpProtocol.HTTP11, HttpProtocol.H2C)
177230
.handle((req, res) -> incomingRequest(req, res))
178231
);
179232

180233
disposableServer = server.bindNow();
181234
return new ReactorNetty4HttpServerChannel(disposableServer.channel());
182235
}
183236

184-
private HttpServer configureChannelOptions(final HttpServer server1) {
185-
HttpServer configured = server1.childOption(ChannelOption.TCP_NODELAY, SETTING_HTTP_TCP_NO_DELAY.get(settings))
237+
private HttpServer configure(final HttpServer server) throws Exception {
238+
HttpServer configured = server.childOption(ChannelOption.TCP_NODELAY, SETTING_HTTP_TCP_NO_DELAY.get(settings))
186239
.childOption(ChannelOption.SO_KEEPALIVE, SETTING_HTTP_TCP_KEEP_ALIVE.get(settings));
187240

188241
if (SETTING_HTTP_TCP_KEEP_ALIVE.get(settings)) {
@@ -229,6 +282,65 @@ private HttpServer configureChannelOptions(final HttpServer server1) {
229282
configured = configured.option(ChannelOption.SO_REUSEADDR, reuseAddress);
230283
configured = configured.childOption(ChannelOption.SO_REUSEADDR, reuseAddress);
231284

285+
// Configure SSL context if available
286+
if (secureHttpTransportSettingsProvider != null) {
287+
final SSLEngine engine = secureHttpTransportSettingsProvider.buildSecureHttpServerEngine(settings, this)
288+
.orElseGet(SslUtils::createDefaultServerSSLEngine);
289+
290+
try {
291+
final List<String> cipherSuites = Arrays.asList(engine.getEnabledCipherSuites());
292+
final List<String> applicationProtocols = Arrays.asList(engine.getSSLParameters().getApplicationProtocols());
293+
294+
configured = configured.secure(spec -> spec.sslContext(new SslContext() {
295+
@Override
296+
public SSLSessionContext sessionContext() {
297+
throw new UnsupportedOperationException(); /* server only, should never be called */
298+
}
299+
300+
@Override
301+
public SSLEngine newEngine(ByteBufAllocator alloc, String peerHost, int peerPort) {
302+
throw new UnsupportedOperationException(); /* server only, should never be called */
303+
}
304+
305+
@Override
306+
public SSLEngine newEngine(ByteBufAllocator alloc) {
307+
try {
308+
return secureHttpTransportSettingsProvider.buildSecureHttpServerEngine(
309+
settings,
310+
ReactorNetty4HttpServerTransport.this
311+
).orElseGet(SslUtils::createDefaultServerSSLEngine);
312+
} catch (final SSLException ex) {
313+
throw new UnsupportedOperationException("Unable to create SSLEngine", ex);
314+
}
315+
}
316+
317+
@Override
318+
public boolean isClient() {
319+
return false; /* server only */
320+
}
321+
322+
@Override
323+
public List<String> cipherSuites() {
324+
return cipherSuites;
325+
}
326+
327+
@Override
328+
public ApplicationProtocolNegotiator applicationProtocolNegotiator() {
329+
return new ApplicationProtocolNegotiator() {
330+
@Override
331+
public List<String> protocols() {
332+
return applicationProtocols;
333+
}
334+
};
335+
}
336+
}).build()).protocol(HttpProtocol.HTTP11, HttpProtocol.H2);
337+
} finally {
338+
ReferenceCountUtil.release(engine);
339+
}
340+
} else {
341+
configured = configured.protocol(HttpProtocol.HTTP11, HttpProtocol.H2C);
342+
}
343+
232344
return configured;
233345
}
234346

@@ -302,6 +414,11 @@ protected void doStart() {
302414
}
303415
}
304416

417+
/**
418+
* Exception handler
419+
* @param channel HTTP channel
420+
* @param cause exception occurred
421+
*/
305422
@Override
306423
public void onException(HttpChannel channel, Exception cause) {
307424
if (cause instanceof ReadTimeoutException) {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
/*
2+
* SPDX-License-Identifier: Apache-2.0
3+
*
4+
* The OpenSearch Contributors require contributions made to
5+
* this file be licensed under the Apache-2.0 license or a
6+
* compatible open source license.
7+
*
8+
* Modifications Copyright OpenSearch Contributors. See
9+
* GitHub history for details.
10+
*/
11+
package org.opensearch.http.reactor.netty4.ssl;
12+
13+
import org.opensearch.OpenSearchSecurityException;
14+
15+
import javax.net.ssl.SSLContext;
16+
import javax.net.ssl.SSLEngine;
17+
18+
import java.security.NoSuchAlgorithmException;
19+
20+
/**
21+
* Helper class for creating default SSL engines
22+
*/
23+
public class SslUtils {
24+
private static final String[] DEFAULT_SSL_PROTOCOLS = { "TLSv1.3", "TLSv1.2", "TLSv1.1" };
25+
26+
private SslUtils() {}
27+
28+
/**
29+
* Creates default server {@link SSLEngine} instance
30+
* @return default server {@link SSLEngine} instance
31+
*/
32+
public static SSLEngine createDefaultServerSSLEngine() {
33+
try {
34+
final SSLEngine engine = SSLContext.getDefault().createSSLEngine();
35+
engine.setEnabledProtocols(DEFAULT_SSL_PROTOCOLS);
36+
engine.setUseClientMode(false);
37+
return engine;
38+
} catch (final NoSuchAlgorithmException ex) {
39+
throw new OpenSearchSecurityException("Unable to initialize default server SSL engine", ex);
40+
}
41+
}
42+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
/*
2+
* SPDX-License-Identifier: Apache-2.0
3+
*
4+
* The OpenSearch Contributors require contributions made to
5+
* this file be licensed under the Apache-2.0 license or a
6+
* compatible open source license.
7+
*/
8+
9+
/**
10+
* SSL supporting utility classes
11+
*/
12+
package org.opensearch.http.reactor.netty4.ssl;

0 commit comments

Comments
 (0)