Skip to content

Commit 3d4532d

Browse files
committed
Add tests
1 parent c99c46f commit 3d4532d

File tree

4 files changed

+165
-13
lines changed

4 files changed

+165
-13
lines changed

libs/entitlement/src/main/java/org/elasticsearch/entitlement/runtime/policy/entitlements/FilesEntitlement.java

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,12 @@
1313
import org.elasticsearch.entitlement.runtime.policy.PolicyValidationException;
1414

1515
import java.util.ArrayList;
16+
import java.util.Arrays;
1617
import java.util.HashMap;
1718
import java.util.List;
19+
import java.util.Locale;
1820
import java.util.Map;
21+
import java.util.stream.Collectors;
1922

2023
/**
2124
* Describes a file entitlement with a path and mode.
@@ -50,6 +53,15 @@ private static Mode parseMode(String mode) {
5053
}
5154
}
5255

56+
private static BaseDir parseBaseDir(String baseDir) {
57+
return switch (baseDir) {
58+
case "config" -> BaseDir.CONFIG;
59+
case "data" -> BaseDir.DATA;
60+
case "temp" -> BaseDir.TEMP;
61+
default -> throw new PolicyValidationException("invalid base_dir: " + baseDir + ", valid values: [config, data, temp]");
62+
};
63+
}
64+
5365
@ExternalEntitlement(parameterNames = { "paths" }, esModulesOnly = false)
5466
@SuppressWarnings("unchecked")
5567
public static FilesEntitlement build(List<Object> paths) {
@@ -68,16 +80,8 @@ public static FilesEntitlement build(List<Object> paths) {
6880
throw new PolicyValidationException("files entitlement must contain mode for every listed file");
6981
}
7082
String baseDirString = file.remove("base_dir");
71-
BaseDir baseDir = BaseDir.NONE;
72-
if (baseDirString != null) {
73-
if ("config".equals(baseDirString)) {
74-
baseDir = BaseDir.CONFIG;
75-
} else {
76-
throw new PolicyValidationException(
77-
"unexpected basedir [" + baseDirString + "] for in a listed file for files entitlement"
78-
);
79-
}
80-
}
83+
final BaseDir baseDir = baseDirString == null ? BaseDir.NONE : parseBaseDir(baseDirString);
84+
8185
if (file.isEmpty() == false) {
8286
throw new PolicyValidationException("unknown key(s) " + file + " in a listed file for files entitlement");
8387
}

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

Lines changed: 70 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,12 @@
1919
import java.util.HashMap;
2020
import java.util.List;
2121
import java.util.Map;
22+
import java.util.stream.Stream;
2223

2324
import static org.elasticsearch.core.PathUtils.getDefaultFileSystem;
2425
import static org.hamcrest.Matchers.is;
26+
import static org.mockito.ArgumentMatchers.any;
27+
import static org.mockito.Mockito.when;
2528

2629
public class FileAccessTreeTests extends ESTestCase {
2730

@@ -85,6 +88,68 @@ public void testReadWriteUnderRead() {
8588
assertThat(tree.canWrite(path("foo/bar")), is(true));
8689
}
8790

91+
public void testReadWithBaseDir() {
92+
var resolver = Mockito.mock(DirectoryResolver.class);
93+
when(resolver.resolveTemp(any(Path.class))).thenReturn(Path.of("/tmp/foo"));
94+
var tree = FileAccessTree.of(
95+
entitlement(Map.of("path", "foo", "mode", "read", "base_dir", "temp")),
96+
resolver
97+
);
98+
assertThat(tree.canRead(path("foo")), is(false));
99+
100+
assertThat(tree.canRead(path("/tmp/foo")), is(true));
101+
102+
assertThat(tree.canRead(path("/tmp/foo/subdir")), is(true));
103+
assertThat(tree.canRead(path("/tmp/food")), is(false));
104+
assertThat(tree.canWrite(path("/tmp/foo")), is(false));
105+
106+
assertThat(tree.canRead(path("/tmp")), is(false));
107+
assertThat(tree.canRead(path("/tmp/before")), is(false));
108+
assertThat(tree.canRead(path("/tmp/later")), is(false));
109+
}
110+
111+
public void testWriteWithBaseDir() {
112+
var resolver = Mockito.mock(DirectoryResolver.class);
113+
when(resolver.resolveConfig(any(Path.class))).thenReturn(Path.of("/config/foo"));
114+
var tree = FileAccessTree.of(
115+
entitlement(Map.of("path", "foo", "mode", "read_write", "base_dir", "config")),
116+
resolver
117+
);
118+
assertThat(tree.canWrite(path("/config/foo")), is(true));
119+
assertThat(tree.canWrite(path("/config/foo/subdir")), is(true));
120+
assertThat(tree.canWrite(path("foo")), is(false));
121+
assertThat(tree.canWrite(path("/config/food")), is(false));
122+
assertThat(tree.canRead(path("/config/foo")), is(true));
123+
assertThat(tree.canRead(path("foo")), is(false));
124+
125+
assertThat(tree.canWrite(path("/config")), is(false));
126+
assertThat(tree.canWrite(path("/config/before")), is(false));
127+
assertThat(tree.canWrite(path("/config/later")), is(false));
128+
}
129+
130+
public void testMultipleDataBaseDir() {
131+
var resolver = Mockito.mock(DirectoryResolver.class);
132+
when(resolver.resolveData(any(Path.class))).thenReturn(Stream.of(Path.of("/data1/foo"), Path.of("/data2/foo")));
133+
var tree = FileAccessTree.of(
134+
entitlement(Map.of("path", "foo", "mode", "read_write", "base_dir", "data")),
135+
resolver
136+
);
137+
assertThat(tree.canWrite(path("/data1/foo")), is(true));
138+
assertThat(tree.canWrite(path("/data2/foo")), is(true));
139+
assertThat(tree.canWrite(path("/data3/foo")), is(false));
140+
assertThat(tree.canWrite(path("/data1/foo/subdir")), is(true));
141+
assertThat(tree.canWrite(path("foo")), is(false));
142+
assertThat(tree.canWrite(path("/data1/food")), is(false));
143+
assertThat(tree.canRead(path("/data1/foo")), is(true));
144+
assertThat(tree.canRead(path("/data2/foo")), is(true));
145+
assertThat(tree.canRead(path("foo")), is(false));
146+
147+
assertThat(tree.canWrite(path("/data1")), is(false));
148+
assertThat(tree.canWrite(path("/data2")), is(false));
149+
assertThat(tree.canWrite(path("/config/before")), is(false));
150+
assertThat(tree.canWrite(path("/config/later")), is(false));
151+
}
152+
88153
public void testNormalizePath() {
89154
var tree = FileAccessTree.of(entitlement("foo/../bar", "read"), Mockito.mock(DirectoryResolver.class));
90155
assertThat(tree.canRead(path("foo/../bar")), is(true));
@@ -105,7 +170,7 @@ public void testForwardSlashes() {
105170
assertThat(tree.canRead(path("m/n")), is(true));
106171
}
107172

108-
FilesEntitlement entitlement(String... values) {
173+
static FilesEntitlement entitlement(String... values) {
109174
List<Object> filesData = new ArrayList<>();
110175
for (int i = 0; i < values.length; i += 2) {
111176
Map<String, String> fileData = new HashMap<>();
@@ -115,4 +180,8 @@ FilesEntitlement entitlement(String... values) {
115180
}
116181
return FilesEntitlement.build(filesData);
117182
}
183+
184+
static FilesEntitlement entitlement(Map<String, String> value) {
185+
return FilesEntitlement.build(List.of(value));
186+
}
118187
}

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

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,74 @@ public void testPolicyBuilderOnExternalPlugin() throws IOException {
109109
assertEquals(expected, parsedPolicy);
110110
}
111111

112+
public void testParseFiles() throws IOException {
113+
Policy policyWithOnePath = new PolicyParser(new ByteArrayInputStream("""
114+
entitlement-module-name:
115+
- files:
116+
- path: "test/path/to/file"
117+
mode: "read_write"
118+
""".getBytes(StandardCharsets.UTF_8)), "test-policy.yaml", false).parsePolicy();
119+
Policy expected = new Policy(
120+
"test-policy.yaml",
121+
List.of(
122+
new Scope(
123+
"entitlement-module-name",
124+
List.of(FilesEntitlement.build(List.of(Map.of("path", "test/path/to/file", "mode", "read_write"))))
125+
)
126+
)
127+
);
128+
assertEquals(expected, policyWithOnePath);
129+
130+
Policy policyWithTwoPaths = new PolicyParser(new ByteArrayInputStream("""
131+
entitlement-module-name:
132+
- files:
133+
- path: "test/path/to/file"
134+
mode: "read_write"
135+
- path: "test/path/to/read-dir/"
136+
mode: "read"
137+
""".getBytes(StandardCharsets.UTF_8)), "test-policy.yaml", false).parsePolicy();
138+
expected = new Policy(
139+
"test-policy.yaml",
140+
List.of(
141+
new Scope(
142+
"entitlement-module-name",
143+
List.of(FilesEntitlement.build(List.of(
144+
Map.of("path", "test/path/to/file", "mode", "read_write"),
145+
Map.of("path", "test/path/to/read-dir/", "mode", "read")
146+
)))
147+
)
148+
)
149+
);
150+
assertEquals(expected, policyWithTwoPaths);
151+
152+
Policy policyWithMultiplePathsAndBaseDir = new PolicyParser(new ByteArrayInputStream("""
153+
entitlement-module-name:
154+
- files:
155+
- path: "test/path/to/file"
156+
mode: "read_write"
157+
base_dir: "temp"
158+
- path: "test/path/to/read-dir/"
159+
mode: "read"
160+
base_dir: "config"
161+
- path: "/path/to/file"
162+
mode: "read_write"
163+
""".getBytes(StandardCharsets.UTF_8)), "test-policy.yaml", false).parsePolicy();
164+
expected = new Policy(
165+
"test-policy.yaml",
166+
List.of(
167+
new Scope(
168+
"entitlement-module-name",
169+
List.of(FilesEntitlement.build(List.of(
170+
Map.of("path", "test/path/to/file", "mode", "read_write", "base_dir", "temp"),
171+
Map.of("path", "test/path/to/read-dir/", "mode", "read", "base_dir", "config"),
172+
Map.of("path", "/path/to/file", "mode", "read_write")
173+
)))
174+
)
175+
)
176+
);
177+
assertEquals(expected, policyWithMultiplePathsAndBaseDir);
178+
}
179+
112180
public void testParseNetwork() throws IOException {
113181
Policy parsedPolicy = new PolicyParser(new ByteArrayInputStream("""
114182
entitlement-module-name:

libs/entitlement/src/test/java/org/elasticsearch/entitlement/runtime/policy/entitlements/FilesEntitlementTests.java

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,13 +13,24 @@
1313
import org.elasticsearch.test.ESTestCase;
1414

1515
import java.util.List;
16+
import java.util.Map;
17+
18+
import static org.hamcrest.Matchers.is;
1619

1720
public class FilesEntitlementTests extends ESTestCase {
1821

1922
public void testEmptyBuild() {
2023
PolicyValidationException pve = expectThrows(PolicyValidationException.class, () -> FilesEntitlement.build(List.of()));
21-
assertEquals(pve.getMessage(), "must specify at least one path");
24+
assertEquals("must specify at least one path", pve.getMessage());
2225
pve = expectThrows(PolicyValidationException.class, () -> FilesEntitlement.build(null));
23-
assertEquals(pve.getMessage(), "must specify at least one path");
26+
assertEquals("must specify at least one path", pve.getMessage());
27+
}
28+
29+
public void testNotABaseDir() {
30+
var ex = expectThrows(
31+
PolicyValidationException.class,
32+
() -> FilesEntitlement.build(List.of((Map.of("path", "foo", "mode", "read", "base_dir", "bar"))))
33+
);
34+
assertThat(ex.getMessage(), is("invalid base_dir: bar, valid values: [config, data, temp]"));
2435
}
2536
}

0 commit comments

Comments
 (0)