diff --git a/src/main/java/org/opensearch/security/filter/SecurityFilter.java b/src/main/java/org/opensearch/security/filter/SecurityFilter.java index 642679a8fd..a887b3d9ac 100644 --- a/src/main/java/org/opensearch/security/filter/SecurityFilter.java +++ b/src/main/java/org/opensearch/security/filter/SecurityFilter.java @@ -61,6 +61,7 @@ import org.opensearch.action.search.SearchRequest; import org.opensearch.action.support.ActionFilter; import org.opensearch.action.support.ActionFilterChain; +import org.opensearch.action.support.ActionRequestMetadata; import org.opensearch.action.update.UpdateRequest; import org.opensearch.cluster.service.ClusterService; import org.opensearch.common.settings.Settings; @@ -158,12 +159,13 @@ public void app Task task, final String action, Request request, + ActionRequestMetadata actionRequestMetadata, ActionListener listener, ActionFilterChain chain ) { try (StoredContext ctx = threadContext.newStoredContext(true)) { org.apache.logging.log4j.ThreadContext.clearAll(); - apply0(task, action, request, listener, chain); + apply0(task, action, request, actionRequestMetadata, listener, chain); } } @@ -175,6 +177,7 @@ private void ap Task task, final String action, Request request, + ActionRequestMetadata actionRequestMetadata, ActionListener listener, ActionFilterChain chain ) { @@ -373,7 +376,7 @@ private void ap log.trace("Evaluate permissions for user: {}", user.getName()); } - PrivilegesEvaluationContext context = eval.createContext(user, action, request, task, injectedRoles); + PrivilegesEvaluationContext context = eval.createContext(user, action, request, actionRequestMetadata, task, injectedRoles); PrivilegesEvaluatorResponse pres = eval.evaluate(context); if (log.isDebugEnabled()) { diff --git a/src/main/java/org/opensearch/security/privileges/PrivilegesEvaluationContext.java b/src/main/java/org/opensearch/security/privileges/PrivilegesEvaluationContext.java index f7e5d6de7d..5d91d04d3a 100644 --- a/src/main/java/org/opensearch/security/privileges/PrivilegesEvaluationContext.java +++ b/src/main/java/org/opensearch/security/privileges/PrivilegesEvaluationContext.java @@ -12,14 +12,17 @@ import java.util.HashMap; import java.util.Map; +import java.util.Optional; import java.util.function.Supplier; import com.google.common.collect.ImmutableSet; import org.opensearch.action.ActionRequest; +import org.opensearch.action.support.ActionRequestMetadata; import org.opensearch.cluster.ClusterState; import org.opensearch.cluster.metadata.IndexAbstraction; import org.opensearch.cluster.metadata.IndexNameExpressionResolver; +import org.opensearch.cluster.metadata.ResolvedIndices; import org.opensearch.security.resolver.IndexResolverReplacer; import org.opensearch.security.support.WildcardMatcher; import org.opensearch.security.user.User; @@ -38,13 +41,14 @@ public class PrivilegesEvaluationContext { private final User user; private final String action; private final ActionRequest request; - private IndexResolverReplacer.Resolved resolvedRequest; + private ResolvedIndices resolvedIndices; private Map indicesLookup; private final Task task; private ImmutableSet mappedRoles; private final IndexResolverReplacer indexResolverReplacer; private final IndexNameExpressionResolver indexNameExpressionResolver; private final Supplier clusterStateSupplier; + private final ActionRequestMetadata actionRequestMetadata; /** * This caches the ready to use WildcardMatcher instances for the current request. Many index patterns have @@ -58,6 +62,7 @@ public PrivilegesEvaluationContext( ImmutableSet mappedRoles, String action, ActionRequest request, + ActionRequestMetadata actionRequestMetadata, Task task, IndexResolverReplacer indexResolverReplacer, IndexNameExpressionResolver indexNameExpressionResolver, @@ -71,6 +76,7 @@ public PrivilegesEvaluationContext( this.indexResolverReplacer = indexResolverReplacer; this.indexNameExpressionResolver = indexNameExpressionResolver; this.task = task; + this.actionRequestMetadata = actionRequestMetadata; } public User getUser() { @@ -110,12 +116,21 @@ public ActionRequest getRequest() { return request; } - public IndexResolverReplacer.Resolved getResolvedRequest() { - IndexResolverReplacer.Resolved result = this.resolvedRequest; + public ResolvedIndices getResolvedRequest() { + if (PrivilegesEvaluator.isClusterPerm(action)) { + return ResolvedIndices.all(); + } + + ResolvedIndices result = this.resolvedIndices; if (result == null) { - result = indexResolverReplacer.resolveRequest(request); - this.resolvedRequest = result; + Optional providedIndices = this.actionRequestMetadata.resolvedIndices(); + if (providedIndices.isPresent()) { + result = this.resolvedIndices = providedIndices.get(); + } else { + // The action does not implement the resolution mechanism; we have to do it by ourselves + // TODO + } } return result; @@ -166,8 +181,8 @@ public String toString() { + '\'' + ", request=" + request - + ", resolvedRequest=" - + resolvedRequest + + ", resolvedIndices=" + + resolvedIndices + ", mappedRoles=" + mappedRoles + '}'; diff --git a/src/main/java/org/opensearch/security/privileges/PrivilegesEvaluator.java b/src/main/java/org/opensearch/security/privileges/PrivilegesEvaluator.java index d0d8408f28..9b03d662f2 100644 --- a/src/main/java/org/opensearch/security/privileges/PrivilegesEvaluator.java +++ b/src/main/java/org/opensearch/security/privileges/PrivilegesEvaluator.java @@ -71,6 +71,7 @@ import org.opensearch.action.search.SearchAction; import org.opensearch.action.search.SearchRequest; import org.opensearch.action.search.SearchScrollAction; +import org.opensearch.action.support.ActionRequestMetadata; import org.opensearch.action.support.IndicesOptions; import org.opensearch.action.termvectors.MultiTermVectorsAction; import org.opensearch.action.update.UpdateAction; @@ -79,6 +80,7 @@ import org.opensearch.cluster.metadata.IndexMetadata; import org.opensearch.cluster.metadata.IndexNameExpressionResolver; import org.opensearch.cluster.metadata.Metadata; +import org.opensearch.cluster.metadata.ResolvedIndices; import org.opensearch.cluster.service.ClusterService; import org.opensearch.common.settings.Settings; import org.opensearch.common.util.concurrent.ThreadContext; @@ -296,13 +298,14 @@ private void setUserInfoInThreadContext(User user, Set mappedRoles) { } public PrivilegesEvaluationContext createContext(User user, String action) { - return createContext(user, action, null, null, null); + return createContext(user, action, null, ActionRequestMetadata.empty(), null, null); } public PrivilegesEvaluationContext createContext( User user, String action0, ActionRequest request, + ActionRequestMetadata actionRequestMetadata, Task task, Set injectedRoles ) { @@ -313,7 +316,7 @@ public PrivilegesEvaluationContext createContext( TransportAddress caller = threadContext.getTransient(ConfigConstants.OPENDISTRO_SECURITY_REMOTE_ADDRESS); ImmutableSet mappedRoles = ImmutableSet.copyOf((injectedRoles == null) ? mapRoles(user, caller) : injectedRoles); - return new PrivilegesEvaluationContext(user, mappedRoles, action0, request, task, irr, resolver, clusterStateSupplier); + return new PrivilegesEvaluationContext(user, mappedRoles, action0, request, actionRequestMetadata, task, irr, resolver, clusterStateSupplier); } public PrivilegesEvaluatorResponse evaluate(PrivilegesEvaluationContext context) { @@ -393,10 +396,10 @@ public PrivilegesEvaluatorResponse evaluate(PrivilegesEvaluationContext context) return presponse; } - final Resolved requestedResolved = context.getResolvedRequest(); + ResolvedIndices resolvedIndices = context.getResolvedRequest(); if (isDebugEnabled) { - log.debug("RequestedResolved : {}", requestedResolved); + log.debug("RequestedResolved : {}", resolvedIndices); } // check snapshot/restore requests @@ -405,13 +408,13 @@ public PrivilegesEvaluatorResponse evaluate(PrivilegesEvaluationContext context) } // Security index access - if (systemIndexAccessEvaluator.evaluate(request, task, action0, requestedResolved, presponse, context, actionPrivileges, user) + if (systemIndexAccessEvaluator.evaluate(request, task, action0, resolvedIndices, presponse, context, actionPrivileges, user) .isComplete()) { return presponse; } // Protected index access - if (protectedIndexAccessEvaluator.evaluate(request, task, action0, requestedResolved, presponse, mappedRoles).isComplete()) { + if (protectedIndexAccessEvaluator.evaluate(request, task, action0, resolvedIndices, presponse, mappedRoles).isComplete()) { return presponse; } @@ -440,7 +443,7 @@ public PrivilegesEvaluatorResponse evaluate(PrivilegesEvaluationContext context) log.info( "No cluster-level perm match for {} {} [Action [{}]] [RolesChecked {}]. No permissions for {}", user, - requestedResolved, + resolvedIndices, action0, mappedRoles, presponse.getMissingPrivileges() @@ -460,7 +463,7 @@ public PrivilegesEvaluatorResponse evaluate(PrivilegesEvaluationContext context) action0, user, dcm, - requestedResolved, + resolvedIndices, context, this.tenantPrivileges.get() ); @@ -495,7 +498,7 @@ public PrivilegesEvaluatorResponse evaluate(PrivilegesEvaluationContext context) } // term aggregations - if (termsAggregationEvaluator.evaluate(requestedResolved, request, context, actionPrivileges, presponse).isComplete()) { + if (termsAggregationEvaluator.evaluate(resolvedIndices, request, context, actionPrivileges, presponse).isComplete()) { return presponse; } @@ -510,7 +513,7 @@ public PrivilegesEvaluatorResponse evaluate(PrivilegesEvaluationContext context) } if (isDebugEnabled) { - log.debug("Requested resolved index types: {}", requestedResolved); + log.debug("Requested resolved index types: {}", resolvedIndices); log.debug("Security roles: {}", mappedRoles); } @@ -523,7 +526,7 @@ public PrivilegesEvaluatorResponse evaluate(PrivilegesEvaluationContext context) action0, user, dcm, - requestedResolved, + resolvedIndices, context, this.tenantPrivileges.get() ); @@ -546,7 +549,7 @@ public PrivilegesEvaluatorResponse evaluate(PrivilegesEvaluationContext context) boolean dnfofPossible = dnfofEnabled && DNFOF_MATCHER.test(action0); - presponse = actionPrivileges.hasIndexPrivilege(context, allIndexPermsRequired, requestedResolved); + presponse = actionPrivileges.hasIndexPrivilege(context, allIndexPermsRequired, resolvedIndices); if (presponse.isPartiallyOk()) { if (dnfofPossible) { @@ -571,7 +574,7 @@ public PrivilegesEvaluatorResponse evaluate(PrivilegesEvaluationContext context) } if (presponse.isAllowed()) { - if (checkFilteredAliases(requestedResolved, action0, isDebugEnabled)) { + if (checkFilteredAliases(resolvedIndices, action0, isDebugEnabled)) { presponse.allowed = false; return presponse; } @@ -584,7 +587,7 @@ public PrivilegesEvaluatorResponse evaluate(PrivilegesEvaluationContext context) "No {}-level perm match for {} {}: {} [Action [{}]] [RolesChecked {}]", "index", user, - requestedResolved, + resolvedIndices, presponse.getReason(), action0, mappedRoles