From ba3ee98943a79f04c3b04682db11a3dac3a9e36f Mon Sep 17 00:00:00 2001 From: Jay Modi Date: Thu, 29 Nov 2018 11:37:06 -0700 Subject: [PATCH] Security: improve exact index matching performance (#36017) This commit improves the efficiency of exact index name matching by separating exact matches from those that include wildcards or regular expressions. Internally, exact matching is done using a HashSet instead of adding the exact matches to the automata. For the wildcard and regular expression matches, the underlying implementation has not changed. --- .../authz/permission/IndicesPermission.java | 30 +++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/security/authz/permission/IndicesPermission.java b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/security/authz/permission/IndicesPermission.java index f0e2f2b7e62..4936071ee84 100644 --- a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/security/authz/permission/IndicesPermission.java +++ b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/security/authz/permission/IndicesPermission.java @@ -64,6 +64,36 @@ public final class IndicesPermission implements Iterable indexMatcher(List indices) { + Set exactMatch = new HashSet<>(); + List nonExactMatch = new ArrayList<>(); + for (String indexPattern : indices) { + if (indexPattern.startsWith("/") || indexPattern.contains("*") || indexPattern.contains("?")) { + nonExactMatch.add(indexPattern); + } else { + exactMatch.add(indexPattern); + } + } + + if (exactMatch.isEmpty() && nonExactMatch.isEmpty()) { + return s -> false; + } else if (exactMatch.isEmpty()) { + return buildAutomataPredicate(nonExactMatch); + } else if (nonExactMatch.isEmpty()) { + return buildExactMatchPredicate(exactMatch); + } else { + return buildExactMatchPredicate(exactMatch).or(buildAutomataPredicate(nonExactMatch)); + } + } + + private static Predicate buildExactMatchPredicate(Set indices) { + if (indices.size() == 1) { + final String singleValue = indices.iterator().next(); + return singleValue::equals; + } + return indices::contains; + } + + private static Predicate buildAutomataPredicate(List indices) { try { return Automatons.predicate(indices); } catch (TooComplexToDeterminizeException e) {