Skip to content

Commit ee155ea

Browse files
committed
More fixes
1 parent c4e8b5a commit ee155ea

File tree

8 files changed

+52
-21
lines changed

8 files changed

+52
-21
lines changed

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

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,10 @@ default Index getWriteIndex(IndexRequest request, Metadata metadata) {
7676
return getWriteIndex();
7777
}
7878

79+
default boolean isFailureIndexOfDataStream() {
80+
return false;
81+
}
82+
7983
/**
8084
* @return the data stream to which this index belongs or <code>null</code> if this is not a concrete index or
8185
* if it is a concrete index that does not belong to a data stream.
@@ -193,6 +197,11 @@ public boolean isSystem() {
193197
return isSystem;
194198
}
195199

200+
@Override
201+
public boolean isFailureIndexOfDataStream() {
202+
return dataStream != null && dataStream.isFailureStoreIndex(getName());
203+
}
204+
196205
@Override
197206
public boolean equals(Object o) {
198207
if (this == o) return true;

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

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@
2121
import java.util.HashSet;
2222
import java.util.List;
2323
import java.util.Set;
24-
import java.util.function.Predicate;
24+
import java.util.function.BiPredicate;
2525
import java.util.function.Supplier;
2626

2727
public class IndexAbstractionResolver {
@@ -37,7 +37,7 @@ public List<String> resolveIndexAbstractions(
3737
IndicesOptions indicesOptions,
3838
Metadata metadata,
3939
Supplier<Set<String>> allAuthorizedAndAvailable,
40-
Predicate<String> isAuthorized,
40+
BiPredicate<String, String> isAuthorized,
4141
boolean includeDataStreams
4242
) {
4343
List<String> finalIndices = new ArrayList<>();
@@ -103,7 +103,7 @@ && isIndexVisible(
103103
resolveSelectorsAndCombine(indexAbstraction, selectorString, indicesOptions, resolvedIndices, metadata);
104104
if (minus) {
105105
finalIndices.removeAll(resolvedIndices);
106-
} else if (indicesOptions.ignoreUnavailable() == false || isAuthorized.test(indexAbstraction)) {
106+
} else if (indicesOptions.ignoreUnavailable() == false || isAuthorized.test(indexAbstraction, selectorString)) {
107107
// Unauthorized names are considered unavailable, so if `ignoreUnavailable` is `true` they should be silently
108108
// discarded from the `finalIndices` list. Other "ways of unavailable" must be handled by the action
109109
// handler, see: https://github.com/elastic/elasticsearch/issues/90215

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -236,6 +236,6 @@ private List<String> resolveAbstractionsSelectorAllowed(List<String> expressions
236236
}
237237

238238
private List<String> resolveAbstractions(List<String> expressions, IndicesOptions indicesOptions, Supplier<Set<String>> mask) {
239-
return indexAbstractionResolver.resolveIndexAbstractions(expressions, indicesOptions, metadata, mask, (idx) -> true, true);
239+
return indexAbstractionResolver.resolveIndexAbstractions(expressions, indicesOptions, metadata, mask, (idx, sel) -> true, true);
240240
}
241241
}

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

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -295,7 +295,11 @@ interface AuthorizedIndices {
295295
/**
296296
* Checks if an index-like resource name is authorized, for an action by a user. The resource might or might not exist.
297297
*/
298-
boolean check(String name);
298+
default boolean check(String name) {
299+
return check(name, null);
300+
}
301+
302+
boolean check(String name, String selector);
299303
}
300304

