[Sandbox] Add local index authorization check to analytics engine before planning phase#21750
Conversation
PR Code Analyzer ❗AI-powered 'Code-Diff-Analyzer' found issues on commit ae21cbe.
The table above displays the top 10 most important findings. Pull Requests Author(s): Please update your Pull Request according to the report above. Repository Maintainer(s): You can Thanks. |
Bukhtawar
left a comment
There was a problem hiding this comment.
I was wondering if we add a transport interceptor that can also validate if the request was indeed authorised.
public class AnalyticsAuthInterceptor implements TransportInterceptor {
@Override
public <T extends TransportRequest> TransportRequestHandler<T> interceptHandler(
String action, ..., TransportRequestHandler<T> actualHandler, ...) {
if (action.equals(FragmentExecutionAction.NAME)) {
return (request, channel, task) -> {
String token = threadContext.getHeader("auth_token");
if (token == null || !verify(token)) {
throw new SecurityException("Analytics auth not performed");
}
actualHandler.messageReceived(request, channel, task);
};
}
return actualHandler;
}
}
Thanks for taking a look @Bukhtawar, I spent a small bit of time trying to implement this and it seems like we would need to work this authorization token down to the thread context from the I can look at implementing this but i'm wondering if we are guarding against anything additional here since the |
…execution The analytics engine's query execution path (PPL, SQL) bypasses the security plugin's index-level privilege evaluation. The FragmentExecutionRequest on the data node is executed with dispatchFragmentStreaming and never evaluated for index permissions by the security plugin SecurityFilter (wraps the ActionFilter). This change adds a probing SearchRequest which passes through ActionFilter before query execution begins in the analytics engine. Checking query authorization ahead of query planning and restricting analytics plugin from un-authorized indices. Signed-off-by: carrofin <carrofin@amazon.com>
984bfcf to
ae21cbe
Compare
|
@finnegancarroll another problem to think about with regards to security is how to extract indices from a request pertinent to indices. There currently are 2 ways:
|
Agreed on putting the call to |
|
Quickly came up with cwperks/security#97 which adds test that would be expected to fail until a fix like this lands. |
|
@finnegancarroll I'm also seeing some action names that I think we should rename: cwperks#362 ^ I haven't been tracking sandbox too closely so lmk what you think and if there are other actions similar. |
expani
left a comment
There was a problem hiding this comment.
Thanks for getting this started @finnegancarroll
| return indices.toArray(String[]::new); | ||
| } | ||
|
|
||
| private static void collectIndices(RelNode node, java.util.Set<String> indices) { |
There was a problem hiding this comment.
RelNodeUtils#findNode(RelNode node, Class<T> type)
We need to write a variation of this method that also takes a parameter of depth as a guard and returns empty if Scan is not found.
The depth parameter can be HardCoded to 10/15 as a constant.
| // through the action filter chain so the SecurityFilter evaluates index-level permissions. | ||
| // Using SearchRequest as the base ensures the legacy security evaluator's IndexResolverReplacer | ||
| // correctly resolves the target indices. | ||
| String[] indices = extractIndices(logicalFragment); |
There was a problem hiding this comment.
If we are extracting indices here, it means Index patterns will also be resolved here.
So, to avoid duplication the OpenSearchTableScanRule needs to be able to read the indices extracted here. Maybe via the PlannerContext or some other common place.
There was a problem hiding this comment.
I think PrivilegesEvaluator in security plugin holds onto a IndexNameExpressionResolver and should handle this for us. So we should only need to provide the literal index names here.
|
For my understanding, why are we implementing security check outside Security plugin? we are trying to move away from that model, by making security aware of the related actions. Adding a transport action should allow using the authz layer of security plugin. (I didn't read through the conversations, maybe this is already discuseed) |
+1 Initially I thought there was some design limitation here but reading through the flow for |
Copying offline discussion here. One issue testing security for this feature is we need all three of SQL plugin, Security plugin, OpenSearch core. Just the security plugin and opensearch core alone do not provide us a front end to test analytics engine with, and using the test-ppl-frontend is insufficient because it does not integrate with security plugin authentication handlers. |
c1d20e5 to
ae21cbe
Compare
|
Hi @DarshitChanpura @finnegancarroll @expani @Bukhtawar . Please let me know your thoughts. Adding integration tests to SQL plugin. |
Description
The analytics engine's query execution path (PPL, SQL) bypasses the security plugin's index-level privilege evaluation. The
FragmentExecutionRequeston the data node is executed withdispatchFragmentStreamingand never evaluated for index permissions by the security pluginSecurityFilter(wraps theActionFilter).SQL / PPL queries with analytics engine
In a typical SQL / PPL query authorization is handled at the node-to-node transport layer on the coordinator as the request is being dispatched to shards. The security plugin provides an ActionFilter which every TransportAction child holds a reference to, and executes on new requests.
The overall flow for a regular DSL search query is then:
The path for an analytics engine SQL / PPL query avoids the
RequestFilterChainentirely. TheShardTaskRunneris responsible for dispatching aFragmentExecutionRequeston the transport layer.The
FragmentExecutionRequestfetches a new connection from the transport service, and directly executes the request itself. Skipping theTransportActionframework which typically holds and applies theActionFilter.DSL queries with analytics engine
DSL permissions are actually evaluated correctly already. This comes from how DSL is routed into the analytics plugin. DSL queries construct a regular
SearchRequestwhich is handled by theTransportSearchActionand are executed on the transport layer with the local node client as usual.Handling of DSL queries is done by a new
SearchActionFilterwhich is also injected into theRequestFilterChainand redirects theseSearchRequests to theDslExecuteAction.INSTANCEhandler instead of executing them as normal search requests. Since thisSearchActionFilterexecutes AFTER the security plugin ActionFilter (which has highest priority), privileges are evaluated correctly.POST /{index}/_search)POST /_plugins/_ppl)POST /_plugins/_sql)Proposed fix
These changes somewhat mimic the functionality of DSL queries for SQL and PPL by adding a pre-planning authorization check which passes a no-op
AnalyticsAuthRequestthrough theActionFilterto determine if permissions are valid for the equivalent set ofFragmentExecutionRequests.No actual request is executed on the transport layer, the
AnalyticsAuthRequestis passed through the fullActionFilterchain to invoke security plugin privilege evaluation, and proceeds with the analytics engine planning + query only if this probingAnalyticsAuthRequestis authorized for the same indices.Testing
Testing this feature requires an analytics engine enabled OpenSearch node, with SQL plugin installed, and security plugin installed. Currently SQL plugin supports this environment with distribution level security enabled tests. This seems like the most ideal place to house ITs validating index level security over the analytics plugin.
Test implementation is pending. Currently changes are validated with local single node testing.
Related Issues
N/A
Check List
By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 license.
For more information on following Developer Certificate of Origin and signing off your commits, please check here.