diff --git a/libs/entitlement/src/main/java/org/elasticsearch/entitlement/initialization/EntitlementInitialization.java b/libs/entitlement/src/main/java/org/elasticsearch/entitlement/initialization/EntitlementInitialization.java index 6c9e12fd984fe..96bf8d3ba6ab9 100644 --- a/libs/entitlement/src/main/java/org/elasticsearch/entitlement/initialization/EntitlementInitialization.java +++ b/libs/entitlement/src/main/java/org/elasticsearch/entitlement/initialization/EntitlementInitialization.java @@ -67,6 +67,7 @@ import static org.elasticsearch.entitlement.runtime.policy.entitlements.FilesEntitlement.BaseDir.SHARED_REPO; import static org.elasticsearch.entitlement.runtime.policy.entitlements.FilesEntitlement.Mode.READ; import static org.elasticsearch.entitlement.runtime.policy.entitlements.FilesEntitlement.Mode.READ_WRITE; +import static org.elasticsearch.entitlement.runtime.policy.entitlements.FilesEntitlement.Platform.LINUX; /** * Called by the agent during {@code agentmain} to configure the entitlement system, @@ -182,22 +183,22 @@ private static PolicyManager createPolicyManager() { FileData.ofRelativePath(Path.of(""), SHARED_REPO, READ_WRITE), // OS release on Linux - FileData.ofPath(Path.of("/etc/os-release"), READ), - FileData.ofPath(Path.of("/etc/system-release"), READ), - FileData.ofPath(Path.of("/usr/lib/os-release"), READ), + FileData.ofPath(Path.of("/etc/os-release"), READ).withPlatform(LINUX), + FileData.ofPath(Path.of("/etc/system-release"), READ).withPlatform(LINUX), + FileData.ofPath(Path.of("/usr/lib/os-release"), READ).withPlatform(LINUX), // read max virtual memory areas - FileData.ofPath(Path.of("/proc/sys/vm/max_map_count"), READ), - FileData.ofPath(Path.of("/proc/meminfo"), READ), + FileData.ofPath(Path.of("/proc/sys/vm/max_map_count"), READ).withPlatform(LINUX), + FileData.ofPath(Path.of("/proc/meminfo"), READ).withPlatform(LINUX), // load averages on Linux - FileData.ofPath(Path.of("/proc/loadavg"), READ), + FileData.ofPath(Path.of("/proc/loadavg"), READ).withPlatform(LINUX), // control group stats on Linux. cgroup v2 stats are in an unpredicable // location under `/sys/fs/cgroup`, so unfortunately we have to allow // read access to the entire directory hierarchy. - FileData.ofPath(Path.of("/proc/self/cgroup"), READ), - FileData.ofPath(Path.of("/sys/fs/cgroup/"), READ), + FileData.ofPath(Path.of("/proc/self/cgroup"), READ).withPlatform(LINUX), + FileData.ofPath(Path.of("/sys/fs/cgroup/"), READ).withPlatform(LINUX), // // io stats on Linux - FileData.ofPath(Path.of("/proc/self/mountinfo"), READ), - FileData.ofPath(Path.of("/proc/diskstats"), READ) + FileData.ofPath(Path.of("/proc/self/mountinfo"), READ).withPlatform(LINUX), + FileData.ofPath(Path.of("/proc/diskstats"), READ).withPlatform(LINUX) ) ) ) diff --git a/libs/entitlement/src/main/java/org/elasticsearch/entitlement/runtime/policy/FileAccessTree.java b/libs/entitlement/src/main/java/org/elasticsearch/entitlement/runtime/policy/FileAccessTree.java index b1773e9a076f4..d0eded74556b7 100644 --- a/libs/entitlement/src/main/java/org/elasticsearch/entitlement/runtime/policy/FileAccessTree.java +++ b/libs/entitlement/src/main/java/org/elasticsearch/entitlement/runtime/policy/FileAccessTree.java @@ -31,6 +31,10 @@ private FileAccessTree(FilesEntitlement filesEntitlement, PathLookup pathLookup) List readPaths = new ArrayList<>(); List writePaths = new ArrayList<>(); for (FilesEntitlement.FileData fileData : filesEntitlement.filesData()) { + var platform = fileData.platform(); + if (platform != null && platform.isCurrent() == false) { + continue; + } var mode = fileData.mode(); var paths = fileData.resolvePaths(pathLookup); paths.forEach(path -> { diff --git a/libs/entitlement/src/main/java/org/elasticsearch/entitlement/runtime/policy/entitlements/FilesEntitlement.java b/libs/entitlement/src/main/java/org/elasticsearch/entitlement/runtime/policy/entitlements/FilesEntitlement.java index c34793c5c1ac5..609e0ed66cfa0 100644 --- a/libs/entitlement/src/main/java/org/elasticsearch/entitlement/runtime/policy/entitlements/FilesEntitlement.java +++ b/libs/entitlement/src/main/java/org/elasticsearch/entitlement/runtime/policy/entitlements/FilesEntitlement.java @@ -42,26 +42,55 @@ public enum BaseDir { HOME } + public enum Platform { + LINUX, + MACOS, + WINDOWS; + + private static final Platform current = findCurrent(); + + private static Platform findCurrent() { + String os = System.getProperty("os.name"); + if (os.startsWith("Linux")) { + return LINUX; + } else if (os.startsWith("Mac OS")) { + return MACOS; + } else if (os.startsWith("Windows")) { + return WINDOWS; + } else { + throw new AssertionError("Unsupported platform [" + os + "]"); + } + } + + public boolean isCurrent() { + return this == current; + } + } + public sealed interface FileData { Stream resolvePaths(PathLookup pathLookup); Mode mode(); + Platform platform(); + + FileData withPlatform(Platform platform); + static FileData ofPath(Path path, Mode mode) { - return new AbsolutePathFileData(path, mode); + return new AbsolutePathFileData(path, mode, null); } static FileData ofRelativePath(Path relativePath, BaseDir baseDir, Mode mode) { - return new RelativePathFileData(relativePath, baseDir, mode); + return new RelativePathFileData(relativePath, baseDir, mode, null); } static FileData ofPathSetting(String setting, Mode mode) { - return new PathSettingFileData(setting, mode); + return new PathSettingFileData(setting, mode, null); } static FileData ofRelativePathSetting(String setting, BaseDir baseDir, Mode mode) { - return new RelativePathSettingFileData(setting, baseDir, mode); + return new RelativePathSettingFileData(setting, baseDir, mode, null); } /** @@ -145,32 +174,70 @@ private static Stream relativePathsCombination(Path[] baseDirs, Stream resolvePaths(PathLookup pathLookup) { return Stream.of(path); } + + @Override + public FileData withPlatform(Platform platform) { + if (platform == platform()) { + return this; + } + return new AbsolutePathFileData(path, mode, platform); + } } - private record RelativePathFileData(Path relativePath, BaseDir baseDir, Mode mode) implements FileData, RelativeFileData { + private record RelativePathFileData(Path relativePath, BaseDir baseDir, Mode mode, Platform platform) + implements + FileData, + RelativeFileData { @Override public Stream resolveRelativePaths(PathLookup pathLookup) { return Stream.of(relativePath); } + + @Override + public FileData withPlatform(Platform platform) { + if (platform == platform()) { + return this; + } + return new RelativePathFileData(relativePath, baseDir, mode, platform); + } } - private record PathSettingFileData(String setting, Mode mode) implements FileData { + private record PathSettingFileData(String setting, Mode mode, Platform platform) implements FileData { @Override public Stream resolvePaths(PathLookup pathLookup) { return resolvePathSettings(pathLookup, setting); } + + @Override + public FileData withPlatform(Platform platform) { + if (platform == platform()) { + return this; + } + return new PathSettingFileData(setting, mode, platform); + } } - private record RelativePathSettingFileData(String setting, BaseDir baseDir, Mode mode) implements FileData, RelativeFileData { + private record RelativePathSettingFileData(String setting, BaseDir baseDir, Mode mode, Platform platform) + implements + FileData, + RelativeFileData { @Override public Stream resolveRelativePaths(PathLookup pathLookup) { return resolvePathSettings(pathLookup, setting); } + + @Override + public FileData withPlatform(Platform platform) { + if (platform == platform()) { + return this; + } + return new RelativePathSettingFileData(setting, baseDir, mode, platform); + } } private static Stream resolvePathSettings(PathLookup pathLookup, String setting) { @@ -191,6 +258,18 @@ private static Mode parseMode(String mode) { } } + private static Platform parsePlatform(String platform) { + if (platform.equals("linux")) { + return Platform.LINUX; + } else if (platform.equals("macos")) { + return Platform.MACOS; + } else if (platform.equals("windows")) { + return Platform.WINDOWS; + } else { + throw new PolicyValidationException("invalid platform: " + platform + ", valid values: [linux, macos, windows]"); + } + } + private static BaseDir parseBaseDir(String baseDir) { return switch (baseDir) { case "config" -> BaseDir.CONFIG; @@ -218,6 +297,7 @@ public static FilesEntitlement build(List paths) { String pathSetting = file.remove("path_setting"); String relativePathSetting = file.remove("relative_path_setting"); String modeAsString = file.remove("mode"); + String platformAsString = file.remove("platform"); if (file.isEmpty() == false) { throw new PolicyValidationException("unknown key(s) [" + file + "] in a listed file for files entitlement"); @@ -234,36 +314,45 @@ public static FilesEntitlement build(List paths) { throw new PolicyValidationException("files entitlement must contain 'mode' for every listed file"); } Mode mode = parseMode(modeAsString); + Platform platform = null; + if (platformAsString != null) { + platform = parsePlatform(platformAsString); + } BaseDir baseDir = null; if (relativeTo != null) { baseDir = parseBaseDir(relativeTo); } + final FileData fileData; if (relativePathAsString != null) { if (baseDir == null) { throw new PolicyValidationException("files entitlement with a 'relative_path' must specify 'relative_to'"); } + Path relativePath = Path.of(relativePathAsString); if (FileData.isAbsolutePath(relativePathAsString)) { throw new PolicyValidationException("'relative_path' [" + relativePathAsString + "] must be relative"); } - filesData.add(FileData.ofRelativePath(Path.of(relativePathAsString), baseDir, mode)); + fileData = FileData.ofRelativePath(relativePath, baseDir, mode); } else if (pathAsString != null) { + Path path = Path.of(pathAsString); if (FileData.isAbsolutePath(pathAsString) == false) { throw new PolicyValidationException("'path' [" + pathAsString + "] must be absolute"); } - filesData.add(FileData.ofPath(Path.of(pathAsString), mode)); + fileData = FileData.ofPath(path, mode); } else if (pathSetting != null) { - filesData.add(FileData.ofPathSetting(pathSetting, mode)); + fileData = FileData.ofPathSetting(pathSetting, mode); } else if (relativePathSetting != null) { if (baseDir == null) { throw new PolicyValidationException("files entitlement with a 'relative_path_setting' must specify 'relative_to'"); } - filesData.add(FileData.ofRelativePathSetting(relativePathSetting, baseDir, mode)); + fileData = FileData.ofRelativePathSetting(relativePathSetting, baseDir, mode); } else { throw new AssertionError("File entry validation error"); } + + filesData.add(fileData.withPlatform(platform)); } return new FilesEntitlement(filesData); } diff --git a/x-pack/plugin/ml/src/main/plugin-metadata/entitlement-policy.yaml b/x-pack/plugin/ml/src/main/plugin-metadata/entitlement-policy.yaml index 664b7d83315de..5fa5ca8813919 100644 --- a/x-pack/plugin/ml/src/main/plugin-metadata/entitlement-policy.yaml +++ b/x-pack/plugin/ml/src/main/plugin-metadata/entitlement-policy.yaml @@ -7,3 +7,6 @@ org.elasticsearch.ml: - relative_path: "ml-local-data/" relative_to: data mode: read_write + - path: \\.\pipe\ + mode: read_write + platform: windows