301305
/**

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

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -193,7 +193,12 @@ public static class IsResourceAuthorizedPredicate {
193193
// public for tests
194194
public IsResourceAuthorizedPredicate(StringMatcher resourceNameMatcher, StringMatcher additionalNonDatastreamNameMatcher) {
195195
this((String name, @Nullable IndexAbstraction indexAbstraction) -> {
196-
assert indexAbstraction == null || name.equals(indexAbstraction.getName());
196+
// TODO this is hacky
197+
assert indexAbstraction == null
198+
|| (name.equals(indexAbstraction.getName())
199+
|| name.equals(
200+
IndexNameExpressionResolver.combineSelector(indexAbstraction.getName(), IndexComponentSelector.FAILURES)
201+
));
197202
return resourceNameMatcher.test(name)
198203
|| (isPartOfDatastream(indexAbstraction) == false && additionalNonDatastreamNameMatcher.test(name));
199204
});
@@ -240,7 +245,8 @@ public final boolean testDataStreamForFailureAccess(IndexAbstraction indexAbstra
240245
assert indexAbstraction != null && indexAbstraction.getType() == IndexAbstraction.Type.DATA_STREAM;
241246
return biPredicate.test(
242247
IndexNameExpressionResolver.combineSelector(indexAbstraction.getName(), IndexComponentSelector.FAILURES),
243-
null
248+
// this cannot be `null`, since otherwise this is not treated as a data stream
249+
indexAbstraction
244250
);
245251
}
246252

x-pack/plugin/security/qa/security-trial/src/javaRestTest/java/org/elasticsearch/xpack/security/FailureStoreSecurityRestIT.java

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ public class FailureStoreSecurityRestIT extends SecurityOnTrialLicenseRestTestCa
3737

3838
@SuppressWarnings("unchecked")
3939
public void testFailureStoreAccess() throws IOException {
40+
// TODO test API keys
4041
String dataAccessRole = "data_access";
4142
String failureStoreAccessRole = "failure_store_access";
4243

@@ -88,11 +89,14 @@ public void testFailureStoreAccess() throws IOException {
8889
performRequest(FAILURE_STORE_ACCESS_USER, new Request("GET", "/" + failureIndexName + "/_search")),
8990
failedDocId
9091
);
91-
// TODO fix this
92-
// assertContainsDocIds(
93-
// performRequest(FAILURE_STORE_ACCESS_USER, new Request("GET", "/" + failureIndexName + "/_search?ignore_unavailable=true")),
94-
// failedDocId
95-
// );
92+
assertContainsDocIds(
93+
performRequest(FAILURE_STORE_ACCESS_USER, new Request("GET", "/test1::failures/_search?ignore_unavailable=true")),
94+
failedDocId
95+
);
96+
assertContainsDocIds(
97+
performRequest(FAILURE_STORE_ACCESS_USER, new Request("GET", "/" + failureIndexName + "/_search?ignore_unavailable=true")),
98+
failedDocId
99+
);
96100

97101
expectThrows404(() -> performRequest(FAILURE_STORE_ACCESS_USER, new Request("GET", "/test12::failures/_search")));
98102
expectThrows404(() -> performRequest(FAILURE_STORE_ACCESS_USER, new Request("GET", "/test2::failures/_search")));
@@ -109,9 +113,9 @@ public void testFailureStoreAccess() throws IOException {
109113
assertEmpty(performRequest(FAILURE_STORE_ACCESS_USER, new Request("GET", "/test2::data/_search?ignore_unavailable=true")));
110114
assertEmpty(performRequest(FAILURE_STORE_ACCESS_USER, new Request("GET", "/test2/_search?ignore_unavailable=true")));
111115
// TODO fix this
112-
// assertEmpty(
113-
// performRequest(FAILURE_STORE_ACCESS_USER, new Request("GET", "/" + dataIndexName + "/_search?ignore_unavailable=true"))
114-
// );
116+
assertEmpty(
117+
performRequest(FAILURE_STORE_ACCESS_USER, new Request("GET", "/" + dataIndexName + "/_search?ignore_unavailable=true"))
118+
);
115119

116120
// assertEmpty(performRequest(FAILURE_STORE_ACCESS_USER, new Request("GET", "/*1::data/_search")));
117121
// assertEmpty(performRequest(FAILURE_STORE_ACCESS_USER, new Request("GET", "/*1/_search")));

x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/authz/RBACEngine.java

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
import org.elasticsearch.action.search.TransportClosePointInTimeAction;
3232
import org.elasticsearch.action.search.TransportMultiSearchAction;
3333
import org.elasticsearch.action.search.TransportSearchScrollAction;
34+
import org.elasticsearch.action.support.IndexComponentSelector;
3435
import org.elasticsearch.action.termvectors.MultiTermVectorsAction;
3536
import org.elasticsearch.cluster.metadata.DataStream;
3637
import org.elasticsearch.cluster.metadata.IndexAbstraction;
@@ -106,6 +107,7 @@
106107
import java.util.Objects;
107108
import java.util.Set;
108109
import java.util.TreeSet;
110+
import java.util.function.BiPredicate;
109111
import java.util.function.Consumer;
110112
import java.util.function.Predicate;
111113
import java.util.function.Supplier;
@@ -907,13 +909,20 @@ static AuthorizedIndices resolveAuthorizedIndicesFromRole(
907909
}
908910
timeChecker.accept(indicesAndAliases);
909911
return indicesAndAliases;
910-
}, name -> {
912+
}, (name, selector) -> {
911913
final IndexAbstraction indexAbstraction = lookup.get(name);
912914
if (indexAbstraction == null) {
913915
// test access (by name) to a resource that does not currently exist
914916
// the action handler must handle the case of accessing resources that do not exist
915917
return predicate.test(name, null);
916918
} else {
919+
if (indexAbstraction.isFailureIndexOfDataStream()
920+
&& predicate.testDataStreamForFailureAccess(indexAbstraction.getParentDataStream())) {
921+
return true;
922+
}
923+
if (IndexComponentSelector.FAILURES.getKey().equals(selector)) {
924+
return predicate.testDataStreamForFailureAccess(indexAbstraction);
925+
}
917926
// We check the parent data stream first if there is one. For testing requested indices, this is most likely
918927
// more efficient than checking the index name first because we recommend grant privileges over data stream
919928
// instead of backing indices.
@@ -1046,9 +1055,9 @@ private static boolean isAsyncRelatedAction(String action) {
10461055
static final class AuthorizedIndices implements AuthorizationEngine.AuthorizedIndices {
10471056

10481057
private final CachedSupplier<Set<String>> allAuthorizedAndAvailableSupplier;
1049-
private final Predicate<String> isAuthorizedPredicate;
1058+
private final BiPredicate<String, String> isAuthorizedPredicate;
10501059

1051-
AuthorizedIndices(Supplier<Set<String>> allAuthorizedAndAvailableSupplier, Predicate<String> isAuthorizedPredicate) {
1060+
AuthorizedIndices(Supplier<Set<String>> allAuthorizedAndAvailableSupplier, BiPredicate<String, String> isAuthorizedPredicate) {
10521061
this.allAuthorizedAndAvailableSupplier = CachedSupplier.wrap(allAuthorizedAndAvailableSupplier);
10531062
this.isAuthorizedPredicate = Objects.requireNonNull(isAuthorizedPredicate);
10541063
}
@@ -1059,8 +1068,8 @@ public Supplier<Set<String>> all() {
10591068
}
10601069

10611070
@Override
1062-
public boolean check(String name) {
1063-
return this.isAuthorizedPredicate.test(name);
1071+
public boolean check(String name, String selector) {
1072+
return isAuthorizedPredicate.test(name, selector);
10641073
}
10651074
}
10661075
}

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

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1455,7 +1455,6 @@ public void testBackingIndicesAreIncludedForAuthorizedDataStreams() {
14551455

14561456
public void testExplicitMappingUpdatesAreNotGrantedWithIngestPrivileges() {
14571457
final String dataStreamName = "my_data_stream";
1458-
User user = new User(randomAlphaOfLengthBetween(4, 12));
14591458
Role role = Role.builder(RESTRICTED_INDICES, "test1")
14601459
.cluster(Collections.emptySet(), Collections.emptyList())
14611460
.add(IndexPrivilege.CREATE, "my_*")

0 commit comments

Comments
 (0)