Skip to content

Commit 9a8aa92

Browse files
authored
Remove ban tasks with the current thread context (#55404)
If we start unbanning when the last child task completed and that child task executed with a specific user, then unban requests are denied because internal requests can't run with a user. We need to remove bans with the current thread context.
1 parent 4a8b843 commit 9a8aa92

File tree

1 file changed

+15
-2
lines changed

1 file changed

+15
-2
lines changed

server/src/main/java/org/elasticsearch/action/admin/cluster/node/tasks/cancel/TransportCancelTasksAction.java

+15-2
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@
1919

2020
package org.elasticsearch.action.admin.cluster.node.tasks.cancel;
2121

22+
import org.elasticsearch.ElasticsearchSecurityException;
23+
import org.elasticsearch.ExceptionsHelper;
2224
import org.elasticsearch.ResourceNotFoundException;
2325
import org.elasticsearch.Version;
2426
import org.elasticsearch.action.ActionListener;
@@ -121,8 +123,12 @@ void cancelTaskAndDescendants(CancellableTask task, String reason, boolean waitF
121123
StepListener<Void> banOnNodesListener = new StepListener<>();
122124
setBanOnNodes(reason, waitForCompletion, task, childrenNodes, banOnNodesListener);
123125
banOnNodesListener.whenComplete(groupedListener::onResponse, groupedListener::onFailure);
126+
// If we start unbanning when the last child task completed and that child task executed with a specific user, then unban
127+
// requests are denied because internal requests can't run with a user. We need to remove bans with the current thread context.
128+
final Runnable removeBansRunnable = transportService.getThreadPool().getThreadContext()
129+
.preserveContext(() -> removeBanOnNodes(task, childrenNodes));
124130
// We remove bans after all child tasks are completed although in theory we can do it on a per-node basis.
125-
completedListener.whenComplete(r -> removeBanOnNodes(task, childrenNodes), e -> removeBanOnNodes(task, childrenNodes));
131+
completedListener.whenComplete(r -> removeBansRunnable.run(), e -> removeBansRunnable.run());
126132
// if wait_for_completion is true, then only return when (1) bans are placed on child nodes, (2) child tasks are
127133
// completed or failed, (3) the main task is cancelled. Otherwise, return after bans are placed on child nodes.
128134
if (waitForCompletion) {
@@ -162,6 +168,7 @@ public void handleResponse(TransportResponse.Empty response) {
162168

163169
@Override
164170
public void handleException(TransportException exp) {
171+
assert ExceptionsHelper.unwrapCause(exp) instanceof ElasticsearchSecurityException == false;
165172
logger.warn("Cannot send ban for tasks with the parent [{}] to the node [{}]", banRequest.parentTaskId, node);
166173
groupedListener.onFailure(exp);
167174
}
@@ -174,7 +181,13 @@ private void removeBanOnNodes(CancellableTask task, Collection<DiscoveryNode> ch
174181
BanParentTaskRequest.createRemoveBanParentTaskRequest(new TaskId(clusterService.localNode().getId(), task.getId()));
175182
for (DiscoveryNode node : childNodes) {
176183
logger.trace("Sending remove ban for tasks with the parent [{}] to the node [{}]", request.parentTaskId, node);
177-
transportService.sendRequest(node, BAN_PARENT_ACTION_NAME, request, EmptyTransportResponseHandler.INSTANCE_SAME);
184+
transportService.sendRequest(node, BAN_PARENT_ACTION_NAME, request, new EmptyTransportResponseHandler(ThreadPool.Names.SAME) {
185+
@Override
186+
public void handleException(TransportException exp) {
187+
assert ExceptionsHelper.unwrapCause(exp) instanceof ElasticsearchSecurityException == false;
188+
logger.info("failed to remove the parent ban for task {} on node {}", request.parentTaskId, node);
189+
}
190+
});
178191
}
179192
}
180193

0 commit comments

Comments
 (0)