Skip to content

Commit 1e23a29

Browse files
committed
Add platform property to files entitlement
Some file paths are OS specific. This commit adds a `platform` property to each file in a files entitlement that can be used to limit that file to a specific platform.
1 parent 8b25a72 commit 1e23a29

File tree

6 files changed

+125
-24
lines changed

6 files changed

+125
-24
lines changed

libs/entitlement/src/main/java/org/elasticsearch/entitlement/initialization/EntitlementInitialization.java

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@
6565

6666
import static org.elasticsearch.entitlement.runtime.policy.entitlements.FilesEntitlement.Mode.READ;
6767
import static org.elasticsearch.entitlement.runtime.policy.entitlements.FilesEntitlement.Mode.READ_WRITE;
68+
import static org.elasticsearch.entitlement.runtime.policy.entitlements.FilesEntitlement.Platform.LINUX;
6869

6970
/**
7071
* Called by the agent during {@code agentmain} to configure the entitlement system,
@@ -179,22 +180,22 @@ private static PolicyManager createPolicyManager() {
179180
FileData.ofPath(bootstrapArgs.repoDirResolver().apply(""), READ_WRITE),
180181

181182
// OS release on Linux
182-
FileData.ofPath(Path.of("/etc/os-release"), READ),
183-
FileData.ofPath(Path.of("/etc/system-release"), READ),
184-
FileData.ofPath(Path.of("/usr/lib/os-release"), READ),
183+
FileData.ofPath(Path.of("/etc/os-release"), READ).withPlatform(LINUX),
184+
FileData.ofPath(Path.of("/etc/system-release"), READ).withPlatform(LINUX),
185+
FileData.ofPath(Path.of("/usr/lib/os-release"), READ).withPlatform(LINUX),
185186
// read max virtual memory areas
186-
FileData.ofPath(Path.of("/proc/sys/vm/max_map_count"), READ),
187-
FileData.ofPath(Path.of("/proc/meminfo"), READ),
187+
FileData.ofPath(Path.of("/proc/sys/vm/max_map_count"), READ).withPlatform(LINUX),
188+
FileData.ofPath(Path.of("/proc/meminfo"), READ).withPlatform(LINUX),
188189
// load averages on Linux
189-
FileData.ofPath(Path.of("/proc/loadavg"), READ),
190+
FileData.ofPath(Path.of("/proc/loadavg"), READ).withPlatform(LINUX),
190191
// control group stats on Linux. cgroup v2 stats are in an unpredicable
191192
// location under `/sys/fs/cgroup`, so unfortunately we have to allow
192193
// read access to the entire directory hierarchy.
193-
FileData.ofPath(Path.of("/proc/self/cgroup"), READ),
194-
FileData.ofPath(Path.of("/sys/fs/cgroup/"), READ),
194+
FileData.ofPath(Path.of("/proc/self/cgroup"), READ).withPlatform(LINUX),
195+
FileData.ofPath(Path.of("/sys/fs/cgroup/"), READ).withPlatform(LINUX),
195196
// // io stats on Linux
196-
FileData.ofPath(Path.of("/proc/self/mountinfo"), READ),
197-
FileData.ofPath(Path.of("/proc/diskstats"), READ)
197+
FileData.ofPath(Path.of("/proc/self/mountinfo"), READ).withPlatform(LINUX),
198+
FileData.ofPath(Path.of("/proc/diskstats"), READ).withPlatform(LINUX)
198199
)
199200
)
200201
)

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

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,10 @@ private FileAccessTree(FilesEntitlement filesEntitlement, PathLookup pathLookup)
3030
List<String> readPaths = new ArrayList<>();
3131
List<String> writePaths = new ArrayList<>();
3232
for (FilesEntitlement.FileData fileData : filesEntitlement.filesData()) {
33+
var platform = fileData.platform();
34+
if (platform != null && platform.isCurrent() == false) {
35+
continue;
36+
}
3337
var mode = fileData.mode();
3438
var paths = fileData.resolvePaths(pathLookup);
3539
paths.forEach(path -> {

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

Lines changed: 101 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -39,26 +39,55 @@ public enum BaseDir {
3939
HOME
4040
}
4141

42+
public enum Platform {
43+
LINUX,
44+
MACOS,
45+
WINDOWS;
46+
47+
private static final Platform current = findCurrent();
48+
49+
private static Platform findCurrent() {
50+
String os = System.getProperty("os.name");
51+
if (os.startsWith("Linux")) {
52+
return LINUX;
53+
} else if (os.startsWith("Mac OS")) {
54+
return MACOS;
55+
} else if (os.startsWith("Windows")) {
56+
return WINDOWS;
57+
} else {
58+
throw new AssertionError("Unsupported platform [" + os + "]");
59+
}
60+
}
61+
62+
public boolean isCurrent() {
63+
return this == current;
64+
}
65+
}
66+
4267
public sealed interface FileData {
4368

4469
Stream<Path> resolvePaths(PathLookup pathLookup);
4570

4671
Mode mode();
4772

73+
Platform platform();
74+
75+
FileData withPlatform(Platform platform);
76+
4877
static FileData ofPath(Path path, Mode mode) {
49-
return new AbsolutePathFileData(path, mode);
78+
return new AbsolutePathFileData(path, mode, null);
5079
}
5180

5281
static FileData ofRelativePath(Path relativePath, BaseDir baseDir, Mode mode) {
53-
return new RelativePathFileData(relativePath, baseDir, mode);
82+
return new RelativePathFileData(relativePath, baseDir, mode, null);
5483
}
5584

5685
static FileData ofPathSetting(String setting, Mode mode) {
57-
return new PathSettingFileData(setting, mode);
86+
return new PathSettingFileData(setting, mode, null);
5887
}
5988

6089
static FileData ofRelativePathSetting(String setting, BaseDir baseDir, Mode mode) {
61-
return new RelativePathSettingFileData(setting, baseDir, mode);
90+
return new RelativePathSettingFileData(setting, baseDir, mode, null);
6291
}
6392
}
6493

@@ -91,32 +120,70 @@ default Stream<Path> resolvePaths(PathLookup pathLookup) {
91120
}
92121
}
93122

94-
private record AbsolutePathFileData(Path path, Mode mode) implements FileData {
123+
private record AbsolutePathFileData(Path path, Mode mode, Platform platform) implements FileData {
95124
@Override
96125
public Stream<Path> resolvePaths(PathLookup pathLookup) {
97126
return Stream.of(path);
98127
}
128+
129+
@Override
130+
public FileData withPlatform(Platform platform) {
131+
if (platform == platform()) {
132+
return this;
133+
}
134+
return new AbsolutePathFileData(path, mode, platform);
135+
}
99136
}
100137

101-
private record RelativePathFileData(Path relativePath, BaseDir baseDir, Mode mode) implements FileData, RelativeFileData {
138+
private record RelativePathFileData(Path relativePath, BaseDir baseDir, Mode mode, Platform platform)
139+
implements
140+
FileData,
141+
RelativeFileData {
102142
@Override
103143
public Stream<Path> resolveRelativePaths(PathLookup pathLookup) {
104144
return Stream.of(relativePath);
105145
}
146+
147+
@Override
148+
public FileData withPlatform(Platform platform) {
149+
if (platform == platform()) {
150+
return this;
151+
}
152+
return new RelativePathFileData(relativePath, baseDir, mode, platform);
153+
}
106154
}
107155

108-
private record PathSettingFileData(String setting, Mode mode) implements FileData {
156+
private record PathSettingFileData(String setting, Mode mode, Platform platform) implements FileData {
109157
@Override
110158
public Stream<Path> resolvePaths(PathLookup pathLookup) {
111159
return resolvePathSettings(pathLookup, setting);
112160
}
161+
162+
@Override
163+
public FileData withPlatform(Platform platform) {
164+
if (platform == platform()) {
165+
return this;
166+
}
167+
return new PathSettingFileData(setting, mode, platform);
168+
}
113169
}
114170

115-
private record RelativePathSettingFileData(String setting, BaseDir baseDir, Mode mode) implements FileData, RelativeFileData {
171+
private record RelativePathSettingFileData(String setting, BaseDir baseDir, Mode mode, Platform platform)
172+
implements
173+
FileData,
174+
RelativeFileData {
116175
@Override
117176
public Stream<Path> resolveRelativePaths(PathLookup pathLookup) {
118177
return resolvePathSettings(pathLookup, setting);
119178
}
179+
180+
@Override
181+
public FileData withPlatform(Platform platform) {
182+
if (platform == platform()) {
183+
return this;
184+
}
185+
return new RelativePathSettingFileData(setting, baseDir, mode, platform);
186+
}
120187
}
121188

122189
private static Stream<Path> resolvePathSettings(PathLookup pathLookup, String setting) {
@@ -137,6 +204,18 @@ private static Mode parseMode(String mode) {
137204
}
138205
}
139206

207+
private static Platform parsePlatform(String platform) {
208+
if (platform.equals("linux")) {
209+
return Platform.LINUX;
210+
} else if (platform.equals("macos")) {
211+
return Platform.MACOS;
212+
} else if (platform.equals("windows")) {
213+
return Platform.WINDOWS;
214+
} else {
215+
throw new PolicyValidationException("invalid platform: " + platform + ", valid values: [linux, macos, windows]");
216+
}
217+
}
218+
140219
private static BaseDir parseBaseDir(String baseDir) {
141220
return switch (baseDir) {
142221
case "config" -> BaseDir.CONFIG;
@@ -163,6 +242,7 @@ public static FilesEntitlement build(List<Object> paths) {
163242
String pathSetting = file.remove("path_setting");
164243
String relativePathSetting = file.remove("relative_path_setting");
165244
String modeAsString = file.remove("mode");
245+
String platformAsString = file.remove("mode");
166246

167247
if (file.isEmpty() == false) {
168248
throw new PolicyValidationException("unknown key(s) [" + file + "] in a listed file for files entitlement");
@@ -179,38 +259,45 @@ public static FilesEntitlement build(List<Object> paths) {
179259
throw new PolicyValidationException("files entitlement must contain 'mode' for every listed file");
180260
}
181261
Mode mode = parseMode(modeAsString);
262+
Platform platform = null;
263+
if (platformAsString != null) {
264+
platform = parsePlatform(platformAsString);
265+
}
182266

183267
BaseDir baseDir = null;
184268
if (relativeTo != null) {
185269
baseDir = parseBaseDir(relativeTo);
186270
}
187271

272+
final FileData fileData;
188273
if (relativePathAsString != null) {
189274
if (baseDir == null) {
190275
throw new PolicyValidationException("files entitlement with a 'relative_path' must specify 'relative_to'");
191276
}
192277

193278
Path relativePath = Path.of(relativePathAsString);
194-
if (relativePath.isAbsolute()) {
279+
if (platform == null || platform.isCurrent() && relativePath.isAbsolute()) {
195280
throw new PolicyValidationException("'relative_path' [" + relativePathAsString + "] must be relative");
196281
}
197-
filesData.add(FileData.ofRelativePath(relativePath, baseDir, mode));
282+
fileData = FileData.ofRelativePath(relativePath, baseDir, mode);
198283
} else if (pathAsString != null) {
199284
Path path = Path.of(pathAsString);
200-
if (path.isAbsolute() == false) {
285+
if (platform == null || platform.isCurrent() && path.isAbsolute() == false) {
201286
throw new PolicyValidationException("'path' [" + pathAsString + "] must be absolute");
202287
}
203-
filesData.add(FileData.ofPath(path, mode));
288+
fileData = FileData.ofPath(path, mode);
204289
} else if (pathSetting != null) {
205-
filesData.add(FileData.ofPathSetting(pathSetting, mode));
290+
fileData = FileData.ofPathSetting(pathSetting, mode);
206291
} else if (relativePathSetting != null) {
207292
if (baseDir == null) {
208293
throw new PolicyValidationException("files entitlement with a 'relative_path_setting' must specify 'relative_to'");
209294
}
210-
filesData.add(FileData.ofRelativePathSetting(relativePathSetting, baseDir, mode));
295+
fileData = FileData.ofRelativePathSetting(relativePathSetting, baseDir, mode);
211296
} else {
212297
throw new AssertionError("File entry validation error");
213298
}
299+
300+
filesData.add(fileData.withPlatform(platform));
214301
}
215302
return new FilesEntitlement(filesData);
216303
}

modules/repository-azure/src/main/plugin-metadata/entitlement-policy.yaml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,13 @@ io.netty.common:
44
- files:
55
- path: "/etc/os-release"
66
mode: "read"
7+
platform: linux
78
- path: "/usr/lib/os-release"
89
mode: "read"
10+
platform: linux
911
- path: "/proc/sys/net/core/somaxconn"
1012
mode: read
13+
platform: linux
1114
com.azure.identity:
1215
- files:
1316
- relative_path: "storage-azure/" #/config/storage-azure/azure-federated-token

modules/transport-netty4/src/main/plugin-metadata/entitlement-policy.yaml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,10 @@ io.netty.common:
99
- files:
1010
- path: "/etc/os-release"
1111
mode: "read"
12+
platform: linux
1213
- path: "/usr/lib/os-release"
1314
mode: "read"
15+
platform: linux
1416
- path: "/proc/sys/net/core/somaxconn"
1517
mode: read
18+
platform: linux

x-pack/plugin/security/src/main/plugin-metadata/entitlement-policy.yaml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,13 @@ io.netty.common:
1515
- files:
1616
- path: "/etc/os-release"
1717
mode: "read"
18+
platform: linux
1819
- path: "/usr/lib/os-release"
1920
mode: "read"
21+
platform: linux
2022
- path: "/proc/sys/net/core/somaxconn"
2123
mode: read
24+
platform: linux
2225
org.opensaml.xmlsec.impl:
2326
- write_system_properties:
2427
properties:

0 commit comments

Comments
 (0)