mirror of
https://github.com/elastic/elasticsearch.git
synced 2025-04-24 15:17:30 -04:00
Merge main into multi-project
This commit is contained in:
commit
f7791a0f5f
235 changed files with 6205 additions and 1372 deletions
|
@ -11,6 +11,7 @@ package org.elasticsearch.entitlement.bridge;
|
|||
|
||||
import java.net.URL;
|
||||
import java.net.URLStreamHandlerFactory;
|
||||
import java.util.List;
|
||||
|
||||
public interface EntitlementChecker {
|
||||
|
||||
|
@ -29,4 +30,10 @@ public interface EntitlementChecker {
|
|||
void check$java_net_URLClassLoader$(Class<?> callerClass, String name, URL[] urls, ClassLoader parent);
|
||||
|
||||
void check$java_net_URLClassLoader$(Class<?> callerClass, String name, URL[] urls, ClassLoader parent, URLStreamHandlerFactory factory);
|
||||
|
||||
// Process creation
|
||||
void check$$start(Class<?> callerClass, ProcessBuilder that, ProcessBuilder.Redirect[] redirects);
|
||||
|
||||
void check$java_lang_ProcessBuilder$startPipeline(Class<?> callerClass, List<ProcessBuilder> builders);
|
||||
|
||||
}
|
||||
|
|
|
@ -29,43 +29,47 @@ import java.util.Set;
|
|||
import java.util.stream.Collectors;
|
||||
|
||||
import static java.util.Map.entry;
|
||||
import static org.elasticsearch.entitlement.qa.common.RestEntitlementsCheckAction.CheckAction.deniedToPlugins;
|
||||
import static org.elasticsearch.entitlement.qa.common.RestEntitlementsCheckAction.CheckAction.forPlugins;
|
||||
import static org.elasticsearch.rest.RestRequest.Method.GET;
|
||||
|
||||
public class RestEntitlementsCheckAction extends BaseRestHandler {
|
||||
private static final Logger logger = LogManager.getLogger(RestEntitlementsCheckAction.class);
|
||||
private final String prefix;
|
||||
|
||||
private record CheckAction(Runnable action, boolean isServerOnly) {
|
||||
|
||||
static CheckAction serverOnly(Runnable action) {
|
||||
record CheckAction(Runnable action, boolean isAlwaysDeniedToPlugins) {
|
||||
/**
|
||||
* These cannot be granted to plugins, so our test plugins cannot test the "allowed" case.
|
||||
* Used both for always-denied entitlements as well as those granted only to the server itself.
|
||||
*/
|
||||
static CheckAction deniedToPlugins(Runnable action) {
|
||||
return new CheckAction(action, true);
|
||||
}
|
||||
|
||||
static CheckAction serverAndPlugin(Runnable action) {
|
||||
static CheckAction forPlugins(Runnable action) {
|
||||
return new CheckAction(action, false);
|
||||
}
|
||||
}
|
||||
|
||||
private static final Map<String, CheckAction> checkActions = Map.ofEntries(
|
||||
entry("runtime_exit", CheckAction.serverOnly(RestEntitlementsCheckAction::runtimeExit)),
|
||||
entry("runtime_halt", CheckAction.serverOnly(RestEntitlementsCheckAction::runtimeHalt)),
|
||||
entry("create_classloader", CheckAction.serverAndPlugin(RestEntitlementsCheckAction::createClassLoader))
|
||||
entry("runtime_exit", deniedToPlugins(RestEntitlementsCheckAction::runtimeExit)),
|
||||
entry("runtime_halt", deniedToPlugins(RestEntitlementsCheckAction::runtimeHalt)),
|
||||
entry("create_classloader", forPlugins(RestEntitlementsCheckAction::createClassLoader)),
|
||||
// entry("processBuilder_start", deniedToPlugins(RestEntitlementsCheckAction::processBuilder_start)),
|
||||
entry("processBuilder_startPipeline", deniedToPlugins(RestEntitlementsCheckAction::processBuilder_startPipeline))
|
||||
);
|
||||
|
||||
@SuppressForbidden(reason = "Specifically testing Runtime.exit")
|
||||
private static void runtimeExit() {
|
||||
logger.info("Calling Runtime.exit;");
|
||||
Runtime.getRuntime().exit(123);
|
||||
}
|
||||
|
||||
@SuppressForbidden(reason = "Specifically testing Runtime.halt")
|
||||
private static void runtimeHalt() {
|
||||
logger.info("Calling Runtime.halt;");
|
||||
Runtime.getRuntime().halt(123);
|
||||
}
|
||||
|
||||
private static void createClassLoader() {
|
||||
logger.info("Calling new URLClassLoader");
|
||||
try (var classLoader = new URLClassLoader("test", new URL[0], RestEntitlementsCheckAction.class.getClassLoader())) {
|
||||
logger.info("Created URLClassLoader [{}]", classLoader.getName());
|
||||
} catch (IOException e) {
|
||||
|
@ -73,6 +77,18 @@ public class RestEntitlementsCheckAction extends BaseRestHandler {
|
|||
}
|
||||
}
|
||||
|
||||
private static void processBuilder_start() {
|
||||
// TODO: processBuilder().start();
|
||||
}
|
||||
|
||||
private static void processBuilder_startPipeline() {
|
||||
try {
|
||||
ProcessBuilder.startPipeline(List.of());
|
||||
} catch (IOException e) {
|
||||
throw new IllegalStateException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public RestEntitlementsCheckAction(String prefix) {
|
||||
this.prefix = prefix;
|
||||
}
|
||||
|
@ -80,7 +96,7 @@ public class RestEntitlementsCheckAction extends BaseRestHandler {
|
|||
public static Set<String> getServerAndPluginsCheckActions() {
|
||||
return checkActions.entrySet()
|
||||
.stream()
|
||||
.filter(kv -> kv.getValue().isServerOnly() == false)
|
||||
.filter(kv -> kv.getValue().isAlwaysDeniedToPlugins() == false)
|
||||
.map(Map.Entry::getKey)
|
||||
.collect(Collectors.toSet());
|
||||
}
|
||||
|
@ -112,6 +128,7 @@ public class RestEntitlementsCheckAction extends BaseRestHandler {
|
|||
}
|
||||
|
||||
return channel -> {
|
||||
logger.info("Calling check action [{}]", actionName);
|
||||
checkAction.action().run();
|
||||
channel.sendResponse(new RestResponse(RestStatus.OK, Strings.format("Succesfully executed action [%s]", actionName)));
|
||||
};
|
||||
|
|
|
@ -27,7 +27,6 @@ import java.util.function.Predicate;
|
|||
import java.util.function.Supplier;
|
||||
|
||||
public class EntitlementAllowedNonModularPlugin extends Plugin implements ActionPlugin {
|
||||
|
||||
@Override
|
||||
public List<RestHandler> getRestHandlers(
|
||||
final Settings settings,
|
||||
|
|
|
@ -27,7 +27,6 @@ import java.util.function.Predicate;
|
|||
import java.util.function.Supplier;
|
||||
|
||||
public class EntitlementAllowedPlugin extends Plugin implements ActionPlugin {
|
||||
|
||||
@Override
|
||||
public List<RestHandler> getRestHandlers(
|
||||
final Settings settings,
|
||||
|
|
|
@ -27,7 +27,6 @@ import java.util.function.Predicate;
|
|||
import java.util.function.Supplier;
|
||||
|
||||
public class EntitlementDeniedNonModularPlugin extends Plugin implements ActionPlugin {
|
||||
|
||||
@Override
|
||||
public List<RestHandler> getRestHandlers(
|
||||
final Settings settings,
|
||||
|
|
|
@ -27,7 +27,6 @@ import java.util.function.Predicate;
|
|||
import java.util.function.Supplier;
|
||||
|
||||
public class EntitlementDeniedPlugin extends Plugin implements ActionPlugin {
|
||||
|
||||
@Override
|
||||
public List<RestHandler> getRestHandlers(
|
||||
final Settings settings,
|
||||
|
|
|
@ -53,6 +53,7 @@ import static org.elasticsearch.entitlement.runtime.policy.PolicyManager.ALL_UNN
|
|||
public class EntitlementInitialization {
|
||||
|
||||
private static final String POLICY_FILE_NAME = "entitlement-policy.yaml";
|
||||
private static final Module ENTITLEMENTS_MODULE = PolicyManager.class.getModule();
|
||||
|
||||
private static ElasticsearchEntitlementChecker manager;
|
||||
|
||||
|
@ -92,7 +93,7 @@ public class EntitlementInitialization {
|
|||
"server",
|
||||
List.of(new Scope("org.elasticsearch.server", List.of(new ExitVMEntitlement(), new CreateClassLoaderEntitlement())))
|
||||
);
|
||||
return new PolicyManager(serverPolicy, pluginPolicies, EntitlementBootstrap.bootstrapArgs().pluginResolver());
|
||||
return new PolicyManager(serverPolicy, pluginPolicies, EntitlementBootstrap.bootstrapArgs().pluginResolver(), ENTITLEMENTS_MODULE);
|
||||
}
|
||||
|
||||
private static Map<String, Policy> createPluginPolicies(Collection<EntitlementBootstrap.PluginData> pluginData) throws IOException {
|
||||
|
|
|
@ -14,6 +14,7 @@ import org.elasticsearch.entitlement.runtime.policy.PolicyManager;
|
|||
|
||||
import java.net.URL;
|
||||
import java.net.URLStreamHandlerFactory;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Implementation of the {@link EntitlementChecker} interface, providing additional
|
||||
|
@ -67,4 +68,14 @@ public class ElasticsearchEntitlementChecker implements EntitlementChecker {
|
|||
) {
|
||||
policyManager.checkCreateClassLoader(callerClass);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void check$$start(Class<?> callerClass, ProcessBuilder processBuilder, ProcessBuilder.Redirect[] redirects) {
|
||||
policyManager.checkStartProcess(callerClass);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void check$java_lang_ProcessBuilder$startPipeline(Class<?> callerClass, List<ProcessBuilder> builders) {
|
||||
policyManager.checkStartProcess(callerClass);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,6 +15,7 @@ import org.elasticsearch.entitlement.runtime.api.NotEntitledException;
|
|||
import org.elasticsearch.logging.LogManager;
|
||||
import org.elasticsearch.logging.Logger;
|
||||
|
||||
import java.lang.StackWalker.StackFrame;
|
||||
import java.lang.module.ModuleFinder;
|
||||
import java.lang.module.ModuleReference;
|
||||
import java.util.ArrayList;
|
||||
|
@ -29,6 +30,10 @@ import java.util.function.Function;
|
|||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import static java.lang.StackWalker.Option.RETAIN_CLASS_REFERENCE;
|
||||
import static java.util.Objects.requireNonNull;
|
||||
import static java.util.function.Predicate.not;
|
||||
|
||||
public class PolicyManager {
|
||||
private static final Logger logger = LogManager.getLogger(ElasticsearchEntitlementChecker.class);
|
||||
|
||||
|
@ -63,6 +68,11 @@ public class PolicyManager {
|
|||
|
||||
private static final Set<Module> systemModules = findSystemModules();
|
||||
|
||||
/**
|
||||
* Frames originating from this module are ignored in the permission logic.
|
||||
*/
|
||||
private final Module entitlementsModule;
|
||||
|
||||
private static Set<Module> findSystemModules() {
|
||||
var systemModulesDescriptors = ModuleFinder.ofSystem()
|
||||
.findAll()
|
||||
|
@ -77,19 +87,44 @@ public class PolicyManager {
|
|||
.collect(Collectors.toUnmodifiableSet());
|
||||
}
|
||||
|
||||
public PolicyManager(Policy defaultPolicy, Map<String, Policy> pluginPolicies, Function<Class<?>, String> pluginResolver) {
|
||||
this.serverEntitlements = buildScopeEntitlementsMap(Objects.requireNonNull(defaultPolicy));
|
||||
this.pluginsEntitlements = Objects.requireNonNull(pluginPolicies)
|
||||
.entrySet()
|
||||
public PolicyManager(
|
||||
Policy defaultPolicy,
|
||||
Map<String, Policy> pluginPolicies,
|
||||
Function<Class<?>, String> pluginResolver,
|
||||
Module entitlementsModule
|
||||
) {
|
||||
this.serverEntitlements = buildScopeEntitlementsMap(requireNonNull(defaultPolicy));
|
||||
this.pluginsEntitlements = requireNonNull(pluginPolicies).entrySet()
|
||||
.stream()
|
||||
.collect(Collectors.toUnmodifiableMap(Map.Entry::getKey, e -> buildScopeEntitlementsMap(e.getValue())));
|
||||
this.pluginResolver = pluginResolver;
|
||||
this.entitlementsModule = entitlementsModule;
|
||||
}
|
||||
|
||||
private static Map<String, List<Entitlement>> buildScopeEntitlementsMap(Policy policy) {
|
||||
return policy.scopes.stream().collect(Collectors.toUnmodifiableMap(scope -> scope.name, scope -> scope.entitlements));
|
||||
}
|
||||
|
||||
public void checkStartProcess(Class<?> callerClass) {
|
||||
neverEntitled(callerClass, "start process");
|
||||
}
|
||||
|
||||
private void neverEntitled(Class<?> callerClass, String operationDescription) {
|
||||
var requestingModule = requestingModule(callerClass);
|
||||
if (isTriviallyAllowed(requestingModule)) {
|
||||
return;
|
||||
}
|
||||
|
||||
throw new NotEntitledException(
|
||||
Strings.format(
|
||||
"Not entitled: caller [%s], module [%s], operation [%s]",
|
||||
callerClass,
|
||||
requestingModule.getName(),
|
||||
operationDescription
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
public void checkExitVM(Class<?> callerClass) {
|
||||
checkEntitlementPresent(callerClass, ExitVMEntitlement.class);
|
||||
}
|
||||
|
@ -185,7 +220,16 @@ public class PolicyManager {
|
|||
return requestingModule.isNamed() && requestingModule.getLayer() == ModuleLayer.boot();
|
||||
}
|
||||
|
||||
private static Module requestingModule(Class<?> callerClass) {
|
||||
/**
|
||||
* Walks the stack to determine which module's entitlements should be checked.
|
||||
*
|
||||
* @param callerClass when non-null will be used if its module is suitable;
|
||||
* this is a fast-path check that can avoid the stack walk
|
||||
* in cases where the caller class is available.
|
||||
* @return the requesting module, or {@code null} if the entire call stack
|
||||
* comes from modules that are trusted.
|
||||
*/
|
||||
Module requestingModule(Class<?> callerClass) {
|
||||
if (callerClass != null) {
|
||||
Module callerModule = callerClass.getModule();
|
||||
if (systemModules.contains(callerModule) == false) {
|
||||
|
@ -193,21 +237,34 @@ public class PolicyManager {
|
|||
return callerModule;
|
||||
}
|
||||
}
|
||||
int framesToSkip = 1 // getCallingClass (this method)
|
||||
+ 1 // the checkXxx method
|
||||
+ 1 // the runtime config method
|
||||
+ 1 // the instrumented method
|
||||
;
|
||||
Optional<Module> module = StackWalker.getInstance(StackWalker.Option.RETAIN_CLASS_REFERENCE)
|
||||
.walk(
|
||||
s -> s.skip(framesToSkip)
|
||||
.map(f -> f.getDeclaringClass().getModule())
|
||||
.filter(m -> systemModules.contains(m) == false)
|
||||
.findFirst()
|
||||
);
|
||||
Optional<Module> module = StackWalker.getInstance(RETAIN_CLASS_REFERENCE)
|
||||
.walk(frames -> findRequestingModule(frames.map(StackFrame::getDeclaringClass)));
|
||||
return module.orElse(null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Given a stream of classes corresponding to the frames from a {@link StackWalker},
|
||||
* returns the module whose entitlements should be checked.
|
||||
*
|
||||
* @throws NullPointerException if the requesting module is {@code null}
|
||||
*/
|
||||
Optional<Module> findRequestingModule(Stream<Class<?>> classes) {
|
||||
return classes.map(Objects::requireNonNull)
|
||||
.map(PolicyManager::moduleOf)
|
||||
.filter(m -> m != entitlementsModule) // Ignore the entitlements library itself
|
||||
.filter(not(systemModules::contains)) // Skip trusted JDK modules
|
||||
.findFirst();
|
||||
}
|
||||
|
||||
private static Module moduleOf(Class<?> c) {
|
||||
var result = c.getModule();
|
||||
if (result == null) {
|
||||
throw new NullPointerException("Entitlements system does not support non-modular class [" + c.getName() + "]");
|
||||
} else {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean isTriviallyAllowed(Module requestingModule) {
|
||||
if (requestingModule == null) {
|
||||
logger.debug("Entitlement trivially allowed: entire call stack is in composed of classes in system modules");
|
||||
|
|
|
@ -22,6 +22,7 @@ import java.util.Arrays;
|
|||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import static java.util.Map.entry;
|
||||
import static org.elasticsearch.entitlement.runtime.policy.PolicyManager.ALL_UNNAMED;
|
||||
|
@ -37,11 +38,14 @@ import static org.hamcrest.Matchers.sameInstance;
|
|||
@ESTestCase.WithoutSecurityManager
|
||||
public class PolicyManagerTests extends ESTestCase {
|
||||
|
||||
private static final Module NO_ENTITLEMENTS_MODULE = null;
|
||||
|
||||
public void testGetEntitlementsThrowsOnMissingPluginUnnamedModule() {
|
||||
var policyManager = new PolicyManager(
|
||||
createEmptyTestServerPolicy(),
|
||||
Map.of("plugin1", createPluginPolicy("plugin.module")),
|
||||
c -> "plugin1"
|
||||
c -> "plugin1",
|
||||
NO_ENTITLEMENTS_MODULE
|
||||
);
|
||||
|
||||
// Any class from the current module (unnamed) will do
|
||||
|
@ -62,7 +66,7 @@ public class PolicyManagerTests extends ESTestCase {
|
|||
}
|
||||
|
||||
public void testGetEntitlementsThrowsOnMissingPolicyForPlugin() {
|
||||
var policyManager = new PolicyManager(createEmptyTestServerPolicy(), Map.of(), c -> "plugin1");
|
||||
var policyManager = new PolicyManager(createEmptyTestServerPolicy(), Map.of(), c -> "plugin1", NO_ENTITLEMENTS_MODULE);
|
||||
|
||||
// Any class from the current module (unnamed) will do
|
||||
var callerClass = this.getClass();
|
||||
|
@ -82,7 +86,7 @@ public class PolicyManagerTests extends ESTestCase {
|
|||
}
|
||||
|
||||
public void testGetEntitlementsFailureIsCached() {
|
||||
var policyManager = new PolicyManager(createEmptyTestServerPolicy(), Map.of(), c -> "plugin1");
|
||||
var policyManager = new PolicyManager(createEmptyTestServerPolicy(), Map.of(), c -> "plugin1", NO_ENTITLEMENTS_MODULE);
|
||||
|
||||
// Any class from the current module (unnamed) will do
|
||||
var callerClass = this.getClass();
|
||||
|
@ -103,7 +107,8 @@ public class PolicyManagerTests extends ESTestCase {
|
|||
var policyManager = new PolicyManager(
|
||||
createEmptyTestServerPolicy(),
|
||||
Map.ofEntries(entry("plugin2", createPluginPolicy(ALL_UNNAMED))),
|
||||
c -> "plugin2"
|
||||
c -> "plugin2",
|
||||
NO_ENTITLEMENTS_MODULE
|
||||
);
|
||||
|
||||
// Any class from the current module (unnamed) will do
|
||||
|
@ -115,7 +120,7 @@ public class PolicyManagerTests extends ESTestCase {
|
|||
}
|
||||
|
||||
public void testGetEntitlementsThrowsOnMissingPolicyForServer() throws ClassNotFoundException {
|
||||
var policyManager = new PolicyManager(createTestServerPolicy("example"), Map.of(), c -> null);
|
||||
var policyManager = new PolicyManager(createTestServerPolicy("example"), Map.of(), c -> null, NO_ENTITLEMENTS_MODULE);
|
||||
|
||||
// Tests do not run modular, so we cannot use a server class.
|
||||
// But we know that in production code the server module and its classes are in the boot layer.
|
||||
|
@ -138,7 +143,7 @@ public class PolicyManagerTests extends ESTestCase {
|
|||
}
|
||||
|
||||
public void testGetEntitlementsReturnsEntitlementsForServerModule() throws ClassNotFoundException {
|
||||
var policyManager = new PolicyManager(createTestServerPolicy("jdk.httpserver"), Map.of(), c -> null);
|
||||
var policyManager = new PolicyManager(createTestServerPolicy("jdk.httpserver"), Map.of(), c -> null, NO_ENTITLEMENTS_MODULE);
|
||||
|
||||
// Tests do not run modular, so we cannot use a server class.
|
||||
// But we know that in production code the server module and its classes are in the boot layer.
|
||||
|
@ -155,12 +160,13 @@ public class PolicyManagerTests extends ESTestCase {
|
|||
public void testGetEntitlementsReturnsEntitlementsForPluginModule() throws IOException, ClassNotFoundException {
|
||||
final Path home = createTempDir();
|
||||
|
||||
Path jar = creteMockPluginJar(home);
|
||||
Path jar = createMockPluginJar(home);
|
||||
|
||||
var policyManager = new PolicyManager(
|
||||
createEmptyTestServerPolicy(),
|
||||
Map.of("mock-plugin", createPluginPolicy("org.example.plugin")),
|
||||
c -> "mock-plugin"
|
||||
c -> "mock-plugin",
|
||||
NO_ENTITLEMENTS_MODULE
|
||||
);
|
||||
|
||||
var layer = createLayerForJar(jar, "org.example.plugin");
|
||||
|
@ -179,7 +185,8 @@ public class PolicyManagerTests extends ESTestCase {
|
|||
var policyManager = new PolicyManager(
|
||||
createEmptyTestServerPolicy(),
|
||||
Map.ofEntries(entry("plugin2", createPluginPolicy(ALL_UNNAMED))),
|
||||
c -> "plugin2"
|
||||
c -> "plugin2",
|
||||
NO_ENTITLEMENTS_MODULE
|
||||
);
|
||||
|
||||
// Any class from the current module (unnamed) will do
|
||||
|
@ -197,6 +204,73 @@ public class PolicyManagerTests extends ESTestCase {
|
|||
assertThat(entitlementsAgain, sameInstance(cachedResult));
|
||||
}
|
||||
|
||||
public void testRequestingModuleFastPath() throws IOException, ClassNotFoundException {
|
||||
var callerClass = makeClassInItsOwnModule();
|
||||
assertEquals(callerClass.getModule(), policyManagerWithEntitlementsModule(NO_ENTITLEMENTS_MODULE).requestingModule(callerClass));
|
||||
}
|
||||
|
||||
public void testRequestingModuleWithStackWalk() throws IOException, ClassNotFoundException {
|
||||
var requestingClass = makeClassInItsOwnModule();
|
||||
var runtimeClass = makeClassInItsOwnModule(); // A class in the entitlements library itself
|
||||
var ignorableClass = makeClassInItsOwnModule();
|
||||
var systemClass = Object.class;
|
||||
|
||||
var policyManager = policyManagerWithEntitlementsModule(runtimeClass.getModule());
|
||||
|
||||
var requestingModule = requestingClass.getModule();
|
||||
|
||||
assertEquals(
|
||||
"Skip one system frame",
|
||||
requestingModule,
|
||||
policyManager.findRequestingModule(Stream.of(systemClass, requestingClass, ignorableClass)).orElse(null)
|
||||
);
|
||||
assertEquals(
|
||||
"Skip multiple system frames",
|
||||
requestingModule,
|
||||
policyManager.findRequestingModule(Stream.of(systemClass, systemClass, systemClass, requestingClass, ignorableClass))
|
||||
.orElse(null)
|
||||
);
|
||||
assertEquals(
|
||||
"Skip system frame between runtime frames",
|
||||
requestingModule,
|
||||
policyManager.findRequestingModule(Stream.of(runtimeClass, systemClass, runtimeClass, requestingClass, ignorableClass))
|
||||
.orElse(null)
|
||||
);
|
||||
assertEquals(
|
||||
"Skip runtime frame between system frames",
|
||||
requestingModule,
|
||||
policyManager.findRequestingModule(Stream.of(systemClass, runtimeClass, systemClass, requestingClass, ignorableClass))
|
||||
.orElse(null)
|
||||
);
|
||||
assertEquals(
|
||||
"No system frames",
|
||||
requestingModule,
|
||||
policyManager.findRequestingModule(Stream.of(requestingClass, ignorableClass)).orElse(null)
|
||||
);
|
||||
assertEquals(
|
||||
"Skip runtime frames up to the first system frame",
|
||||
requestingModule,
|
||||
policyManager.findRequestingModule(Stream.of(runtimeClass, runtimeClass, systemClass, requestingClass, ignorableClass))
|
||||
.orElse(null)
|
||||
);
|
||||
assertThrows(
|
||||
"Non-modular caller frames are not supported",
|
||||
NullPointerException.class,
|
||||
() -> policyManager.findRequestingModule(Stream.of(systemClass, null))
|
||||
);
|
||||
}
|
||||
|
||||
private static Class<?> makeClassInItsOwnModule() throws IOException, ClassNotFoundException {
|
||||
final Path home = createTempDir();
|
||||
Path jar = createMockPluginJar(home);
|
||||
var layer = createLayerForJar(jar, "org.example.plugin");
|
||||
return layer.findLoader("org.example.plugin").loadClass("q.B");
|
||||
}
|
||||
|
||||
private static PolicyManager policyManagerWithEntitlementsModule(Module entitlementsModule) {
|
||||
return new PolicyManager(createEmptyTestServerPolicy(), Map.of(), c -> "test", entitlementsModule);
|
||||
}
|
||||
|
||||
private static Policy createEmptyTestServerPolicy() {
|
||||
return new Policy("server", List.of());
|
||||
}
|
||||
|
@ -219,7 +293,7 @@ public class PolicyManagerTests extends ESTestCase {
|
|||
);
|
||||
}
|
||||
|
||||
private static Path creteMockPluginJar(Path home) throws IOException {
|
||||
private static Path createMockPluginJar(Path home) throws IOException {
|
||||
Path jar = home.resolve("mock-plugin.jar");
|
||||
|
||||
Map<String, CharSequence> sources = Map.ofEntries(
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue