Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@

package org.elasticsearch.entitlement.initialization;

import org.elasticsearch.core.PathUtils;
import org.elasticsearch.core.internal.provider.ProviderLocator;
import org.elasticsearch.entitlement.bootstrap.EntitlementBootstrap;
import org.elasticsearch.entitlement.bridge.EntitlementChecker;
Expand Down Expand Up @@ -133,7 +134,7 @@ private static Class<?>[] findClassesToRetransform(Class<?>[] loadedClasses, Set
private static PolicyManager createPolicyManager() {
EntitlementBootstrap.BootstrapArgs bootstrapArgs = EntitlementBootstrap.bootstrapArgs();
Map<String, Policy> pluginPolicies = bootstrapArgs.pluginPolicies();
var pathLookup = new PathLookup(bootstrapArgs.configDir(), bootstrapArgs.dataDirs(), bootstrapArgs.tempDir());
var pathLookup = new PathLookup(getUserHome(), bootstrapArgs.configDir(), bootstrapArgs.dataDirs(), bootstrapArgs.tempDir());
Path logsDir = EntitlementBootstrap.bootstrapArgs().logsDir();

// TODO(ES-10031): Decide what goes in the elasticsearch default policy and extend it
Expand Down Expand Up @@ -221,6 +222,14 @@ private static PolicyManager createPolicyManager() {
);
}

private static Path getUserHome() {
String userHome = System.getProperty("user.home");
if (userHome == null) {
throw new IllegalStateException("user.home system property is required");
}
return PathUtils.get(userHome);
}

private static Stream<InstrumentationService.InstrumentationInfo> fileSystemProviderChecks() throws ClassNotFoundException,
NoSuchMethodException {
var fileSystemProviderClass = FileSystems.getDefault().provider().getClass();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,4 @@

import java.nio.file.Path;

public record PathLookup(Path configDir, Path[] dataDirs, Path tempDir) {}
public record PathLookup(Path homeDir, Path configDir, Path[] dataDirs, Path tempDir) {}
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,8 @@ public enum Mode {

public enum BaseDir {
CONFIG,
DATA
DATA,
HOME
}

public sealed interface FileData {
Expand Down Expand Up @@ -73,6 +74,8 @@ public Stream<Path> resolvePaths(PathLookup pathLookup) {
return Stream.of(pathLookup.configDir().resolve(relativePath));
case DATA:
return Arrays.stream(pathLookup.dataDirs()).map(d -> d.resolve(relativePath));
case HOME:
return Stream.of(pathLookup.homeDir().resolve(relativePath));
default:
throw new IllegalArgumentException();
}
Expand All @@ -90,12 +93,14 @@ private static Mode parseMode(String mode) {
}

private static BaseDir parseBaseDir(String baseDir) {
if (baseDir.equals("config")) {
return BaseDir.CONFIG;
} else if (baseDir.equals("data")) {
return BaseDir.DATA;
}
throw new PolicyValidationException("invalid relative directory: " + baseDir + ", valid values: [config, data]");
return switch (baseDir) {
case "config" -> BaseDir.CONFIG;
case "data" -> BaseDir.DATA;
case "home" -> BaseDir.HOME;
default -> throw new PolicyValidationException(
"invalid relative directory: " + baseDir + ", valid values: [config, data, home]"
);
};
}

@ExternalEntitlement(parameterNames = { "paths" }, esModulesOnly = false)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ private static Path path(String s) {
}

private static final PathLookup TEST_PATH_LOOKUP = new PathLookup(
Path.of("/home"),
Path.of("/config"),
new Path[] { Path.of("/data1"), Path.of("/data2") },
Path.of("/tmp")
Expand Down Expand Up @@ -91,32 +92,36 @@ public void testReadWriteUnderRead() {
}

public void testReadWithRelativePath() {
var tree = accessTree(entitlement(Map.of("relative_path", "foo", "mode", "read", "relative_to", "config")));
assertThat(tree.canRead(path("foo")), is(false));
for (var dir : List.of("config", "home")) {
var tree = accessTree(entitlement(Map.of("relative_path", "foo", "mode", "read", "relative_to", dir)));
assertThat(tree.canRead(path("foo")), is(false));

assertThat(tree.canRead(path("/config/foo")), is(true));
assertThat(tree.canRead(path("/" + dir + "/foo")), is(true));

assertThat(tree.canRead(path("/config/foo/subdir")), is(true));
assertThat(tree.canRead(path("/config/food")), is(false));
assertThat(tree.canWrite(path("/config/foo")), is(false));
assertThat(tree.canRead(path("/" + dir + "/foo/subdir")), is(true));
assertThat(tree.canRead(path("/" + dir + "/food")), is(false));
assertThat(tree.canWrite(path("/" + dir + "/foo")), is(false));

assertThat(tree.canRead(path("/config")), is(false));
assertThat(tree.canRead(path("/config/before")), is(false));
assertThat(tree.canRead(path("/config/later")), is(false));
assertThat(tree.canRead(path("/" + dir)), is(false));
assertThat(tree.canRead(path("/" + dir + "/before")), is(false));
assertThat(tree.canRead(path("/" + dir + "/later")), is(false));
}
}

public void testWriteWithRelativePath() {
var tree = accessTree(entitlement(Map.of("relative_path", "foo", "mode", "read_write", "relative_to", "config")));
assertThat(tree.canWrite(path("/config/foo")), is(true));
assertThat(tree.canWrite(path("/config/foo/subdir")), is(true));
assertThat(tree.canWrite(path("foo")), is(false));
assertThat(tree.canWrite(path("/config/food")), is(false));
assertThat(tree.canRead(path("/config/foo")), is(true));
assertThat(tree.canRead(path("foo")), is(false));

assertThat(tree.canWrite(path("/config")), is(false));
assertThat(tree.canWrite(path("/config/before")), is(false));
assertThat(tree.canWrite(path("/config/later")), is(false));
for (var dir : List.of("config", "home")) {
var tree = accessTree(entitlement(Map.of("relative_path", "foo", "mode", "read_write", "relative_to", dir)));
assertThat(tree.canWrite(path("/" + dir + "/foo")), is(true));
assertThat(tree.canWrite(path("/" + dir + "/foo/subdir")), is(true));
assertThat(tree.canWrite(path("/" + dir)), is(false));
assertThat(tree.canWrite(path("/" + dir + "/food")), is(false));
assertThat(tree.canRead(path("/" + dir + "/foo")), is(true));
assertThat(tree.canRead(path("/" + dir)), is(false));

assertThat(tree.canWrite(path("/" + dir)), is(false));
assertThat(tree.canWrite(path("/" + dir + "/before")), is(false));
assertThat(tree.canWrite(path("/" + dir + "/later")), is(false));
}
}

public void testMultipleDataDirs() {
Expand Down Expand Up @@ -161,7 +166,7 @@ public void testTempDirAccess() {
Path tempDir = createTempDir();
var tree = FileAccessTree.of(
FilesEntitlement.EMPTY,
new PathLookup(Path.of("/config"), new Path[] { Path.of("/data1"), Path.of("/data2") }, tempDir)
new PathLookup(Path.of("/home"), Path.of("/config"), new Path[] { Path.of("/data1"), Path.of("/data2") }, tempDir)
);
assertThat(tree.canRead(tempDir), is(true));
assertThat(tree.canWrite(tempDir), is(true));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ public class PolicyManagerTests extends ESTestCase {
private static Module NO_ENTITLEMENTS_MODULE;

private static final PathLookup TEST_PATH_LOOKUP = new PathLookup(
Path.of("/user/home"),
Path.of("/config"),
new Path[] { Path.of("/data1/"), Path.of("/data2") },
Path.of("/temp")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,13 +35,13 @@ public void testInvalidRelativeDirectory() {
PolicyValidationException.class,
() -> FilesEntitlement.build(List.of((Map.of("relative_path", "foo", "mode", "read", "relative_to", "bar"))))
);
assertThat(ex.getMessage(), is("invalid relative directory: bar, valid values: [config, data]"));
assertThat(ex.getMessage(), is("invalid relative directory: bar, valid values: [config, data, home]"));
}

public void testFileDataRelativeWithEmptyDirectory() {
var fileData = FilesEntitlement.FileData.ofRelativePath(Path.of(""), FilesEntitlement.BaseDir.DATA, READ_WRITE);
var dataDirs = fileData.resolvePaths(
new PathLookup(Path.of("/config"), new Path[] { Path.of("/data1/"), Path.of("/data2") }, Path.of("/temp"))
new PathLookup(Path.of("/home"), Path.of("/config"), new Path[] { Path.of("/data1/"), Path.of("/data2") }, Path.of("/temp"))
);
assertThat(dataDirs.toList(), contains(Path.of("/data1/"), Path.of("/data2")));
}
Expand Down