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 a01d8f2d17844..a864225ac400b 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 @@ -269,10 +269,7 @@ public interface EntitlementChecker { // Network miscellanea void check$java_net_URL$openConnection(Class callerClass, java.net.URL that, Proxy proxy); - // HttpClient.Builder is an interface, so we instrument its only (internal) implementation - void check$jdk_internal_net_http_HttpClientBuilderImpl$build(Class callerClass, HttpClient.Builder that); - - // HttpClient#send and sendAsync are abstract, so we instrument their internal implementation + // HttpClient#send and sendAsync are abstract, so we instrument their internal implementations void check$jdk_internal_net_http_HttpClientImpl$send( Class callerClass, HttpClient that, @@ -295,6 +292,28 @@ public interface EntitlementChecker { HttpResponse.PushPromiseHandler pushPromiseHandler ); + void check$jdk_internal_net_http_HttpClientFacade$send( + Class callerClass, + HttpClient that, + HttpRequest request, + HttpResponse.BodyHandler responseBodyHandler + ); + + void check$jdk_internal_net_http_HttpClientFacade$sendAsync( + Class callerClass, + HttpClient that, + HttpRequest userRequest, + HttpResponse.BodyHandler responseHandler + ); + + void check$jdk_internal_net_http_HttpClientFacade$sendAsync( + Class callerClass, + HttpClient that, + HttpRequest userRequest, + HttpResponse.BodyHandler responseHandler, + HttpResponse.PushPromiseHandler pushPromiseHandler + ); + // We need to check the LDAPCertStore, as this will connect, but this is internal/created via SPI, // so we instrument the general factory instead and then filter in the check method implementation void check$java_security_cert_CertStore$$getInstance(Class callerClass, String type, CertStoreParameters params); 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 index 553c025143725..f27dd9a0d36cb 100644 --- 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 @@ -84,12 +84,6 @@ static void urlOpenConnectionWithProxy() throws URISyntaxException, IOException assert urlConnection != null; } - static void httpClientBuilderBuild() { - try (HttpClient httpClient = HttpClient.newBuilder().build()) { - assert httpClient != null; - } - } - static void httpClientSend() throws InterruptedException { try (HttpClient httpClient = HttpClient.newBuilder().build()) { // Shutdown the client, so the send action will shortcut before actually executing any network operation 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 5286430dc25f7..7c8e23343683a 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 @@ -160,7 +160,6 @@ static CheckAction alwaysDenied(CheckedRunnable action) { entry("server_socket_accept", forPlugins(NetworkAccessCheckActions::serverSocketAccept)), entry("url_open_connection_proxy", forPlugins(NetworkAccessCheckActions::urlOpenConnectionWithProxy)), - entry("http_client_builder_build", forPlugins(NetworkAccessCheckActions::httpClientBuilderBuild)), entry("http_client_send", forPlugins(NetworkAccessCheckActions::httpClientSend)), entry("http_client_send_async", forPlugins(NetworkAccessCheckActions::httpClientSendAsync)), entry("create_ldap_cert_store", forPlugins(NetworkAccessCheckActions::createLDAPCertStore)), diff --git a/libs/entitlement/qa/entitlement-allowed-nonmodular/src/main/plugin-metadata/entitlement-policy.yaml b/libs/entitlement/qa/entitlement-allowed-nonmodular/src/main/plugin-metadata/entitlement-policy.yaml index 05a94f09264a8..ecfc8af8d1bff 100644 --- a/libs/entitlement/qa/entitlement-allowed-nonmodular/src/main/plugin-metadata/entitlement-policy.yaml +++ b/libs/entitlement/qa/entitlement-allowed-nonmodular/src/main/plugin-metadata/entitlement-policy.yaml @@ -1,8 +1,5 @@ ALL-UNNAMED: - create_class_loader - set_https_connection_properties - - network: - actions: - - listen - - accept - - connect + - inbound_network + - outbound_network diff --git a/libs/entitlement/qa/entitlement-allowed/src/main/plugin-metadata/entitlement-policy.yaml b/libs/entitlement/qa/entitlement-allowed/src/main/plugin-metadata/entitlement-policy.yaml index 0d2c66c2daa2c..730f4a066712c 100644 --- a/libs/entitlement/qa/entitlement-allowed/src/main/plugin-metadata/entitlement-policy.yaml +++ b/libs/entitlement/qa/entitlement-allowed/src/main/plugin-metadata/entitlement-policy.yaml @@ -1,8 +1,5 @@ org.elasticsearch.entitlement.qa.common: - create_class_loader - set_https_connection_properties - - network: - actions: - - listen - - accept - - connect + - inbound_network + - outbound_network 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 aa16215d0f832..0ad8fc350026c 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,7 +22,8 @@ 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.InboundNetworkEntitlement; +import org.elasticsearch.entitlement.runtime.policy.OutboundNetworkEntitlement; import org.elasticsearch.entitlement.runtime.policy.Policy; import org.elasticsearch.entitlement.runtime.policy.PolicyManager; import org.elasticsearch.entitlement.runtime.policy.PolicyParser; @@ -45,9 +46,6 @@ 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; /** @@ -106,11 +104,12 @@ private static PolicyManager createPolicyManager() throws IOException { List.of( new ExitVMEntitlement(), new CreateClassLoaderEntitlement(), - new NetworkEntitlement(LISTEN_ACTION | CONNECT_ACTION | ACCEPT_ACTION) + new InboundNetworkEntitlement(), + new OutboundNetworkEntitlement() ) ), - new Scope("org.apache.httpcomponents.httpclient", List.of(new NetworkEntitlement(CONNECT_ACTION))), - new Scope("io.netty.transport", List.of(new NetworkEntitlement(LISTEN_ACTION))) + new Scope("org.apache.httpcomponents.httpclient", List.of(new OutboundNetworkEntitlement())), + new Scope("io.netty.transport", List.of(new InboundNetworkEntitlement(), new OutboundNetworkEntitlement())) ) ); // 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 3748323131e33..0801e40388cb2 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 @@ -10,7 +10,6 @@ package org.elasticsearch.entitlement.runtime.api; import org.elasticsearch.entitlement.bridge.EntitlementChecker; -import org.elasticsearch.entitlement.runtime.policy.NetworkEntitlement; import org.elasticsearch.entitlement.runtime.policy.PolicyManager; import java.io.InputStream; @@ -368,167 +367,162 @@ public ElasticsearchEntitlementChecker(PolicyManager policyManager) { @Override public void check$java_net_DatagramSocket$bind(Class callerClass, DatagramSocket that, SocketAddress addr) { - policyManager.checkNetworkAccess(callerClass, NetworkEntitlement.LISTEN_ACTION); + policyManager.checkInboundNetworkAccess(callerClass); } @Override public void check$java_net_DatagramSocket$connect(Class callerClass, DatagramSocket that, InetAddress addr) { - policyManager.checkNetworkAccess(callerClass, NetworkEntitlement.CONNECT_ACTION | NetworkEntitlement.ACCEPT_ACTION); + policyManager.checkAllNetworkAccess(callerClass); } @Override public void check$java_net_DatagramSocket$connect(Class callerClass, DatagramSocket that, SocketAddress addr) { - policyManager.checkNetworkAccess(callerClass, NetworkEntitlement.CONNECT_ACTION | NetworkEntitlement.ACCEPT_ACTION); + policyManager.checkAllNetworkAccess(callerClass); } @Override public void check$java_net_DatagramSocket$send(Class callerClass, DatagramSocket that, DatagramPacket p) { - var actions = NetworkEntitlement.CONNECT_ACTION; if (p.getAddress().isMulticastAddress()) { - actions |= NetworkEntitlement.ACCEPT_ACTION; + policyManager.checkAllNetworkAccess(callerClass); + } else { + policyManager.checkOutboundNetworkAccess(callerClass); } - policyManager.checkNetworkAccess(callerClass, actions); } @Override public void check$java_net_DatagramSocket$receive(Class callerClass, DatagramSocket that, DatagramPacket p) { - policyManager.checkNetworkAccess(callerClass, NetworkEntitlement.ACCEPT_ACTION); + policyManager.checkInboundNetworkAccess(callerClass); } @Override public void check$java_net_DatagramSocket$joinGroup(Class caller, DatagramSocket that, SocketAddress addr, NetworkInterface ni) { - policyManager.checkNetworkAccess(caller, NetworkEntitlement.CONNECT_ACTION | NetworkEntitlement.ACCEPT_ACTION); + policyManager.checkAllNetworkAccess(caller); } @Override public void check$java_net_DatagramSocket$leaveGroup(Class caller, DatagramSocket that, SocketAddress addr, NetworkInterface ni) { - policyManager.checkNetworkAccess(caller, NetworkEntitlement.CONNECT_ACTION | NetworkEntitlement.ACCEPT_ACTION); + policyManager.checkAllNetworkAccess(caller); } @Override - public void check$java_net_MulticastSocket$joinGroup(Class callerClass, MulticastSocket that, InetAddress addr) { - policyManager.checkNetworkAccess(callerClass, NetworkEntitlement.CONNECT_ACTION | NetworkEntitlement.ACCEPT_ACTION); + public void check$java_net_MulticastSocket$joinGroup(Class caller, MulticastSocket that, InetAddress addr) { + policyManager.checkAllNetworkAccess(caller); } @Override public void check$java_net_MulticastSocket$joinGroup(Class caller, MulticastSocket that, SocketAddress addr, NetworkInterface ni) { - policyManager.checkNetworkAccess(caller, NetworkEntitlement.CONNECT_ACTION | NetworkEntitlement.ACCEPT_ACTION); + policyManager.checkAllNetworkAccess(caller); } @Override public void check$java_net_MulticastSocket$leaveGroup(Class caller, MulticastSocket that, InetAddress addr) { - policyManager.checkNetworkAccess(caller, NetworkEntitlement.CONNECT_ACTION | NetworkEntitlement.ACCEPT_ACTION); + policyManager.checkAllNetworkAccess(caller); } @Override public void check$java_net_MulticastSocket$leaveGroup(Class caller, MulticastSocket that, SocketAddress addr, NetworkInterface ni) { - policyManager.checkNetworkAccess(caller, NetworkEntitlement.CONNECT_ACTION | NetworkEntitlement.ACCEPT_ACTION); + policyManager.checkAllNetworkAccess(caller); } @Override public void check$java_net_MulticastSocket$send(Class callerClass, MulticastSocket that, DatagramPacket p, byte ttl) { - policyManager.checkNetworkAccess(callerClass, NetworkEntitlement.CONNECT_ACTION | NetworkEntitlement.ACCEPT_ACTION); + policyManager.checkAllNetworkAccess(callerClass); } @Override public void check$java_net_ServerSocket$(Class callerClass, int port) { - policyManager.checkNetworkAccess(callerClass, NetworkEntitlement.LISTEN_ACTION); + policyManager.checkInboundNetworkAccess(callerClass); } @Override public void check$java_net_ServerSocket$(Class callerClass, int port, int backlog) { - policyManager.checkNetworkAccess(callerClass, NetworkEntitlement.LISTEN_ACTION); + policyManager.checkInboundNetworkAccess(callerClass); } @Override public void check$java_net_ServerSocket$(Class callerClass, int port, int backlog, InetAddress bindAddr) { - policyManager.checkNetworkAccess(callerClass, NetworkEntitlement.LISTEN_ACTION); + policyManager.checkInboundNetworkAccess(callerClass); } @Override public void check$java_net_ServerSocket$accept(Class callerClass, ServerSocket that) { - policyManager.checkNetworkAccess(callerClass, NetworkEntitlement.ACCEPT_ACTION); + policyManager.checkInboundNetworkAccess(callerClass); } @Override public void check$java_net_ServerSocket$implAccept(Class callerClass, ServerSocket that, Socket s) { - policyManager.checkNetworkAccess(callerClass, NetworkEntitlement.ACCEPT_ACTION); + policyManager.checkInboundNetworkAccess(callerClass); } @Override public void check$java_net_ServerSocket$bind(Class callerClass, ServerSocket that, SocketAddress endpoint) { - policyManager.checkNetworkAccess(callerClass, NetworkEntitlement.LISTEN_ACTION); + policyManager.checkInboundNetworkAccess(callerClass); } @Override public void check$java_net_ServerSocket$bind(Class callerClass, ServerSocket that, SocketAddress endpoint, int backlog) { - policyManager.checkNetworkAccess(callerClass, NetworkEntitlement.LISTEN_ACTION); + policyManager.checkInboundNetworkAccess(callerClass); } @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); + policyManager.checkOutboundNetworkAccess(callerClass); } } @Override public void check$java_net_Socket$(Class callerClass, String host, int port) { - policyManager.checkNetworkAccess(callerClass, NetworkEntitlement.LISTEN_ACTION | NetworkEntitlement.CONNECT_ACTION); + policyManager.checkOutboundNetworkAccess(callerClass); } @Override public void check$java_net_Socket$(Class callerClass, InetAddress address, int port) { - policyManager.checkNetworkAccess(callerClass, NetworkEntitlement.LISTEN_ACTION | NetworkEntitlement.CONNECT_ACTION); + policyManager.checkOutboundNetworkAccess(callerClass); } @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); + policyManager.checkOutboundNetworkAccess(callerClass); } @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); + policyManager.checkOutboundNetworkAccess(callerClass); } @Override public void check$java_net_Socket$(Class callerClass, String host, int port, boolean stream) { - policyManager.checkNetworkAccess(callerClass, NetworkEntitlement.LISTEN_ACTION | NetworkEntitlement.CONNECT_ACTION); + policyManager.checkOutboundNetworkAccess(callerClass); } @Override public void check$java_net_Socket$(Class callerClass, InetAddress host, int port, boolean stream) { - policyManager.checkNetworkAccess(callerClass, NetworkEntitlement.LISTEN_ACTION | NetworkEntitlement.CONNECT_ACTION); + policyManager.checkOutboundNetworkAccess(callerClass); } @Override public void check$java_net_Socket$bind(Class callerClass, Socket that, SocketAddress endpoint) { - policyManager.checkNetworkAccess(callerClass, NetworkEntitlement.LISTEN_ACTION); + policyManager.checkOutboundNetworkAccess(callerClass); } @Override public void check$java_net_Socket$connect(Class callerClass, Socket that, SocketAddress endpoint) { - policyManager.checkNetworkAccess(callerClass, NetworkEntitlement.CONNECT_ACTION); + policyManager.checkOutboundNetworkAccess(callerClass); } @Override public void check$java_net_Socket$connect(Class callerClass, Socket that, SocketAddress endpoint, int backlog) { - policyManager.checkNetworkAccess(callerClass, NetworkEntitlement.CONNECT_ACTION); + policyManager.checkOutboundNetworkAccess(callerClass); } @Override public void check$java_net_URL$openConnection(Class callerClass, URL that, Proxy proxy) { if (proxy.type() != Proxy.Type.DIRECT) { - policyManager.checkNetworkAccess(callerClass, NetworkEntitlement.CONNECT_ACTION); + policyManager.checkOutboundNetworkAccess(callerClass); } } - @Override - public void check$jdk_internal_net_http_HttpClientBuilderImpl$build(Class callerClass, HttpClient.Builder that) { - policyManager.checkNetworkAccess(callerClass, NetworkEntitlement.LISTEN_ACTION); - } - @Override public void check$jdk_internal_net_http_HttpClientImpl$send( Class callerClass, @@ -536,7 +530,7 @@ public ElasticsearchEntitlementChecker(PolicyManager policyManager) { HttpRequest request, HttpResponse.BodyHandler responseBodyHandler ) { - policyManager.checkNetworkAccess(callerClass, NetworkEntitlement.CONNECT_ACTION); + policyManager.checkOutboundNetworkAccess(callerClass); } @Override @@ -546,7 +540,7 @@ public ElasticsearchEntitlementChecker(PolicyManager policyManager) { HttpRequest userRequest, HttpResponse.BodyHandler responseHandler ) { - policyManager.checkNetworkAccess(callerClass, NetworkEntitlement.CONNECT_ACTION); + policyManager.checkOutboundNetworkAccess(callerClass); } @Override @@ -557,7 +551,38 @@ public ElasticsearchEntitlementChecker(PolicyManager policyManager) { HttpResponse.BodyHandler responseHandler, HttpResponse.PushPromiseHandler pushPromiseHandler ) { - policyManager.checkNetworkAccess(callerClass, NetworkEntitlement.CONNECT_ACTION); + policyManager.checkOutboundNetworkAccess(callerClass); + } + + @Override + public void check$jdk_internal_net_http_HttpClientFacade$send( + Class callerClass, + HttpClient that, + HttpRequest request, + HttpResponse.BodyHandler responseBodyHandler + ) { + check$jdk_internal_net_http_HttpClientImpl$send(callerClass, that, request, responseBodyHandler); + } + + @Override + public void check$jdk_internal_net_http_HttpClientFacade$sendAsync( + Class callerClass, + HttpClient that, + HttpRequest userRequest, + HttpResponse.BodyHandler responseHandler + ) { + check$jdk_internal_net_http_HttpClientImpl$sendAsync(callerClass, that, userRequest, responseHandler); + } + + @Override + public void check$jdk_internal_net_http_HttpClientFacade$sendAsync( + Class callerClass, + HttpClient that, + HttpRequest userRequest, + HttpResponse.BodyHandler responseHandler, + HttpResponse.PushPromiseHandler pushPromiseHandler + ) { + check$jdk_internal_net_http_HttpClientImpl$sendAsync(callerClass, that, userRequest, responseHandler, pushPromiseHandler); } @Override @@ -566,7 +591,7 @@ public ElasticsearchEntitlementChecker(PolicyManager policyManager) { // (connect to an LDAP server). But LDAPCertStore is internal (created via SPI), so we instrument the general factory instead and // then do the check only for the path that leads to sensitive code (by looking at the `type` parameter). if ("LDAP".equals(type)) { - policyManager.checkNetworkAccess(callerClass, NetworkEntitlement.CONNECT_ACTION); + policyManager.checkOutboundNetworkAccess(callerClass); } } @@ -576,7 +601,7 @@ public ElasticsearchEntitlementChecker(PolicyManager policyManager) { AsynchronousServerSocketChannel that, SocketAddress local ) { - policyManager.checkNetworkAccess(callerClass, NetworkEntitlement.LISTEN_ACTION); + policyManager.checkInboundNetworkAccess(callerClass); } @Override @@ -586,7 +611,7 @@ public ElasticsearchEntitlementChecker(PolicyManager policyManager) { SocketAddress local, int backlog ) { - policyManager.checkNetworkAccess(callerClass, NetworkEntitlement.LISTEN_ACTION); + policyManager.checkInboundNetworkAccess(callerClass); } @Override @@ -595,17 +620,17 @@ public ElasticsearchEntitlementChecker(PolicyManager policyManager) { AsynchronousSocketChannel that, SocketAddress local ) { - policyManager.checkNetworkAccess(callerClass, NetworkEntitlement.LISTEN_ACTION); + policyManager.checkInboundNetworkAccess(callerClass); } @Override public void check$sun_nio_ch_DatagramChannelImpl$bind(Class callerClass, DatagramChannel that, SocketAddress local) { - policyManager.checkNetworkAccess(callerClass, NetworkEntitlement.LISTEN_ACTION); + policyManager.checkInboundNetworkAccess(callerClass); } @Override public void check$java_nio_channels_ServerSocketChannel$bind(Class callerClass, ServerSocketChannel that, SocketAddress local) { - policyManager.checkNetworkAccess(callerClass, NetworkEntitlement.LISTEN_ACTION); + policyManager.checkInboundNetworkAccess(callerClass); } @Override @@ -615,17 +640,17 @@ public ElasticsearchEntitlementChecker(PolicyManager policyManager) { SocketAddress local, int backlog ) { - policyManager.checkNetworkAccess(callerClass, NetworkEntitlement.LISTEN_ACTION); + policyManager.checkInboundNetworkAccess(callerClass); } @Override public void check$sun_nio_ch_SocketChannelImpl$bind(Class callerClass, SocketChannel that, SocketAddress local) { - policyManager.checkNetworkAccess(callerClass, NetworkEntitlement.LISTEN_ACTION); + policyManager.checkOutboundNetworkAccess(callerClass); } @Override public void check$sun_nio_ch_SocketChannelImpl$connect(Class callerClass, SocketChannel that, SocketAddress remote) { - policyManager.checkNetworkAccess(callerClass, NetworkEntitlement.CONNECT_ACTION); + policyManager.checkOutboundNetworkAccess(callerClass); } @Override @@ -634,7 +659,7 @@ public ElasticsearchEntitlementChecker(PolicyManager policyManager) { AsynchronousSocketChannel that, SocketAddress remote ) { - policyManager.checkNetworkAccess(callerClass, NetworkEntitlement.CONNECT_ACTION); + policyManager.checkOutboundNetworkAccess(callerClass); } @Override @@ -645,22 +670,22 @@ public ElasticsearchEntitlementChecker(PolicyManager policyManager) { Object attachment, CompletionHandler handler ) { - policyManager.checkNetworkAccess(callerClass, NetworkEntitlement.CONNECT_ACTION); + policyManager.checkOutboundNetworkAccess(callerClass); } @Override public void check$sun_nio_ch_DatagramChannelImpl$connect(Class callerClass, DatagramChannel that, SocketAddress remote) { - policyManager.checkNetworkAccess(callerClass, NetworkEntitlement.CONNECT_ACTION); + policyManager.checkOutboundNetworkAccess(callerClass); } @Override public void check$sun_nio_ch_ServerSocketChannelImpl$accept(Class callerClass, ServerSocketChannel that) { - policyManager.checkNetworkAccess(callerClass, NetworkEntitlement.ACCEPT_ACTION); + policyManager.checkInboundNetworkAccess(callerClass); } @Override public void check$sun_nio_ch_AsynchronousServerSocketChannelImpl$accept(Class callerClass, AsynchronousServerSocketChannel that) { - policyManager.checkNetworkAccess(callerClass, NetworkEntitlement.ACCEPT_ACTION); + policyManager.checkInboundNetworkAccess(callerClass); } @Override @@ -670,7 +695,7 @@ public ElasticsearchEntitlementChecker(PolicyManager policyManager) { Object attachment, CompletionHandler handler ) { - policyManager.checkNetworkAccess(callerClass, NetworkEntitlement.ACCEPT_ACTION); + policyManager.checkInboundNetworkAccess(callerClass); } @Override @@ -681,13 +706,14 @@ public ElasticsearchEntitlementChecker(PolicyManager policyManager) { SocketAddress target ) { if (target instanceof InetSocketAddress isa && isa.getAddress().isMulticastAddress()) { - policyManager.checkNetworkAccess(callerClass, NetworkEntitlement.ACCEPT_ACTION | NetworkEntitlement.CONNECT_ACTION); + policyManager.checkAllNetworkAccess(callerClass); + } else { + policyManager.checkOutboundNetworkAccess(callerClass); } - policyManager.checkNetworkAccess(callerClass, NetworkEntitlement.CONNECT_ACTION); } @Override public void check$sun_nio_ch_DatagramChannelImpl$receive(Class callerClass, DatagramChannel that, ByteBuffer dst) { - policyManager.checkNetworkAccess(callerClass, NetworkEntitlement.ACCEPT_ACTION); + policyManager.checkInboundNetworkAccess(callerClass); } } diff --git a/libs/entitlement/src/main/java/org/elasticsearch/entitlement/runtime/policy/InboundNetworkEntitlement.java b/libs/entitlement/src/main/java/org/elasticsearch/entitlement/runtime/policy/InboundNetworkEntitlement.java new file mode 100644 index 0000000000000..482d4e5100c0b --- /dev/null +++ b/libs/entitlement/src/main/java/org/elasticsearch/entitlement/runtime/policy/InboundNetworkEntitlement.java @@ -0,0 +1,18 @@ +/* + * 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.runtime.policy; + +/** + * Describes an entitlement for inbound network actions (listen/accept/receive) + */ +public record InboundNetworkEntitlement() implements Entitlement { + @ExternalEntitlement + public InboundNetworkEntitlement {} +} 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 deleted file mode 100644 index ea78c8cafc908..0000000000000 --- a/libs/entitlement/src/main/java/org/elasticsearch/entitlement/runtime/policy/NetworkEntitlement.java +++ /dev/null @@ -1,111 +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.runtime.policy; - -import org.elasticsearch.core.Strings; - -import java.util.List; -import java.util.Map; -import java.util.Objects; -import java.util.StringJoiner; - -import static java.util.Map.entry; - -/** - * Describes a network entitlement (sockets) with actions. - */ -public class NetworkEntitlement implements Entitlement { - - public static final int LISTEN_ACTION = 0x1; - public static final int CONNECT_ACTION = 0x2; - public static final int ACCEPT_ACTION = 0x4; - - static final String LISTEN = "listen"; - static final String CONNECT = "connect"; - static final String ACCEPT = "accept"; - - private static final Map ACTION_MAP = Map.ofEntries( - entry(LISTEN, LISTEN_ACTION), - entry(CONNECT, CONNECT_ACTION), - entry(ACCEPT, ACCEPT_ACTION) - ); - - private final int actions; - - @ExternalEntitlement(parameterNames = { "actions" }, esModulesOnly = false) - public NetworkEntitlement(List actionsList) { - - int actionsInt = 0; - - for (String actionString : actionsList) { - var action = ACTION_MAP.get(actionString); - if (action == null) { - throw new PolicyValidationException("unknown network action [" + actionString + "]"); - } - if ((actionsInt & action) == action) { - throw new PolicyValidationException(Strings.format("network action [%s] specified multiple times", actionString)); - } - actionsInt |= action; - } - - this.actions = actionsInt; - } - - 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(); - if ((actions & action) == action) { - joiner.add(entry.getKey()); - } - } - return joiner.toString(); - } - - /** - * For the actions to match, the actions present in this entitlement must be a superset - * of the actions required by a check. - * There is only one "negative" case (action required by the check but not present in the entitlement), - * and it can be expressed efficiently via this truth table: - * this.actions | requiredActions | - * 0 | 0 | 0 - * 0 | 1 | 1 --> NOT this.action AND requiredActions - * 1 | 0 | 0 - * 1 | 1 | 0 - * - * @param requiredActions the actions required to be present for a check to pass - * @return true if requiredActions are present, false otherwise - */ - public boolean matchActions(int requiredActions) { - return (~this.actions & requiredActions) == 0; - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - NetworkEntitlement that = (NetworkEntitlement) o; - return actions == that.actions; - } - - @Override - public int hashCode() { - return Objects.hash(actions); - } - - @Override - public String toString() { - return "NetworkEntitlement{actions=" + actions + '}'; - } -} diff --git a/libs/entitlement/src/main/java/org/elasticsearch/entitlement/runtime/policy/OutboundNetworkEntitlement.java b/libs/entitlement/src/main/java/org/elasticsearch/entitlement/runtime/policy/OutboundNetworkEntitlement.java new file mode 100644 index 0000000000000..50d9a47f580e5 --- /dev/null +++ b/libs/entitlement/src/main/java/org/elasticsearch/entitlement/runtime/policy/OutboundNetworkEntitlement.java @@ -0,0 +1,18 @@ +/* + * 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.runtime.policy; + +/** + * Describes an entitlement for outbound network actions (connect/send) + */ +public record OutboundNetworkEntitlement() implements Entitlement { + @ExternalEntitlement(esModulesOnly = false) + public OutboundNetworkEntitlement {} +} 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 13ac564f67196..5274d805a55d8 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 @@ -194,30 +194,45 @@ private String operationDescription(String methodName) { return methodName.substring(methodName.indexOf('$')); } - public void checkNetworkAccess(Class callerClass, int actions) { + public void checkInboundNetworkAccess(Class callerClass) { + checkEntitlementPresent(callerClass, InboundNetworkEntitlement.class); + } + + public void checkOutboundNetworkAccess(Class callerClass) { + checkEntitlementPresent(callerClass, OutboundNetworkEntitlement.class); + } + + public void checkAllNetworkAccess(Class callerClass) { var requestingClass = requestingClass(callerClass); if (isTriviallyAllowed(requestingClass)) { return; } - 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 [%s]", + var classEntitlements = getEntitlements(requestingClass); + if (classEntitlements.hasEntitlement(InboundNetworkEntitlement.class) == false) { + throw new NotEntitledException( + Strings.format( + "Missing entitlement: class [%s], module [%s], entitlement [inbound_network]", requestingClass, - requestingClass.getModule() == null ? "" : requestingClass.getModule().getName(), - NetworkEntitlement.printActions(actions) + requestingClass.getModule().getName() ) ); - return; } - throw new NotEntitledException( - Strings.format( - "Missing entitlement: class [%s], module [%s], entitlement [network], actions [%s]", + + if (classEntitlements.hasEntitlement(OutboundNetworkEntitlement.class) == false) { + throw new NotEntitledException( + Strings.format( + "Missing entitlement: class [%s], module [%s], entitlement [outbound_network]", + requestingClass, + requestingClass.getModule().getName() + ) + ); + } + logger.debug( + () -> Strings.format( + "Entitled: class [%s], module [%s], entitlements [inbound_network, outbound_network]", requestingClass, - requestingClass.getModule() == null ? "" : requestingClass.getModule().getName(), - NetworkEntitlement.printActions(actions) + requestingClass.getModule().getName() ) ); } @@ -228,7 +243,7 @@ private void checkEntitlementPresent(Class callerClass, Class Strings.format( @@ -250,17 +265,14 @@ private void checkEntitlementPresent(Class callerClass, Class requestingClass, Class entitlementClass) { - return moduleEntitlementsMap.computeIfAbsent( - requestingClass.getModule(), - m -> computeEntitlements(requestingClass, entitlementClass) - ); + ModuleEntitlements getEntitlements(Class requestingClass) { + return moduleEntitlementsMap.computeIfAbsent(requestingClass.getModule(), m -> computeEntitlements(requestingClass)); } - private ModuleEntitlements computeEntitlements(Class requestingClass, Class entitlementClass) { + private ModuleEntitlements computeEntitlements(Class requestingClass) { Module requestingModule = requestingClass.getModule(); if (isServerModule(requestingModule)) { - return getModuleScopeEntitlements(requestingClass, serverEntitlements, requestingModule.getName(), "server", entitlementClass); + return getModuleScopeEntitlements(requestingClass, serverEntitlements, requestingModule.getName(), "server"); } // plugins @@ -274,7 +286,7 @@ private ModuleEntitlements computeEntitlements(Class requestingClass, Class callerClass, Map> scopeEntitlements, String moduleName, - String component, - Class entitlementClass + String component ) { var entitlements = scopeEntitlements.get(moduleName); if (entitlements == null) { - logger.warn( - "No applicable entitlement policy for entitlement [{}] in [{}], module [{}], class [{}]", - PolicyParser.getEntitlementTypeName(entitlementClass), - component, - moduleName, - callerClass - ); + logger.warn("No applicable entitlement policy for [{}], module [{}], class [{}]", component, moduleName, callerClass); return ModuleEntitlements.NONE; } return ModuleEntitlements.from(entitlements); diff --git a/libs/entitlement/src/main/java/org/elasticsearch/entitlement/runtime/policy/PolicyParser.java b/libs/entitlement/src/main/java/org/elasticsearch/entitlement/runtime/policy/PolicyParser.java index 42c0da8444b27..c5de9e34d5ca0 100644 --- a/libs/entitlement/src/main/java/org/elasticsearch/entitlement/runtime/policy/PolicyParser.java +++ b/libs/entitlement/src/main/java/org/elasticsearch/entitlement/runtime/policy/PolicyParser.java @@ -39,7 +39,8 @@ public class PolicyParser { FileEntitlement.class, CreateClassLoaderEntitlement.class, SetHttpsConnectionPropertiesEntitlement.class, - NetworkEntitlement.class + OutboundNetworkEntitlement.class, + InboundNetworkEntitlement.class ).collect(Collectors.toUnmodifiableMap(PolicyParser::getEntitlementTypeName, Function.identity())); protected final XContentParser policyParser; diff --git a/libs/entitlement/src/test/java/org/elasticsearch/entitlement/runtime/policy/NetworkEntitlementTests.java b/libs/entitlement/src/test/java/org/elasticsearch/entitlement/runtime/policy/NetworkEntitlementTests.java deleted file mode 100644 index 91051d48c365f..0000000000000 --- a/libs/entitlement/src/test/java/org/elasticsearch/entitlement/runtime/policy/NetworkEntitlementTests.java +++ /dev/null @@ -1,49 +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.runtime.policy; - -import org.elasticsearch.test.ESTestCase; - -import java.util.List; - -import static org.hamcrest.Matchers.is; - -public class NetworkEntitlementTests extends ESTestCase { - - public void testMatchesActions() { - var listenEntitlement = new NetworkEntitlement(List.of(NetworkEntitlement.LISTEN)); - var emptyEntitlement = new NetworkEntitlement(List.of()); - var connectAcceptEntitlement = new NetworkEntitlement(List.of(NetworkEntitlement.CONNECT, NetworkEntitlement.ACCEPT)); - - assertThat(listenEntitlement.matchActions(0), is(true)); - assertThat(listenEntitlement.matchActions(NetworkEntitlement.LISTEN_ACTION), is(true)); - assertThat(listenEntitlement.matchActions(NetworkEntitlement.ACCEPT_ACTION), is(false)); - assertThat(listenEntitlement.matchActions(NetworkEntitlement.CONNECT_ACTION), is(false)); - assertThat(listenEntitlement.matchActions(NetworkEntitlement.LISTEN_ACTION | NetworkEntitlement.ACCEPT_ACTION), is(false)); - assertThat(listenEntitlement.matchActions(NetworkEntitlement.LISTEN_ACTION | NetworkEntitlement.CONNECT_ACTION), is(false)); - assertThat(listenEntitlement.matchActions(NetworkEntitlement.CONNECT_ACTION | NetworkEntitlement.ACCEPT_ACTION), is(false)); - - assertThat(connectAcceptEntitlement.matchActions(0), is(true)); - assertThat(connectAcceptEntitlement.matchActions(NetworkEntitlement.LISTEN_ACTION), is(false)); - assertThat(connectAcceptEntitlement.matchActions(NetworkEntitlement.ACCEPT_ACTION), is(true)); - assertThat(connectAcceptEntitlement.matchActions(NetworkEntitlement.CONNECT_ACTION), is(true)); - assertThat(connectAcceptEntitlement.matchActions(NetworkEntitlement.LISTEN_ACTION | NetworkEntitlement.ACCEPT_ACTION), is(false)); - assertThat(connectAcceptEntitlement.matchActions(NetworkEntitlement.LISTEN_ACTION | NetworkEntitlement.CONNECT_ACTION), is(false)); - assertThat(connectAcceptEntitlement.matchActions(NetworkEntitlement.CONNECT_ACTION | NetworkEntitlement.ACCEPT_ACTION), is(true)); - - assertThat(emptyEntitlement.matchActions(0), is(true)); - assertThat(emptyEntitlement.matchActions(NetworkEntitlement.LISTEN_ACTION), is(false)); - assertThat(emptyEntitlement.matchActions(NetworkEntitlement.ACCEPT_ACTION), is(false)); - assertThat(emptyEntitlement.matchActions(NetworkEntitlement.CONNECT_ACTION), is(false)); - assertThat(emptyEntitlement.matchActions(NetworkEntitlement.LISTEN_ACTION | NetworkEntitlement.ACCEPT_ACTION), is(false)); - assertThat(emptyEntitlement.matchActions(NetworkEntitlement.LISTEN_ACTION | NetworkEntitlement.CONNECT_ACTION), is(false)); - assertThat(emptyEntitlement.matchActions(NetworkEntitlement.CONNECT_ACTION | NetworkEntitlement.ACCEPT_ACTION), is(false)); - } -} 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 092813be75cc8..c3acefbbb323b 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 @@ -66,11 +66,7 @@ public void testGetEntitlementsThrowsOnMissingPluginUnnamedModule() { var callerClass = this.getClass(); var requestingModule = callerClass.getModule(); - assertEquals( - "No policy for the unnamed module", - ModuleEntitlements.NONE, - policyManager.getEntitlements(callerClass, Entitlement.class) - ); + assertEquals("No policy for the unnamed module", ModuleEntitlements.NONE, policyManager.getEntitlements(callerClass)); assertEquals(Map.of(requestingModule, ModuleEntitlements.NONE), policyManager.moduleEntitlementsMap); } @@ -82,7 +78,7 @@ public void testGetEntitlementsThrowsOnMissingPolicyForPlugin() { var callerClass = this.getClass(); var requestingModule = callerClass.getModule(); - assertEquals("No policy for this plugin", ModuleEntitlements.NONE, policyManager.getEntitlements(callerClass, Entitlement.class)); + assertEquals("No policy for this plugin", ModuleEntitlements.NONE, policyManager.getEntitlements(callerClass)); assertEquals(Map.of(requestingModule, ModuleEntitlements.NONE), policyManager.moduleEntitlementsMap); } @@ -94,11 +90,11 @@ public void testGetEntitlementsFailureIsCached() { var callerClass = this.getClass(); var requestingModule = callerClass.getModule(); - assertEquals(ModuleEntitlements.NONE, policyManager.getEntitlements(callerClass, Entitlement.class)); + assertEquals(ModuleEntitlements.NONE, policyManager.getEntitlements(callerClass)); assertEquals(Map.of(requestingModule, ModuleEntitlements.NONE), policyManager.moduleEntitlementsMap); // A second time - assertEquals(ModuleEntitlements.NONE, policyManager.getEntitlements(callerClass, Entitlement.class)); + assertEquals(ModuleEntitlements.NONE, policyManager.getEntitlements(callerClass)); // Nothing new in the map assertEquals(Map.of(requestingModule, ModuleEntitlements.NONE), policyManager.moduleEntitlementsMap); @@ -116,7 +112,7 @@ public void testGetEntitlementsReturnsEntitlementsForPluginUnnamedModule() { // Any class from the current module (unnamed) will do var callerClass = this.getClass(); - var entitlements = policyManager.getEntitlements(callerClass, Entitlement.class); + var entitlements = policyManager.getEntitlements(callerClass); assertThat(entitlements.hasEntitlement(CreateClassLoaderEntitlement.class), is(true)); } @@ -130,11 +126,7 @@ public void testGetEntitlementsThrowsOnMissingPolicyForServer() throws ClassNotF 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, Entitlement.class) - ); + assertEquals("No policy for this module in server", ModuleEntitlements.NONE, policyManager.getEntitlements(mockServerClass)); assertEquals(Map.of(requestingModule, ModuleEntitlements.NONE), policyManager.moduleEntitlementsMap); } @@ -154,7 +146,7 @@ public void testGetEntitlementsReturnsEntitlementsForServerModule() throws Class // 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 entitlements = policyManager.getEntitlements(mockServerClass, Entitlement.class); + var entitlements = policyManager.getEntitlements(mockServerClass); assertThat(entitlements.hasEntitlement(CreateClassLoaderEntitlement.class), is(true)); assertThat(entitlements.hasEntitlement(ExitVMEntitlement.class), is(true)); } @@ -175,7 +167,7 @@ public void testGetEntitlementsReturnsEntitlementsForPluginModule() throws IOExc var layer = createLayerForJar(jar, "org.example.plugin"); var mockPluginClass = layer.findLoader("org.example.plugin").loadClass("q.B"); - var entitlements = policyManager.getEntitlements(mockPluginClass, Entitlement.class); + var entitlements = policyManager.getEntitlements(mockPluginClass); assertThat(entitlements.hasEntitlement(CreateClassLoaderEntitlement.class), is(true)); assertThat( entitlements.getEntitlements(FileEntitlement.class).toList(), @@ -195,11 +187,11 @@ public void testGetEntitlementsResultIsCached() { // Any class from the current module (unnamed) will do var callerClass = this.getClass(); - var entitlements = policyManager.getEntitlements(callerClass, Entitlement.class); + var entitlements = policyManager.getEntitlements(callerClass); assertThat(entitlements.hasEntitlement(CreateClassLoaderEntitlement.class), is(true)); assertThat(policyManager.moduleEntitlementsMap, aMapWithSize(1)); var cachedResult = policyManager.moduleEntitlementsMap.values().stream().findFirst().orElseThrow(); - var entitlementsAgain = policyManager.getEntitlements(callerClass, Entitlement.class); + var entitlementsAgain = policyManager.getEntitlements(callerClass); // Nothing new in the map assertThat(policyManager.moduleEntitlementsMap, aMapWithSize(1)); diff --git a/libs/entitlement/src/test/java/org/elasticsearch/entitlement/runtime/policy/PolicyParserTests.java b/libs/entitlement/src/test/java/org/elasticsearch/entitlement/runtime/policy/PolicyParserTests.java index 2951ac190654f..a801a49c0a9b1 100644 --- a/libs/entitlement/src/test/java/org/elasticsearch/entitlement/runtime/policy/PolicyParserTests.java +++ b/libs/entitlement/src/test/java/org/elasticsearch/entitlement/runtime/policy/PolicyParserTests.java @@ -55,35 +55,31 @@ public void testPolicyBuilderOnExternalPlugin() throws IOException { public void testParseNetwork() throws IOException { Policy parsedPolicy = new PolicyParser(new ByteArrayInputStream(""" entitlement-module-name: - - network: - actions: - - listen - - accept - - connect + - inbound_network """.getBytes(StandardCharsets.UTF_8)), "test-policy.yaml", false).parsePolicy(); Policy expected = new Policy( "test-policy.yaml", - List.of(new Scope("entitlement-module-name", List.of(new NetworkEntitlement(List.of("listen", "accept", "connect"))))) + List.of(new Scope("entitlement-module-name", List.of(new InboundNetworkEntitlement()))) ); assertEquals(expected, parsedPolicy); - } - public void testParseNetworkIllegalAction() throws IOException { - var ex = expectThrows(PolicyParserException.class, () -> new PolicyParser(new ByteArrayInputStream(""" + parsedPolicy = new PolicyParser(new ByteArrayInputStream(""" entitlement-module-name: - - network: - actions: - - listen - - doesnotexist - - connect - """.getBytes(StandardCharsets.UTF_8)), "test-policy.yaml", false).parsePolicy()); - assertThat( - ex.getMessage(), - equalTo( - "[2:5] policy parsing error for [test-policy.yaml] in scope [entitlement-module-name] for entitlement type [network]: " - + "unknown network action [doesnotexist]" - ) + - outbound_network + """.getBytes(StandardCharsets.UTF_8)), "test-policy.yaml", false).parsePolicy(); + expected = new Policy("test-policy.yaml", List.of(new Scope("entitlement-module-name", List.of(new OutboundNetworkEntitlement())))); + assertEquals(expected, parsedPolicy); + + parsedPolicy = new PolicyParser(new ByteArrayInputStream(""" + entitlement-module-name: + - outbound_network + - inbound_network + """.getBytes(StandardCharsets.UTF_8)), "test-policy.yaml", false).parsePolicy(); + expected = new Policy( + "test-policy.yaml", + List.of(new Scope("entitlement-module-name", List.of(new OutboundNetworkEntitlement(), new InboundNetworkEntitlement()))) ); + assertEquals(expected, parsedPolicy); } public void testParseCreateClassloader() throws IOException { diff --git a/modules/reindex/src/main/plugin-metadata/entitlement-policy.yaml b/modules/reindex/src/main/plugin-metadata/entitlement-policy.yaml index 4c42ec110a257..df557f9944253 100644 --- a/modules/reindex/src/main/plugin-metadata/entitlement-policy.yaml +++ b/modules/reindex/src/main/plugin-metadata/entitlement-policy.yaml @@ -1,4 +1,2 @@ ALL-UNNAMED: - - network: - actions: - - connect + - outbound_network diff --git a/modules/repository-azure/src/main/plugin-metadata/entitlement-policy.yaml b/modules/repository-azure/src/main/plugin-metadata/entitlement-policy.yaml index 9340655013763..74197fb3ed9ae 100644 --- a/modules/repository-azure/src/main/plugin-metadata/entitlement-policy.yaml +++ b/modules/repository-azure/src/main/plugin-metadata/entitlement-policy.yaml @@ -1,4 +1,2 @@ io.netty.common: - - network: - actions: - - connect + - outbound_network diff --git a/modules/repository-s3/src/main/plugin-metadata/entitlement-policy.yaml b/modules/repository-s3/src/main/plugin-metadata/entitlement-policy.yaml index 4c42ec110a257..df557f9944253 100644 --- a/modules/repository-s3/src/main/plugin-metadata/entitlement-policy.yaml +++ b/modules/repository-s3/src/main/plugin-metadata/entitlement-policy.yaml @@ -1,4 +1,2 @@ ALL-UNNAMED: - - network: - actions: - - connect + - outbound_network diff --git a/modules/repository-url/src/main/plugin-metadata/entitlement-policy.yaml b/modules/repository-url/src/main/plugin-metadata/entitlement-policy.yaml index f1dc1fc7755ef..081ac21f88864 100644 --- a/modules/repository-url/src/main/plugin-metadata/entitlement-policy.yaml +++ b/modules/repository-url/src/main/plugin-metadata/entitlement-policy.yaml @@ -1,4 +1,2 @@ org.apache.httpcomponents.httpclient: - - network: - actions: - - connect # for URLHttpClient + - outbound_network # for URLHttpClient diff --git a/modules/transport-netty4/src/main/plugin-metadata/entitlement-policy.yaml b/modules/transport-netty4/src/main/plugin-metadata/entitlement-policy.yaml index 4ccf7e0af393e..eb772a06423a3 100644 --- a/modules/transport-netty4/src/main/plugin-metadata/entitlement-policy.yaml +++ b/modules/transport-netty4/src/main/plugin-metadata/entitlement-policy.yaml @@ -1,9 +1,6 @@ io.netty.transport: - - network: - actions: - - listen + - inbound_network + - outbound_network io.netty.common: - - network: - actions: - - connect - - accept + - inbound_network + - outbound_network diff --git a/plugins/discovery-ec2/src/main/plugin-metadata/entitlement-policy.yaml b/plugins/discovery-ec2/src/main/plugin-metadata/entitlement-policy.yaml index 4c42ec110a257..df557f9944253 100644 --- a/plugins/discovery-ec2/src/main/plugin-metadata/entitlement-policy.yaml +++ b/plugins/discovery-ec2/src/main/plugin-metadata/entitlement-policy.yaml @@ -1,4 +1,2 @@ ALL-UNNAMED: - - network: - actions: - - connect + - outbound_network diff --git a/plugins/repository-hdfs/src/main/plugin-metadata/entitlement-policy.yaml b/plugins/repository-hdfs/src/main/plugin-metadata/entitlement-policy.yaml index 4c42ec110a257..df557f9944253 100644 --- a/plugins/repository-hdfs/src/main/plugin-metadata/entitlement-policy.yaml +++ b/plugins/repository-hdfs/src/main/plugin-metadata/entitlement-policy.yaml @@ -1,4 +1,2 @@ ALL-UNNAMED: - - network: - actions: - - connect + - outbound_network 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 index ca6f10e526cef..9a1dde9ce3f33 100644 --- a/x-pack/plugin/core/src/main/plugin-metadata/entitlement-policy.yaml +++ b/x-pack/plugin/core/src/main/plugin-metadata/entitlement-policy.yaml @@ -1,8 +1,4 @@ org.apache.httpcomponents.httpclient: - - network: - actions: - - connect # For SamlRealm + - outbound_network # For SamlRealm org.apache.httpcomponents.httpcore.nio: - - network: - actions: - - connect + - outbound_network diff --git a/x-pack/plugin/security/src/main/plugin-metadata/entitlement-policy.yaml b/x-pack/plugin/security/src/main/plugin-metadata/entitlement-policy.yaml index df059585cef44..c3d07b157a9af 100644 --- a/x-pack/plugin/security/src/main/plugin-metadata/entitlement-policy.yaml +++ b/x-pack/plugin/security/src/main/plugin-metadata/entitlement-policy.yaml @@ -1,11 +1,8 @@ org.elasticsearch.security: - set_https_connection_properties # for CommandLineHttpClient io.netty.transport: - - network: - actions: - - listen + - inbound_network + - outbound_network io.netty.common: - - network: - actions: - - accept - - connect + - inbound_network + - outbound_network