Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -517,8 +517,14 @@ private boolean modifyQuery(String localClusterAlias) throws IOException {

for (QueryBuilder queryBuilder : queryBuilders) {
TermsQueryBuilder termsQueryBuilder = (TermsQueryBuilder) queryBuilder;
final var lookupIndex = termsQueryBuilder.termsLookup().index();
final var lookupId = termsQueryBuilder.termsLookup().id();

documentAllowlist.add(termsQueryBuilder.termsLookup().index(), termsQueryBuilder.termsLookup().id());
if (lookupId != null) {
documentAllowlist.add(lookupIndex, lookupId);
} else {
documentAllowlist.add(lookupIndex, DocumentAllowList.ANY_DOCUMENT_ID);
}
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -211,7 +211,7 @@ public boolean invoke(PrivilegesEvaluationContext context, final ActionListener<
&& resolvedIndices.local()
.namesOfIndices(context.clusterState())
.stream()
.anyMatch(index -> documentAllowList.isAllowed(index, "*"))) {
.anyMatch(index -> documentAllowList.isAllowed(index, DocumentAllowList.ANY_DOCUMENT_ID))) {
// The documentAllowList is needed here for Dashboards multi tenancy which can redirect index accesses to indices for which no
// normal index privileges are present
// If we would not use the documentAllowList here, the index would appear to be protected
Expand Down Expand Up @@ -481,7 +481,7 @@ public void handleSearchContext(SearchContext searchContext, ThreadPool threadPo
// - DLS rules which use "term lookup queries" and thus need to access indices for which no privileges are present
// - Dashboards multi tenancy which can redirect index accesses to indices for which no normal index privileges are present

if (!dlsRestriction.isUnrestricted() && documentAllowList.isAllowed(index, "*")) {
if (!dlsRestriction.isUnrestricted() && documentAllowList.isAllowed(index, DocumentAllowList.ANY_DOCUMENT_ID)) {
dlsRestriction = DlsRestriction.NONE;
log.debug("Lifting DLS for {} due to present document allowlist", index);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -163,7 +163,7 @@ protected DirectoryReader dlsFlsWrap(final DirectoryReader reader, boolean isAdm
// - DLS rules which use "term lookup queries" and thus need to access indices for which no privileges are present
// - Dashboards multi tenancy which can redirect index accesses to indices for which no normal index privileges are present

if (!dlsRestriction.isUnrestricted() && documentAllowList.isAllowed(index.getName(), "*")) {
if (!dlsRestriction.isUnrestricted() && documentAllowList.isAllowed(index.getName(), DocumentAllowList.ANY_DOCUMENT_ID)) {
dlsRestriction = DlsRestriction.NONE;
log.debug("Lifting DLS for {} due to present document allowlist", index.getName());
dlsQuery = null;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,9 @@
import org.apache.logging.log4j.Logger;

import org.opensearch.action.ActionRequest;
import org.opensearch.action.admin.indices.settings.get.GetSettingsRequest;
import org.opensearch.action.get.GetRequest;
import org.opensearch.action.search.SearchRequest;
import org.opensearch.common.util.concurrent.ThreadContext;
import org.opensearch.security.support.ConfigConstants;

Expand All @@ -32,6 +34,8 @@ public class DocumentAllowList {

private static final Logger log = LogManager.getLogger(DocumentAllowList.class);

public static final String ANY_DOCUMENT_ID = "*";

public static DocumentAllowList get(ThreadContext threadContext) {
String header = threadContext.getHeader(ConfigConstants.OPENDISTRO_SECURITY_DOC_ALLOWLIST_HEADER);

Expand All @@ -48,34 +52,51 @@ public static DocumentAllowList get(ThreadContext threadContext) {
}

public static boolean isAllowed(ActionRequest request, ThreadContext threadContext) {
String docAllowListHeader = threadContext.getHeader(ConfigConstants.OPENDISTRO_SECURITY_DOC_ALLOWLIST_HEADER);
final var documentAllowList = DocumentAllowList.get(threadContext);

if (docAllowListHeader == null) {
if (documentAllowList.isEmpty()) {
return false;
}

if (!(request instanceof GetRequest)) {
// GetRequest: id-based TLQ resolves via GET; match exact (index, id) entry.
// SearchRequest: query-based TLQ resolves via SEARCH; match wildcard entry.
// GetSettingsRequest: query-based TLQ retrieves the index setting (during the fetch phase).
// Other request types (including writes) are never allowlisted.
if (request instanceof GetRequest getRequest) {
if (documentAllowList.isAllowed(getRequest.index(), getRequest.id())) {
log.debug("Request {} is allowed by {}", request, documentAllowList);
return true;
}
return false;
} else if (request instanceof SearchRequest searchRequest) {
if (isIndicesAllowlisted(documentAllowList, searchRequest.indices())) {
log.debug("Request {} is allowed by {}", request, documentAllowList);
return true;
}
return false;
} else if (request instanceof GetSettingsRequest getSettingsRequest) {
Comment thread
reta marked this conversation as resolved.
if (isIndicesAllowlisted(documentAllowList, getSettingsRequest.indices())) {
log.debug("Request {} is allowed by {}", request, documentAllowList);
return true;
}
return false;
}

try {
DocumentAllowList documentAllowList = DocumentAllowList.parse(docAllowListHeader);
GetRequest getRequest = (GetRequest) request;

if (documentAllowList.isAllowed(getRequest.index(), getRequest.id())) {
if (log.isDebugEnabled()) {
log.debug("Request " + request + " is allowed by " + documentAllowList);
}
return false;
}

return true;
} else {
// allMatch semantics: at privilege-evaluation time, every index in the request must be
// covered. DlsFlsValveImpl uses anyMatch+size()==1 for a different purpose (per-shard bypass).
private static boolean isIndicesAllowlisted(DocumentAllowList documentAllowList, String[] indices) {
if (indices == null || indices.length == 0) {
return false;
}
for (String index : indices) {
if (index == null || !documentAllowList.isAllowed(index, ANY_DOCUMENT_ID)) {
return false;
}

} catch (Exception e) {
log.error("Error while handling document allow list: " + docAllowListHeader, e);
return false;
}
return true;
}

private static final DocumentAllowList EMPTY = new DocumentAllowList();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,6 @@
import org.opensearch.action.bulk.BulkRequest;
import org.opensearch.action.bulk.BulkShardRequest;
import org.opensearch.action.delete.DeleteAction;
import org.opensearch.action.get.GetRequest;
import org.opensearch.action.get.MultiGetAction;
import org.opensearch.action.index.IndexAction;
import org.opensearch.action.search.MultiSearchAction;
Expand Down Expand Up @@ -699,31 +698,7 @@ public Iterator<IndexMetadata> iterator() {
}

private boolean checkDocAllowListHeader(User user, String action, ActionRequest request) {
String docAllowListHeader = threadContext.getHeader(ConfigConstants.OPENDISTRO_SECURITY_DOC_ALLOWLIST_HEADER);

if (docAllowListHeader == null) {
return false;
}

if (!(request instanceof GetRequest)) {
return false;
}

try {
DocumentAllowList documentAllowList = DocumentAllowList.parse(docAllowListHeader);
GetRequest getRequest = (GetRequest) request;

if (documentAllowList.isAllowed(getRequest.index(), getRequest.id())) {
log.debug("Request {} is allowed by {}", request, documentAllowList);
return true;
} else {
return false;
}

} catch (Exception e) {
log.error("Error while handling document allow list: {}", docAllowListHeader, e);
return false;
}
return DocumentAllowList.isAllowed(request, threadContext);
}

private List<String> toString(List<AliasMetadata> aliases) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -258,12 +258,12 @@ public ReplaceResult replaceDashboardsIndex(

private void applyDocumentAllowList(String indexName) {
DocumentAllowList documentAllowList = new DocumentAllowList();
documentAllowList.add(indexName, "*");
documentAllowList.add(indexName, DocumentAllowList.ANY_DOCUMENT_ID);
IndexAbstraction indexAbstraction = clusterStateSupplier.get().getMetadata().getIndicesLookup().get(indexName);

if (indexAbstraction instanceof IndexAbstraction.Alias) {
for (IndexMetadata index : ((IndexAbstraction.Alias) indexAbstraction).getIndices()) {
documentAllowList.add(index.getIndex().getName(), "*");
documentAllowList.add(index.getIndex().getName(), DocumentAllowList.ANY_DOCUMENT_ID);
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -224,12 +224,12 @@ private boolean hasPermission(PrivilegesEvaluationContext context) {

private void applyDocumentAllowList(String indexName) {
DocumentAllowList documentAllowList = new DocumentAllowList();
documentAllowList.add(indexName, "*");
documentAllowList.add(indexName, DocumentAllowList.ANY_DOCUMENT_ID);
IndexAbstraction indexAbstraction = this.clusterStateSupplier.get().getMetadata().getIndicesLookup().get(indexName);

if (indexAbstraction instanceof IndexAbstraction.Alias) {
for (IndexMetadata index : indexAbstraction.getIndices()) {
documentAllowList.add(index.getIndex().getName(), "*");
documentAllowList.add(index.getIndex().getName(), DocumentAllowList.ANY_DOCUMENT_ID);
}
}

Expand Down
Loading
Loading