Fix query rewriting for document-level security to be stable.
Original commit: elastic/x-pack-elasticsearch@3ad7eb4ded
This commit is contained in:
parent
f270e585f4
commit
b4d5ef5904
|
@ -196,12 +196,19 @@ public final class ShieldIndexSearcherWrapper extends AbstractIndexShardComponen
|
||||||
setSimilarity(in.getSimilarity(true));
|
setSimilarity(in.getSimilarity(true));
|
||||||
setQueryCache(engineConfig.getQueryCache());
|
setQueryCache(engineConfig.getQueryCache());
|
||||||
setQueryCachingPolicy(engineConfig.getQueryCachingPolicy());
|
setQueryCachingPolicy(engineConfig.getQueryCachingPolicy());
|
||||||
this.roleQuery = roleQuery;
|
try {
|
||||||
|
this.roleQuery = super.rewrite(roleQuery);
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new IllegalStateException("Could not rewrite role query", e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Query rewrite(Query original) throws IOException {
|
public Query rewrite(Query query) throws IOException {
|
||||||
return super.rewrite(wrap(original));
|
query = super.rewrite(query);
|
||||||
|
query = wrap(query);
|
||||||
|
query = super.rewrite(query);
|
||||||
|
return query;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -209,21 +216,37 @@ public final class ShieldIndexSearcherWrapper extends AbstractIndexShardComponen
|
||||||
return "ShieldIndexSearcher(" + super.toString() + ")";
|
return "ShieldIndexSearcher(" + super.toString() + ")";
|
||||||
}
|
}
|
||||||
|
|
||||||
private Query wrap(Query original) throws IOException {
|
private boolean isFilteredBy(Query query, Query filter) {
|
||||||
// If already wrapped, don't wrap twice:
|
if (query instanceof ConstantScoreQuery) {
|
||||||
if (original instanceof BooleanQuery) {
|
return isFilteredBy(((ConstantScoreQuery) query).getQuery(), filter);
|
||||||
BooleanQuery bq = (BooleanQuery) original;
|
} else if (query instanceof BooleanQuery) {
|
||||||
if (bq.clauses().size() == 2) {
|
BooleanQuery bq = (BooleanQuery) query;
|
||||||
Query rewrittenRoleQuery = rewrite(roleQuery);
|
for (BooleanClause clause : bq) {
|
||||||
if (rewrittenRoleQuery.equals(bq.clauses().get(1).getQuery())) {
|
if (clause.isRequired() && isFilteredBy(clause.getQuery(), filter)) {
|
||||||
return original;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return false;
|
||||||
|
} else {
|
||||||
|
Query queryClone = query.clone();
|
||||||
|
queryClone.setBoost(1);
|
||||||
|
Query filterClone = filter.clone();
|
||||||
|
filterClone.setBoost(1f);
|
||||||
|
return queryClone.equals(filterClone);
|
||||||
}
|
}
|
||||||
BooleanQuery bq = new BooleanQuery();
|
}
|
||||||
bq.add(original, MUST);
|
|
||||||
bq.add(roleQuery, FILTER);
|
private Query wrap(Query original) throws IOException {
|
||||||
return bq;
|
if (isFilteredBy(original, roleQuery)) {
|
||||||
|
// this is necessary in order to make rewrite "stable",
|
||||||
|
// ie calling it several times on the same query keeps
|
||||||
|
// on returning the same query instance
|
||||||
|
return original;
|
||||||
|
}
|
||||||
|
return new BooleanQuery.Builder()
|
||||||
|
.add(original, MUST)
|
||||||
|
.add(roleQuery, FILTER)
|
||||||
|
.build();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue