diff --git a/server/src/main/java/org/elasticsearch/transport/RemoteClusterConnection.java b/server/src/main/java/org/elasticsearch/transport/RemoteClusterConnection.java index ef2cb83ed90..603b4625ee4 100644 --- a/server/src/main/java/org/elasticsearch/transport/RemoteClusterConnection.java +++ b/server/src/main/java/org/elasticsearch/transport/RemoteClusterConnection.java @@ -192,39 +192,52 @@ final class RemoteClusterConnection implements TransportConnectionListener, Clos /** * Collects all nodes on the connected cluster and returns / passes a nodeID to {@link DiscoveryNode} lookup function * that returns null if the node ID is not found. + * + * The requests to get cluster state on the connected cluster are made in the system context because logically + * they are equivalent to checking a single detail in the local cluster state and should not require that the + * user who made the request that is using this method in its implementation is authorized to view the entire + * cluster state. */ void collectNodes(ActionListener> listener) { Runnable runnable = () -> { - final ClusterStateRequest request = new ClusterStateRequest(); - request.clear(); - request.nodes(true); - request.local(true); // run this on the node that gets the request it's as good as any other - final DiscoveryNode node = getAnyConnectedNode(); - Transport.Connection connection = connectionManager.getConnection(node); - transportService.sendRequest(connection, ClusterStateAction.NAME, request, TransportRequestOptions.EMPTY, - new TransportResponseHandler() { + final ThreadContext threadContext = threadPool.getThreadContext(); + final ContextPreservingActionListener> contextPreservingActionListener = + new ContextPreservingActionListener<>(threadContext.newRestorableContext(false), listener); + try (ThreadContext.StoredContext ignore = threadContext.stashContext()) { + // we stash any context here since this is an internal execution and should not leak any existing context information + threadContext.markAsSystemContext(); - @Override - public ClusterStateResponse read(StreamInput in) throws IOException { - return new ClusterStateResponse(in); - } + final ClusterStateRequest request = new ClusterStateRequest(); + request.clear(); + request.nodes(true); + request.local(true); // run this on the node that gets the request it's as good as any other + final DiscoveryNode node = getAnyConnectedNode(); + Transport.Connection connection = connectionManager.getConnection(node); + transportService.sendRequest(connection, ClusterStateAction.NAME, request, TransportRequestOptions.EMPTY, + new TransportResponseHandler() { - @Override - public void handleResponse(ClusterStateResponse response) { - DiscoveryNodes nodes = response.getState().nodes(); - listener.onResponse(nodes::get); - } + @Override + public ClusterStateResponse read(StreamInput in) throws IOException { + return new ClusterStateResponse(in); + } - @Override - public void handleException(TransportException exp) { - listener.onFailure(exp); - } + @Override + public void handleResponse(ClusterStateResponse response) { + DiscoveryNodes nodes = response.getState().nodes(); + contextPreservingActionListener.onResponse(nodes::get); + } - @Override - public String executor() { - return ThreadPool.Names.SAME; - } - }); + @Override + public void handleException(TransportException exp) { + contextPreservingActionListener.onFailure(exp); + } + + @Override + public String executor() { + return ThreadPool.Names.SAME; + } + }); + } }; try { // just in case if we are not connected for some reason we try to connect and if we fail we have to notify the listener