diff --git a/libs/entitlement/src/main/java/org/elasticsearch/entitlement/bootstrap/EntitlementBootstrap.java b/libs/entitlement/src/main/java/org/elasticsearch/entitlement/bootstrap/EntitlementBootstrap.java index e82ec923618f0..6e12d3cc8c30b 100644 --- a/libs/entitlement/src/main/java/org/elasticsearch/entitlement/bootstrap/EntitlementBootstrap.java +++ b/libs/entitlement/src/main/java/org/elasticsearch/entitlement/bootstrap/EntitlementBootstrap.java @@ -41,6 +41,7 @@ public record BootstrapArgs( Path configDir, Path libDir, Path pluginsDir, + Map sourcePaths, Path logsDir, Path tempDir, Path pidFile, @@ -58,6 +59,7 @@ public record BootstrapArgs( requireNonNull(configDir); requireNonNull(libDir); requireNonNull(pluginsDir); + requireNonNull(sourcePaths); requireNonNull(logsDir); requireNonNull(tempDir); requireNonNull(suppressFailureLogClasses); @@ -78,10 +80,11 @@ public static BootstrapArgs bootstrapArgs() { * @param pluginResolver a functor to map a Java Class to the plugin it belongs to (the plugin name). * @param settingResolver a functor to resolve a setting name pattern for one or more Elasticsearch settings. * @param dataDirs data directories for Elasticsearch - * @param sharedRepoDirs shared repository directories for Elasticsearch + * @param sharedRepoDirs shared repository directories for Elasticsearch * @param configDir the config directory for Elasticsearch * @param libDir the lib directory for Elasticsearch * @param pluginsDir the directory where plugins are installed for Elasticsearch + * @param sourcePaths a map holding the path to each plugin or module jars, by plugin (or module) name. * @param tempDir the temp directory for Elasticsearch * @param logsDir the log directory for Elasticsearch * @param pidFile path to a pid file for Elasticsearch, or {@code null} if one was not specified @@ -96,6 +99,7 @@ public static void bootstrap( Path configDir, Path libDir, Path pluginsDir, + Map sourcePaths, Path logsDir, Path tempDir, Path pidFile, @@ -114,6 +118,7 @@ public static void bootstrap( configDir, libDir, pluginsDir, + sourcePaths, logsDir, tempDir, pidFile, 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 6dc3f99c7b381..8463681c53fe9 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 @@ -279,12 +279,12 @@ private static PolicyManager createPolicyManager() { ) ) ); - var resolver = EntitlementBootstrap.bootstrapArgs().pluginResolver(); return new PolicyManager( serverPolicy, agentEntitlements, pluginPolicies, - resolver, + EntitlementBootstrap.bootstrapArgs().pluginResolver(), + EntitlementBootstrap.bootstrapArgs().sourcePaths(), AGENTS_PACKAGE_NAME, ENTITLEMENTS_MODULE, pathLookup, 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 fd2590c114d0d..b951a4d7b42f4 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 @@ -9,6 +9,7 @@ package org.elasticsearch.entitlement.runtime.policy; +import org.elasticsearch.core.Nullable; import org.elasticsearch.core.Strings; import org.elasticsearch.entitlement.runtime.policy.entitlements.FilesEntitlement; import org.elasticsearch.entitlement.runtime.policy.entitlements.FilesEntitlement.Mode; @@ -91,6 +92,7 @@ private FileAccessTree( String moduleName, FilesEntitlement filesEntitlement, PathLookup pathLookup, + Path componentPath, List exclusivePaths ) { List updatedExclusivePaths = new ArrayList<>(); @@ -139,10 +141,13 @@ private FileAccessTree( }); } - // everything has access to the temp dir, config dir and the jdk + // everything has access to the temp dir, config dir, to their own dir (their own jar files) and the jdk addPathAndMaybeLink.accept(pathLookup.tempDir(), READ_WRITE); // TODO: this grants read access to the config dir for all modules until explicit read entitlements can be added addPathAndMaybeLink.accept(pathLookup.configDir(), Mode.READ); + if (componentPath != null) { + addPathAndMaybeLink.accept(componentPath, Mode.READ); + } // TODO: watcher uses javax.activation which looks for known mime types configuration, should this be global or explicit in watcher? Path jdk = Paths.get(System.getProperty("java.home")); @@ -179,9 +184,10 @@ public static FileAccessTree of( String moduleName, FilesEntitlement filesEntitlement, PathLookup pathLookup, + @Nullable Path componentPath, List exclusivePaths ) { - return new FileAccessTree(componentName, moduleName, filesEntitlement, pathLookup, exclusivePaths); + return new FileAccessTree(componentName, moduleName, filesEntitlement, pathLookup, componentPath, exclusivePaths); } boolean canRead(Path path) { diff --git a/libs/entitlement/src/main/java/org/elasticsearch/entitlement/runtime/policy/PolicyManager.java b/libs/entitlement/src/main/java/org/elasticsearch/entitlement/runtime/policy/PolicyManager.java index 63492b265ca6d..12d9bb4af566a 100644 --- a/libs/entitlement/src/main/java/org/elasticsearch/entitlement/runtime/policy/PolicyManager.java +++ b/libs/entitlement/src/main/java/org/elasticsearch/entitlement/runtime/policy/PolicyManager.java @@ -35,6 +35,7 @@ import java.lang.module.ModuleFinder; import java.lang.module.ModuleReference; import java.nio.file.Path; +import java.nio.file.Paths; import java.util.ArrayList; import java.util.HashSet; import java.util.List; @@ -91,13 +92,17 @@ public Stream getEntitlements(Class entitlementCla } } + private FileAccessTree getDefaultFileAccess(String componentName, Path componentPath) { + return FileAccessTree.of(componentName, UNKNOWN_COMPONENT_NAME, FilesEntitlement.EMPTY, pathLookup, componentPath, List.of()); + } + // pkg private for testing - ModuleEntitlements defaultEntitlements(String componentName) { - return new ModuleEntitlements(componentName, Map.of(), defaultFileAccess); + ModuleEntitlements defaultEntitlements(String componentName, Path componentPath) { + return new ModuleEntitlements(componentName, Map.of(), getDefaultFileAccess(componentName, componentPath)); } // pkg private for testing - ModuleEntitlements policyEntitlements(String componentName, String moduleName, List entitlements) { + ModuleEntitlements policyEntitlements(String componentName, Path componentPath, String moduleName, List entitlements) { FilesEntitlement filesEntitlement = FilesEntitlement.EMPTY; for (Entitlement entitlement : entitlements) { if (entitlement instanceof FilesEntitlement) { @@ -107,7 +112,7 @@ ModuleEntitlements policyEntitlements(String componentName, String moduleName, L return new ModuleEntitlements( componentName, entitlements.stream().collect(groupingBy(Entitlement::getClass)), - FileAccessTree.of(componentName, moduleName, filesEntitlement, pathLookup, exclusivePaths) + FileAccessTree.of(componentName, moduleName, filesEntitlement, pathLookup, componentPath, exclusivePaths) ); } @@ -118,7 +123,6 @@ ModuleEntitlements policyEntitlements(String componentName, String moduleName, L private final Map>> pluginsEntitlements; private final Function, String> pluginResolver; private final PathLookup pathLookup; - private final FileAccessTree defaultFileAccess; private final Set> mutedClasses; public static final String ALL_UNNAMED = "ALL-UNNAMED"; @@ -139,6 +143,7 @@ private static Set findSystemModules() { ).collect(Collectors.toUnmodifiableSet()); } + private final Map sourcePaths; /** * The package name containing classes from the APM agent. */ @@ -161,6 +166,7 @@ public PolicyManager( List apmAgentEntitlements, Map pluginPolicies, Function, String> pluginResolver, + Map sourcePaths, String apmAgentPackageName, Module entitlementsModule, PathLookup pathLookup, @@ -172,16 +178,10 @@ public PolicyManager( .stream() .collect(toUnmodifiableMap(Map.Entry::getKey, e -> buildScopeEntitlementsMap(e.getValue()))); this.pluginResolver = pluginResolver; + this.sourcePaths = sourcePaths; this.apmAgentPackageName = apmAgentPackageName; this.entitlementsModule = entitlementsModule; this.pathLookup = requireNonNull(pathLookup); - this.defaultFileAccess = FileAccessTree.of( - UNKNOWN_COMPONENT_NAME, - UNKNOWN_COMPONENT_NAME, - FilesEntitlement.EMPTY, - pathLookup, - List.of() - ); this.mutedClasses = suppressFailureLogClasses; List exclusiveFileEntitlements = new ArrayList<>(); @@ -529,7 +529,12 @@ ModuleEntitlements getEntitlements(Class requestingClass) { private ModuleEntitlements computeEntitlements(Class requestingClass) { Module requestingModule = requestingClass.getModule(); if (isServerModule(requestingModule)) { - return getModuleScopeEntitlements(serverEntitlements, requestingModule.getName(), SERVER_COMPONENT_NAME); + return getModuleScopeEntitlements( + serverEntitlements, + requestingModule.getName(), + SERVER_COMPONENT_NAME, + getComponentPathFromClass(requestingClass) + ); } // plugins @@ -537,36 +542,68 @@ private ModuleEntitlements computeEntitlements(Class requestingClass) { if (pluginName != null) { var pluginEntitlements = pluginsEntitlements.get(pluginName); if (pluginEntitlements == null) { - return defaultEntitlements(pluginName); + return defaultEntitlements(pluginName, sourcePaths.get(pluginName)); } else { - final String scopeName; - if (requestingModule.isNamed() == false) { - scopeName = ALL_UNNAMED; - } else { - scopeName = requestingModule.getName(); - } - return getModuleScopeEntitlements(pluginEntitlements, scopeName, pluginName); + return getModuleScopeEntitlements( + pluginEntitlements, + getScopeName(requestingModule), + pluginName, + sourcePaths.get(pluginName) + ); } } if (requestingModule.isNamed() == false && requestingClass.getPackageName().startsWith(apmAgentPackageName)) { // The APM agent is the only thing running non-modular in the system classloader - return policyEntitlements(APM_AGENT_COMPONENT_NAME, ALL_UNNAMED, apmAgentEntitlements); + return policyEntitlements( + APM_AGENT_COMPONENT_NAME, + getComponentPathFromClass(requestingClass), + ALL_UNNAMED, + apmAgentEntitlements + ); + } + + return defaultEntitlements(UNKNOWN_COMPONENT_NAME, null); + } + + private static String getScopeName(Module requestingModule) { + if (requestingModule.isNamed() == false) { + return ALL_UNNAMED; + } else { + return requestingModule.getName(); } + } - return defaultEntitlements(UNKNOWN_COMPONENT_NAME); + // pkg private for testing + static Path getComponentPathFromClass(Class requestingClass) { + var codeSource = requestingClass.getProtectionDomain().getCodeSource(); + if (codeSource == null) { + return null; + } + try { + return Paths.get(codeSource.getLocation().toURI()); + } catch (Exception e) { + // If we get a URISyntaxException, or any other Exception due to an invalid URI, we return null to safely skip this location + logger.info( + "Cannot get component path for [{}]: [{}] cannot be converted to a valid Path", + requestingClass.getName(), + codeSource.getLocation().toString() + ); + return null; + } } private ModuleEntitlements getModuleScopeEntitlements( Map> scopeEntitlements, - String moduleName, - String componentName + String scopeName, + String componentName, + Path componentPath ) { - var entitlements = scopeEntitlements.get(moduleName); + var entitlements = scopeEntitlements.get(scopeName); if (entitlements == null) { - return defaultEntitlements(componentName); + return defaultEntitlements(componentName, componentPath); } - return policyEntitlements(componentName, moduleName, entitlements); + return policyEntitlements(componentName, componentPath, scopeName, entitlements); } private static boolean isServerModule(Module requestingModule) { diff --git a/libs/entitlement/src/test/java/org/elasticsearch/entitlement/runtime/policy/FileAccessTreeTests.java b/libs/entitlement/src/test/java/org/elasticsearch/entitlement/runtime/policy/FileAccessTreeTests.java index ac9430246324f..938a946a95c61 100644 --- a/libs/entitlement/src/test/java/org/elasticsearch/entitlement/runtime/policy/FileAccessTreeTests.java +++ b/libs/entitlement/src/test/java/org/elasticsearch/entitlement/runtime/policy/FileAccessTreeTests.java @@ -291,13 +291,13 @@ public void testFollowLinks() throws IOException { } public void testTempDirAccess() { - var tree = FileAccessTree.of("test-component", "test-module", FilesEntitlement.EMPTY, TEST_PATH_LOOKUP, List.of()); + var tree = FileAccessTree.of("test-component", "test-module", FilesEntitlement.EMPTY, TEST_PATH_LOOKUP, null, List.of()); assertThat(tree.canRead(TEST_PATH_LOOKUP.tempDir()), is(true)); assertThat(tree.canWrite(TEST_PATH_LOOKUP.tempDir()), is(true)); } public void testConfigDirAccess() { - var tree = FileAccessTree.of("test-component", "test-module", FilesEntitlement.EMPTY, TEST_PATH_LOOKUP, List.of()); + var tree = FileAccessTree.of("test-component", "test-module", FilesEntitlement.EMPTY, TEST_PATH_LOOKUP, null, List.of()); assertThat(tree.canRead(TEST_PATH_LOOKUP.configDir()), is(true)); assertThat(tree.canWrite(TEST_PATH_LOOKUP.configDir()), is(false)); } @@ -453,6 +453,7 @@ public void testWindowsAbsolutPathAccess() { ) ), TEST_PATH_LOOKUP, + null, List.of() ); @@ -464,7 +465,7 @@ public void testWindowsAbsolutPathAccess() { } FileAccessTree accessTree(FilesEntitlement entitlement, List exclusivePaths) { - return FileAccessTree.of("test-component", "test-module", entitlement, TEST_PATH_LOOKUP, exclusivePaths); + return FileAccessTree.of("test-component", "test-module", entitlement, TEST_PATH_LOOKUP, null, exclusivePaths); } static FilesEntitlement entitlement(String... values) { diff --git a/libs/entitlement/src/test/java/org/elasticsearch/entitlement/runtime/policy/PolicyManagerTests.java b/libs/entitlement/src/test/java/org/elasticsearch/entitlement/runtime/policy/PolicyManagerTests.java index af3eb324f2dc7..a0868563b87e1 100644 --- a/libs/entitlement/src/test/java/org/elasticsearch/entitlement/runtime/policy/PolicyManagerTests.java +++ b/libs/entitlement/src/test/java/org/elasticsearch/entitlement/runtime/policy/PolicyManagerTests.java @@ -80,11 +80,13 @@ public static void beforeClass() { } public void testGetEntitlementsThrowsOnMissingPluginUnnamedModule() { + var plugin1SourcePath = Path.of("modules", "plugin1"); var policyManager = new PolicyManager( createEmptyTestServerPolicy(), List.of(), Map.of("plugin1", createPluginPolicy("plugin.module")), c -> "plugin1", + Map.of("plugin1", plugin1SourcePath), TEST_AGENTS_PACKAGE_NAME, NO_ENTITLEMENTS_MODULE, TEST_PATH_LOOKUP, @@ -97,19 +99,24 @@ public void testGetEntitlementsThrowsOnMissingPluginUnnamedModule() { assertEquals( "No policy for the unnamed module", - policyManager.defaultEntitlements("plugin1"), + policyManager.defaultEntitlements("plugin1", plugin1SourcePath), policyManager.getEntitlements(callerClass) ); - assertEquals(Map.of(requestingModule, policyManager.defaultEntitlements("plugin1")), policyManager.moduleEntitlementsMap); + assertEquals( + Map.of(requestingModule, policyManager.defaultEntitlements("plugin1", plugin1SourcePath)), + policyManager.moduleEntitlementsMap + ); } public void testGetEntitlementsThrowsOnMissingPolicyForPlugin() { + var plugin1SourcePath = Path.of("modules", "plugin1"); var policyManager = new PolicyManager( createEmptyTestServerPolicy(), List.of(), Map.of(), c -> "plugin1", + Map.of("plugin1", plugin1SourcePath), TEST_AGENTS_PACKAGE_NAME, NO_ENTITLEMENTS_MODULE, TEST_PATH_LOOKUP, @@ -120,17 +127,26 @@ public void testGetEntitlementsThrowsOnMissingPolicyForPlugin() { var callerClass = this.getClass(); var requestingModule = callerClass.getModule(); - assertEquals("No policy for this plugin", policyManager.defaultEntitlements("plugin1"), policyManager.getEntitlements(callerClass)); + assertEquals( + "No policy for this plugin", + policyManager.defaultEntitlements("plugin1", plugin1SourcePath), + policyManager.getEntitlements(callerClass) + ); - assertEquals(Map.of(requestingModule, policyManager.defaultEntitlements("plugin1")), policyManager.moduleEntitlementsMap); + assertEquals( + Map.of(requestingModule, policyManager.defaultEntitlements("plugin1", plugin1SourcePath)), + policyManager.moduleEntitlementsMap + ); } public void testGetEntitlementsFailureIsCached() { + var plugin1SourcePath = Path.of("modules", "plugin1"); var policyManager = new PolicyManager( createEmptyTestServerPolicy(), List.of(), Map.of(), c -> "plugin1", + Map.of("plugin1", plugin1SourcePath), TEST_AGENTS_PACKAGE_NAME, NO_ENTITLEMENTS_MODULE, TEST_PATH_LOOKUP, @@ -141,14 +157,20 @@ public void testGetEntitlementsFailureIsCached() { var callerClass = this.getClass(); var requestingModule = callerClass.getModule(); - assertEquals(policyManager.defaultEntitlements("plugin1"), policyManager.getEntitlements(callerClass)); - assertEquals(Map.of(requestingModule, policyManager.defaultEntitlements("plugin1")), policyManager.moduleEntitlementsMap); + assertEquals(policyManager.defaultEntitlements("plugin1", plugin1SourcePath), policyManager.getEntitlements(callerClass)); + assertEquals( + Map.of(requestingModule, policyManager.defaultEntitlements("plugin1", plugin1SourcePath)), + policyManager.moduleEntitlementsMap + ); // A second time - assertEquals(policyManager.defaultEntitlements("plugin1"), policyManager.getEntitlements(callerClass)); + assertEquals(policyManager.defaultEntitlements("plugin1", plugin1SourcePath), policyManager.getEntitlements(callerClass)); // Nothing new in the map - assertEquals(Map.of(requestingModule, policyManager.defaultEntitlements("plugin1")), policyManager.moduleEntitlementsMap); + assertEquals( + Map.of(requestingModule, policyManager.defaultEntitlements("plugin1", plugin1SourcePath)), + policyManager.moduleEntitlementsMap + ); } public void testGetEntitlementsReturnsEntitlementsForPluginUnnamedModule() { @@ -157,6 +179,7 @@ public void testGetEntitlementsReturnsEntitlementsForPluginUnnamedModule() { List.of(), Map.ofEntries(entry("plugin2", createPluginPolicy(ALL_UNNAMED))), c -> "plugin2", + Map.of("plugin2", Path.of("modules", "plugin2")), TEST_AGENTS_PACKAGE_NAME, NO_ENTITLEMENTS_MODULE, TEST_PATH_LOOKUP, @@ -176,6 +199,7 @@ public void testGetEntitlementsThrowsOnMissingPolicyForServer() throws ClassNotF List.of(), Map.of(), c -> null, + Map.of(), TEST_AGENTS_PACKAGE_NAME, NO_ENTITLEMENTS_MODULE, TEST_PATH_LOOKUP, @@ -187,16 +211,17 @@ public void testGetEntitlementsThrowsOnMissingPolicyForServer() throws ClassNotF // So we use a random module in the boot layer, and a random class from that module (not java.base -- it is // loaded too early) to mimic a class that would be in the server module. var mockServerClass = ModuleLayer.boot().findLoader("jdk.httpserver").loadClass("com.sun.net.httpserver.HttpServer"); + var mockServerSourcePath = PolicyManager.getComponentPathFromClass(mockServerClass); var requestingModule = mockServerClass.getModule(); assertEquals( "No policy for this module in server", - policyManager.defaultEntitlements(SERVER_COMPONENT_NAME), + policyManager.defaultEntitlements(SERVER_COMPONENT_NAME, mockServerSourcePath), policyManager.getEntitlements(mockServerClass) ); assertEquals( - Map.of(requestingModule, policyManager.defaultEntitlements(SERVER_COMPONENT_NAME)), + Map.of(requestingModule, policyManager.defaultEntitlements(SERVER_COMPONENT_NAME, mockServerSourcePath)), policyManager.moduleEntitlementsMap ); } @@ -207,6 +232,7 @@ public void testGetEntitlementsReturnsEntitlementsForServerModule() throws Class List.of(), Map.of(), c -> null, + Map.of(), TEST_AGENTS_PACKAGE_NAME, NO_ENTITLEMENTS_MODULE, TEST_PATH_LOOKUP, @@ -234,6 +260,7 @@ public void testGetEntitlementsReturnsEntitlementsForPluginModule() throws IOExc List.of(), Map.of("mock-plugin", createPluginPolicy("org.example.plugin")), c -> "mock-plugin", + Map.of("mock-plugin", Path.of("modules", "mock-plugin")), TEST_AGENTS_PACKAGE_NAME, NO_ENTITLEMENTS_MODULE, TEST_PATH_LOOKUP, @@ -254,6 +281,7 @@ public void testGetEntitlementsResultIsCached() { List.of(), Map.ofEntries(entry("plugin2", createPluginPolicy(ALL_UNNAMED))), c -> "plugin2", + Map.of("plugin2", Path.of("modules", "plugin2")), TEST_AGENTS_PACKAGE_NAME, NO_ENTITLEMENTS_MODULE, TEST_PATH_LOOKUP, @@ -314,6 +342,7 @@ public void testAgentsEntitlements() throws IOException, ClassNotFoundException List.of(new CreateClassLoaderEntitlement()), Map.of(), c -> c.getPackageName().startsWith(TEST_AGENTS_PACKAGE_NAME) ? null : "test", + Map.of(), TEST_AGENTS_PACKAGE_NAME, NO_ENTITLEMENTS_MODULE, TEST_PATH_LOOKUP, @@ -343,6 +372,7 @@ public void testDuplicateEntitlements() { List.of(), Map.of(), c -> "test", + Map.of(), TEST_AGENTS_PACKAGE_NAME, NO_ENTITLEMENTS_MODULE, TEST_PATH_LOOKUP, @@ -361,6 +391,7 @@ public void testDuplicateEntitlements() { List.of(new CreateClassLoaderEntitlement(), new CreateClassLoaderEntitlement()), Map.of(), c -> "test", + Map.of(), TEST_AGENTS_PACKAGE_NAME, NO_ENTITLEMENTS_MODULE, TEST_PATH_LOOKUP, @@ -399,6 +430,7 @@ public void testDuplicateEntitlements() { ) ), c -> "plugin1", + Map.of("plugin1", Path.of("modules", "plugin1")), TEST_AGENTS_PACKAGE_NAME, NO_ENTITLEMENTS_MODULE, TEST_PATH_LOOKUP, @@ -451,6 +483,7 @@ public void testFilesEntitlementsWithExclusive() { ) ), c -> "", + Map.of("plugin1", Path.of("modules", "plugin1"), "plugin2", Path.of("modules", "plugin2")), TEST_AGENTS_PACKAGE_NAME, NO_ENTITLEMENTS_MODULE, TEST_PATH_LOOKUP, @@ -497,6 +530,7 @@ public void testFilesEntitlementsWithExclusive() { ) ), c -> "", + Map.of(), TEST_AGENTS_PACKAGE_NAME, NO_ENTITLEMENTS_MODULE, TEST_PATH_LOOKUP, @@ -523,6 +557,7 @@ public void testPluginResolverOverridesAgents() { List.of(new CreateClassLoaderEntitlement()), Map.of(), c -> "test", // Insist that the class is in a plugin + Map.of(), TEST_AGENTS_PACKAGE_NAME, NO_ENTITLEMENTS_MODULE, TEST_PATH_LOOKUP, @@ -545,6 +580,7 @@ private static PolicyManager policyManager(String agentsPackageName, Module enti List.of(), Map.of(), c -> "test", + Map.of(), agentsPackageName, entitlementsModule, TEST_PATH_LOOKUP, diff --git a/server/src/main/java/org/elasticsearch/bootstrap/Elasticsearch.java b/server/src/main/java/org/elasticsearch/bootstrap/Elasticsearch.java index 8f89b30f16aa1..fb4fcef71ee97 100644 --- a/server/src/main/java/org/elasticsearch/bootstrap/Elasticsearch.java +++ b/server/src/main/java/org/elasticsearch/bootstrap/Elasticsearch.java @@ -48,6 +48,7 @@ import org.elasticsearch.nativeaccess.NativeAccess; import org.elasticsearch.node.Node; import org.elasticsearch.node.NodeValidationException; +import org.elasticsearch.plugins.PluginBundle; import org.elasticsearch.plugins.PluginsLoader; import org.elasticsearch.rest.MethodHandlers; import org.elasticsearch.transport.RequestHandlerRegistry; @@ -70,6 +71,7 @@ import java.util.Set; import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; +import java.util.stream.Collectors; import java.util.stream.Stream; import static org.elasticsearch.bootstrap.BootstrapSettings.SECURITY_FILTER_BAD_DEFAULTS_SETTING; @@ -245,6 +247,8 @@ private static void initPhase2(Bootstrap bootstrap) throws IOException { pluginsLoader = PluginsLoader.createPluginsLoader(modulesBundles, pluginsBundles, findPluginsWithNativeAccess(pluginPolicies)); var pluginsResolver = PluginsResolver.create(pluginsLoader); + Map sourcePaths = Stream.concat(modulesBundles.stream(), pluginsBundles.stream()) + .collect(Collectors.toUnmodifiableMap(bundle -> bundle.pluginDescriptor().getName(), PluginBundle::getDir)); EntitlementBootstrap.bootstrap( pluginPolicies, pluginsResolver::resolveClassToPluginName, @@ -254,6 +258,7 @@ private static void initPhase2(Bootstrap bootstrap) throws IOException { nodeEnv.configDir(), nodeEnv.libDir(), nodeEnv.pluginsDir(), + sourcePaths, nodeEnv.logsDir(), nodeEnv.tmpDir(), args.pidFile(),