forked from opensearch-project/security
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[Backport 1.3] Add early rejection from RestHandler for unauthorized …
…requests (opensearch-project#3418) (opensearch-project#3495) Backport of 6b0b682 from opensearch-project#3418 Previously unauthorized requests were fully processed and rejected once they reached the RestHandler. This allocations more memory and resources for these requests that might not be useful if they are already detected as unauthorized. Using the headerVerifer and decompressor customization from [1], perform an early authorization check when only the headers are available, save an 'early response' for transmission and do not perform the decompression on the request to speed up closing out the connection. - Resolves opensearch-project/OpenSearch#10260 Signed-off-by: Peter Nied <petern@amazon.com> Signed-off-by: Craig Perkins <cwperx@amazon.com> Signed-off-by: Craig Perkins <craig5008@gmail.com> Co-authored-by: Craig Perkins <cwperx@amazon.com> Signed-off-by: Peter Nied <petern@amazon.com>
- Loading branch information
Showing
24 changed files
with
752 additions
and
243 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
49 changes: 49 additions & 0 deletions
49
src/main/java/org/opensearch/security/filter/NettyAttribute.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
package org.opensearch.security.filter; | ||
|
||
import java.util.Optional; | ||
|
||
import org.opensearch.http.netty4.Netty4HttpChannel; | ||
import org.opensearch.rest.RestRequest; | ||
|
||
import io.netty.channel.Channel; | ||
import io.netty.channel.ChannelHandlerContext; | ||
import io.netty.util.AttributeKey; | ||
|
||
public class NettyAttribute { | ||
|
||
/** | ||
* Gets an attribute value from the request context and clears it from that context | ||
*/ | ||
public static <T> Optional<T> popFrom(final RestRequest request, final AttributeKey<T> attribute) { | ||
if (request.getHttpChannel() instanceof Netty4HttpChannel) { | ||
Channel nettyChannel = ((Netty4HttpChannel) request.getHttpChannel()).getNettyChannel(); | ||
return Optional.ofNullable(nettyChannel.attr(attribute).getAndSet(null)); | ||
} | ||
return Optional.empty(); | ||
} | ||
|
||
/** | ||
* Gets an attribute value from the channel handler context and clears it from that context | ||
*/ | ||
public static <T> Optional<T> popFrom(final ChannelHandlerContext ctx, final AttributeKey<T> attribute) { | ||
return Optional.ofNullable(ctx.channel().attr(attribute).getAndSet(null)); | ||
} | ||
|
||
/** | ||
* Gets an attribute value from the channel handler context | ||
*/ | ||
public static <T> Optional<T> peekFrom(final ChannelHandlerContext ctx, final AttributeKey<T> attribute) { | ||
return Optional.ofNullable(ctx.channel().attr(attribute).get()); | ||
} | ||
|
||
/** | ||
* Clears an attribute value from the channel handler context | ||
*/ | ||
public static <T> void clearAttribute(final RestRequest request, final AttributeKey<T> attribute) { | ||
if (request.getHttpChannel() instanceof Netty4HttpChannel) { | ||
Channel nettyChannel = ((Netty4HttpChannel) request.getHttpChannel()).getNettyChannel(); | ||
nettyChannel.attr(attribute).set(null); | ||
} | ||
} | ||
|
||
} |
100 changes: 100 additions & 0 deletions
100
src/main/java/org/opensearch/security/filter/NettyRequest.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,100 @@ | ||
/* | ||
* SPDX-License-Identifier: Apache-2.0 | ||
* | ||
* The OpenSearch Contributors require contributions made to | ||
* this file be licensed under the Apache-2.0 license or a | ||
* compatible open source license. | ||
* | ||
* Modifications Copyright OpenSearch Contributors. See | ||
* GitHub history for details. | ||
*/ | ||
|
||
package org.opensearch.security.filter; | ||
|
||
import java.net.InetSocketAddress; | ||
import java.util.Collections; | ||
import java.util.HashMap; | ||
import java.util.List; | ||
import java.util.Map; | ||
import java.util.Optional; | ||
import java.util.TreeMap; | ||
|
||
import javax.net.ssl.SSLEngine; | ||
|
||
import io.netty.handler.ssl.SslHandler; | ||
import org.opensearch.http.netty4.Netty4HttpChannel; | ||
import org.opensearch.rest.RestRequest.Method; | ||
|
||
import io.netty.handler.codec.http.HttpRequest; | ||
import org.opensearch.rest.RestUtils; | ||
|
||
/** | ||
* Wraps the functionality of HttpRequest for use in the security plugin | ||
*/ | ||
public class NettyRequest implements SecurityRequest { | ||
|
||
protected final HttpRequest underlyingRequest; | ||
protected final Netty4HttpChannel underlyingChannel; | ||
|
||
NettyRequest(final HttpRequest request, final Netty4HttpChannel channel) { | ||
this.underlyingRequest = request; | ||
this.underlyingChannel = channel; | ||
} | ||
|
||
@Override | ||
public Map<String, List<String>> getHeaders() { | ||
final Map<String, List<String>> headers = new TreeMap<>(String.CASE_INSENSITIVE_ORDER); | ||
underlyingRequest.headers().forEach(h -> headers.put(h.getKey(), List.of(h.getValue()))); | ||
return headers; | ||
} | ||
|
||
@Override | ||
public SSLEngine getSSLEngine() { | ||
// We look for Ssl_handler called `ssl_http` in the outbound pipeline of Netty channel first, and if its not | ||
// present we look for it in inbound channel. If its present in neither we return null, else we return the sslHandler. | ||
SslHandler sslhandler = (SslHandler) underlyingChannel.getNettyChannel().pipeline().get("ssl_http"); | ||
return sslhandler != null ? sslhandler.engine() : null; | ||
} | ||
|
||
@Override | ||
public String path() { | ||
String rawPath = SecurityRestUtils.path(underlyingRequest.uri()); | ||
return RestUtils.decodeComponent(rawPath); | ||
} | ||
|
||
@Override | ||
public Method method() { | ||
return Method.valueOf(underlyingRequest.method().name()); | ||
} | ||
|
||
@Override | ||
public Optional<InetSocketAddress> getRemoteAddress() { | ||
return Optional.ofNullable(this.underlyingChannel.getRemoteAddress()); | ||
} | ||
|
||
@Override | ||
public String uri() { | ||
return underlyingRequest.uri(); | ||
} | ||
|
||
@Override | ||
public Map<String, String> params() { | ||
return params(underlyingRequest.uri()); | ||
} | ||
|
||
private static Map<String, String> params(String uri) { | ||
// Sourced from | ||
// https://github.com/opensearch-project/OpenSearch/blob/main/server/src/main/java/org/opensearch/http/AbstractHttpServerTransport.java#L419-L422 | ||
final Map<String, String> params = new HashMap<>(); | ||
final int index = uri.indexOf(63); | ||
if (index >= 0) { | ||
try { | ||
RestUtils.decodeQueryString(uri, index + 1, params); | ||
} catch (IllegalArgumentException var4) { | ||
return Collections.emptyMap(); | ||
} | ||
} | ||
|
||
return params; | ||
} | ||
} |
54 changes: 54 additions & 0 deletions
54
src/main/java/org/opensearch/security/filter/NettyRequestChannel.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
/* | ||
* SPDX-License-Identifier: Apache-2.0 | ||
* | ||
* The OpenSearch Contributors require contributions made to | ||
* this file be licensed under the Apache-2.0 license or a | ||
* compatible open source license. | ||
* | ||
* Modifications Copyright OpenSearch Contributors. See | ||
* GitHub history for details. | ||
*/ | ||
|
||
package org.opensearch.security.filter; | ||
|
||
import java.util.Optional; | ||
import java.util.concurrent.atomic.AtomicBoolean; | ||
import java.util.concurrent.atomic.AtomicReference; | ||
|
||
import io.netty.handler.codec.http.HttpRequest; | ||
import org.apache.logging.log4j.LogManager; | ||
import org.apache.logging.log4j.Logger; | ||
import org.opensearch.http.netty4.Netty4HttpChannel; | ||
|
||
public class NettyRequestChannel extends NettyRequest implements SecurityRequestChannel { | ||
private final Logger log = LogManager.getLogger(NettyRequestChannel.class); | ||
|
||
private AtomicBoolean hasCompleted = new AtomicBoolean(false); | ||
private final AtomicReference<SecurityResponse> responseRef = new AtomicReference<SecurityResponse>(null); | ||
|
||
NettyRequestChannel(final HttpRequest request, Netty4HttpChannel channel) { | ||
super(request, channel); | ||
} | ||
|
||
@Override | ||
public void queueForSending(SecurityResponse response) { | ||
if (underlyingChannel == null) { | ||
throw new UnsupportedOperationException("Channel was not defined"); | ||
} | ||
|
||
if (hasCompleted.get()) { | ||
throw new UnsupportedOperationException("This channel has already completed"); | ||
} | ||
|
||
if (getQueuedResponse().isPresent()) { | ||
throw new UnsupportedOperationException("Another response was already queued"); | ||
} | ||
|
||
responseRef.set(response); | ||
} | ||
|
||
@Override | ||
public Optional<SecurityResponse> getQueuedResponse() { | ||
return Optional.ofNullable(responseRef.get()); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.