Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@
import org.opensearch.security.action.configupdate.ConfigUpdateResponse;
import org.opensearch.security.action.configupdate.SecurityConfigWriteAction;
import org.opensearch.security.action.configupdate.SecurityConfigWriteRequest;
import org.opensearch.security.dlic.rest.api.pagination.PaginationHelper;
import org.opensearch.security.dlic.rest.support.Utils;
import org.opensearch.security.dlic.rest.validation.EndpointValidator;
import org.opensearch.security.dlic.rest.validation.RequestContentValidator;
Expand Down Expand Up @@ -692,6 +693,11 @@ protected final RestChannelConsumer prepareRequest(RestRequest request, NodeClie
// override consumeParameters — and don't call super — still don't reject
// ?wait_for_completion=... as an unrecognized parameter.
request.paramAsBoolean("wait_for_completion", true);
// Same rationale for the cursor-based pagination parameters used by collection GETs.
// Subclasses opt into pagination behavior via
// {@link RequestHandler.RequestHandlersBuilder#onCollectionGetRequest}; consuming here
// means unopted endpoints simply ignore the parameters rather than 400-ing on them.
PaginationHelper.consumeParameters(request);

// check if .opendistro_security index has been initialized
if (!ensureIndexExists()) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,9 @@ protected CType<?> getConfigType() {
}

private void actionGroupsApiRequestHandlers(RequestHandler.RequestHandlersBuilder requestHandlersBuilder) {
requestHandlersBuilder.onChangeRequest(Method.PATCH, this::processPatchRequest).override(Method.POST, methodNotImplementedHandler);
requestHandlersBuilder.onCollectionGetRequest(getConfigType(), this::processGetRequest)
.onChangeRequest(Method.PATCH, this::processPatchRequest)
.override(Method.POST, methodNotImplementedHandler);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,8 @@ protected boolean supportsAsync() {
}

private void internalUsersApiRequestHandlers(RequestHandler.RequestHandlersBuilder requestHandlersBuilder) {
requestHandlersBuilder.onGetRequest(
requestHandlersBuilder.onCollectionGetRequest(
getConfigType(),
request -> ValidationResult.success(request).map(this::processGetRequest).map(securityConfiguration -> {
final var configuration = securityConfiguration.configuration();
filterUsers(configuration, filterParam(request));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -123,13 +123,15 @@ protected void consumeParameters(final RestRequest request) {
}

private void nodesDnApiRequestHandlers(RequestHandler.RequestHandlersBuilder requestHandlersBuilder) {
requestHandlersBuilder.verifyAccessForAllMethods().onGetRequest(request -> processGetRequest(request).map(securityConfiguration -> {
if (request.paramAsBoolean("show_all", false)) {
final var configuration = securityConfiguration.configuration();
addStaticNodesDn(configuration);
}
return ValidationResult.success(securityConfiguration);
})).onChangeRequest(Method.PATCH, this::processPatchRequest);
requestHandlersBuilder.verifyAccessForAllMethods()
.onCollectionGetRequest(getConfigType(), request -> processGetRequest(request).map(securityConfiguration -> {
if (request.paramAsBoolean("show_all", false)) {
final var configuration = securityConfiguration.configuration();
addStaticNodesDn(configuration);
}
return ValidationResult.success(securityConfiguration);
}))
.onChangeRequest(Method.PATCH, this::processPatchRequest);
}

@SuppressWarnings("unchecked")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,9 @@
import org.opensearch.core.xcontent.ToXContent;
import org.opensearch.rest.RestChannel;
import org.opensearch.rest.RestRequest;
import org.opensearch.security.dlic.rest.api.pagination.PaginationHelper;
import org.opensearch.security.dlic.rest.validation.ValidationResult;
import org.opensearch.security.securityconf.impl.CType;
import org.opensearch.security.securityconf.impl.SecurityDynamicConfiguration;
import org.opensearch.transport.client.Client;

Expand Down Expand Up @@ -185,6 +187,36 @@ public RequestHandlersBuilder onJsonContentGetRequest(
return this;
}

/**
* Registers a GET handler that supports opt-in cursor-based pagination via
* {@link org.opensearch.security.dlic.rest.api.pagination.PaginationHelper}.
*
* <p>Callers pass the same {@code CheckedFunction<RestRequest, ValidationResult<SecurityConfiguration>, IOException>}
* mapper used with {@link #onGetRequest(CheckedFunction)}. The wrapper then invokes
* {@link org.opensearch.security.dlic.rest.api.pagination.PaginationHelper#apply(RestRequest, CType, SecurityConfiguration)}
* before rendering. When no pagination parameters were provided, the response retains its
* exact pre-existing shape. When any of {@code size}, {@code next_token}, or {@code sort} is
* provided, the response is wrapped as {@code {"next_token": ..., "<ctype>": {entries}}}.
*
* <p>The provided {@code ctype} binds cursors issued by this endpoint: a {@code next_token}
* from a different endpoint or a different sort direction is rejected with HTTP 400.
*/
public RequestHandlersBuilder onCollectionGetRequest(
final CType<?> ctype,
final CheckedFunction<RestRequest, ValidationResult<SecurityConfiguration>, IOException> mapper
) {
Objects.requireNonNull(ctype, "ctype can't be null");
Objects.requireNonNull(mapper, "onCollectionGetRequest request handler can't be null");
add(
RestRequest.Method.GET,
(channel, request, client) -> mapper.apply(request)
.map(sc -> PaginationHelper.apply(request, ctype, sc))
.valid(toXContent -> Responses.ok(channel, toXContent))
.error((status, toXContent) -> response(channel, status, toXContent))
);
return this;
}

public RequestHandlersBuilder onChangeRequest(
final RestRequest.Method method,
final CheckedFunction<RestRequest, ValidationResult<SecurityConfiguration>, IOException> mapper
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,9 @@ protected boolean supportsAsync() {
}

private void rolesApiRequestHandlers(RequestHandler.RequestHandlersBuilder requestHandlersBuilder) {
requestHandlersBuilder.onChangeRequest(Method.PATCH, this::processPatchRequest).override(Method.POST, methodNotImplementedHandler);
requestHandlersBuilder.onCollectionGetRequest(getConfigType(), this::processGetRequest)
.onChangeRequest(Method.PATCH, this::processPatchRequest)
.override(Method.POST, methodNotImplementedHandler);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,9 @@ public RolesMappingApiAction(
) {
super(Endpoint.ROLESMAPPING, clusterService, threadPool, securityApiDependencies);
this.requestHandlersBuilder.configureRequestHandlers(
builder -> builder.onChangeRequest(Method.PATCH, this::processPatchRequest).override(Method.POST, methodNotImplementedHandler)
builder -> builder.onCollectionGetRequest(getConfigType(), this::processGetRequest)
.onChangeRequest(Method.PATCH, this::processPatchRequest)
.override(Method.POST, methodNotImplementedHandler)
);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,10 @@ public TenantsApiAction(
final SecurityApiDependencies securityApiDependencies
) {
super(Endpoint.TENANTS, clusterService, threadPool, securityApiDependencies);
this.requestHandlersBuilder.configureRequestHandlers(builder -> builder.onChangeRequest(Method.PATCH, this::processPatchRequest));
this.requestHandlersBuilder.configureRequestHandlers(
builder -> builder.onCollectionGetRequest(getConfigType(), this::processGetRequest)
.onChangeRequest(Method.PATCH, this::processPatchRequest)
);
}

@Override
Expand Down
Loading
Loading