From 1848d6bb9327853dfff1eb868bd873debcc50311 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lorenzo=20Dematt=C3=A9?= Date: Wed, 15 Jan 2025 22:01:56 +0100 Subject: [PATCH] [Entitlements] Network access checks on Sockets (#120093) --- .../bridge/EntitlementChecker.java | 39 ++++++++ .../qa/common/DummyImplementations.java | 79 ++++++++++++++++ .../qa/common/NetworkAccessCheckActions.java | 62 +++++++++++++ .../common/RestEntitlementsCheckAction.java | 8 +- .../EntitlementInitialization.java | 14 ++- .../api/ElasticsearchEntitlementChecker.java | 90 +++++++++++++++++++ .../runtime/policy/NetworkEntitlement.java | 6 +- .../runtime/policy/PolicyManager.java | 39 +++++--- .../runtime/policy/PolicyManagerTests.java | 34 ++++--- .../plugin-metadata/entitlement-policy.yaml | 4 + .../plugin-metadata/entitlement-policy.yaml | 4 + .../plugin-metadata/entitlement-policy.yaml | 4 + .../plugin-metadata/entitlement-policy.yaml | 4 + 13 files changed, 356 insertions(+), 31 deletions(-) create mode 100644 libs/entitlement/qa/common/src/main/java/org/elasticsearch/entitlement/qa/common/NetworkAccessCheckActions.java create mode 100644 modules/repository-s3/src/main/plugin-metadata/entitlement-policy.yaml create mode 100644 modules/repository-url/src/main/plugin-metadata/entitlement-policy.yaml create mode 100644 plugins/discovery-ec2/src/main/plugin-metadata/entitlement-policy.yaml create mode 100644 x-pack/plugin/core/src/main/plugin-metadata/entitlement-policy.yaml diff --git a/libs/entitlement/bridge/src/main/java/org/elasticsearch/entitlement/bridge/EntitlementChecker.java b/libs/entitlement/bridge/src/main/java/org/elasticsearch/entitlement/bridge/EntitlementChecker.java index a2656c902c24..1e03c61df98e 100644 --- a/libs/entitlement/bridge/src/main/java/org/elasticsearch/entitlement/bridge/EntitlementChecker.java +++ b/libs/entitlement/bridge/src/main/java/org/elasticsearch/entitlement/bridge/EntitlementChecker.java @@ -20,8 +20,11 @@ import java.net.FileNameMap; import java.net.InetAddress; import java.net.MulticastSocket; import java.net.NetworkInterface; +import java.net.Proxy; import java.net.ProxySelector; import java.net.ResponseCache; +import java.net.ServerSocket; +import java.net.Socket; import java.net.SocketAddress; import java.net.SocketImplFactory; import java.net.URL; @@ -215,4 +218,40 @@ public interface EntitlementChecker { void check$java_net_MulticastSocket$leaveGroup(Class callerClass, MulticastSocket that, SocketAddress addr, NetworkInterface ni); void check$java_net_MulticastSocket$send(Class callerClass, MulticastSocket that, DatagramPacket p, byte ttl); + + // Binding/connecting ctor + void check$java_net_ServerSocket$(Class callerClass, int port); + + void check$java_net_ServerSocket$(Class callerClass, int port, int backlog); + + void check$java_net_ServerSocket$(Class callerClass, int port, int backlog, InetAddress bindAddr); + + void check$java_net_ServerSocket$accept(Class callerClass, ServerSocket that); + + void check$java_net_ServerSocket$implAccept(Class callerClass, ServerSocket that, Socket s); + + void check$java_net_ServerSocket$bind(Class callerClass, ServerSocket that, SocketAddress endpoint); + + void check$java_net_ServerSocket$bind(Class callerClass, ServerSocket that, SocketAddress endpoint, int backlog); + + // Binding/connecting ctors + void check$java_net_Socket$(Class callerClass, Proxy proxy); + + void check$java_net_Socket$(Class callerClass, String host, int port); + + void check$java_net_Socket$(Class callerClass, InetAddress address, int port); + + void check$java_net_Socket$(Class callerClass, String host, int port, InetAddress localAddr, int localPort); + + void check$java_net_Socket$(Class callerClass, InetAddress address, int port, InetAddress localAddr, int localPort); + + void check$java_net_Socket$(Class callerClass, String host, int port, boolean stream); + + void check$java_net_Socket$(Class callerClass, InetAddress host, int port, boolean stream); + + void check$java_net_Socket$bind(Class callerClass, Socket that, SocketAddress endpoint); + + void check$java_net_Socket$connect(Class callerClass, Socket that, SocketAddress endpoint); + + void check$java_net_Socket$connect(Class callerClass, Socket that, SocketAddress endpoint, int backlog); } diff --git a/libs/entitlement/qa/common/src/main/java/org/elasticsearch/entitlement/qa/common/DummyImplementations.java b/libs/entitlement/qa/common/src/main/java/org/elasticsearch/entitlement/qa/common/DummyImplementations.java index fae873123528..304aead1e2bf 100644 --- a/libs/entitlement/qa/common/src/main/java/org/elasticsearch/entitlement/qa/common/DummyImplementations.java +++ b/libs/entitlement/qa/common/src/main/java/org/elasticsearch/entitlement/qa/common/DummyImplementations.java @@ -10,14 +10,18 @@ package org.elasticsearch.entitlement.qa.common; import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; import java.net.DatagramPacket; import java.net.DatagramSocket; import java.net.DatagramSocketImpl; import java.net.InetAddress; import java.net.NetworkInterface; +import java.net.ServerSocket; import java.net.Socket; import java.net.SocketAddress; import java.net.SocketException; +import java.net.SocketImpl; import java.security.cert.Certificate; import java.text.BreakIterator; import java.text.Collator; @@ -297,6 +301,81 @@ class DummyImplementations { } } + private static class DummySocketImpl extends SocketImpl { + @Override + protected void create(boolean stream) {} + + @Override + protected void connect(String host, int port) {} + + @Override + protected void connect(InetAddress address, int port) {} + + @Override + protected void connect(SocketAddress address, int timeout) {} + + @Override + protected void bind(InetAddress host, int port) {} + + @Override + protected void listen(int backlog) {} + + @Override + protected void accept(SocketImpl s) {} + + @Override + protected InputStream getInputStream() { + return null; + } + + @Override + protected OutputStream getOutputStream() { + return null; + } + + @Override + protected int available() { + return 0; + } + + @Override + protected void close() {} + + @Override + protected void sendUrgentData(int data) {} + + @Override + public void setOption(int optID, Object value) {} + + @Override + public Object getOption(int optID) { + return null; + } + } + + static class DummySocket extends Socket { + DummySocket() throws SocketException { + super(new DummySocketImpl()); + } + } + + static class DummyServerSocket extends ServerSocket { + DummyServerSocket() { + super(new DummySocketImpl()); + } + } + + static class DummyBoundServerSocket extends ServerSocket { + DummyBoundServerSocket() { + super(new DummySocketImpl()); + } + + @Override + public boolean isBound() { + return true; + } + } + static class DummySSLSocketFactory extends SSLSocketFactory { @Override public Socket createSocket(String host, int port) { diff --git a/libs/entitlement/qa/common/src/main/java/org/elasticsearch/entitlement/qa/common/NetworkAccessCheckActions.java b/libs/entitlement/qa/common/src/main/java/org/elasticsearch/entitlement/qa/common/NetworkAccessCheckActions.java new file mode 100644 index 000000000000..c88d4ce2b11a --- /dev/null +++ b/libs/entitlement/qa/common/src/main/java/org/elasticsearch/entitlement/qa/common/NetworkAccessCheckActions.java @@ -0,0 +1,62 @@ +/* + * 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 org.elasticsearch.core.SuppressForbidden; + +import java.io.IOException; +import java.net.InetAddress; +import java.net.InetSocketAddress; +import java.net.Proxy; +import java.net.ServerSocket; +import java.net.Socket; + +class NetworkAccessCheckActions { + + static void serverSocketAccept() throws IOException { + try (ServerSocket socket = new DummyImplementations.DummyBoundServerSocket()) { + try { + socket.accept(); + } catch (IOException e) { + // Our dummy socket cannot accept connections unless we tell the JDK how to create a socket for it. + // But Socket.setSocketImplFactory(); is one of the methods we always forbid, so we cannot use it. + // Still, we can check accept is called (allowed/denied), we don't care if it fails later for this + // known reason. + assert e.getMessage().contains("client socket implementation factory not set"); + } + } + } + + static void serverSocketBind() throws IOException { + try (ServerSocket socket = new DummyImplementations.DummyServerSocket()) { + socket.bind(null); + } + } + + @SuppressForbidden(reason = "Testing entitlement check on forbidden action") + static void createSocketWithProxy() throws IOException { + try (Socket socket = new Socket(new Proxy(Proxy.Type.HTTP, new InetSocketAddress(0)))) { + assert socket.isBound() == false; + } + } + + static void socketBind() throws IOException { + try (Socket socket = new DummyImplementations.DummySocket()) { + socket.bind(new InetSocketAddress(InetAddress.getLoopbackAddress(), 0)); + } + } + + @SuppressForbidden(reason = "Testing entitlement check on forbidden action") + static void socketConnect() throws IOException { + try (Socket socket = new DummyImplementations.DummySocket()) { + socket.connect(new InetSocketAddress(InetAddress.getLoopbackAddress(), 0)); + } + } +} diff --git a/libs/entitlement/qa/common/src/main/java/org/elasticsearch/entitlement/qa/common/RestEntitlementsCheckAction.java b/libs/entitlement/qa/common/src/main/java/org/elasticsearch/entitlement/qa/common/RestEntitlementsCheckAction.java index ea9a1ec487ec..a156d20e3686 100644 --- a/libs/entitlement/qa/common/src/main/java/org/elasticsearch/entitlement/qa/common/RestEntitlementsCheckAction.java +++ b/libs/entitlement/qa/common/src/main/java/org/elasticsearch/entitlement/qa/common/RestEntitlementsCheckAction.java @@ -149,7 +149,13 @@ public class RestEntitlementsCheckAction extends BaseRestHandler { entry("datagram_socket_send", forPlugins(RestEntitlementsCheckAction::sendDatagramSocket)), entry("datagram_socket_receive", forPlugins(RestEntitlementsCheckAction::receiveDatagramSocket)), entry("datagram_socket_join_group", forPlugins(RestEntitlementsCheckAction::joinGroupDatagramSocket)), - entry("datagram_socket_leave_group", forPlugins(RestEntitlementsCheckAction::leaveGroupDatagramSocket)) + entry("datagram_socket_leave_group", forPlugins(RestEntitlementsCheckAction::leaveGroupDatagramSocket)), + + entry("create_socket_with_proxy", forPlugins(NetworkAccessCheckActions::createSocketWithProxy)), + entry("socket_bind", forPlugins(NetworkAccessCheckActions::socketBind)), + entry("socket_connect", forPlugins(NetworkAccessCheckActions::socketConnect)), + entry("server_socket_bind", forPlugins(NetworkAccessCheckActions::serverSocketBind)), + entry("server_socket_accept", forPlugins(NetworkAccessCheckActions::serverSocketAccept)) ); private static void createURLStreamHandlerProvider() { diff --git a/libs/entitlement/src/main/java/org/elasticsearch/entitlement/initialization/EntitlementInitialization.java b/libs/entitlement/src/main/java/org/elasticsearch/entitlement/initialization/EntitlementInitialization.java index ba5ccbafa70a..9b621461403d 100644 --- a/libs/entitlement/src/main/java/org/elasticsearch/entitlement/initialization/EntitlementInitialization.java +++ b/libs/entitlement/src/main/java/org/elasticsearch/entitlement/initialization/EntitlementInitialization.java @@ -22,6 +22,7 @@ import org.elasticsearch.entitlement.runtime.api.ElasticsearchEntitlementChecker import org.elasticsearch.entitlement.runtime.policy.CreateClassLoaderEntitlement; import org.elasticsearch.entitlement.runtime.policy.Entitlement; import org.elasticsearch.entitlement.runtime.policy.ExitVMEntitlement; +import org.elasticsearch.entitlement.runtime.policy.NetworkEntitlement; import org.elasticsearch.entitlement.runtime.policy.Policy; import org.elasticsearch.entitlement.runtime.policy.PolicyManager; import org.elasticsearch.entitlement.runtime.policy.PolicyParser; @@ -44,6 +45,9 @@ import java.util.Map; import java.util.Set; import java.util.stream.Collectors; +import static org.elasticsearch.entitlement.runtime.policy.NetworkEntitlement.ACCEPT_ACTION; +import static org.elasticsearch.entitlement.runtime.policy.NetworkEntitlement.CONNECT_ACTION; +import static org.elasticsearch.entitlement.runtime.policy.NetworkEntitlement.LISTEN_ACTION; import static org.elasticsearch.entitlement.runtime.policy.PolicyManager.ALL_UNNAMED; /** @@ -97,7 +101,15 @@ public class EntitlementInitialization { List.of( new Scope("org.elasticsearch.base", List.of(new CreateClassLoaderEntitlement())), new Scope("org.elasticsearch.xcontent", List.of(new CreateClassLoaderEntitlement())), - new Scope("org.elasticsearch.server", List.of(new ExitVMEntitlement(), new CreateClassLoaderEntitlement())) + new Scope( + "org.elasticsearch.server", + List.of( + new ExitVMEntitlement(), + new CreateClassLoaderEntitlement(), + new NetworkEntitlement(LISTEN_ACTION | CONNECT_ACTION | ACCEPT_ACTION) + ) + ), + new Scope("org.apache.httpcomponents.httpclient", List.of(new NetworkEntitlement(CONNECT_ACTION))) ) ); // agents run without a module, so this is a special hack for the apm agent diff --git a/libs/entitlement/src/main/java/org/elasticsearch/entitlement/runtime/api/ElasticsearchEntitlementChecker.java b/libs/entitlement/src/main/java/org/elasticsearch/entitlement/runtime/api/ElasticsearchEntitlementChecker.java index 102ed54a873c..695d1c574c7c 100644 --- a/libs/entitlement/src/main/java/org/elasticsearch/entitlement/runtime/api/ElasticsearchEntitlementChecker.java +++ b/libs/entitlement/src/main/java/org/elasticsearch/entitlement/runtime/api/ElasticsearchEntitlementChecker.java @@ -24,8 +24,11 @@ import java.net.FileNameMap; import java.net.InetAddress; import java.net.MulticastSocket; import java.net.NetworkInterface; +import java.net.Proxy; import java.net.ProxySelector; import java.net.ResponseCache; +import java.net.ServerSocket; +import java.net.Socket; import java.net.SocketAddress; import java.net.SocketImplFactory; import java.net.URL; @@ -414,4 +417,91 @@ public class ElasticsearchEntitlementChecker implements EntitlementChecker { public void check$java_net_MulticastSocket$send(Class callerClass, MulticastSocket that, DatagramPacket p, byte ttl) { policyManager.checkNetworkAccess(callerClass, NetworkEntitlement.CONNECT_ACTION | NetworkEntitlement.ACCEPT_ACTION); } + + @Override + public void check$java_net_ServerSocket$(Class callerClass, int port) { + policyManager.checkNetworkAccess(callerClass, NetworkEntitlement.LISTEN_ACTION); + } + + @Override + public void check$java_net_ServerSocket$(Class callerClass, int port, int backlog) { + policyManager.checkNetworkAccess(callerClass, NetworkEntitlement.LISTEN_ACTION); + } + + @Override + public void check$java_net_ServerSocket$(Class callerClass, int port, int backlog, InetAddress bindAddr) { + policyManager.checkNetworkAccess(callerClass, NetworkEntitlement.LISTEN_ACTION); + } + + @Override + public void check$java_net_ServerSocket$accept(Class callerClass, ServerSocket that) { + policyManager.checkNetworkAccess(callerClass, NetworkEntitlement.ACCEPT_ACTION); + } + + @Override + public void check$java_net_ServerSocket$implAccept(Class callerClass, ServerSocket that, Socket s) { + policyManager.checkNetworkAccess(callerClass, NetworkEntitlement.ACCEPT_ACTION); + } + + @Override + public void check$java_net_ServerSocket$bind(Class callerClass, ServerSocket that, SocketAddress endpoint) { + policyManager.checkNetworkAccess(callerClass, NetworkEntitlement.LISTEN_ACTION); + } + + @Override + public void check$java_net_ServerSocket$bind(Class callerClass, ServerSocket that, SocketAddress endpoint, int backlog) { + policyManager.checkNetworkAccess(callerClass, NetworkEntitlement.LISTEN_ACTION); + } + + @Override + public void check$java_net_Socket$(Class callerClass, Proxy proxy) { + if (proxy.type() == Proxy.Type.SOCKS || proxy.type() == Proxy.Type.HTTP) { + policyManager.checkNetworkAccess(callerClass, NetworkEntitlement.CONNECT_ACTION); + } + } + + @Override + public void check$java_net_Socket$(Class callerClass, String host, int port) { + policyManager.checkNetworkAccess(callerClass, NetworkEntitlement.LISTEN_ACTION | NetworkEntitlement.CONNECT_ACTION); + } + + @Override + public void check$java_net_Socket$(Class callerClass, InetAddress address, int port) { + policyManager.checkNetworkAccess(callerClass, NetworkEntitlement.LISTEN_ACTION | NetworkEntitlement.CONNECT_ACTION); + } + + @Override + public void check$java_net_Socket$(Class callerClass, String host, int port, InetAddress localAddr, int localPort) { + policyManager.checkNetworkAccess(callerClass, NetworkEntitlement.LISTEN_ACTION | NetworkEntitlement.CONNECT_ACTION); + } + + @Override + public void check$java_net_Socket$(Class callerClass, InetAddress address, int port, InetAddress localAddr, int localPort) { + policyManager.checkNetworkAccess(callerClass, NetworkEntitlement.LISTEN_ACTION | NetworkEntitlement.CONNECT_ACTION); + } + + @Override + public void check$java_net_Socket$(Class callerClass, String host, int port, boolean stream) { + policyManager.checkNetworkAccess(callerClass, NetworkEntitlement.LISTEN_ACTION | NetworkEntitlement.CONNECT_ACTION); + } + + @Override + public void check$java_net_Socket$(Class callerClass, InetAddress host, int port, boolean stream) { + policyManager.checkNetworkAccess(callerClass, NetworkEntitlement.LISTEN_ACTION | NetworkEntitlement.CONNECT_ACTION); + } + + @Override + public void check$java_net_Socket$bind(Class callerClass, Socket that, SocketAddress endpoint) { + policyManager.checkNetworkAccess(callerClass, NetworkEntitlement.LISTEN_ACTION); + } + + @Override + public void check$java_net_Socket$connect(Class callerClass, Socket that, SocketAddress endpoint) { + policyManager.checkNetworkAccess(callerClass, NetworkEntitlement.CONNECT_ACTION); + } + + @Override + public void check$java_net_Socket$connect(Class callerClass, Socket that, SocketAddress endpoint, int backlog) { + policyManager.checkNetworkAccess(callerClass, NetworkEntitlement.CONNECT_ACTION); + } } diff --git a/libs/entitlement/src/main/java/org/elasticsearch/entitlement/runtime/policy/NetworkEntitlement.java b/libs/entitlement/src/main/java/org/elasticsearch/entitlement/runtime/policy/NetworkEntitlement.java index b6c6a41d5be7..9b4035cee98d 100644 --- a/libs/entitlement/src/main/java/org/elasticsearch/entitlement/runtime/policy/NetworkEntitlement.java +++ b/libs/entitlement/src/main/java/org/elasticsearch/entitlement/runtime/policy/NetworkEntitlement.java @@ -58,7 +58,11 @@ public class NetworkEntitlement implements Entitlement { this.actions = actionsInt; } - public static Object printActions(int actions) { + public NetworkEntitlement(int actions) { + this.actions = actions; + } + + public static String printActions(int actions) { var joiner = new StringJoiner(","); for (var entry : ACTION_MAP.entrySet()) { var action = entry.getValue(); diff --git a/libs/entitlement/src/main/java/org/elasticsearch/entitlement/runtime/policy/PolicyManager.java b/libs/entitlement/src/main/java/org/elasticsearch/entitlement/runtime/policy/PolicyManager.java index f039fbda3dfb..aeb54d5c1156 100644 --- a/libs/entitlement/src/main/java/org/elasticsearch/entitlement/runtime/policy/PolicyManager.java +++ b/libs/entitlement/src/main/java/org/elasticsearch/entitlement/runtime/policy/PolicyManager.java @@ -200,21 +200,21 @@ public class PolicyManager { return; } - ModuleEntitlements entitlements = getEntitlements(requestingClass); + ModuleEntitlements entitlements = getEntitlements(requestingClass, NetworkEntitlement.class); if (entitlements.getEntitlements(NetworkEntitlement.class).anyMatch(n -> n.matchActions(actions))) { logger.debug( () -> Strings.format( - "Entitled: class [%s], module [%s], entitlement [Network], actions [Ox%X]", + "Entitled: class [%s], module [%s], entitlement [network], actions [%s]", requestingClass, requestingClass.getModule().getName(), - actions + NetworkEntitlement.printActions(actions) ) ); return; } throw new NotEntitledException( Strings.format( - "Missing entitlement: class [%s], module [%s], entitlement [Network], actions [%s]", + "Missing entitlement: class [%s], module [%s], entitlement [network], actions [%s]", requestingClass, requestingClass.getModule().getName(), NetworkEntitlement.printActions(actions) @@ -228,14 +228,14 @@ public class PolicyManager { return; } - ModuleEntitlements entitlements = getEntitlements(requestingClass); + ModuleEntitlements entitlements = getEntitlements(requestingClass, entitlementClass); if (entitlements.hasEntitlement(entitlementClass)) { logger.debug( () -> Strings.format( "Entitled: class [%s], module [%s], entitlement [%s]", requestingClass, requestingClass.getModule().getName(), - entitlementClass.getSimpleName() + PolicyParser.getEntitlementTypeName(entitlementClass) ) ); return; @@ -245,19 +245,22 @@ public class PolicyManager { "Missing entitlement: class [%s], module [%s], entitlement [%s]", requestingClass, requestingClass.getModule().getName(), - entitlementClass.getSimpleName() + PolicyParser.getEntitlementTypeName(entitlementClass) ) ); } - ModuleEntitlements getEntitlements(Class requestingClass) { - return moduleEntitlementsMap.computeIfAbsent(requestingClass.getModule(), m -> computeEntitlements(requestingClass)); + ModuleEntitlements getEntitlements(Class requestingClass, Class entitlementClass) { + return moduleEntitlementsMap.computeIfAbsent( + requestingClass.getModule(), + m -> computeEntitlements(requestingClass, entitlementClass) + ); } - private ModuleEntitlements computeEntitlements(Class requestingClass) { + private ModuleEntitlements computeEntitlements(Class requestingClass, Class entitlementClass) { Module requestingModule = requestingClass.getModule(); if (isServerModule(requestingModule)) { - return getModuleScopeEntitlements(requestingClass, serverEntitlements, requestingModule.getName()); + return getModuleScopeEntitlements(requestingClass, serverEntitlements, requestingModule.getName(), "server", entitlementClass); } // plugins @@ -271,7 +274,7 @@ public class PolicyManager { } else { scopeName = requestingModule.getName(); } - return getModuleScopeEntitlements(requestingClass, pluginEntitlements, scopeName); + return getModuleScopeEntitlements(requestingClass, pluginEntitlements, scopeName, pluginName, entitlementClass); } } @@ -287,11 +290,19 @@ public class PolicyManager { private ModuleEntitlements getModuleScopeEntitlements( Class callerClass, Map> scopeEntitlements, - String moduleName + String moduleName, + String component, + Class entitlementClass ) { var entitlements = scopeEntitlements.get(moduleName); if (entitlements == null) { - logger.warn("No applicable entitlement policy for module [{}], class [{}]", moduleName, callerClass); + logger.warn( + "No applicable entitlement policy for entitlement [{}] in [{}], module [{}], class [{}]", + PolicyParser.getEntitlementTypeName(entitlementClass), + component, + moduleName, + callerClass + ); return ModuleEntitlements.NONE; } return ModuleEntitlements.from(entitlements); diff --git a/libs/entitlement/src/test/java/org/elasticsearch/entitlement/runtime/policy/PolicyManagerTests.java b/libs/entitlement/src/test/java/org/elasticsearch/entitlement/runtime/policy/PolicyManagerTests.java index d22c2f598e34..092813be75cc 100644 --- a/libs/entitlement/src/test/java/org/elasticsearch/entitlement/runtime/policy/PolicyManagerTests.java +++ b/libs/entitlement/src/test/java/org/elasticsearch/entitlement/runtime/policy/PolicyManagerTests.java @@ -38,7 +38,7 @@ import static org.hamcrest.Matchers.sameInstance; public class PolicyManagerTests extends ESTestCase { /** * A module you can use for test cases that don't actually care about the - * entitlements module. + * entitlement module. */ private static Module NO_ENTITLEMENTS_MODULE; @@ -66,7 +66,11 @@ public class PolicyManagerTests extends ESTestCase { var callerClass = this.getClass(); var requestingModule = callerClass.getModule(); - assertEquals("No policy for the unnamed module", ModuleEntitlements.NONE, policyManager.getEntitlements(callerClass)); + assertEquals( + "No policy for the unnamed module", + ModuleEntitlements.NONE, + policyManager.getEntitlements(callerClass, Entitlement.class) + ); assertEquals(Map.of(requestingModule, ModuleEntitlements.NONE), policyManager.moduleEntitlementsMap); } @@ -78,7 +82,7 @@ public class PolicyManagerTests extends ESTestCase { var callerClass = this.getClass(); var requestingModule = callerClass.getModule(); - assertEquals("No policy for this plugin", ModuleEntitlements.NONE, policyManager.getEntitlements(callerClass)); + assertEquals("No policy for this plugin", ModuleEntitlements.NONE, policyManager.getEntitlements(callerClass, Entitlement.class)); assertEquals(Map.of(requestingModule, ModuleEntitlements.NONE), policyManager.moduleEntitlementsMap); } @@ -90,11 +94,11 @@ public class PolicyManagerTests extends ESTestCase { var callerClass = this.getClass(); var requestingModule = callerClass.getModule(); - assertEquals(ModuleEntitlements.NONE, policyManager.getEntitlements(callerClass)); + assertEquals(ModuleEntitlements.NONE, policyManager.getEntitlements(callerClass, Entitlement.class)); assertEquals(Map.of(requestingModule, ModuleEntitlements.NONE), policyManager.moduleEntitlementsMap); // A second time - assertEquals(ModuleEntitlements.NONE, policyManager.getEntitlements(callerClass)); + assertEquals(ModuleEntitlements.NONE, policyManager.getEntitlements(callerClass, Entitlement.class)); // Nothing new in the map assertEquals(Map.of(requestingModule, ModuleEntitlements.NONE), policyManager.moduleEntitlementsMap); @@ -112,7 +116,7 @@ public class PolicyManagerTests extends ESTestCase { // Any class from the current module (unnamed) will do var callerClass = this.getClass(); - var entitlements = policyManager.getEntitlements(callerClass); + var entitlements = policyManager.getEntitlements(callerClass, Entitlement.class); assertThat(entitlements.hasEntitlement(CreateClassLoaderEntitlement.class), is(true)); } @@ -126,7 +130,11 @@ public class PolicyManagerTests extends ESTestCase { var mockServerClass = ModuleLayer.boot().findLoader("jdk.httpserver").loadClass("com.sun.net.httpserver.HttpServer"); var requestingModule = mockServerClass.getModule(); - assertEquals("No policy for this module in server", ModuleEntitlements.NONE, policyManager.getEntitlements(mockServerClass)); + assertEquals( + "No policy for this module in server", + ModuleEntitlements.NONE, + policyManager.getEntitlements(mockServerClass, Entitlement.class) + ); assertEquals(Map.of(requestingModule, ModuleEntitlements.NONE), policyManager.moduleEntitlementsMap); } @@ -145,9 +153,8 @@ public class PolicyManagerTests extends ESTestCase { // So we use a random module in the boot layer, and a random class from that module (not java.base -- it is // loaded too early) to mimic a class that would be in the server module. var mockServerClass = ModuleLayer.boot().findLoader("jdk.httpserver").loadClass("com.sun.net.httpserver.HttpServer"); - var requestingModule = mockServerClass.getModule(); - var entitlements = policyManager.getEntitlements(mockServerClass); + var entitlements = policyManager.getEntitlements(mockServerClass, Entitlement.class); assertThat(entitlements.hasEntitlement(CreateClassLoaderEntitlement.class), is(true)); assertThat(entitlements.hasEntitlement(ExitVMEntitlement.class), is(true)); } @@ -167,9 +174,8 @@ public class PolicyManagerTests extends ESTestCase { var layer = createLayerForJar(jar, "org.example.plugin"); var mockPluginClass = layer.findLoader("org.example.plugin").loadClass("q.B"); - var requestingModule = mockPluginClass.getModule(); - var entitlements = policyManager.getEntitlements(mockPluginClass); + var entitlements = policyManager.getEntitlements(mockPluginClass, Entitlement.class); assertThat(entitlements.hasEntitlement(CreateClassLoaderEntitlement.class), is(true)); assertThat( entitlements.getEntitlements(FileEntitlement.class).toList(), @@ -189,11 +195,11 @@ public class PolicyManagerTests extends ESTestCase { // Any class from the current module (unnamed) will do var callerClass = this.getClass(); - var entitlements = policyManager.getEntitlements(callerClass); + var entitlements = policyManager.getEntitlements(callerClass, Entitlement.class); assertThat(entitlements.hasEntitlement(CreateClassLoaderEntitlement.class), is(true)); assertThat(policyManager.moduleEntitlementsMap, aMapWithSize(1)); - var cachedResult = policyManager.moduleEntitlementsMap.values().stream().findFirst().get(); - var entitlementsAgain = policyManager.getEntitlements(callerClass); + var cachedResult = policyManager.moduleEntitlementsMap.values().stream().findFirst().orElseThrow(); + var entitlementsAgain = policyManager.getEntitlements(callerClass, Entitlement.class); // Nothing new in the map assertThat(policyManager.moduleEntitlementsMap, aMapWithSize(1)); diff --git a/modules/repository-s3/src/main/plugin-metadata/entitlement-policy.yaml b/modules/repository-s3/src/main/plugin-metadata/entitlement-policy.yaml new file mode 100644 index 000000000000..4c42ec110a25 --- /dev/null +++ b/modules/repository-s3/src/main/plugin-metadata/entitlement-policy.yaml @@ -0,0 +1,4 @@ +ALL-UNNAMED: + - network: + actions: + - connect diff --git a/modules/repository-url/src/main/plugin-metadata/entitlement-policy.yaml b/modules/repository-url/src/main/plugin-metadata/entitlement-policy.yaml new file mode 100644 index 000000000000..f1dc1fc7755e --- /dev/null +++ b/modules/repository-url/src/main/plugin-metadata/entitlement-policy.yaml @@ -0,0 +1,4 @@ +org.apache.httpcomponents.httpclient: + - network: + actions: + - connect # for URLHttpClient diff --git a/plugins/discovery-ec2/src/main/plugin-metadata/entitlement-policy.yaml b/plugins/discovery-ec2/src/main/plugin-metadata/entitlement-policy.yaml new file mode 100644 index 000000000000..4c42ec110a25 --- /dev/null +++ b/plugins/discovery-ec2/src/main/plugin-metadata/entitlement-policy.yaml @@ -0,0 +1,4 @@ +ALL-UNNAMED: + - network: + actions: + - connect diff --git a/x-pack/plugin/core/src/main/plugin-metadata/entitlement-policy.yaml b/x-pack/plugin/core/src/main/plugin-metadata/entitlement-policy.yaml new file mode 100644 index 000000000000..8983dd6663e6 --- /dev/null +++ b/x-pack/plugin/core/src/main/plugin-metadata/entitlement-policy.yaml @@ -0,0 +1,4 @@ +org.apache.httpcomponents.httpclient: + - network: + actions: + - connect # For SamlRealm