Skip to content

Commit 9287268

Browse files
Cross-project context preserving
1 parent 2b91dd5 commit 9287268

File tree

19 files changed

+202
-185
lines changed

19 files changed

+202
-185
lines changed

plugins/examples/security-authorization-engine/src/main/java/org/elasticsearch/example/CustomAuthorizationEngine.java

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -87,14 +87,14 @@ public void authorizeClusterAction(RequestInfo requestInfo, AuthorizationInfo au
8787
}
8888

8989
@Override
90-
public SubscribableListener<IndexAuthorizationResult> authorizeIndexAction(
90+
public void authorizeIndexAction(
9191
RequestInfo requestInfo,
9292
AuthorizationInfo authorizationInfo,
9393
AsyncSupplier<ResolvedIndices> indicesAsyncSupplier,
94-
ProjectMetadata project
94+
ProjectMetadata project,
95+
ActionListener<IndexAuthorizationResult> listener
9596
) {
9697
if (isSuperuser(requestInfo.getAuthentication().getEffectiveSubject().getUser())) {
97-
SubscribableListener<IndexAuthorizationResult> listener = new SubscribableListener<>();
9898
indicesAsyncSupplier.getAsync().addListener(ActionListener.wrap(resolvedIndices -> {
9999
Map<String, IndexAccessControl> indexAccessControlMap = new HashMap<>();
100100
for (String name : resolvedIndices.getLocal()) {
@@ -104,9 +104,8 @@ public SubscribableListener<IndexAuthorizationResult> authorizeIndexAction(
104104
new IndicesAccessControl(true, Collections.unmodifiableMap(indexAccessControlMap));
105105
listener.onResponse(new IndexAuthorizationResult(indicesAccessControl));
106106
}, listener::onFailure));
107-
return listener;
108107
} else {
109-
return SubscribableListener.newSucceeded(new IndexAuthorizationResult(IndicesAccessControl.DENIED));
108+
listener.onResponse(new IndexAuthorizationResult(IndicesAccessControl.DENIED));
110109
}
111110
}
112111

server/src/main/java/org/elasticsearch/action/support/ContextPreservingActionListener.java

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,4 +48,16 @@ public void onFailure(Exception e) {
4848
public static <R> ContextPreservingActionListener<R> wrapPreservingContext(ActionListener<R> listener, ThreadContext threadContext) {
4949
return new ContextPreservingActionListener<>(threadContext.newRestorableContext(true), listener);
5050
}
51+
52+
public static <R> ContextPreservingActionListener<R> wrapPreservingTransientContext(
53+
ActionListener<R> listener,
54+
ThreadContext threadContext
55+
) {
56+
return new ContextPreservingActionListener<>(
57+
threadContext.wrapRestorable(
58+
threadContext.newStoredContextPreservingResponseHeaders("_security_serverless_request_scoped_credential")
59+
),
60+
listener
61+
);
62+
}
5163
}

server/src/main/java/org/elasticsearch/common/util/concurrent/ThreadContext.java

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -364,6 +364,23 @@ public StoredContext newStoredContextPreservingResponseHeaders() {
364364
};
365365
}
366366

367+
public StoredContext newStoredContextPreservingResponseHeaders(String transientHeader) {
368+
final ThreadContextStruct originalContext = threadLocal.get();
369+
return () -> {
370+
var found = threadLocal.get();
371+
if (found != originalContext) {
372+
if (found.transientHeaders.containsKey(transientHeader)) {
373+
threadLocal.set(
374+
originalContext.putResponseHeaders(found.responseHeaders)
375+
.putTransient(transientHeader, found.transientHeaders.get(transientHeader))
376+
);
377+
} else {
378+
threadLocal.set(originalContext.putResponseHeaders(found.responseHeaders));
379+
}
380+
}
381+
};
382+
}
383+
367384
/**
368385
* Capture the current context and then restore the given context, returning a {@link StoredContext} that reverts back to the current
369386
* context again. Equivalent to using {@link #newStoredContext()} and then calling {@code existingContext.restore()}.

x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/security/authz/AuthorizationEngine.java

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@
1212
import org.elasticsearch.action.ActionRequestValidationException;
1313
import org.elasticsearch.action.IndicesRequest;
1414
import org.elasticsearch.action.support.IndexComponentSelector;
15-
import org.elasticsearch.action.support.SubscribableListener;
1615
import org.elasticsearch.cluster.metadata.IndexAbstraction;
1716
import org.elasticsearch.cluster.metadata.IndexNameExpressionResolver;
1817
import org.elasticsearch.cluster.metadata.ProjectMetadata;
@@ -77,7 +76,7 @@
7776
* can actually impersonate the user running the request.</li>
7877
* <li>{@link #authorizeClusterAction(RequestInfo, AuthorizationInfo, ActionListener)} if the
7978
* request is a cluster level operation.</li>
80-
* <li>{@link #authorizeIndexAction(RequestInfo, AuthorizationInfo, AsyncSupplier, ProjectMetadata)} if
79+
* <li>{@link #authorizeIndexAction(RequestInfo, AuthorizationInfo, AsyncSupplier, ProjectMetadata,ActionListener)} if
8180
* the request is a an index action. This method may be called multiple times for a single
8281
* request as the request may be made up of sub-requests that also need to be authorized. The async supplier
8382
* for resolved indices will invoke the
@@ -87,7 +86,7 @@
8786
* <br><p>
8887
* <em>NOTE:</em> the {@link #loadAuthorizedIndices(RequestInfo, AuthorizationInfo, Map, ActionListener)}
8988
* method may be called prior to
90-
* {@link #authorizeIndexAction(RequestInfo, AuthorizationInfo, AsyncSupplier, ProjectMetadata)}
89+
* {@link #authorizeIndexAction(RequestInfo, AuthorizationInfo, AsyncSupplier, ProjectMetadata,ActionListener)}
9190
* in cases where wildcards need to be expanded.
9291
* </p><br>
9392
* Authorization engines can be called from various threads including network threads that should
@@ -163,13 +162,13 @@ public interface AuthorizationEngine {
163162
* attempting to operate on
164163
* @param metadata a map of a string name to the cluster metadata specific to that
165164
* alias or index
166-
* @return a listener to be notified of the authorization result
167165
*/
168-
SubscribableListener<IndexAuthorizationResult> authorizeIndexAction(
166+
void authorizeIndexAction(
169167
RequestInfo requestInfo,
170168
AuthorizationInfo authorizationInfo,
171169
AsyncSupplier<ResolvedIndices> indicesAsyncSupplier,
172-
ProjectMetadata metadata
170+
ProjectMetadata metadata,
171+
ActionListener<IndexAuthorizationResult> listener
173172
);
174173

175174
/**
@@ -779,6 +778,6 @@ interface AsyncSupplier<V> {
779778
* Asynchronously retrieves the value that is being supplied and notifies the listener upon
780779
* completion.
781780
*/
782-
SubscribableListener<V> getAsync();
781+
void getAsync(ActionListener<V> listener);
783782
}
784783
}

x-pack/plugin/security/src/internalClusterTest/java/org/elasticsearch/xpack/security/profile/ProfileCancellationIntegTests.java

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@
1111
import org.apache.logging.log4j.Logger;
1212
import org.elasticsearch.action.ActionListener;
1313
import org.elasticsearch.action.search.TransportSearchAction;
14-
import org.elasticsearch.action.support.SubscribableListener;
1514
import org.elasticsearch.client.Cancellable;
1615
import org.elasticsearch.client.Request;
1716
import org.elasticsearch.client.RequestOptions;
@@ -407,13 +406,14 @@ public void authorizeClusterAction(
407406
}
408407

409408
@Override
410-
public SubscribableListener<IndexAuthorizationResult> authorizeIndexAction(
409+
public void authorizeIndexAction(
411410
RequestInfo requestInfo,
412411
AuthorizationInfo authorizationInfo,
413412
AsyncSupplier<ResolvedIndices> indicesAsyncSupplier,
414-
ProjectMetadata metadata
413+
ProjectMetadata metadata,
414+
ActionListener<IndexAuthorizationResult> listener
415415
) {
416-
return SubscribableListener.newSucceeded(IndexAuthorizationResult.ALLOW_NO_INDICES);
416+
listener.onResponse(IndexAuthorizationResult.ALLOW_NO_INDICES);
417417
}
418418

419419
@Override

0 commit comments

Comments
 (0)