diff --git a/libs/entitlement/qa/entitlement-test-plugin/src/main/java/org/elasticsearch/entitlement/qa/test/WritePropertiesCheckActions.java b/libs/entitlement/qa/entitlement-test-plugin/src/main/java/org/elasticsearch/entitlement/qa/test/JvmActions.java similarity index 55% rename from libs/entitlement/qa/entitlement-test-plugin/src/main/java/org/elasticsearch/entitlement/qa/test/WritePropertiesCheckActions.java rename to libs/entitlement/qa/entitlement-test-plugin/src/main/java/org/elasticsearch/entitlement/qa/test/JvmActions.java index ba4bfa5e896b9..29e4ffccce0b3 100644 --- a/libs/entitlement/qa/entitlement-test-plugin/src/main/java/org/elasticsearch/entitlement/qa/test/WritePropertiesCheckActions.java +++ b/libs/entitlement/qa/entitlement-test-plugin/src/main/java/org/elasticsearch/entitlement/qa/test/JvmActions.java @@ -12,13 +12,20 @@ import org.elasticsearch.core.SuppressForbidden; import org.elasticsearch.entitlement.qa.entitled.EntitledPlugin; +import java.io.IOException; +import java.net.URL; +import java.net.URLClassLoader; import java.util.Locale; import java.util.TimeZone; +import static org.elasticsearch.entitlement.qa.test.EntitlementTest.ExpectedAccess.ALWAYS_DENIED; +import static org.elasticsearch.entitlement.qa.test.EntitlementTest.ExpectedAccess.PLUGINS; + @SuppressForbidden(reason = "testing entitlements") -class WritePropertiesCheckActions { - private WritePropertiesCheckActions() {} +@SuppressWarnings({ "unused" /* called via reflection */ }) +class JvmActions { + @EntitlementTest(expectedAccess = PLUGINS) static void setSystemProperty() { System.setProperty("es.entitlements.checkSetSystemProperty", "true"); try { @@ -29,24 +36,49 @@ static void setSystemProperty() { } + @EntitlementTest(expectedAccess = PLUGINS) static void clearSystemProperty() { EntitledPlugin.selfTest(); // TODO: find a better home System.clearProperty("es.entitlements.checkClearSystemProperty"); } + @EntitlementTest(expectedAccess = ALWAYS_DENIED) static void setSystemProperties() { System.setProperties(System.getProperties()); // no side effect in case if allowed (but shouldn't) } + @EntitlementTest(expectedAccess = ALWAYS_DENIED) static void setDefaultLocale() { Locale.setDefault(Locale.getDefault()); } + @EntitlementTest(expectedAccess = ALWAYS_DENIED) static void setDefaultLocaleForCategory() { Locale.setDefault(Locale.Category.DISPLAY, Locale.getDefault(Locale.Category.DISPLAY)); } + @EntitlementTest(expectedAccess = ALWAYS_DENIED) static void setDefaultTimeZone() { TimeZone.setDefault(TimeZone.getDefault()); } + + @EntitlementTest(expectedAccess = PLUGINS) + static void createClassLoader() throws IOException { + try (var classLoader = new URLClassLoader("test", new URL[0], RestEntitlementsCheckAction.class.getClassLoader())) { + // intentionally empty, just let the loader close + } + } + + @EntitlementTest(expectedAccess = ALWAYS_DENIED) + static void createLogManager() { + new java.util.logging.LogManager() { + }; + } + + @EntitlementTest(expectedAccess = ALWAYS_DENIED) + static void thread$$setDefaultUncaughtExceptionHandler() { + Thread.setDefaultUncaughtExceptionHandler(Thread.getDefaultUncaughtExceptionHandler()); + } + + private JvmActions() {} } diff --git a/libs/entitlement/qa/entitlement-test-plugin/src/main/java/org/elasticsearch/entitlement/qa/test/OperatingSystemActions.java b/libs/entitlement/qa/entitlement-test-plugin/src/main/java/org/elasticsearch/entitlement/qa/test/OperatingSystemActions.java new file mode 100644 index 0000000000000..82bac3d6808eb --- /dev/null +++ b/libs/entitlement/qa/entitlement-test-plugin/src/main/java/org/elasticsearch/entitlement/qa/test/OperatingSystemActions.java @@ -0,0 +1,27 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the "Elastic License + * 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side + * Public License v 1"; you may not use this file except in compliance with, at + * your election, the "Elastic License 2.0", the "GNU Affero General Public + * License v3.0 only", or the "Server Side Public License, v 1". + */ + +package org.elasticsearch.entitlement.qa.test; + +import java.io.IOException; +import java.util.List; + +@SuppressWarnings({ "unused" /* called via reflection */ }) +class OperatingSystemActions { + + static void processBuilder_start() throws IOException { + new ProcessBuilder("").start(); + } + + static void processBuilder_startPipeline() throws IOException { + ProcessBuilder.startPipeline(List.of()); + } + + private OperatingSystemActions() {} +} diff --git a/libs/entitlement/qa/entitlement-test-plugin/src/main/java/org/elasticsearch/entitlement/qa/test/RestEntitlementsCheckAction.java b/libs/entitlement/qa/entitlement-test-plugin/src/main/java/org/elasticsearch/entitlement/qa/test/RestEntitlementsCheckAction.java index e2422fd32706c..70cca99b0a74a 100644 --- a/libs/entitlement/qa/entitlement-test-plugin/src/main/java/org/elasticsearch/entitlement/qa/test/RestEntitlementsCheckAction.java +++ b/libs/entitlement/qa/entitlement-test-plugin/src/main/java/org/elasticsearch/entitlement/qa/test/RestEntitlementsCheckAction.java @@ -40,7 +40,6 @@ import java.net.Socket; import java.net.SocketException; import java.net.URL; -import java.net.URLClassLoader; import java.net.URLConnection; import java.net.URLStreamHandler; import java.net.spi.URLStreamHandlerProvider; @@ -63,7 +62,6 @@ import static org.elasticsearch.entitlement.qa.test.EntitlementTest.ExpectedAccess.PLUGINS; import static org.elasticsearch.entitlement.qa.test.EntitlementTest.ExpectedAccess.SERVER_ONLY; import static org.elasticsearch.entitlement.qa.test.RestEntitlementsCheckAction.CheckAction.alwaysDenied; -import static org.elasticsearch.entitlement.qa.test.RestEntitlementsCheckAction.CheckAction.deniedToPlugins; import static org.elasticsearch.entitlement.qa.test.RestEntitlementsCheckAction.CheckAction.forPlugins; import static org.elasticsearch.rest.RestRequest.Method.GET; @@ -95,26 +93,10 @@ static CheckAction alwaysDenied(CheckedRunnable action) { private static final Map checkActions = Stream.of( Stream.>of( - entry("create_classloader", forPlugins(RestEntitlementsCheckAction::createClassLoader)), - entry("processBuilder_start", deniedToPlugins(RestEntitlementsCheckAction::processBuilder_start)), - entry("processBuilder_startPipeline", deniedToPlugins(RestEntitlementsCheckAction::processBuilder_startPipeline)), entry("set_https_connection_properties", forPlugins(RestEntitlementsCheckAction::setHttpsConnectionProperties)), entry("set_default_ssl_socket_factory", alwaysDenied(RestEntitlementsCheckAction::setDefaultSSLSocketFactory)), entry("set_default_hostname_verifier", alwaysDenied(RestEntitlementsCheckAction::setDefaultHostnameVerifier)), entry("set_default_ssl_context", alwaysDenied(RestEntitlementsCheckAction::setDefaultSSLContext)), - entry( - "thread_setDefaultUncaughtExceptionHandler", - alwaysDenied(RestEntitlementsCheckAction::thread$$setDefaultUncaughtExceptionHandler) - ), - entry("logManager", alwaysDenied(RestEntitlementsCheckAction::logManager$)), - - entry("locale_setDefault", alwaysDenied(WritePropertiesCheckActions::setDefaultLocale)), - entry("locale_setDefaultForCategory", alwaysDenied(WritePropertiesCheckActions::setDefaultLocaleForCategory)), - entry("timeZone_setDefault", alwaysDenied(WritePropertiesCheckActions::setDefaultTimeZone)), - - entry("system_setProperty", forPlugins(WritePropertiesCheckActions::setSystemProperty)), - entry("system_clearProperty", forPlugins(WritePropertiesCheckActions::clearSystemProperty)), - entry("system_setSystemProperties", alwaysDenied(WritePropertiesCheckActions::setSystemProperties)), // This group is a bit nasty: if entitlements don't prevent these, then networking is // irreparably borked for the remainder of the test run. @@ -211,7 +193,9 @@ static CheckAction alwaysDenied(CheckedRunnable action) { getTestEntries(SpiActions.class), getTestEntries(SystemActions.class), getTestEntries(URLConnectionFileActions.class), - getTestEntries(URLConnectionNetworkActions.class) + getTestEntries(URLConnectionNetworkActions.class), + getTestEntries(JvmActions.class), + getTestEntries(OperatingSystemActions.class) ) .flatMap(Function.identity()) .filter(entry -> entry.getValue().fromJavaVersion() == null || Runtime.version().feature() >= entry.getValue().fromJavaVersion()) @@ -323,33 +307,10 @@ private static void setDefaultSSLSocketFactory() { HttpsURLConnection.setDefaultSSLSocketFactory(new DummyImplementations.DummySSLSocketFactory()); } - private static void createClassLoader() throws IOException { - try (var classLoader = new URLClassLoader("test", new URL[0], RestEntitlementsCheckAction.class.getClassLoader())) { - logger.info("Created URLClassLoader [{}]", classLoader.getName()); - } - } - - private static void processBuilder_start() throws IOException { - new ProcessBuilder("").start(); - } - - private static void processBuilder_startPipeline() throws IOException { - ProcessBuilder.startPipeline(List.of()); - } - private static void setHttpsConnectionProperties() { new DummyImplementations.DummyHttpsURLConnection().setSSLSocketFactory(new DummyImplementations.DummySSLSocketFactory()); } - private static void thread$$setDefaultUncaughtExceptionHandler() { - Thread.setDefaultUncaughtExceptionHandler(Thread.getDefaultUncaughtExceptionHandler()); - } - - private static void logManager$() { - new java.util.logging.LogManager() { - }; - } - @SuppressWarnings("deprecation") @SuppressForbidden(reason = "We're required to prevent calls to this forbidden API") private static void datagramSocket$$setDatagramSocketImplFactory() throws IOException {