Skip to content

Commit 7cbd305

Browse files
authored
Prune extraneous files entitlements paths to prevent incorrect binary search (#123177)
1 parent df71ccf commit 7cbd305

File tree

2 files changed

+39
-2
lines changed

2 files changed

+39
-2
lines changed

libs/entitlement/src/main/java/org/elasticsearch/entitlement/runtime/policy/FileAccessTree.java

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -49,8 +49,24 @@ private FileAccessTree(FilesEntitlement filesEntitlement, PathLookup pathLookup)
4949
readPaths.sort(String::compareTo);
5050
writePaths.sort(String::compareTo);
5151

52-
this.readPaths = readPaths.toArray(new String[0]);
53-
this.writePaths = writePaths.toArray(new String[0]);
52+
this.readPaths = pruneSortedPaths(readPaths).toArray(new String[0]);
53+
this.writePaths = pruneSortedPaths(writePaths).toArray(new String[0]);
54+
}
55+
56+
private static List<String> pruneSortedPaths(List<String> paths) {
57+
List<String> prunedReadPaths = new ArrayList<>();
58+
if (paths.isEmpty() == false) {
59+
String currentPath = paths.get(0);
60+
prunedReadPaths.add(currentPath);
61+
for (int i = 1; i < paths.size(); ++i) {
62+
String nextPath = paths.get(i);
63+
if (nextPath.startsWith(currentPath) == false) {
64+
prunedReadPaths.add(nextPath);
65+
currentPath = nextPath;
66+
}
67+
}
68+
}
69+
return prunedReadPaths;
5470
}
5571

5672
public static FileAccessTree of(FilesEntitlement filesEntitlement, PathLookup pathLookup) {

libs/entitlement/src/test/java/org/elasticsearch/entitlement/runtime/policy/FileAccessTreeTests.java

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,27 @@ public void testReadWriteUnderRead() {
9696
assertThat(tree.canWrite(path("foo/bar")), is(true));
9797
}
9898

99+
public void testPrunedPaths() {
100+
var tree = accessTree(entitlement("foo", "read", "foo/baz", "read", "foo/bar", "read"));
101+
assertThat(tree.canRead(path("foo")), is(true));
102+
assertThat(tree.canWrite(path("foo")), is(false));
103+
assertThat(tree.canRead(path("foo/bar")), is(true));
104+
assertThat(tree.canWrite(path("foo/bar")), is(false));
105+
assertThat(tree.canRead(path("foo/baz")), is(true));
106+
assertThat(tree.canWrite(path("foo/baz")), is(false));
107+
// also test a non-existent subpath
108+
assertThat(tree.canRead(path("foo/barf")), is(true));
109+
assertThat(tree.canWrite(path("foo/barf")), is(false));
110+
111+
tree = accessTree(entitlement("foo", "read", "foo/bar", "read_write"));
112+
assertThat(tree.canRead(path("foo")), is(true));
113+
assertThat(tree.canWrite(path("foo")), is(false));
114+
assertThat(tree.canRead(path("foo/bar")), is(true));
115+
assertThat(tree.canWrite(path("foo/bar")), is(true));
116+
assertThat(tree.canRead(path("foo/baz")), is(true));
117+
assertThat(tree.canWrite(path("foo/baz")), is(false));
118+
}
119+
99120
public void testReadWithRelativePath() {
100121
for (var dir : List.of("config", "home")) {
101122
var tree = accessTree(entitlement(Map.of("relative_path", "foo", "mode", "read", "relative_to", dir)));

0 commit comments

Comments
 (0)