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
60010f991e
44 changed files with 1264 additions and 332 deletions
|
@ -66,7 +66,7 @@ public class InstrumentationServiceImpl implements InstrumentationService {
|
|||
|
||||
private static final Type CLASS_TYPE = Type.getType(Class.class);
|
||||
|
||||
static MethodKey parseCheckerMethodSignature(String checkerMethodName, Type[] checkerMethodArgumentTypes) {
|
||||
static ParsedCheckerMethod parseCheckerMethodName(String checkerMethodName) {
|
||||
boolean targetMethodIsStatic;
|
||||
int classNameEndIndex = checkerMethodName.lastIndexOf("$$");
|
||||
int methodNameStartIndex;
|
||||
|
@ -100,9 +100,14 @@ public class InstrumentationServiceImpl implements InstrumentationService {
|
|||
if (targetClassName.isBlank()) {
|
||||
throw new IllegalArgumentException(String.format(Locale.ROOT, "Checker method %s has no class name", checkerMethodName));
|
||||
}
|
||||
return new ParsedCheckerMethod(targetClassName, targetMethodName, targetMethodIsStatic, targetMethodIsCtor);
|
||||
}
|
||||
|
||||
static MethodKey parseCheckerMethodSignature(String checkerMethodName, Type[] checkerMethodArgumentTypes) {
|
||||
ParsedCheckerMethod checkerMethod = parseCheckerMethodName(checkerMethodName);
|
||||
|
||||
final List<String> targetParameterTypes;
|
||||
if (targetMethodIsStatic || targetMethodIsCtor) {
|
||||
if (checkerMethod.targetMethodIsStatic() || checkerMethod.targetMethodIsCtor()) {
|
||||
if (checkerMethodArgumentTypes.length < 1 || CLASS_TYPE.equals(checkerMethodArgumentTypes[0]) == false) {
|
||||
throw new IllegalArgumentException(
|
||||
String.format(
|
||||
|
@ -130,7 +135,13 @@ public class InstrumentationServiceImpl implements InstrumentationService {
|
|||
}
|
||||
targetParameterTypes = Arrays.stream(checkerMethodArgumentTypes).skip(2).map(Type::getInternalName).toList();
|
||||
}
|
||||
boolean hasReceiver = (targetMethodIsStatic || targetMethodIsCtor) == false;
|
||||
return new MethodKey(targetClassName, targetMethodName, targetParameterTypes);
|
||||
return new MethodKey(checkerMethod.targetClassName(), checkerMethod.targetMethodName(), targetParameterTypes);
|
||||
}
|
||||
|
||||
private record ParsedCheckerMethod(
|
||||
String targetClassName,
|
||||
String targetMethodName,
|
||||
boolean targetMethodIsStatic,
|
||||
boolean targetMethodIsCtor
|
||||
) {}
|
||||
}
|
||||
|
|
|
@ -9,6 +9,13 @@
|
|||
|
||||
package org.elasticsearch.entitlement.bridge;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.io.PrintStream;
|
||||
import java.io.PrintWriter;
|
||||
import java.net.ContentHandlerFactory;
|
||||
import java.net.DatagramSocketImplFactory;
|
||||
import java.net.FileNameMap;
|
||||
import java.net.SocketImplFactory;
|
||||
import java.net.URL;
|
||||
import java.net.URLStreamHandlerFactory;
|
||||
import java.util.List;
|
||||
|
@ -21,26 +28,42 @@ import javax.net.ssl.SSLSocketFactory;
|
|||
@SuppressWarnings("unused") // Called from instrumentation code inserted by the Entitlements agent
|
||||
public interface EntitlementChecker {
|
||||
|
||||
////////////////////
|
||||
//
|
||||
// Exit the JVM process
|
||||
//
|
||||
|
||||
void check$java_lang_Runtime$exit(Class<?> callerClass, Runtime runtime, int status);
|
||||
|
||||
void check$java_lang_Runtime$halt(Class<?> callerClass, Runtime runtime, int status);
|
||||
|
||||
////////////////////
|
||||
//
|
||||
// ClassLoader ctor
|
||||
//
|
||||
|
||||
void check$java_lang_ClassLoader$(Class<?> callerClass);
|
||||
|
||||
void check$java_lang_ClassLoader$(Class<?> callerClass, ClassLoader parent);
|
||||
|
||||
void check$java_lang_ClassLoader$(Class<?> callerClass, String name, ClassLoader parent);
|
||||
|
||||
////////////////////
|
||||
//
|
||||
// SecureClassLoader ctor
|
||||
//
|
||||
|
||||
void check$java_security_SecureClassLoader$(Class<?> callerClass);
|
||||
|
||||
void check$java_security_SecureClassLoader$(Class<?> callerClass, ClassLoader parent);
|
||||
|
||||
void check$java_security_SecureClassLoader$(Class<?> callerClass, String name, ClassLoader parent);
|
||||
|
||||
////////////////////
|
||||
//
|
||||
// URLClassLoader constructors
|
||||
//
|
||||
|
||||
void check$java_net_URLClassLoader$(Class<?> callerClass, URL[] urls);
|
||||
|
||||
void check$java_net_URLClassLoader$(Class<?> callerClass, URL[] urls, ClassLoader parent);
|
||||
|
@ -51,7 +74,11 @@ public interface EntitlementChecker {
|
|||
|
||||
void check$java_net_URLClassLoader$(Class<?> callerClass, String name, URL[] urls, ClassLoader parent, URLStreamHandlerFactory factory);
|
||||
|
||||
////////////////////
|
||||
//
|
||||
// "setFactory" methods
|
||||
//
|
||||
|
||||
void check$javax_net_ssl_HttpsURLConnection$setSSLSocketFactory(Class<?> callerClass, HttpsURLConnection conn, SSLSocketFactory sf);
|
||||
|
||||
void check$javax_net_ssl_HttpsURLConnection$$setDefaultSSLSocketFactory(Class<?> callerClass, SSLSocketFactory sf);
|
||||
|
@ -60,9 +87,82 @@ public interface EntitlementChecker {
|
|||
|
||||
void check$javax_net_ssl_SSLContext$$setDefault(Class<?> callerClass, SSLContext context);
|
||||
|
||||
////////////////////
|
||||
//
|
||||
// Process creation
|
||||
//
|
||||
|
||||
void check$java_lang_ProcessBuilder$start(Class<?> callerClass, ProcessBuilder that);
|
||||
|
||||
void check$java_lang_ProcessBuilder$$startPipeline(Class<?> callerClass, List<ProcessBuilder> builders);
|
||||
|
||||
////////////////////
|
||||
//
|
||||
// JVM-wide state changes
|
||||
//
|
||||
|
||||
void check$java_lang_System$$setIn(Class<?> callerClass, InputStream in);
|
||||
|
||||
void check$java_lang_System$$setOut(Class<?> callerClass, PrintStream out);
|
||||
|
||||
void check$java_lang_System$$setErr(Class<?> callerClass, PrintStream err);
|
||||
|
||||
void check$java_lang_Runtime$addShutdownHook(Class<?> callerClass, Runtime runtime, Thread hook);
|
||||
|
||||
void check$java_lang_Runtime$removeShutdownHook(Class<?> callerClass, Runtime runtime, Thread hook);
|
||||
|
||||
void check$jdk_tools_jlink_internal_Jlink$(Class<?> callerClass);
|
||||
|
||||
void check$jdk_tools_jlink_internal_Main$$run(Class<?> callerClass, PrintWriter out, PrintWriter err, String... args);
|
||||
|
||||
void check$jdk_vm_ci_services_JVMCIServiceLocator$$getProviders(Class<?> callerClass, Class<?> service);
|
||||
|
||||
void check$jdk_vm_ci_services_Services$$load(Class<?> callerClass, Class<?> service);
|
||||
|
||||
void check$jdk_vm_ci_services_Services$$loadSingle(Class<?> callerClass, Class<?> service, boolean required);
|
||||
|
||||
void check$com_sun_tools_jdi_VirtualMachineManagerImpl$$virtualMachineManager(Class<?> callerClass);
|
||||
|
||||
void check$java_lang_Thread$$setDefaultUncaughtExceptionHandler(Class<?> callerClass, Thread.UncaughtExceptionHandler ueh);
|
||||
|
||||
void check$java_util_spi_LocaleServiceProvider$(Class<?> callerClass);
|
||||
|
||||
void check$java_text_spi_BreakIteratorProvider$(Class<?> callerClass);
|
||||
|
||||
void check$java_text_spi_CollatorProvider$(Class<?> callerClass);
|
||||
|
||||
void check$java_text_spi_DateFormatProvider$(Class<?> callerClass);
|
||||
|
||||
void check$java_text_spi_DateFormatSymbolsProvider$(Class<?> callerClass);
|
||||
|
||||
void check$java_text_spi_DecimalFormatSymbolsProvider$(Class<?> callerClass);
|
||||
|
||||
void check$java_text_spi_NumberFormatProvider$(Class<?> callerClass);
|
||||
|
||||
void check$java_util_spi_CalendarDataProvider$(Class<?> callerClass);
|
||||
|
||||
void check$java_util_spi_CalendarNameProvider$(Class<?> callerClass);
|
||||
|
||||
void check$java_util_spi_CurrencyNameProvider$(Class<?> callerClass);
|
||||
|
||||
void check$java_util_spi_LocaleNameProvider$(Class<?> callerClass);
|
||||
|
||||
void check$java_util_spi_TimeZoneNameProvider$(Class<?> callerClass);
|
||||
|
||||
void check$java_util_logging_LogManager$(Class<?> callerClass);
|
||||
|
||||
void check$java_net_DatagramSocket$$setDatagramSocketImplFactory(Class<?> callerClass, DatagramSocketImplFactory fac);
|
||||
|
||||
void check$java_net_HttpURLConnection$$setFollowRedirects(Class<?> callerClass, boolean set);
|
||||
|
||||
void check$java_net_ServerSocket$$setSocketFactory(Class<?> callerClass, SocketImplFactory fac);
|
||||
|
||||
void check$java_net_Socket$$setSocketImplFactory(Class<?> callerClass, SocketImplFactory fac);
|
||||
|
||||
void check$java_net_URL$$setURLStreamHandlerFactory(Class<?> callerClass, URLStreamHandlerFactory fac);
|
||||
|
||||
void check$java_net_URLConnection$$setFileNameMap(Class<?> callerClass, FileNameMap map);
|
||||
|
||||
void check$java_net_URLConnection$$setContentHandlerFactory(Class<?> callerClass, ContentHandlerFactory fac);
|
||||
|
||||
}
|
||||
|
|
|
@ -12,5 +12,8 @@ module org.elasticsearch.entitlement.qa.common {
|
|||
requires org.elasticsearch.base;
|
||||
requires org.elasticsearch.logging;
|
||||
|
||||
// Modules we'll attempt to use in order to exercise entitlements
|
||||
requires java.logging;
|
||||
|
||||
exports org.elasticsearch.entitlement.qa.common;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,334 @@
|
|||
/*
|
||||
* 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.common;
|
||||
|
||||
import java.net.InetAddress;
|
||||
import java.net.Socket;
|
||||
import java.security.cert.Certificate;
|
||||
import java.text.BreakIterator;
|
||||
import java.text.Collator;
|
||||
import java.text.DateFormat;
|
||||
import java.text.DateFormatSymbols;
|
||||
import java.text.DecimalFormatSymbols;
|
||||
import java.text.NumberFormat;
|
||||
import java.text.spi.BreakIteratorProvider;
|
||||
import java.text.spi.CollatorProvider;
|
||||
import java.text.spi.DateFormatProvider;
|
||||
import java.text.spi.DateFormatSymbolsProvider;
|
||||
import java.text.spi.DecimalFormatSymbolsProvider;
|
||||
import java.text.spi.NumberFormatProvider;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.spi.CalendarDataProvider;
|
||||
import java.util.spi.CalendarNameProvider;
|
||||
import java.util.spi.CurrencyNameProvider;
|
||||
import java.util.spi.LocaleNameProvider;
|
||||
import java.util.spi.LocaleServiceProvider;
|
||||
import java.util.spi.TimeZoneNameProvider;
|
||||
|
||||
import javax.net.ssl.HttpsURLConnection;
|
||||
import javax.net.ssl.SSLSocketFactory;
|
||||
|
||||
/**
|
||||
* A collection of concrete subclasses that we can instantiate but that don't actually work.
|
||||
* <p>
|
||||
* A bit like Mockito but way more painful.
|
||||
*/
|
||||
class DummyImplementations {
|
||||
|
||||
static class DummyLocaleServiceProvider extends LocaleServiceProvider {
|
||||
|
||||
@Override
|
||||
public Locale[] getAvailableLocales() {
|
||||
throw unexpected();
|
||||
}
|
||||
}
|
||||
|
||||
static class DummyBreakIteratorProvider extends BreakIteratorProvider {
|
||||
|
||||
@Override
|
||||
public BreakIterator getWordInstance(Locale locale) {
|
||||
throw unexpected();
|
||||
}
|
||||
|
||||
@Override
|
||||
public BreakIterator getLineInstance(Locale locale) {
|
||||
throw unexpected();
|
||||
}
|
||||
|
||||
@Override
|
||||
public BreakIterator getCharacterInstance(Locale locale) {
|
||||
throw unexpected();
|
||||
}
|
||||
|
||||
@Override
|
||||
public BreakIterator getSentenceInstance(Locale locale) {
|
||||
throw unexpected();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Locale[] getAvailableLocales() {
|
||||
throw unexpected();
|
||||
}
|
||||
}
|
||||
|
||||
static class DummyCollatorProvider extends CollatorProvider {
|
||||
|
||||
@Override
|
||||
public Collator getInstance(Locale locale) {
|
||||
throw unexpected();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Locale[] getAvailableLocales() {
|
||||
throw unexpected();
|
||||
}
|
||||
}
|
||||
|
||||
static class DummyDateFormatProvider extends DateFormatProvider {
|
||||
|
||||
@Override
|
||||
public DateFormat getTimeInstance(int style, Locale locale) {
|
||||
throw unexpected();
|
||||
}
|
||||
|
||||
@Override
|
||||
public DateFormat getDateInstance(int style, Locale locale) {
|
||||
throw unexpected();
|
||||
}
|
||||
|
||||
@Override
|
||||
public DateFormat getDateTimeInstance(int dateStyle, int timeStyle, Locale locale) {
|
||||
throw unexpected();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Locale[] getAvailableLocales() {
|
||||
throw unexpected();
|
||||
}
|
||||
}
|
||||
|
||||
static class DummyDateFormatSymbolsProvider extends DateFormatSymbolsProvider {
|
||||
|
||||
@Override
|
||||
public DateFormatSymbols getInstance(Locale locale) {
|
||||
throw unexpected();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Locale[] getAvailableLocales() {
|
||||
throw unexpected();
|
||||
}
|
||||
}
|
||||
|
||||
static class DummyDecimalFormatSymbolsProvider extends DecimalFormatSymbolsProvider {
|
||||
|
||||
@Override
|
||||
public DecimalFormatSymbols getInstance(Locale locale) {
|
||||
throw unexpected();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Locale[] getAvailableLocales() {
|
||||
throw unexpected();
|
||||
}
|
||||
}
|
||||
|
||||
static class DummyNumberFormatProvider extends NumberFormatProvider {
|
||||
|
||||
@Override
|
||||
public NumberFormat getCurrencyInstance(Locale locale) {
|
||||
throw unexpected();
|
||||
}
|
||||
|
||||
@Override
|
||||
public NumberFormat getIntegerInstance(Locale locale) {
|
||||
throw unexpected();
|
||||
}
|
||||
|
||||
@Override
|
||||
public NumberFormat getNumberInstance(Locale locale) {
|
||||
throw unexpected();
|
||||
}
|
||||
|
||||
@Override
|
||||
public NumberFormat getPercentInstance(Locale locale) {
|
||||
throw unexpected();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Locale[] getAvailableLocales() {
|
||||
throw unexpected();
|
||||
}
|
||||
}
|
||||
|
||||
static class DummyCalendarDataProvider extends CalendarDataProvider {
|
||||
|
||||
@Override
|
||||
public int getFirstDayOfWeek(Locale locale) {
|
||||
throw unexpected();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMinimalDaysInFirstWeek(Locale locale) {
|
||||
throw unexpected();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Locale[] getAvailableLocales() {
|
||||
throw unexpected();
|
||||
}
|
||||
}
|
||||
|
||||
static class DummyCalendarNameProvider extends CalendarNameProvider {
|
||||
|
||||
@Override
|
||||
public String getDisplayName(String calendarType, int field, int value, int style, Locale locale) {
|
||||
throw unexpected();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Integer> getDisplayNames(String calendarType, int field, int style, Locale locale) {
|
||||
throw unexpected();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Locale[] getAvailableLocales() {
|
||||
throw unexpected();
|
||||
}
|
||||
}
|
||||
|
||||
static class DummyCurrencyNameProvider extends CurrencyNameProvider {
|
||||
|
||||
@Override
|
||||
public String getSymbol(String currencyCode, Locale locale) {
|
||||
throw unexpected();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Locale[] getAvailableLocales() {
|
||||
throw unexpected();
|
||||
}
|
||||
}
|
||||
|
||||
static class DummyLocaleNameProvider extends LocaleNameProvider {
|
||||
|
||||
@Override
|
||||
public String getDisplayLanguage(String languageCode, Locale locale) {
|
||||
throw unexpected();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDisplayCountry(String countryCode, Locale locale) {
|
||||
throw unexpected();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDisplayVariant(String variant, Locale locale) {
|
||||
throw unexpected();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Locale[] getAvailableLocales() {
|
||||
throw unexpected();
|
||||
}
|
||||
}
|
||||
|
||||
static class DummyTimeZoneNameProvider extends TimeZoneNameProvider {
|
||||
|
||||
@Override
|
||||
public String getDisplayName(String ID, boolean daylight, int style, Locale locale) {
|
||||
throw unexpected();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Locale[] getAvailableLocales() {
|
||||
throw unexpected();
|
||||
}
|
||||
}
|
||||
|
||||
static class DummyHttpsURLConnection extends HttpsURLConnection {
|
||||
DummyHttpsURLConnection() {
|
||||
super(null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void connect() {
|
||||
throw unexpected();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void disconnect() {
|
||||
throw unexpected();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean usingProxy() {
|
||||
throw unexpected();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getCipherSuite() {
|
||||
throw unexpected();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Certificate[] getLocalCertificates() {
|
||||
throw unexpected();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Certificate[] getServerCertificates() {
|
||||
throw unexpected();
|
||||
}
|
||||
}
|
||||
|
||||
static class DummySSLSocketFactory extends SSLSocketFactory {
|
||||
@Override
|
||||
public Socket createSocket(String host, int port) {
|
||||
throw unexpected();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Socket createSocket(String host, int port, InetAddress localHost, int localPort) {
|
||||
throw unexpected();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Socket createSocket(InetAddress host, int port) {
|
||||
throw unexpected();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Socket createSocket(InetAddress address, int port, InetAddress localAddress, int localPort) {
|
||||
throw unexpected();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] getDefaultCipherSuites() {
|
||||
throw unexpected();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] getSupportedCipherSuites() {
|
||||
throw unexpected();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Socket createSocket(Socket s, String host, int port, boolean autoClose) {
|
||||
throw unexpected();
|
||||
}
|
||||
}
|
||||
|
||||
private static RuntimeException unexpected() {
|
||||
return new IllegalStateException("This method isn't supposed to be called");
|
||||
}
|
||||
|
||||
}
|
|
@ -12,6 +12,18 @@ package org.elasticsearch.entitlement.qa.common;
|
|||
import org.elasticsearch.client.internal.node.NodeClient;
|
||||
import org.elasticsearch.common.Strings;
|
||||
import org.elasticsearch.core.SuppressForbidden;
|
||||
import org.elasticsearch.entitlement.qa.common.DummyImplementations.DummyBreakIteratorProvider;
|
||||
import org.elasticsearch.entitlement.qa.common.DummyImplementations.DummyCalendarDataProvider;
|
||||
import org.elasticsearch.entitlement.qa.common.DummyImplementations.DummyCalendarNameProvider;
|
||||
import org.elasticsearch.entitlement.qa.common.DummyImplementations.DummyCollatorProvider;
|
||||
import org.elasticsearch.entitlement.qa.common.DummyImplementations.DummyCurrencyNameProvider;
|
||||
import org.elasticsearch.entitlement.qa.common.DummyImplementations.DummyDateFormatProvider;
|
||||
import org.elasticsearch.entitlement.qa.common.DummyImplementations.DummyDateFormatSymbolsProvider;
|
||||
import org.elasticsearch.entitlement.qa.common.DummyImplementations.DummyDecimalFormatSymbolsProvider;
|
||||
import org.elasticsearch.entitlement.qa.common.DummyImplementations.DummyLocaleNameProvider;
|
||||
import org.elasticsearch.entitlement.qa.common.DummyImplementations.DummyLocaleServiceProvider;
|
||||
import org.elasticsearch.entitlement.qa.common.DummyImplementations.DummyNumberFormatProvider;
|
||||
import org.elasticsearch.entitlement.qa.common.DummyImplementations.DummyTimeZoneNameProvider;
|
||||
import org.elasticsearch.logging.LogManager;
|
||||
import org.elasticsearch.logging.Logger;
|
||||
import org.elasticsearch.rest.BaseRestHandler;
|
||||
|
@ -21,8 +33,15 @@ import org.elasticsearch.rest.RestStatus;
|
|||
|
||||
import java.io.IOException;
|
||||
import java.io.UncheckedIOException;
|
||||
import java.net.DatagramSocket;
|
||||
import java.net.DatagramSocketImpl;
|
||||
import java.net.DatagramSocketImplFactory;
|
||||
import java.net.HttpURLConnection;
|
||||
import java.net.ServerSocket;
|
||||
import java.net.Socket;
|
||||
import java.net.URL;
|
||||
import java.net.URLClassLoader;
|
||||
import java.net.URLConnection;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
@ -40,6 +59,7 @@ import static org.elasticsearch.rest.RestRequest.Method.GET;
|
|||
|
||||
public class RestEntitlementsCheckAction extends BaseRestHandler {
|
||||
private static final Logger logger = LogManager.getLogger(RestEntitlementsCheckAction.class);
|
||||
public static final Thread NO_OP_SHUTDOWN_HOOK = new Thread(() -> {}, "Shutdown hook for testing");
|
||||
private final String prefix;
|
||||
|
||||
record CheckAction(Runnable action, boolean isAlwaysDeniedToPlugins) {
|
||||
|
@ -69,11 +89,45 @@ public class RestEntitlementsCheckAction extends BaseRestHandler {
|
|||
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("set_default_ssl_context", alwaysDenied(RestEntitlementsCheckAction::setDefaultSSLContext)),
|
||||
entry("system_setIn", alwaysDenied(RestEntitlementsCheckAction::system$$setIn)),
|
||||
entry("system_setOut", alwaysDenied(RestEntitlementsCheckAction::system$$setOut)),
|
||||
entry("system_setErr", alwaysDenied(RestEntitlementsCheckAction::system$$setErr)),
|
||||
entry("runtime_addShutdownHook", alwaysDenied(RestEntitlementsCheckAction::runtime$addShutdownHook)),
|
||||
entry("runtime_removeShutdownHook", alwaysDenied(RestEntitlementsCheckAction::runtime$$removeShutdownHook)),
|
||||
entry(
|
||||
"thread_setDefaultUncaughtExceptionHandler",
|
||||
alwaysDenied(RestEntitlementsCheckAction::thread$$setDefaultUncaughtExceptionHandler)
|
||||
),
|
||||
entry("localeServiceProvider", alwaysDenied(RestEntitlementsCheckAction::localeServiceProvider$)),
|
||||
entry("breakIteratorProvider", alwaysDenied(RestEntitlementsCheckAction::breakIteratorProvider$)),
|
||||
entry("collatorProvider", alwaysDenied(RestEntitlementsCheckAction::collatorProvider$)),
|
||||
entry("dateFormatProvider", alwaysDenied(RestEntitlementsCheckAction::dateFormatProvider$)),
|
||||
entry("dateFormatSymbolsProvider", alwaysDenied(RestEntitlementsCheckAction::dateFormatSymbolsProvider$)),
|
||||
entry("decimalFormatSymbolsProvider", alwaysDenied(RestEntitlementsCheckAction::decimalFormatSymbolsProvider$)),
|
||||
entry("numberFormatProvider", alwaysDenied(RestEntitlementsCheckAction::numberFormatProvider$)),
|
||||
entry("calendarDataProvider", alwaysDenied(RestEntitlementsCheckAction::calendarDataProvider$)),
|
||||
entry("calendarNameProvider", alwaysDenied(RestEntitlementsCheckAction::calendarNameProvider$)),
|
||||
entry("currencyNameProvider", alwaysDenied(RestEntitlementsCheckAction::currencyNameProvider$)),
|
||||
entry("localeNameProvider", alwaysDenied(RestEntitlementsCheckAction::localeNameProvider$)),
|
||||
entry("timeZoneNameProvider", alwaysDenied(RestEntitlementsCheckAction::timeZoneNameProvider$)),
|
||||
entry("logManager", alwaysDenied(RestEntitlementsCheckAction::logManager$)),
|
||||
|
||||
// This group is a bit nasty: if entitlements don't prevent these, then networking is
|
||||
// irreparably borked for the remainder of the test run.
|
||||
entry(
|
||||
"datagramSocket_setDatagramSocketImplFactory",
|
||||
alwaysDenied(RestEntitlementsCheckAction::datagramSocket$$setDatagramSocketImplFactory)
|
||||
),
|
||||
entry("httpURLConnection_setFollowRedirects", alwaysDenied(RestEntitlementsCheckAction::httpURLConnection$$setFollowRedirects)),
|
||||
entry("serverSocket_setSocketFactory", alwaysDenied(RestEntitlementsCheckAction::serverSocket$$setSocketFactory)),
|
||||
entry("socket_setSocketImplFactory", alwaysDenied(RestEntitlementsCheckAction::socket$$setSocketImplFactory)),
|
||||
entry("url_setURLStreamHandlerFactory", alwaysDenied(RestEntitlementsCheckAction::url$$setURLStreamHandlerFactory)),
|
||||
entry("urlConnection_setFileNameMap", alwaysDenied(RestEntitlementsCheckAction::urlConnection$$setFileNameMap)),
|
||||
entry("urlConnection_setContentHandlerFactory", alwaysDenied(RestEntitlementsCheckAction::urlConnection$$setContentHandlerFactory))
|
||||
);
|
||||
|
||||
private static void setDefaultSSLContext() {
|
||||
logger.info("Calling SSLContext.setDefault");
|
||||
try {
|
||||
SSLContext.setDefault(SSLContext.getDefault());
|
||||
} catch (NoSuchAlgorithmException e) {
|
||||
|
@ -82,13 +136,11 @@ public class RestEntitlementsCheckAction extends BaseRestHandler {
|
|||
}
|
||||
|
||||
private static void setDefaultHostnameVerifier() {
|
||||
logger.info("Calling HttpsURLConnection.setDefaultHostnameVerifier");
|
||||
HttpsURLConnection.setDefaultHostnameVerifier((hostname, session) -> false);
|
||||
}
|
||||
|
||||
private static void setDefaultSSLSocketFactory() {
|
||||
logger.info("Calling HttpsURLConnection.setDefaultSSLSocketFactory");
|
||||
HttpsURLConnection.setDefaultSSLSocketFactory(new TestSSLSocketFactory());
|
||||
HttpsURLConnection.setDefaultSSLSocketFactory(new DummyImplementations.DummySSLSocketFactory());
|
||||
}
|
||||
|
||||
@SuppressForbidden(reason = "Specifically testing Runtime.exit")
|
||||
|
@ -126,9 +178,137 @@ public class RestEntitlementsCheckAction extends BaseRestHandler {
|
|||
}
|
||||
|
||||
private static void setHttpsConnectionProperties() {
|
||||
logger.info("Calling setSSLSocketFactory");
|
||||
var connection = new TestHttpsURLConnection();
|
||||
connection.setSSLSocketFactory(new TestSSLSocketFactory());
|
||||
new DummyImplementations.DummyHttpsURLConnection().setSSLSocketFactory(new DummyImplementations.DummySSLSocketFactory());
|
||||
}
|
||||
|
||||
private static void system$$setIn() {
|
||||
System.setIn(System.in);
|
||||
}
|
||||
|
||||
@SuppressForbidden(reason = "This should be a no-op so we don't interfere with system streams")
|
||||
private static void system$$setOut() {
|
||||
System.setOut(System.out);
|
||||
}
|
||||
|
||||
@SuppressForbidden(reason = "This should be a no-op so we don't interfere with system streams")
|
||||
private static void system$$setErr() {
|
||||
System.setErr(System.err);
|
||||
}
|
||||
|
||||
private static void runtime$addShutdownHook() {
|
||||
Runtime.getRuntime().addShutdownHook(NO_OP_SHUTDOWN_HOOK);
|
||||
}
|
||||
|
||||
private static void runtime$$removeShutdownHook() {
|
||||
Runtime.getRuntime().removeShutdownHook(NO_OP_SHUTDOWN_HOOK);
|
||||
}
|
||||
|
||||
private static void thread$$setDefaultUncaughtExceptionHandler() {
|
||||
Thread.setDefaultUncaughtExceptionHandler(Thread.getDefaultUncaughtExceptionHandler());
|
||||
}
|
||||
|
||||
private static void localeServiceProvider$() {
|
||||
new DummyLocaleServiceProvider();
|
||||
}
|
||||
|
||||
private static void breakIteratorProvider$() {
|
||||
new DummyBreakIteratorProvider();
|
||||
}
|
||||
|
||||
private static void collatorProvider$() {
|
||||
new DummyCollatorProvider();
|
||||
}
|
||||
|
||||
private static void dateFormatProvider$() {
|
||||
new DummyDateFormatProvider();
|
||||
}
|
||||
|
||||
private static void dateFormatSymbolsProvider$() {
|
||||
new DummyDateFormatSymbolsProvider();
|
||||
}
|
||||
|
||||
private static void decimalFormatSymbolsProvider$() {
|
||||
new DummyDecimalFormatSymbolsProvider();
|
||||
}
|
||||
|
||||
private static void numberFormatProvider$() {
|
||||
new DummyNumberFormatProvider();
|
||||
}
|
||||
|
||||
private static void calendarDataProvider$() {
|
||||
new DummyCalendarDataProvider();
|
||||
}
|
||||
|
||||
private static void calendarNameProvider$() {
|
||||
new DummyCalendarNameProvider();
|
||||
}
|
||||
|
||||
private static void currencyNameProvider$() {
|
||||
new DummyCurrencyNameProvider();
|
||||
}
|
||||
|
||||
private static void localeNameProvider$() {
|
||||
new DummyLocaleNameProvider();
|
||||
}
|
||||
|
||||
private static void timeZoneNameProvider$() {
|
||||
new DummyTimeZoneNameProvider();
|
||||
}
|
||||
|
||||
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() {
|
||||
try {
|
||||
DatagramSocket.setDatagramSocketImplFactory(new DatagramSocketImplFactory() {
|
||||
@Override
|
||||
public DatagramSocketImpl createDatagramSocketImpl() {
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
});
|
||||
} catch (IOException e) {
|
||||
throw new IllegalStateException(e);
|
||||
}
|
||||
}
|
||||
|
||||
private static void httpURLConnection$$setFollowRedirects() {
|
||||
HttpURLConnection.setFollowRedirects(HttpURLConnection.getFollowRedirects());
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
@SuppressForbidden(reason = "We're required to prevent calls to this forbidden API")
|
||||
private static void serverSocket$$setSocketFactory() {
|
||||
try {
|
||||
ServerSocket.setSocketFactory(() -> { throw new IllegalStateException(); });
|
||||
} catch (IOException e) {
|
||||
throw new IllegalStateException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
@SuppressForbidden(reason = "We're required to prevent calls to this forbidden API")
|
||||
private static void socket$$setSocketImplFactory() {
|
||||
try {
|
||||
Socket.setSocketImplFactory(() -> { throw new IllegalStateException(); });
|
||||
} catch (IOException e) {
|
||||
throw new IllegalStateException(e);
|
||||
}
|
||||
}
|
||||
|
||||
private static void url$$setURLStreamHandlerFactory() {
|
||||
URL.setURLStreamHandlerFactory(__ -> { throw new IllegalStateException(); });
|
||||
}
|
||||
|
||||
private static void urlConnection$$setFileNameMap() {
|
||||
URLConnection.setFileNameMap(__ -> { throw new IllegalStateException(); });
|
||||
}
|
||||
|
||||
private static void urlConnection$$setContentHandlerFactory() {
|
||||
URLConnection.setContentHandlerFactory(__ -> { throw new IllegalStateException(); });
|
||||
}
|
||||
|
||||
public RestEntitlementsCheckAction(String prefix) {
|
||||
|
|
|
@ -1,48 +0,0 @@
|
|||
/*
|
||||
* 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.common;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.security.cert.Certificate;
|
||||
|
||||
import javax.net.ssl.HttpsURLConnection;
|
||||
import javax.net.ssl.SSLPeerUnverifiedException;
|
||||
|
||||
class TestHttpsURLConnection extends HttpsURLConnection {
|
||||
TestHttpsURLConnection() {
|
||||
super(null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void connect() throws IOException {}
|
||||
|
||||
@Override
|
||||
public void disconnect() {}
|
||||
|
||||
@Override
|
||||
public boolean usingProxy() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getCipherSuite() {
|
||||
return "";
|
||||
}
|
||||
|
||||
@Override
|
||||
public Certificate[] getLocalCertificates() {
|
||||
return new Certificate[0];
|
||||
}
|
||||
|
||||
@Override
|
||||
public Certificate[] getServerCertificates() throws SSLPeerUnverifiedException {
|
||||
return new Certificate[0];
|
||||
}
|
||||
}
|
|
@ -1,54 +0,0 @@
|
|||
/*
|
||||
* 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.common;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.InetAddress;
|
||||
import java.net.Socket;
|
||||
import java.net.UnknownHostException;
|
||||
|
||||
import javax.net.ssl.SSLSocketFactory;
|
||||
|
||||
class TestSSLSocketFactory extends SSLSocketFactory {
|
||||
@Override
|
||||
public Socket createSocket(String host, int port) throws IOException, UnknownHostException {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Socket createSocket(String host, int port, InetAddress localHost, int localPort) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Socket createSocket(InetAddress host, int port) throws IOException {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Socket createSocket(InetAddress address, int port, InetAddress localAddress, int localPort) throws IOException {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] getDefaultCipherSuites() {
|
||||
return new String[0];
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] getSupportedCipherSuites() {
|
||||
return new String[0];
|
||||
}
|
||||
|
||||
@Override
|
||||
public Socket createSocket(Socket s, String host, int port, boolean autoClose) throws IOException {
|
||||
return null;
|
||||
}
|
||||
}
|
|
@ -32,7 +32,7 @@ public class EntitlementsDeniedIT extends ESRestTestCase {
|
|||
.systemProperty("es.entitlements.enabled", "true")
|
||||
.setting("xpack.security.enabled", "false")
|
||||
// Logs in libs/entitlement/qa/build/test-results/javaRestTest/TEST-org.elasticsearch.entitlement.qa.EntitlementsDeniedIT.xml
|
||||
.setting("logger.org.elasticsearch.entitlement", "TRACE")
|
||||
// .setting("logger.org.elasticsearch.entitlement", "DEBUG")
|
||||
.build();
|
||||
|
||||
@Override
|
||||
|
|
|
@ -12,6 +12,13 @@ package org.elasticsearch.entitlement.runtime.api;
|
|||
import org.elasticsearch.entitlement.bridge.EntitlementChecker;
|
||||
import org.elasticsearch.entitlement.runtime.policy.PolicyManager;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.io.PrintStream;
|
||||
import java.io.PrintWriter;
|
||||
import java.net.ContentHandlerFactory;
|
||||
import java.net.DatagramSocketImplFactory;
|
||||
import java.net.FileNameMap;
|
||||
import java.net.SocketImplFactory;
|
||||
import java.net.URL;
|
||||
import java.net.URLStreamHandlerFactory;
|
||||
import java.util.List;
|
||||
|
@ -115,6 +122,166 @@ public class ElasticsearchEntitlementChecker implements EntitlementChecker {
|
|||
policyManager.checkStartProcess(callerClass);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void check$java_lang_System$$setIn(Class<?> callerClass, InputStream in) {
|
||||
policyManager.checkChangeJVMGlobalState(callerClass);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void check$java_lang_System$$setOut(Class<?> callerClass, PrintStream out) {
|
||||
policyManager.checkChangeJVMGlobalState(callerClass);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void check$java_lang_System$$setErr(Class<?> callerClass, PrintStream err) {
|
||||
policyManager.checkChangeJVMGlobalState(callerClass);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void check$java_lang_Runtime$addShutdownHook(Class<?> callerClass, Runtime runtime, Thread hook) {
|
||||
policyManager.checkChangeJVMGlobalState(callerClass);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void check$java_lang_Runtime$removeShutdownHook(Class<?> callerClass, Runtime runtime, Thread hook) {
|
||||
policyManager.checkChangeJVMGlobalState(callerClass);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void check$jdk_tools_jlink_internal_Jlink$(Class<?> callerClass) {
|
||||
policyManager.checkChangeJVMGlobalState(callerClass);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void check$jdk_tools_jlink_internal_Main$$run(Class<?> callerClass, PrintWriter out, PrintWriter err, String... args) {
|
||||
policyManager.checkChangeJVMGlobalState(callerClass);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void check$jdk_vm_ci_services_JVMCIServiceLocator$$getProviders(Class<?> callerClass, Class<?> service) {
|
||||
policyManager.checkChangeJVMGlobalState(callerClass);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void check$jdk_vm_ci_services_Services$$load(Class<?> callerClass, Class<?> service) {
|
||||
policyManager.checkChangeJVMGlobalState(callerClass);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void check$jdk_vm_ci_services_Services$$loadSingle(Class<?> callerClass, Class<?> service, boolean required) {
|
||||
policyManager.checkChangeJVMGlobalState(callerClass);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void check$com_sun_tools_jdi_VirtualMachineManagerImpl$$virtualMachineManager(Class<?> callerClass) {
|
||||
policyManager.checkChangeJVMGlobalState(callerClass);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void check$java_lang_Thread$$setDefaultUncaughtExceptionHandler(Class<?> callerClass, Thread.UncaughtExceptionHandler ueh) {
|
||||
policyManager.checkChangeJVMGlobalState(callerClass);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void check$java_util_spi_LocaleServiceProvider$(Class<?> callerClass) {
|
||||
policyManager.checkChangeJVMGlobalState(callerClass);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void check$java_text_spi_BreakIteratorProvider$(Class<?> callerClass) {
|
||||
policyManager.checkChangeJVMGlobalState(callerClass);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void check$java_text_spi_CollatorProvider$(Class<?> callerClass) {
|
||||
policyManager.checkChangeJVMGlobalState(callerClass);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void check$java_text_spi_DateFormatProvider$(Class<?> callerClass) {
|
||||
policyManager.checkChangeJVMGlobalState(callerClass);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void check$java_text_spi_DateFormatSymbolsProvider$(Class<?> callerClass) {
|
||||
policyManager.checkChangeJVMGlobalState(callerClass);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void check$java_text_spi_DecimalFormatSymbolsProvider$(Class<?> callerClass) {
|
||||
policyManager.checkChangeJVMGlobalState(callerClass);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void check$java_text_spi_NumberFormatProvider$(Class<?> callerClass) {
|
||||
policyManager.checkChangeJVMGlobalState(callerClass);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void check$java_util_spi_CalendarDataProvider$(Class<?> callerClass) {
|
||||
policyManager.checkChangeJVMGlobalState(callerClass);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void check$java_util_spi_CalendarNameProvider$(Class<?> callerClass) {
|
||||
policyManager.checkChangeJVMGlobalState(callerClass);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void check$java_util_spi_CurrencyNameProvider$(Class<?> callerClass) {
|
||||
policyManager.checkChangeJVMGlobalState(callerClass);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void check$java_util_spi_LocaleNameProvider$(Class<?> callerClass) {
|
||||
policyManager.checkChangeJVMGlobalState(callerClass);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void check$java_util_spi_TimeZoneNameProvider$(Class<?> callerClass) {
|
||||
policyManager.checkChangeJVMGlobalState(callerClass);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void check$java_util_logging_LogManager$(Class<?> callerClass) {
|
||||
policyManager.checkChangeJVMGlobalState(callerClass);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void check$java_net_DatagramSocket$$setDatagramSocketImplFactory(Class<?> callerClass, DatagramSocketImplFactory fac) {
|
||||
policyManager.checkChangeJVMGlobalState(callerClass);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void check$java_net_HttpURLConnection$$setFollowRedirects(Class<?> callerClass, boolean set) {
|
||||
policyManager.checkChangeJVMGlobalState(callerClass);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void check$java_net_ServerSocket$$setSocketFactory(Class<?> callerClass, SocketImplFactory fac) {
|
||||
policyManager.checkChangeJVMGlobalState(callerClass);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void check$java_net_Socket$$setSocketImplFactory(Class<?> callerClass, SocketImplFactory fac) {
|
||||
policyManager.checkChangeJVMGlobalState(callerClass);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void check$java_net_URL$$setURLStreamHandlerFactory(Class<?> callerClass, URLStreamHandlerFactory fac) {
|
||||
policyManager.checkChangeJVMGlobalState(callerClass);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void check$java_net_URLConnection$$setFileNameMap(Class<?> callerClass, FileNameMap map) {
|
||||
policyManager.checkChangeJVMGlobalState(callerClass);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void check$java_net_URLConnection$$setContentHandlerFactory(Class<?> callerClass, ContentHandlerFactory fac) {
|
||||
policyManager.checkChangeJVMGlobalState(callerClass);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void check$javax_net_ssl_HttpsURLConnection$setSSLSocketFactory(
|
||||
Class<?> callerClass,
|
||||
|
@ -126,16 +293,16 @@ public class ElasticsearchEntitlementChecker implements EntitlementChecker {
|
|||
|
||||
@Override
|
||||
public void check$javax_net_ssl_HttpsURLConnection$$setDefaultSSLSocketFactory(Class<?> callerClass, SSLSocketFactory sf) {
|
||||
policyManager.checkSetGlobalHttpsConnectionProperties(callerClass);
|
||||
policyManager.checkChangeJVMGlobalState(callerClass);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void check$javax_net_ssl_HttpsURLConnection$$setDefaultHostnameVerifier(Class<?> callerClass, HostnameVerifier hv) {
|
||||
policyManager.checkSetGlobalHttpsConnectionProperties(callerClass);
|
||||
policyManager.checkChangeJVMGlobalState(callerClass);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void check$javax_net_ssl_SSLContext$$setDefault(Class<?> callerClass, SSLContext context) {
|
||||
policyManager.checkSetGlobalHttpsConnectionProperties(callerClass);
|
||||
policyManager.checkChangeJVMGlobalState(callerClass);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -23,12 +23,15 @@ import java.util.Optional;
|
|||
import java.util.Set;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.function.Function;
|
||||
import java.util.function.Supplier;
|
||||
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;
|
||||
import static java.util.stream.Collectors.groupingBy;
|
||||
import static java.util.stream.Collectors.toUnmodifiableMap;
|
||||
|
||||
public class PolicyManager {
|
||||
private static final Logger logger = LogManager.getLogger(PolicyManager.class);
|
||||
|
@ -93,13 +96,13 @@ public class PolicyManager {
|
|||
this.agentEntitlements = agentEntitlements;
|
||||
this.pluginsEntitlements = requireNonNull(pluginPolicies).entrySet()
|
||||
.stream()
|
||||
.collect(Collectors.toUnmodifiableMap(Map.Entry::getKey, e -> buildScopeEntitlementsMap(e.getValue())));
|
||||
.collect(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.moduleName(), scope -> scope.entitlements()));
|
||||
return policy.scopes().stream().collect(toUnmodifiableMap(Scope::moduleName, Scope::entitlements));
|
||||
}
|
||||
|
||||
public void checkStartProcess(Class<?> callerClass) {
|
||||
|
@ -122,6 +125,26 @@ public class PolicyManager {
|
|||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param operationDescription is only called when the operation is not trivially allowed, meaning the check is about to fail;
|
||||
* therefore, its performance is not a major concern.
|
||||
*/
|
||||
private void neverEntitled(Class<?> callerClass, Supplier<String> operationDescription) {
|
||||
var requestingModule = requestingClass(callerClass);
|
||||
if (isTriviallyAllowed(requestingModule)) {
|
||||
return;
|
||||
}
|
||||
|
||||
throw new NotEntitledException(
|
||||
Strings.format(
|
||||
"Not entitled: caller [%s], module [%s], operation [%s]",
|
||||
callerClass,
|
||||
requestingModule.getName(),
|
||||
operationDescription.get()
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
public void checkExitVM(Class<?> callerClass) {
|
||||
checkEntitlementPresent(callerClass, ExitVMEntitlement.class);
|
||||
}
|
||||
|
@ -134,8 +157,23 @@ public class PolicyManager {
|
|||
checkEntitlementPresent(callerClass, SetHttpsConnectionPropertiesEntitlement.class);
|
||||
}
|
||||
|
||||
public void checkSetGlobalHttpsConnectionProperties(Class<?> callerClass) {
|
||||
neverEntitled(callerClass, "set global https connection properties");
|
||||
public void checkChangeJVMGlobalState(Class<?> callerClass) {
|
||||
neverEntitled(callerClass, () -> {
|
||||
// Look up the check$ method to compose an informative error message.
|
||||
// This way, we don't need to painstakingly describe every individual global-state change.
|
||||
Optional<String> checkMethodName = StackWalker.getInstance()
|
||||
.walk(
|
||||
frames -> frames.map(StackFrame::getMethodName)
|
||||
.dropWhile(not(methodName -> methodName.startsWith("check$")))
|
||||
.findFirst()
|
||||
);
|
||||
return checkMethodName.map(this::operationDescription).orElse("change JVM global state");
|
||||
});
|
||||
}
|
||||
|
||||
private String operationDescription(String methodName) {
|
||||
// TODO: Use a more human-readable description. Perhaps share code with InstrumentationServiceImpl.parseCheckerMethodName
|
||||
return methodName.substring(methodName.indexOf('$'));
|
||||
}
|
||||
|
||||
private void checkEntitlementPresent(Class<?> callerClass, Class<? extends Entitlement> entitlementClass) {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue