Skip to content

Commit dcb05d0

Browse files
committed
Add header verifier and decompressor support of secure NIO transport variant
Signed-off-by: Andriy Redko <[email protected]>
1 parent 7abf006 commit dcb05d0

File tree

4 files changed

+102
-4
lines changed

4 files changed

+102
-4
lines changed

modules/transport-netty4/src/main/java/org/opensearch/http/netty4/ssl/SecureNetty4HttpServerTransport.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -67,8 +67,8 @@
6767
* @see <a href="https://github.com/opensearch-project/security/blob/d526c9f6c2a438c14db8b413148204510b9fe2e2/src/main/java/org/opensearch/security/ssl/http/netty/SecuritySSLNettyHttpServerTransport.java">SecuritySSLNettyHttpServerTransport</a>
6868
*/
6969
public class SecureNetty4HttpServerTransport extends Netty4HttpServerTransport {
70-
public static final String REQUEST_HEADER_VERIFIER = "HeaderVerifier";
71-
public static final String REQUEST_DECOMPRESSOR = "RequestDecompressor";
70+
public static final String REQUEST_HEADER_VERIFIER = SecureHttpTransportSettingsProvider.REQUEST_HEADER_VERIFIER;
71+
public static final String REQUEST_DECOMPRESSOR = SecureHttpTransportSettingsProvider.REQUEST_DECOMPRESSOR;
7272

7373
private static final Logger logger = LogManager.getLogger(SecureNetty4HttpServerTransport.class);
7474
private final SecureHttpTransportSettingsProvider secureHttpTransportSettingsProvider;

plugins/transport-nio/src/main/java/org/opensearch/http/nio/HttpReadWriteHandler.java

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,16 @@ public HttpReadWriteHandler(
8282
TaskScheduler taskScheduler,
8383
LongSupplier nanoClock
8484
) {
85-
this(nioHttpChannel, transport, settings, taskScheduler, nanoClock, null /* no SSL/TLS */);
85+
this(
86+
nioHttpChannel,
87+
transport,
88+
settings,
89+
taskScheduler,
90+
nanoClock,
91+
null, /* no header verifier */
92+
new HttpContentDecompressor(),
93+
null /* no SSL/TLS */
94+
);
8695
}
8796

8897
HttpReadWriteHandler(
@@ -91,6 +100,8 @@ public HttpReadWriteHandler(
91100
HttpHandlingSettings settings,
92101
TaskScheduler taskScheduler,
93102
LongSupplier nanoClock,
103+
@Nullable ChannelHandler headerVerifier,
104+
ChannelHandler decompressor,
94105
@Nullable SSLEngine sslEngine
95106
) {
96107
this.nioHttpChannel = nioHttpChannel;
@@ -113,7 +124,10 @@ public HttpReadWriteHandler(
113124
);
114125
decoder.setCumulator(ByteToMessageDecoder.COMPOSITE_CUMULATOR);
115126
handlers.add(decoder);
116-
handlers.add(new HttpContentDecompressor());
127+
if (headerVerifier != null) {
128+
handlers.add(headerVerifier);
129+
}
130+
handlers.add(decompressor);
117131
handlers.add(new HttpResponseEncoder());
118132
handlers.add(new HttpObjectAggregator(settings.getMaxContentLength()));
119133
if (settings.isCompression()) {

plugins/transport-nio/src/main/java/org/opensearch/http/nio/NioHttpServerTransport.java

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@
4848
import org.opensearch.http.AbstractHttpServerTransport;
4949
import org.opensearch.http.HttpChannel;
5050
import org.opensearch.http.HttpServerChannel;
51+
import org.opensearch.http.HttpServerTransport;
5152
import org.opensearch.http.nio.ssl.SslUtils;
5253
import org.opensearch.nio.BytesChannelContext;
5354
import org.opensearch.nio.ChannelFactory;
@@ -61,6 +62,7 @@
6162
import org.opensearch.plugins.SecureHttpTransportSettingsProvider;
6263
import org.opensearch.telemetry.tracing.Tracer;
6364
import org.opensearch.threadpool.ThreadPool;
65+
import org.opensearch.transport.TransportAdapterProvider;
6466
import org.opensearch.transport.nio.NioGroupFactory;
6567
import org.opensearch.transport.nio.PageAllocator;
6668

@@ -71,7 +73,14 @@
7173
import java.net.InetSocketAddress;
7274
import java.nio.channels.ServerSocketChannel;
7375
import java.nio.channels.SocketChannel;
76+
import java.util.Collections;
77+
import java.util.List;
78+
import java.util.Optional;
7479
import java.util.function.Consumer;
80+
import java.util.stream.Collectors;
81+
82+
import io.netty.channel.ChannelInboundHandlerAdapter;
83+
import io.netty.handler.codec.http.HttpContentDecompressor;
7584

7685
import static org.opensearch.http.HttpTransportSettings.SETTING_HTTP_MAX_CHUNK_SIZE;
7786
import static org.opensearch.http.HttpTransportSettings.SETTING_HTTP_MAX_HEADER_SIZE;
@@ -89,6 +98,9 @@
8998
public class NioHttpServerTransport extends AbstractHttpServerTransport {
9099
private static final Logger logger = LogManager.getLogger(NioHttpServerTransport.class);
91100

101+
public static final String REQUEST_HEADER_VERIFIER = SecureHttpTransportSettingsProvider.REQUEST_HEADER_VERIFIER;
102+
public static final String REQUEST_DECOMPRESSOR = SecureHttpTransportSettingsProvider.REQUEST_DECOMPRESSOR;
103+
92104
protected final PageAllocator pageAllocator;
93105
private final NioGroupFactory nioGroupFactory;
94106

@@ -224,6 +236,8 @@ protected void acceptChannel(NioSocketChannel socketChannel) {
224236

225237
private class HttpChannelFactory extends ChannelFactory<NioHttpServerChannel, NioHttpChannel> {
226238
private final SecureHttpTransportSettingsProvider secureHttpTransportSettingsProvider;
239+
private final ChannelInboundHandlerAdapter headerVerifier;
240+
private final TransportAdapterProvider<HttpServerTransport> decompressorProvider;
227241

228242
private HttpChannelFactory(@Nullable SecureHttpTransportSettingsProvider secureHttpTransportSettingsProvider) {
229243
super(
@@ -237,6 +251,63 @@ private HttpChannelFactory(@Nullable SecureHttpTransportSettingsProvider secureH
237251
tcpReceiveBufferSize
238252
);
239253
this.secureHttpTransportSettingsProvider = secureHttpTransportSettingsProvider;
254+
255+
final List<ChannelInboundHandlerAdapter> headerVerifiers = getHeaderVerifiers(secureHttpTransportSettingsProvider);
256+
final Optional<TransportAdapterProvider<HttpServerTransport>> decompressorProviderOpt = getDecompressorProvider(
257+
secureHttpTransportSettingsProvider
258+
);
259+
260+
// There could be multiple request decompressor providers configured, using the first one
261+
decompressorProviderOpt.ifPresent(p -> logger.debug("Using request decompressor provider: {}", p));
262+
263+
if (headerVerifiers.size() > 1) {
264+
throw new IllegalArgumentException(
265+
"Cannot have more than one header verifier configured, supplied " + headerVerifiers.size()
266+
);
267+
}
268+
269+
this.headerVerifier = headerVerifiers.isEmpty() ? null : headerVerifiers.get(0);
270+
this.decompressorProvider = decompressorProviderOpt.orElseGet(() -> new TransportAdapterProvider<HttpServerTransport>() {
271+
@Override
272+
public String name() {
273+
return REQUEST_DECOMPRESSOR;
274+
}
275+
276+
@Override
277+
public <C> Optional<C> create(Settings settings, HttpServerTransport transport, Class<C> adapterClass) {
278+
return Optional.empty();
279+
}
280+
});
281+
282+
}
283+
284+
private List<ChannelInboundHandlerAdapter> getHeaderVerifiers(
285+
@Nullable SecureHttpTransportSettingsProvider secureHttpTransportSettingsProvider
286+
) {
287+
if (secureHttpTransportSettingsProvider == null) {
288+
return Collections.emptyList();
289+
}
290+
291+
return secureHttpTransportSettingsProvider.getHttpTransportAdapterProviders(settings)
292+
.stream()
293+
.filter(p -> REQUEST_HEADER_VERIFIER.equalsIgnoreCase(p.name()))
294+
.map(p -> p.create(settings, NioHttpServerTransport.this, ChannelInboundHandlerAdapter.class))
295+
.filter(Optional::isPresent)
296+
.map(Optional::get)
297+
.collect(Collectors.toList());
298+
}
299+
300+
private Optional<TransportAdapterProvider<HttpServerTransport>> getDecompressorProvider(
301+
@Nullable SecureHttpTransportSettingsProvider secureHttpTransportSettingsProvider
302+
) {
303+
if (secureHttpTransportSettingsProvider == null) {
304+
return Optional.empty();
305+
}
306+
307+
return secureHttpTransportSettingsProvider.getHttpTransportAdapterProviders(settings)
308+
.stream()
309+
.filter(p -> REQUEST_DECOMPRESSOR.equalsIgnoreCase(p.name()))
310+
.findFirst();
240311
}
241312

242313
@Override
@@ -254,6 +325,9 @@ public NioHttpChannel createChannel(NioSelector selector, SocketChannel channel,
254325
handlingSettings,
255326
selector.getTaskScheduler(),
256327
threadPool::relativeTimeInMillis,
328+
headerVerifier,
329+
decompressorProvider.create(settings, NioHttpServerTransport.this, ChannelInboundHandlerAdapter.class)
330+
.orElseGet(HttpContentDecompressor::new),
257331
engine
258332
);
259333
Consumer<Exception> exceptionHandler = (e) -> onException(httpChannel, e);

server/src/main/java/org/opensearch/plugins/SecureHttpTransportSettingsProvider.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,16 @@
2727
*/
2828
@ExperimentalApi
2929
public interface SecureHttpTransportSettingsProvider {
30+
/**
31+
* The well-known name of header verifier {@link TransportAdapterProvider} provider instance
32+
*/
33+
final String REQUEST_HEADER_VERIFIER = "HeaderVerifier";
34+
35+
/**
36+
* The well-known name of request decompressor {@link TransportAdapterProvider} provider instance
37+
*/
38+
final String REQUEST_DECOMPRESSOR = "RequestDecompressor";
39+
3040
/**
3141
* Collection of additional {@link TransportAdapterProvider}s that are specific to particular HTTP transport
3242
* @param settings settings

0 commit comments

Comments
 (0)