Skip to content

Commit d097bf0

Browse files
authored
[8.19] Check TooComplex exception for HasPrivileges body (#128870) (#128892)
* Check TooComplex exception for HasPrivileges body (#128870) The index pattern provided in the body of `_has_privileges` can trigger a `TooComplexToDeterminizeException` which is then bubbled up (badly). This change catches that exception and provides a better message * Change test to reflect high work load limit in 8.x
1 parent efbb482 commit d097bf0

File tree

3 files changed

+53
-5
lines changed

3 files changed

+53
-5
lines changed

docs/changelog/128870.yaml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
pr: 128870
2+
summary: Check `TooComplex` exception for `HasPrivileges` body
3+
area: Authorization
4+
type: enhancement
5+
issues: []

x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/security/authz/permission/IndicesPermission.java

Lines changed: 24 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,11 @@
66
*/
77
package org.elasticsearch.xpack.core.security.authz.permission;
88

9+
import org.apache.logging.log4j.LogManager;
10+
import org.apache.logging.log4j.Logger;
911
import org.apache.lucene.util.automaton.Automaton;
1012
import org.apache.lucene.util.automaton.Operations;
13+
import org.apache.lucene.util.automaton.TooComplexToDeterminizeException;
1114
import org.elasticsearch.action.admin.indices.mapping.put.TransportAutoPutMappingAction;
1215
import org.elasticsearch.action.admin.indices.mapping.put.TransportPutMappingAction;
1316
import org.elasticsearch.action.support.IndexComponentSelector;
@@ -43,8 +46,10 @@
4346
import java.util.Set;
4447
import java.util.concurrent.ConcurrentHashMap;
4548
import java.util.function.BiPredicate;
49+
import java.util.function.Function;
4650
import java.util.function.Predicate;
4751
import java.util.function.Supplier;
52+
import java.util.stream.Collectors;
4853

4954
import static java.util.Collections.unmodifiableMap;
5055

@@ -54,6 +59,8 @@
5459
*/
5560
public final class IndicesPermission {
5661

62+
private final Logger logger = LogManager.getLogger(getClass());
63+
5764
private static final DeprecationLogger deprecationLogger = DeprecationLogger.getLogger(IndicesPermission.class);
5865

5966
public static final IndicesPermission NONE = new IndicesPermission(new RestrictedIndices(Automatons.EMPTY), Group.EMPTY_ARRAY);
@@ -330,11 +337,23 @@ public boolean checkResourcePrivileges(
330337
combineIndexGroups && checkForIndexPatterns.stream().anyMatch(Automatons::isLuceneRegex),
331338
IndexComponentSelector.FAILURES
332339
);
333-
for (String forIndexPattern : checkForIndexPatterns) {
334-
Automaton checkIndexAutomaton = Automatons.patterns(forIndexPattern);
335-
if (false == allowRestrictedIndices && false == isConcreteRestrictedIndex(forIndexPattern)) {
336-
checkIndexAutomaton = Automatons.minusAndMinimize(checkIndexAutomaton, restrictedIndices.getAutomaton());
337-
}
340+
Map<String, Automaton> checkIndexPatterns = checkForIndexPatterns.stream()
341+
.collect(Collectors.toMap(Function.identity(), pattern -> {
342+
try {
343+
Automaton automaton = Automatons.patterns(pattern);
344+
if (false == allowRestrictedIndices && false == isConcreteRestrictedIndex(pattern)) {
345+
automaton = Automatons.minusAndMinimize(automaton, restrictedIndices.getAutomaton());
346+
}
347+
return automaton;
348+
} catch (TooComplexToDeterminizeException e) {
349+
final String text = pattern.length() > 260 ? Strings.cleanTruncate(pattern, 256) + "..." : pattern;
350+
logger.info("refusing to check privileges against complex index pattern [{}]", text);
351+
throw new IllegalArgumentException("the provided index pattern [" + text + "] is too complex to be evaluated", e);
352+
}
353+
}));
354+
for (var entry : checkIndexPatterns.entrySet()) {
355+
final String forIndexPattern = entry.getKey();
356+
final Automaton checkIndexAutomaton = entry.getValue();
338357
if (false == Operations.isEmpty(checkIndexAutomaton)) {
339358
Automaton allowedPrivilegesAutomatonForDataSelector = getIndexPrivilegesAutomaton(
340359
indexGroupAutomatonsForDataSelector,

x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authz/accesscontrol/IndicesPermissionTests.java

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
*/
77
package org.elasticsearch.xpack.security.authz.accesscontrol;
88

9+
import org.apache.lucene.util.automaton.TooComplexToDeterminizeException;
910
import org.elasticsearch.ElasticsearchSecurityException;
1011
import org.elasticsearch.TransportVersion;
1112
import org.elasticsearch.action.admin.indices.mapping.put.TransportAutoPutMappingAction;
@@ -54,6 +55,7 @@
5455
import static org.hamcrest.Matchers.containsString;
5556
import static org.hamcrest.Matchers.equalTo;
5657
import static org.hamcrest.Matchers.hasSize;
58+
import static org.hamcrest.Matchers.instanceOf;
5759
import static org.hamcrest.Matchers.is;
5860
import static org.hamcrest.Matchers.notNullValue;
5961
import static org.hamcrest.Matchers.nullValue;
@@ -1083,6 +1085,28 @@ public void testResourceAuthorizedPredicateAndWithFailures() {
10831085
assertThat(predicate.test(concreteIndexF, IndexComponentSelector.FAILURES), is(true));
10841086
}
10851087

1088+
public void testCheckResourcePrivilegesWithTooComplexAutomaton() {
1089+
IndicesPermission permission = new IndicesPermission.Builder(RESTRICTED_INDICES).addGroup(
1090+
IndexPrivilege.ALL,
1091+
FieldPermissions.DEFAULT,
1092+
null,
1093+
false,
1094+
"my-index"
1095+
).build();
1096+
1097+
var ex = expectThrows(
1098+
IllegalArgumentException.class,
1099+
() -> permission.checkResourcePrivileges(
1100+
Set.of("a?*b??*c?de**?f?oh*i?????j*k*l?m*n?????*o*p**qr*?s**t*"),
1101+
false,
1102+
Set.of("read"),
1103+
null
1104+
)
1105+
);
1106+
assertThat(ex.getMessage(), containsString("index pattern [a?*b??*c?de**?f?oh*i?????j*k*l?m*n?????*o*p**qr*?s**t*]"));
1107+
assertThat(ex.getCause(), instanceOf(TooComplexToDeterminizeException.class));
1108+
}
1109+
10861110
private static IndexAbstraction concreteIndexAbstraction(String name) {
10871111
return new IndexAbstraction.ConcreteIndex(
10881112
IndexMetadata.builder(name).settings(indexSettings(IndexVersion.current(), 1, 0)).build()

0 commit comments

Comments
 (0)