diff --git a/server/src/main/java/org/elasticsearch/cluster/metadata/IndexAbstractionResolver.java b/server/src/main/java/org/elasticsearch/cluster/metadata/IndexAbstractionResolver.java index 6e6d9844c1154..6b68981661699 100644 --- a/server/src/main/java/org/elasticsearch/cluster/metadata/IndexAbstractionResolver.java +++ b/server/src/main/java/org/elasticsearch/cluster/metadata/IndexAbstractionResolver.java @@ -48,92 +48,114 @@ public ResolvedIndexExpressions resolveIndexAbstractions( boolean includeDataStreams ) { final ResolvedIndexExpressions.Builder resolvedExpressionsBuilder = ResolvedIndexExpressions.builder(); - boolean wildcardSeen = false; for (String index : indices) { - String indexAbstraction; - boolean minus = false; - if (index.charAt(0) == '-' && wildcardSeen) { - indexAbstraction = index.substring(1); - minus = true; - } else { - indexAbstraction = index; - } + wildcardSeen = resolveIndexAbstraction( + resolvedExpressionsBuilder, + index, + indicesOptions, + projectMetadata, + allAuthorizedAndAvailableBySelector, + isAuthorized, + includeDataStreams, + wildcardSeen + ); + } + return resolvedExpressionsBuilder.build(); + } - // Always check to see if there's a selector on the index expression - final Tuple expressionAndSelector = IndexNameExpressionResolver.splitSelectorExpression(indexAbstraction); - final String selectorString = expressionAndSelector.v2(); - if (indicesOptions.allowSelectors() == false && selectorString != null) { - throw new UnsupportedSelectorException(indexAbstraction); - } - indexAbstraction = expressionAndSelector.v1(); - IndexComponentSelector selector = IndexComponentSelector.getByKeyOrThrow(selectorString); + private boolean resolveIndexAbstraction( + ResolvedIndexExpressions.Builder resolvedExpressionsBuilder, + String index, + IndicesOptions indicesOptions, + ProjectMetadata projectMetadata, + Function> allAuthorizedAndAvailableBySelector, + BiPredicate isAuthorized, + boolean includeDataStreams, + boolean wildcardSeen + ) { + String indexAbstraction; + boolean minus = false; + if (index.charAt(0) == '-' && wildcardSeen) { + indexAbstraction = index.substring(1); + minus = true; + } else { + indexAbstraction = index; + } + + // Always check to see if there's a selector on the index expression + final Tuple expressionAndSelector = IndexNameExpressionResolver.splitSelectorExpression(indexAbstraction); + final String selectorString = expressionAndSelector.v2(); + if (indicesOptions.allowSelectors() == false && selectorString != null) { + throw new UnsupportedSelectorException(indexAbstraction); + } + indexAbstraction = expressionAndSelector.v1(); + IndexComponentSelector selector = IndexComponentSelector.getByKeyOrThrow(selectorString); - // we always need to check for date math expressions - indexAbstraction = IndexNameExpressionResolver.resolveDateMathExpression(indexAbstraction); + // we always need to check for date math expressions + indexAbstraction = IndexNameExpressionResolver.resolveDateMathExpression(indexAbstraction); - if (indicesOptions.expandWildcardExpressions() && Regex.isSimpleMatchPattern(indexAbstraction)) { - wildcardSeen = true; - final HashSet resolvedIndices = new HashSet<>(); - for (String authorizedIndex : allAuthorizedAndAvailableBySelector.apply(selector)) { - if (Regex.simpleMatch(indexAbstraction, authorizedIndex) + if (indicesOptions.expandWildcardExpressions() && Regex.isSimpleMatchPattern(indexAbstraction)) { + wildcardSeen = true; + final HashSet resolvedIndices = new HashSet<>(); + for (String authorizedIndex : allAuthorizedAndAvailableBySelector.apply(selector)) { + if (Regex.simpleMatch(indexAbstraction, authorizedIndex) + && isIndexVisible( + indexAbstraction, + selectorString, + authorizedIndex, + indicesOptions, + projectMetadata, + indexNameExpressionResolver, + includeDataStreams + )) { + resolveSelectorsAndCollect(authorizedIndex, selectorString, indicesOptions, resolvedIndices, projectMetadata); + } + } + if (resolvedIndices.isEmpty()) { + // es core honours allow_no_indices for each wildcard expression, we do the same here by throwing index not found. + if (indicesOptions.allowNoIndices() == false) { + throw new IndexNotFoundException(indexAbstraction); + } + resolvedExpressionsBuilder.addLocalExpressions(index, new HashSet<>(), SUCCESS); + } else { + if (minus) { + resolvedExpressionsBuilder.excludeFromLocalExpressions(resolvedIndices); + } else { + resolvedExpressionsBuilder.addLocalExpressions(index, resolvedIndices, SUCCESS); + } + } + } else { + final HashSet resolvedIndices = new HashSet<>(); + resolveSelectorsAndCollect(indexAbstraction, selectorString, indicesOptions, resolvedIndices, projectMetadata); + if (minus) { + resolvedExpressionsBuilder.excludeFromLocalExpressions(resolvedIndices); + } else { + final boolean authorized = isAuthorized.test(indexAbstraction, selector); + if (authorized) { + final boolean visible = indexExists(projectMetadata, indexAbstraction) && isIndexVisible( indexAbstraction, selectorString, - authorizedIndex, + indexAbstraction, indicesOptions, projectMetadata, indexNameExpressionResolver, includeDataStreams - )) { - resolveSelectorsAndCollect(authorizedIndex, selectorString, indicesOptions, resolvedIndices, projectMetadata); - } - } - if (resolvedIndices.isEmpty()) { - // es core honours allow_no_indices for each wildcard expression, we do the same here by throwing index not found. - if (indicesOptions.allowNoIndices() == false) { - throw new IndexNotFoundException(indexAbstraction); - } - resolvedExpressionsBuilder.addLocalExpressions(index, new HashSet<>(), SUCCESS); - } else { - if (minus) { - resolvedExpressionsBuilder.excludeFromLocalExpressions(resolvedIndices); - } else { - resolvedExpressionsBuilder.addLocalExpressions(index, resolvedIndices, SUCCESS); - } - } - } else { - final HashSet resolvedIndices = new HashSet<>(); - resolveSelectorsAndCollect(indexAbstraction, selectorString, indicesOptions, resolvedIndices, projectMetadata); - if (minus) { - resolvedExpressionsBuilder.excludeFromLocalExpressions(resolvedIndices); + ); + final LocalIndexResolutionResult result = visible ? SUCCESS : CONCRETE_RESOURCE_NOT_VISIBLE; + resolvedExpressionsBuilder.addLocalExpressions(index, resolvedIndices, result); + } else if (indicesOptions.ignoreUnavailable()) { + // ignoreUnavailable implies that the request should not fail if an index is not authorized + // so we map this expression to an empty list, + resolvedExpressionsBuilder.addLocalExpressions(index, new HashSet<>(), CONCRETE_RESOURCE_UNAUTHORIZED); } else { - final boolean authorized = isAuthorized.test(indexAbstraction, selector); - if (authorized) { - final boolean visible = indexExists(projectMetadata, indexAbstraction) - && isIndexVisible( - indexAbstraction, - selectorString, - indexAbstraction, - indicesOptions, - projectMetadata, - indexNameExpressionResolver, - includeDataStreams - ); - final LocalIndexResolutionResult result = visible ? SUCCESS : CONCRETE_RESOURCE_NOT_VISIBLE; - resolvedExpressionsBuilder.addLocalExpressions(index, resolvedIndices, result); - } else if (indicesOptions.ignoreUnavailable()) { - // ignoreUnavailable implies that the request should not fail if an index is not authorized - // so we map this expression to an empty list, - resolvedExpressionsBuilder.addLocalExpressions(index, new HashSet<>(), CONCRETE_RESOURCE_UNAUTHORIZED); - } else { - // store the calculated expansion as unauthorized, it will be rejected later - resolvedExpressionsBuilder.addLocalExpressions(index, resolvedIndices, CONCRETE_RESOURCE_UNAUTHORIZED); - } + // store the calculated expansion as unauthorized, it will be rejected later + resolvedExpressionsBuilder.addLocalExpressions(index, resolvedIndices, CONCRETE_RESOURCE_UNAUTHORIZED); } } } - return resolvedExpressionsBuilder.build(); + return wildcardSeen; } private static void resolveSelectorsAndCollect(