Skip to content

Commit b5fea97

Browse files
[8.13] GET /_all should return hidden indices with visible aliases (#106975) (#107441)
GET /_all should return hidden indices if they are accessible through a visible alias. This is currently the behavior when resolution occurs in the security layer. This changes adds this behavior to name resolution when security is not used. (cherry picked from da81510)
1 parent 8c36f08 commit b5fea97

File tree

4 files changed

+156
-24
lines changed

4 files changed

+156
-24
lines changed

docs/changelog/106975.yaml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
pr: 106975
2+
summary: GET /_all should return hidden indices with visible aliases
3+
area: Indices APIs
4+
type: bug
5+
issues: []

server/src/main/java/org/elasticsearch/cluster/metadata/IndexNameExpressionResolver.java

Lines changed: 26 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1151,32 +1151,36 @@ private WildcardExpressionResolver() {
11511151
}
11521152

11531153
/**
1154-
* Returns all the indices and all the datastreams, considering the open/closed, system, and hidden context parameters.
1154+
* Returns all the indices, datastreams, and aliases, considering the open/closed, system, and hidden context parameters.
11551155
* Depending on the context, returns the names of the datastreams themselves or their backing indices.
11561156
*/
11571157
public static Collection<String> resolveAll(Context context) {
1158-
List<String> resolvedExpressions = resolveEmptyOrTrivialWildcard(context);
1159-
if (context.includeDataStreams() == false) {
1160-
return resolvedExpressions;
1161-
} else {
1162-
Stream<IndexAbstraction> dataStreamsAbstractions = context.getState()
1163-
.metadata()
1164-
.getIndicesLookup()
1165-
.values()
1166-
.stream()
1167-
.filter(indexAbstraction -> indexAbstraction.getType() == Type.DATA_STREAM)
1168-
.filter(
1169-
indexAbstraction -> indexAbstraction.isSystem() == false
1170-
|| context.systemIndexAccessPredicate.test(indexAbstraction.getName())
1171-
);
1172-
if (context.getOptions().expandWildcardsHidden() == false) {
1173-
dataStreamsAbstractions = dataStreamsAbstractions.filter(indexAbstraction -> indexAbstraction.isHidden() == false);
1174-
}
1175-
// dedup backing indices if expand hidden indices option is true
1176-
Set<String> resolvedIncludingDataStreams = expandToOpenClosed(context, dataStreamsAbstractions).collect(Collectors.toSet());
1177-
resolvedIncludingDataStreams.addAll(resolvedExpressions);
1178-
return resolvedIncludingDataStreams;
1158+
List<String> concreteIndices = resolveEmptyOrTrivialWildcard(context);
1159+
1160+
if (context.includeDataStreams() == false && context.getOptions().ignoreAliases()) {
1161+
return concreteIndices;
11791162
}
1163+
1164+
Stream<IndexAbstraction> ias = context.getState()
1165+
.metadata()
1166+
.getIndicesLookup()
1167+
.values()
1168+
.stream()
1169+
.filter(ia -> context.getOptions().expandWildcardsHidden() || ia.isHidden() == false)
1170+
.filter(ia -> shouldIncludeIfDataStream(ia, context) || shouldIncludeIfAlias(ia, context))
1171+
.filter(ia -> ia.isSystem() == false || context.systemIndexAccessPredicate.test(ia.getName()));
1172+
1173+
Set<String> resolved = expandToOpenClosed(context, ias).collect(Collectors.toSet());
1174+
resolved.addAll(concreteIndices);
1175+
return resolved;
1176+
}
1177+
1178+
private static boolean shouldIncludeIfDataStream(IndexAbstraction ia, IndexNameExpressionResolver.Context context) {
1179+
return context.includeDataStreams() && ia.getType() == Type.DATA_STREAM;
1180+
}
1181+
1182+
private static boolean shouldIncludeIfAlias(IndexAbstraction ia, IndexNameExpressionResolver.Context context) {
1183+
return context.getOptions().ignoreAliases() == false && ia.getType() == Type.ALIAS;
11801184
}
11811185

11821186
/**

server/src/test/java/org/elasticsearch/cluster/metadata/IndexNameExpressionResolverTests.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1215,9 +1215,9 @@ public void testHiddenAliasAndHiddenIndexResolution() {
12151215
indexNames = indexNameExpressionResolver.concreteIndexNames(state, includeHiddenOptions, visibleAlias);
12161216
assertThat(Arrays.asList(indexNames), containsInAnyOrder(visibleIndex, hiddenIndex));
12171217

1218-
// A total wildcards does not resolve the hidden index in this case
1218+
// total wildcards should also resolve both visible and hidden indices if there is a visible alias
12191219
indexNames = indexNameExpressionResolver.concreteIndexNames(state, excludeHiddenOptions, "*");
1220-
assertThat(Arrays.asList(indexNames), containsInAnyOrder(visibleIndex));
1220+
assertThat(Arrays.asList(indexNames), containsInAnyOrder(visibleIndex, hiddenIndex));
12211221
}
12221222

12231223
{

server/src/test/java/org/elasticsearch/cluster/metadata/WildcardExpressionResolverTests.java

Lines changed: 123 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -280,6 +280,129 @@ public void testAll() {
280280
assertThat(IndexNameExpressionResolver.resolveExpressions(noExpandContext, "_all").size(), equalTo(0));
281281
}
282282

283+
public void testAllAliases() {
284+
{
285+
// hidden index with hidden alias should not be returned
286+
Metadata.Builder mdBuilder = Metadata.builder()
287+
.put(
288+
indexBuilder("index-hidden-alias", true) // index hidden
289+
.state(State.OPEN)
290+
.putAlias(AliasMetadata.builder("alias-hidden").isHidden(true)) // alias hidden
291+
);
292+
293+
ClusterState state = ClusterState.builder(new ClusterName("_name")).metadata(mdBuilder).build();
294+
295+
IndexNameExpressionResolver.Context context = new IndexNameExpressionResolver.Context(
296+
state,
297+
IndicesOptions.lenientExpandOpen(), // don't include hidden
298+
SystemIndexAccessLevel.NONE
299+
);
300+
assertThat(newHashSet(IndexNameExpressionResolver.WildcardExpressionResolver.resolveAll(context)), equalTo(newHashSet()));
301+
}
302+
303+
{
304+
// hidden index with visible alias should be returned
305+
Metadata.Builder mdBuilder = Metadata.builder()
306+
.put(
307+
indexBuilder("index-visible-alias", true) // index hidden
308+
.state(State.OPEN)
309+
.putAlias(AliasMetadata.builder("alias-visible").isHidden(false)) // alias visible
310+
);
311+
312+
ClusterState state = ClusterState.builder(new ClusterName("_name")).metadata(mdBuilder).build();
313+
314+
IndexNameExpressionResolver.Context context = new IndexNameExpressionResolver.Context(
315+
state,
316+
IndicesOptions.lenientExpandOpen(), // don't include hidden
317+
SystemIndexAccessLevel.NONE
318+
);
319+
assertThat(
320+
newHashSet(IndexNameExpressionResolver.WildcardExpressionResolver.resolveAll(context)),
321+
equalTo(newHashSet("index-visible-alias"))
322+
);
323+
}
324+
}
325+
326+
public void testAllDataStreams() {
327+
328+
String dataStreamName = "foo_logs";
329+
long epochMillis = randomLongBetween(1580536800000L, 1583042400000L);
330+
IndexMetadata firstBackingIndexMetadata = createBackingIndex(dataStreamName, 1, epochMillis).build();
331+
332+
IndicesOptions indicesAndAliasesOptions = IndicesOptions.fromOptions(
333+
randomBoolean(),
334+
randomBoolean(),
335+
true,
336+
false,
337+
true,
338+
false,
339+
false,
340+
false
341+
);
342+
343+
{
344+
// visible data streams should be returned by _all even show backing indices are hidden
345+
Metadata.Builder mdBuilder = Metadata.builder()
346+
.put(firstBackingIndexMetadata, true)
347+
.put(DataStreamTestHelper.newInstance(dataStreamName, List.of(firstBackingIndexMetadata.getIndex())));
348+
349+
ClusterState state = ClusterState.builder(new ClusterName("_name")).metadata(mdBuilder).build();
350+
351+
IndexNameExpressionResolver.Context context = new IndexNameExpressionResolver.Context(
352+
state,
353+
indicesAndAliasesOptions,
354+
false,
355+
false,
356+
true,
357+
SystemIndexAccessLevel.NONE,
358+
NONE,
359+
NONE
360+
);
361+
362+
assertThat(
363+
newHashSet(IndexNameExpressionResolver.WildcardExpressionResolver.resolveAll(context)),
364+
equalTo(newHashSet(DataStream.getDefaultBackingIndexName("foo_logs", 1, epochMillis)))
365+
);
366+
}
367+
368+
{
369+
// if data stream itself is hidden, backing indices should not be returned
370+
boolean hidden = true;
371+
var dataStream = new DataStream(
372+
dataStreamName,
373+
List.of(firstBackingIndexMetadata.getIndex()),
374+
1,
375+
null,
376+
hidden,
377+
false,
378+
false,
379+
false,
380+
null,
381+
null,
382+
false,
383+
List.of(),
384+
false
385+
);
386+
387+
Metadata.Builder mdBuilder = Metadata.builder().put(firstBackingIndexMetadata, true).put(dataStream);
388+
389+
ClusterState state = ClusterState.builder(new ClusterName("_name")).metadata(mdBuilder).build();
390+
391+
IndexNameExpressionResolver.Context context = new IndexNameExpressionResolver.Context(
392+
state,
393+
indicesAndAliasesOptions,
394+
false,
395+
false,
396+
true,
397+
SystemIndexAccessLevel.NONE,
398+
NONE,
399+
NONE
400+
);
401+
402+
assertThat(newHashSet(IndexNameExpressionResolver.WildcardExpressionResolver.resolveAll(context)), equalTo(newHashSet()));
403+
}
404+
}
405+
283406
public void testResolveEmpty() {
284407
Metadata.Builder mdBuilder = Metadata.builder()
285408
.put(

0 commit comments

Comments
 (0)