Skip to content

Commit 81b2169

Browse files
committed
allow read access for each plugin to its own directory
1 parent 346f914 commit 81b2169

File tree

7 files changed

+46
-9
lines changed

7 files changed

+46
-9
lines changed

libs/entitlement/src/main/java/org/elasticsearch/entitlement/bootstrap/EntitlementBootstrap.java

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ public record BootstrapArgs(
4242
Path libDir,
4343
Path modulesDir,
4444
Path pluginsDir,
45+
Map<String, Path> bundlesDirs,
4546
Path logsDir,
4647
Path tempDir,
4748
Path pidFile,
@@ -60,6 +61,7 @@ public record BootstrapArgs(
6061
requireNonNull(libDir);
6162
requireNonNull(modulesDir);
6263
requireNonNull(pluginsDir);
64+
requireNonNull(bundlesDirs);
6365
requireNonNull(logsDir);
6466
requireNonNull(tempDir);
6567
requireNonNull(suppressFailureLogClasses);
@@ -80,11 +82,12 @@ public static BootstrapArgs bootstrapArgs() {
8082
* @param pluginResolver a functor to map a Java Class to the plugin it belongs to (the plugin name).
8183
* @param settingResolver a functor to resolve a setting name pattern for one or more Elasticsearch settings.
8284
* @param dataDirs data directories for Elasticsearch
83-
* @param sharedRepoDirs shared repository directories for Elasticsearch
85+
* @param sharedRepoDirs shared repository directories for Elasticsearch
8486
* @param configDir the config directory for Elasticsearch
8587
* @param libDir the lib directory for Elasticsearch
8688
* @param modulesDir the directory where Elasticsearch modules are
8789
* @param pluginsDir the directory where plugins are installed for Elasticsearch
90+
* @param bundlesDirs a map holding the path for each plugin or module, by plugin (or module) name.
8891
* @param tempDir the temp directory for Elasticsearch
8992
* @param logsDir the log directory for Elasticsearch
9093
* @param pidFile path to a pid file for Elasticsearch, or {@code null} if one was not specified
@@ -100,6 +103,7 @@ public static void bootstrap(
100103
Path libDir,
101104
Path modulesDir,
102105
Path pluginsDir,
106+
Map<String, Path> bundlesDirs,
103107
Path logsDir,
104108
Path tempDir,
105109
Path pidFile,
@@ -119,6 +123,7 @@ public static void bootstrap(
119123
libDir,
120124
modulesDir,
121125
pluginsDir,
126+
bundlesDirs,
122127
logsDir,
123128
tempDir,
124129
pidFile,

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -281,12 +281,12 @@ private static PolicyManager createPolicyManager() {
281281
)
282282
)
283283
);
284-
var resolver = EntitlementBootstrap.bootstrapArgs().pluginResolver();
285284
return new PolicyManager(
286285
serverPolicy,
287286
agentEntitlements,
288287
pluginPolicies,
289-
resolver,
288+
EntitlementBootstrap.bootstrapArgs().pluginResolver(),
289+
EntitlementBootstrap.bootstrapArgs().bundlesDirs(),
290290
AGENTS_PACKAGE_NAME,
291291
ENTITLEMENTS_MODULE,
292292
pathLookup,

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

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99

1010
package org.elasticsearch.entitlement.runtime.policy;
1111

12+
import org.elasticsearch.core.Nullable;
1213
import org.elasticsearch.core.Strings;
1314
import org.elasticsearch.entitlement.runtime.policy.entitlements.FilesEntitlement;
1415
import org.elasticsearch.entitlement.runtime.policy.entitlements.FilesEntitlement.Mode;
@@ -91,6 +92,7 @@ private FileAccessTree(
9192
String moduleName,
9293
FilesEntitlement filesEntitlement,
9394
PathLookup pathLookup,
95+
Path componentDir,
9496
List<ExclusivePath> exclusivePaths
9597
) {
9698
List<String> updatedExclusivePaths = new ArrayList<>();
@@ -139,10 +141,13 @@ private FileAccessTree(
139141
});
140142
}
141143

142-
// everything has access to the temp dir, config dir and the jdk
144+
// everything has access to the temp dir, config dir, to their own dir (their own jar files) and the jdk
143145
addPathAndMaybeLink.accept(pathLookup.tempDir(), READ_WRITE);
144146
// TODO: this grants read access to the config dir for all modules until explicit read entitlements can be added
145147
addPathAndMaybeLink.accept(pathLookup.configDir(), Mode.READ);
148+
if (componentDir != null) {
149+
addPathAndMaybeLink.accept(componentDir, Mode.READ);
150+
}
146151

147152
// TODO: watcher uses javax.activation which looks for known mime types configuration, should this be global or explicit in watcher?
148153
Path jdk = Paths.get(System.getProperty("java.home"));
@@ -179,9 +184,10 @@ public static FileAccessTree of(
179184
String moduleName,
180185
FilesEntitlement filesEntitlement,
181186
PathLookup pathLookup,
187+
@Nullable Path componentDir,
182188
List<ExclusivePath> exclusivePaths
183189
) {
184-
return new FileAccessTree(componentName, moduleName, filesEntitlement, pathLookup, exclusivePaths);
190+
return new FileAccessTree(componentName, moduleName, filesEntitlement, pathLookup, componentDir, exclusivePaths);
185191
}
186192

187193
boolean canRead(Path path) {

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

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,7 @@ ModuleEntitlements policyEntitlements(String componentName, String moduleName, L
107107
return new ModuleEntitlements(
108108
componentName,
109109
entitlements.stream().collect(groupingBy(Entitlement::getClass)),
110-
FileAccessTree.of(componentName, moduleName, filesEntitlement, pathLookup, exclusivePaths)
110+
FileAccessTree.of(componentName, moduleName, filesEntitlement, pathLookup, bundlesDirs.get(componentName), exclusivePaths)
111111
);
112112
}
113113

@@ -139,6 +139,7 @@ private static Set<Module> findSystemModules() {
139139
).collect(Collectors.toUnmodifiableSet());
140140
}
141141

142+
private final Map<String, Path> bundlesDirs;
142143
/**
143144
* The package name containing classes from the APM agent.
144145
*/
@@ -161,6 +162,7 @@ public PolicyManager(
161162
List<Entitlement> apmAgentEntitlements,
162163
Map<String, Policy> pluginPolicies,
163164
Function<Class<?>, String> pluginResolver,
165+
Map<String, Path> bundlesDirs,
164166
String apmAgentPackageName,
165167
Module entitlementsModule,
166168
PathLookup pathLookup,
@@ -172,6 +174,7 @@ public PolicyManager(
172174
.stream()
173175
.collect(toUnmodifiableMap(Map.Entry::getKey, e -> buildScopeEntitlementsMap(e.getValue())));
174176
this.pluginResolver = pluginResolver;
177+
this.bundlesDirs = bundlesDirs;
175178
this.apmAgentPackageName = apmAgentPackageName;
176179
this.entitlementsModule = entitlementsModule;
177180
this.pathLookup = requireNonNull(pathLookup);
@@ -180,6 +183,7 @@ public PolicyManager(
180183
UNKNOWN_COMPONENT_NAME,
181184
FilesEntitlement.EMPTY,
182185
pathLookup,
186+
null,
183187
List.of()
184188
);
185189
this.mutedClasses = suppressFailureLogClasses;

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

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -291,13 +291,13 @@ public void testFollowLinks() throws IOException {
291291
}
292292

293293
public void testTempDirAccess() {
294-
var tree = FileAccessTree.of("test-component", "test-module", FilesEntitlement.EMPTY, TEST_PATH_LOOKUP, List.of());
294+
var tree = FileAccessTree.of("test-component", "test-module", FilesEntitlement.EMPTY, TEST_PATH_LOOKUP, null, List.of());
295295
assertThat(tree.canRead(TEST_PATH_LOOKUP.tempDir()), is(true));
296296
assertThat(tree.canWrite(TEST_PATH_LOOKUP.tempDir()), is(true));
297297
}
298298

299299
public void testConfigDirAccess() {
300-
var tree = FileAccessTree.of("test-component", "test-module", FilesEntitlement.EMPTY, TEST_PATH_LOOKUP, List.of());
300+
var tree = FileAccessTree.of("test-component", "test-module", FilesEntitlement.EMPTY, TEST_PATH_LOOKUP, null, List.of());
301301
assertThat(tree.canRead(TEST_PATH_LOOKUP.configDir()), is(true));
302302
assertThat(tree.canWrite(TEST_PATH_LOOKUP.configDir()), is(false));
303303
}
@@ -453,6 +453,7 @@ public void testWindowsAbsolutPathAccess() {
453453
)
454454
),
455455
TEST_PATH_LOOKUP,
456+
null,
456457
List.of()
457458
);
458459

@@ -464,7 +465,7 @@ public void testWindowsAbsolutPathAccess() {
464465
}
465466

466467
FileAccessTree accessTree(FilesEntitlement entitlement, List<ExclusivePath> exclusivePaths) {
467-
return FileAccessTree.of("test-component", "test-module", entitlement, TEST_PATH_LOOKUP, exclusivePaths);
468+
return FileAccessTree.of("test-component", "test-module", entitlement, TEST_PATH_LOOKUP, null, exclusivePaths);
468469
}
469470

470471
static FilesEntitlement entitlement(String... values) {

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

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,7 @@ public void testGetEntitlementsThrowsOnMissingPluginUnnamedModule() {
8585
List.of(),
8686
Map.of("plugin1", createPluginPolicy("plugin.module")),
8787
c -> "plugin1",
88+
Map.of("plugin1", Path.of("modules", "plugin1")),
8889
TEST_AGENTS_PACKAGE_NAME,
8990
NO_ENTITLEMENTS_MODULE,
9091
TEST_PATH_LOOKUP,
@@ -110,6 +111,7 @@ public void testGetEntitlementsThrowsOnMissingPolicyForPlugin() {
110111
List.of(),
111112
Map.of(),
112113
c -> "plugin1",
114+
Map.of("plugin1", Path.of("modules", "plugin1")),
113115
TEST_AGENTS_PACKAGE_NAME,
114116
NO_ENTITLEMENTS_MODULE,
115117
TEST_PATH_LOOKUP,
@@ -131,6 +133,7 @@ public void testGetEntitlementsFailureIsCached() {
131133
List.of(),
132134
Map.of(),
133135
c -> "plugin1",
136+
Map.of("plugin1", Path.of("modules", "plugin1")),
134137
TEST_AGENTS_PACKAGE_NAME,
135138
NO_ENTITLEMENTS_MODULE,
136139
TEST_PATH_LOOKUP,
@@ -157,6 +160,7 @@ public void testGetEntitlementsReturnsEntitlementsForPluginUnnamedModule() {
157160
List.of(),
158161
Map.ofEntries(entry("plugin2", createPluginPolicy(ALL_UNNAMED))),
159162
c -> "plugin2",
163+
Map.of("plugin2", Path.of("modules", "plugin2")),
160164
TEST_AGENTS_PACKAGE_NAME,
161165
NO_ENTITLEMENTS_MODULE,
162166
TEST_PATH_LOOKUP,
@@ -176,6 +180,7 @@ public void testGetEntitlementsThrowsOnMissingPolicyForServer() throws ClassNotF
176180
List.of(),
177181
Map.of(),
178182
c -> null,
183+
Map.of(),
179184
TEST_AGENTS_PACKAGE_NAME,
180185
NO_ENTITLEMENTS_MODULE,
181186
TEST_PATH_LOOKUP,
@@ -207,6 +212,7 @@ public void testGetEntitlementsReturnsEntitlementsForServerModule() throws Class
207212
List.of(),
208213
Map.of(),
209214
c -> null,
215+
Map.of(),
210216
TEST_AGENTS_PACKAGE_NAME,
211217
NO_ENTITLEMENTS_MODULE,
212218
TEST_PATH_LOOKUP,
@@ -234,6 +240,7 @@ public void testGetEntitlementsReturnsEntitlementsForPluginModule() throws IOExc
234240
List.of(),
235241
Map.of("mock-plugin", createPluginPolicy("org.example.plugin")),
236242
c -> "mock-plugin",
243+
Map.of("mock-plugin", Path.of("modules", "mock-plugin")),
237244
TEST_AGENTS_PACKAGE_NAME,
238245
NO_ENTITLEMENTS_MODULE,
239246
TEST_PATH_LOOKUP,
@@ -254,6 +261,7 @@ public void testGetEntitlementsResultIsCached() {
254261
List.of(),
255262
Map.ofEntries(entry("plugin2", createPluginPolicy(ALL_UNNAMED))),
256263
c -> "plugin2",
264+
Map.of("plugin2", Path.of("modules", "plugin2")),
257265
TEST_AGENTS_PACKAGE_NAME,
258266
NO_ENTITLEMENTS_MODULE,
259267
TEST_PATH_LOOKUP,
@@ -314,6 +322,7 @@ public void testAgentsEntitlements() throws IOException, ClassNotFoundException
314322
List.of(new CreateClassLoaderEntitlement()),
315323
Map.of(),
316324
c -> c.getPackageName().startsWith(TEST_AGENTS_PACKAGE_NAME) ? null : "test",
325+
Map.of(),
317326
TEST_AGENTS_PACKAGE_NAME,
318327
NO_ENTITLEMENTS_MODULE,
319328
TEST_PATH_LOOKUP,
@@ -343,6 +352,7 @@ public void testDuplicateEntitlements() {
343352
List.of(),
344353
Map.of(),
345354
c -> "test",
355+
Map.of(),
346356
TEST_AGENTS_PACKAGE_NAME,
347357
NO_ENTITLEMENTS_MODULE,
348358
TEST_PATH_LOOKUP,
@@ -361,6 +371,7 @@ public void testDuplicateEntitlements() {
361371
List.of(new CreateClassLoaderEntitlement(), new CreateClassLoaderEntitlement()),
362372
Map.of(),
363373
c -> "test",
374+
Map.of(),
364375
TEST_AGENTS_PACKAGE_NAME,
365376
NO_ENTITLEMENTS_MODULE,
366377
TEST_PATH_LOOKUP,
@@ -399,6 +410,7 @@ public void testDuplicateEntitlements() {
399410
)
400411
),
401412
c -> "plugin1",
413+
Map.of("plugin1", Path.of("modules", "plugin1")),
402414
TEST_AGENTS_PACKAGE_NAME,
403415
NO_ENTITLEMENTS_MODULE,
404416
TEST_PATH_LOOKUP,
@@ -451,6 +463,7 @@ public void testFilesEntitlementsWithExclusive() {
451463
)
452464
),
453465
c -> "",
466+
Map.of("plugin1", Path.of("modules", "plugin1"), "plugin2", Path.of("modules", "plugin2")),
454467
TEST_AGENTS_PACKAGE_NAME,
455468
NO_ENTITLEMENTS_MODULE,
456469
TEST_PATH_LOOKUP,
@@ -497,6 +510,7 @@ public void testFilesEntitlementsWithExclusive() {
497510
)
498511
),
499512
c -> "",
513+
Map.of(),
500514
TEST_AGENTS_PACKAGE_NAME,
501515
NO_ENTITLEMENTS_MODULE,
502516
TEST_PATH_LOOKUP,
@@ -523,6 +537,7 @@ public void testPluginResolverOverridesAgents() {
523537
List.of(new CreateClassLoaderEntitlement()),
524538
Map.of(),
525539
c -> "test", // Insist that the class is in a plugin
540+
Map.of(),
526541
TEST_AGENTS_PACKAGE_NAME,
527542
NO_ENTITLEMENTS_MODULE,
528543
TEST_PATH_LOOKUP,
@@ -545,6 +560,7 @@ private static PolicyManager policyManager(String agentsPackageName, Module enti
545560
List.of(),
546561
Map.of(),
547562
c -> "test",
563+
Map.of(),
548564
agentsPackageName,
549565
entitlementsModule,
550566
TEST_PATH_LOOKUP,

server/src/main/java/org/elasticsearch/bootstrap/Elasticsearch.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@
4848
import org.elasticsearch.nativeaccess.NativeAccess;
4949
import org.elasticsearch.node.Node;
5050
import org.elasticsearch.node.NodeValidationException;
51+
import org.elasticsearch.plugins.PluginBundle;
5152
import org.elasticsearch.plugins.PluginsLoader;
5253
import org.elasticsearch.rest.MethodHandlers;
5354
import org.elasticsearch.transport.RequestHandlerRegistry;
@@ -70,6 +71,7 @@
7071
import java.util.Set;
7172
import java.util.concurrent.CountDownLatch;
7273
import java.util.concurrent.TimeUnit;
74+
import java.util.stream.Collectors;
7375
import java.util.stream.Stream;
7476

7577
import static org.elasticsearch.bootstrap.BootstrapSettings.SECURITY_FILTER_BAD_DEFAULTS_SETTING;
@@ -245,6 +247,8 @@ private static void initPhase2(Bootstrap bootstrap) throws IOException {
245247
pluginsLoader = PluginsLoader.createPluginsLoader(modulesBundles, pluginsBundles, findPluginsWithNativeAccess(pluginPolicies));
246248

247249
var pluginsResolver = PluginsResolver.create(pluginsLoader);
250+
Map<String, Path> bundlesDirs = Stream.concat(modulesBundles.stream(), pluginsBundles.stream())
251+
.collect(Collectors.toUnmodifiableMap(bundle -> bundle.pluginDescriptor().getName(), PluginBundle::getDir));
248252
EntitlementBootstrap.bootstrap(
249253
pluginPolicies,
250254
pluginsResolver::resolveClassToPluginName,
@@ -255,6 +259,7 @@ private static void initPhase2(Bootstrap bootstrap) throws IOException {
255259
nodeEnv.libDir(),
256260
nodeEnv.modulesDir(),
257261
nodeEnv.pluginsDir(),
262+
bundlesDirs,
258263
nodeEnv.logsDir(),
259264
nodeEnv.tmpDir(),
260265
args.pidFile(),

0 commit comments

Comments
 (0)