Skip to content

Commit fb87484

Browse files
authored
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
1 parent 46e5f1c commit fb87484

File tree

3 files changed

+48
-5
lines changed

3 files changed

+48
-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: 19 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;
@@ -55,6 +56,7 @@
5556
import static org.hamcrest.Matchers.containsString;
5657
import static org.hamcrest.Matchers.equalTo;
5758
import static org.hamcrest.Matchers.hasSize;
59+
import static org.hamcrest.Matchers.instanceOf;
5860
import static org.hamcrest.Matchers.is;
5961
import static org.hamcrest.Matchers.notNullValue;
6062
import static org.hamcrest.Matchers.nullValue;
@@ -1090,6 +1092,23 @@ public void testResourceAuthorizedPredicateAndWithFailures() {
10901092
assertThat(predicate.test(concreteIndexF, IndexComponentSelector.FAILURES), is(true));
10911093
}
10921094

1095+
public void testCheckResourcePrivilegesWithTooComplexAutomaton() {
1096+
IndicesPermission permission = new IndicesPermission.Builder(RESTRICTED_INDICES).addGroup(
1097+
IndexPrivilege.ALL,
1098+
FieldPermissions.DEFAULT,
1099+
null,
1100+
false,
1101+
"my-index"
1102+
).build();
1103+
1104+
var ex = expectThrows(
1105+
IllegalArgumentException.class,
1106+
() -> permission.checkResourcePrivileges(Set.of("****a*b?c**d**e*f??*g**h???i??*j*k*l*m*n???o*"), false, Set.of("read"), null)
1107+
);
1108+
assertThat(ex.getMessage(), containsString("index pattern [****a*b?c**d**e*f??*g**h???i??*j*k*l*m*n???o*]"));
1109+
assertThat(ex.getCause(), instanceOf(TooComplexToDeterminizeException.class));
1110+
}
1111+
10931112
private static IndexAbstraction concreteIndexAbstraction(String name) {
10941113
return new IndexAbstraction.ConcreteIndex(
10951114
IndexMetadata.builder(name).settings(indexSettings(IndexVersion.current(), 1, 0)).build()

0 commit comments

Comments
 (0)