mirror of
https://github.com/elastic/elasticsearch.git
synced 2025-04-24 23:27:25 -04:00
Process execution checks and IT tests (#119010)
* Process creation checks and IT tests * Remove process queries; only forbid execution
This commit is contained in:
parent
c54a26db49
commit
c3a59bb965
8 changed files with 66 additions and 15 deletions
|
@ -11,6 +11,7 @@ package org.elasticsearch.entitlement.bridge;
|
||||||
|
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
import java.net.URLStreamHandlerFactory;
|
import java.net.URLStreamHandlerFactory;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
public interface EntitlementChecker {
|
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);
|
||||||
|
|
||||||
void check$java_net_URLClassLoader$(Class<?> callerClass, String name, URL[] urls, ClassLoader parent, URLStreamHandlerFactory factory);
|
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 java.util.stream.Collectors;
|
||||||
|
|
||||||
import static java.util.Map.entry;
|
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;
|
import static org.elasticsearch.rest.RestRequest.Method.GET;
|
||||||
|
|
||||||
public class RestEntitlementsCheckAction extends BaseRestHandler {
|
public class RestEntitlementsCheckAction extends BaseRestHandler {
|
||||||
private static final Logger logger = LogManager.getLogger(RestEntitlementsCheckAction.class);
|
private static final Logger logger = LogManager.getLogger(RestEntitlementsCheckAction.class);
|
||||||
private final String prefix;
|
private final String prefix;
|
||||||
|
|
||||||
private record CheckAction(Runnable action, boolean isServerOnly) {
|
record CheckAction(Runnable action, boolean isAlwaysDeniedToPlugins) {
|
||||||
|
/**
|
||||||
static CheckAction serverOnly(Runnable action) {
|
* 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);
|
return new CheckAction(action, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
static CheckAction serverAndPlugin(Runnable action) {
|
static CheckAction forPlugins(Runnable action) {
|
||||||
return new CheckAction(action, false);
|
return new CheckAction(action, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static final Map<String, CheckAction> checkActions = Map.ofEntries(
|
private static final Map<String, CheckAction> checkActions = Map.ofEntries(
|
||||||
entry("runtime_exit", CheckAction.serverOnly(RestEntitlementsCheckAction::runtimeExit)),
|
entry("runtime_exit", deniedToPlugins(RestEntitlementsCheckAction::runtimeExit)),
|
||||||
entry("runtime_halt", CheckAction.serverOnly(RestEntitlementsCheckAction::runtimeHalt)),
|
entry("runtime_halt", deniedToPlugins(RestEntitlementsCheckAction::runtimeHalt)),
|
||||||
entry("create_classloader", CheckAction.serverAndPlugin(RestEntitlementsCheckAction::createClassLoader))
|
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")
|
@SuppressForbidden(reason = "Specifically testing Runtime.exit")
|
||||||
private static void runtimeExit() {
|
private static void runtimeExit() {
|
||||||
logger.info("Calling Runtime.exit;");
|
|
||||||
Runtime.getRuntime().exit(123);
|
Runtime.getRuntime().exit(123);
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressForbidden(reason = "Specifically testing Runtime.halt")
|
@SuppressForbidden(reason = "Specifically testing Runtime.halt")
|
||||||
private static void runtimeHalt() {
|
private static void runtimeHalt() {
|
||||||
logger.info("Calling Runtime.halt;");
|
|
||||||
Runtime.getRuntime().halt(123);
|
Runtime.getRuntime().halt(123);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void createClassLoader() {
|
private static void createClassLoader() {
|
||||||
logger.info("Calling new URLClassLoader");
|
|
||||||
try (var classLoader = new URLClassLoader("test", new URL[0], RestEntitlementsCheckAction.class.getClassLoader())) {
|
try (var classLoader = new URLClassLoader("test", new URL[0], RestEntitlementsCheckAction.class.getClassLoader())) {
|
||||||
logger.info("Created URLClassLoader [{}]", classLoader.getName());
|
logger.info("Created URLClassLoader [{}]", classLoader.getName());
|
||||||
} catch (IOException e) {
|
} 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) {
|
public RestEntitlementsCheckAction(String prefix) {
|
||||||
this.prefix = prefix;
|
this.prefix = prefix;
|
||||||
}
|
}
|
||||||
|
@ -80,7 +96,7 @@ public class RestEntitlementsCheckAction extends BaseRestHandler {
|
||||||
public static Set<String> getServerAndPluginsCheckActions() {
|
public static Set<String> getServerAndPluginsCheckActions() {
|
||||||
return checkActions.entrySet()
|
return checkActions.entrySet()
|
||||||
.stream()
|
.stream()
|
||||||
.filter(kv -> kv.getValue().isServerOnly() == false)
|
.filter(kv -> kv.getValue().isAlwaysDeniedToPlugins() == false)
|
||||||
.map(Map.Entry::getKey)
|
.map(Map.Entry::getKey)
|
||||||
.collect(Collectors.toSet());
|
.collect(Collectors.toSet());
|
||||||
}
|
}
|
||||||
|
@ -112,6 +128,7 @@ public class RestEntitlementsCheckAction extends BaseRestHandler {
|
||||||
}
|
}
|
||||||
|
|
||||||
return channel -> {
|
return channel -> {
|
||||||
|
logger.info("Calling check action [{}]", actionName);
|
||||||
checkAction.action().run();
|
checkAction.action().run();
|
||||||
channel.sendResponse(new RestResponse(RestStatus.OK, Strings.format("Succesfully executed action [%s]", actionName)));
|
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;
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
public class EntitlementAllowedNonModularPlugin extends Plugin implements ActionPlugin {
|
public class EntitlementAllowedNonModularPlugin extends Plugin implements ActionPlugin {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<RestHandler> getRestHandlers(
|
public List<RestHandler> getRestHandlers(
|
||||||
final Settings settings,
|
final Settings settings,
|
||||||
|
|
|
@ -27,7 +27,6 @@ import java.util.function.Predicate;
|
||||||
import java.util.function.Supplier;
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
public class EntitlementAllowedPlugin extends Plugin implements ActionPlugin {
|
public class EntitlementAllowedPlugin extends Plugin implements ActionPlugin {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<RestHandler> getRestHandlers(
|
public List<RestHandler> getRestHandlers(
|
||||||
final Settings settings,
|
final Settings settings,
|
||||||
|
|
|
@ -27,7 +27,6 @@ import java.util.function.Predicate;
|
||||||
import java.util.function.Supplier;
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
public class EntitlementDeniedNonModularPlugin extends Plugin implements ActionPlugin {
|
public class EntitlementDeniedNonModularPlugin extends Plugin implements ActionPlugin {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<RestHandler> getRestHandlers(
|
public List<RestHandler> getRestHandlers(
|
||||||
final Settings settings,
|
final Settings settings,
|
||||||
|
|
|
@ -27,7 +27,6 @@ import java.util.function.Predicate;
|
||||||
import java.util.function.Supplier;
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
public class EntitlementDeniedPlugin extends Plugin implements ActionPlugin {
|
public class EntitlementDeniedPlugin extends Plugin implements ActionPlugin {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<RestHandler> getRestHandlers(
|
public List<RestHandler> getRestHandlers(
|
||||||
final Settings settings,
|
final Settings settings,
|
||||||
|
|
|
@ -14,6 +14,7 @@ import org.elasticsearch.entitlement.runtime.policy.PolicyManager;
|
||||||
|
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
import java.net.URLStreamHandlerFactory;
|
import java.net.URLStreamHandlerFactory;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Implementation of the {@link EntitlementChecker} interface, providing additional
|
* Implementation of the {@link EntitlementChecker} interface, providing additional
|
||||||
|
@ -67,4 +68,14 @@ public class ElasticsearchEntitlementChecker implements EntitlementChecker {
|
||||||
) {
|
) {
|
||||||
policyManager.checkCreateClassLoader(callerClass);
|
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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -105,6 +105,26 @@ public class PolicyManager {
|
||||||
return policy.scopes.stream().collect(Collectors.toUnmodifiableMap(scope -> scope.name, scope -> scope.entitlements));
|
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) {
|
public void checkExitVM(Class<?> callerClass) {
|
||||||
checkEntitlementPresent(callerClass, ExitVMEntitlement.class);
|
checkEntitlementPresent(callerClass, ExitVMEntitlement.class);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue