Add a base security rest handler (elastic/x-pack-elasticsearch#1239)

This commit adds a base rest handler for security that handles the license checking in the security
apis. This was done previously in some rest handlers but not all and actually had issues where a
value would be returned but we may not have consumed all of the request parameters, which could
lead to a different response being returned than what we would have expected.

relates elastic/x-pack-elasticsearch#1236

Original commit: elastic/x-pack-elasticsearch@2f1100b64a
This commit is contained in:
Jay Modi 2017-05-09 14:47:11 -04:00 committed by GitHub
parent 2d8eb8fbf7
commit 590eea57ac
20 changed files with 251 additions and 145 deletions

View File

@ -586,22 +586,22 @@ public class Security implements ActionPlugin, IngestPlugin, NetworkPlugin {
} }
return Arrays.asList( return Arrays.asList(
new RestAuthenticateAction(settings, restController, securityContext.get(), licenseState), new RestAuthenticateAction(settings, restController, securityContext.get(), licenseState),
new RestClearRealmCacheAction(settings, restController), new RestClearRealmCacheAction(settings, restController, licenseState),
new RestClearRolesCacheAction(settings, restController), new RestClearRolesCacheAction(settings, restController, licenseState),
new RestGetUsersAction(settings, restController), new RestGetUsersAction(settings, restController, licenseState),
new RestPutUserAction(settings, restController), new RestPutUserAction(settings, restController, licenseState),
new RestDeleteUserAction(settings, restController), new RestDeleteUserAction(settings, restController, licenseState),
new RestGetRolesAction(settings, restController), new RestGetRolesAction(settings, restController, licenseState),
new RestPutRoleAction(settings, restController), new RestPutRoleAction(settings, restController, licenseState),
new RestDeleteRoleAction(settings, restController), new RestDeleteRoleAction(settings, restController, licenseState),
new RestChangePasswordAction(settings, restController, securityContext.get()), new RestChangePasswordAction(settings, restController, securityContext.get(), licenseState),
new RestSetEnabledAction(settings, restController), new RestSetEnabledAction(settings, restController, licenseState),
new RestHasPrivilegesAction(settings, restController, securityContext.get()), new RestHasPrivilegesAction(settings, restController, securityContext.get(), licenseState),
new RestGetRoleMappingsAction(settings, restController), new RestGetRoleMappingsAction(settings, restController, licenseState),
new RestPutRoleMappingAction(settings, restController), new RestPutRoleMappingAction(settings, restController, licenseState),
new RestDeleteRoleMappingAction(settings, restController), new RestDeleteRoleMappingAction(settings, restController, licenseState),
new RestGetTokenAction(settings, licenseState, restController), new RestGetTokenAction(settings, restController, licenseState),
new RestInvalidateTokenAction(settings, licenseState, restController) new RestInvalidateTokenAction(settings, restController, licenseState)
); );
} }

View File

@ -9,16 +9,13 @@ import org.elasticsearch.client.node.NodeClient;
import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.xcontent.ToXContent; import org.elasticsearch.common.xcontent.ToXContent;
import org.elasticsearch.common.xcontent.XContentBuilder; import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.license.LicenseUtils;
import org.elasticsearch.license.XPackLicenseState; import org.elasticsearch.license.XPackLicenseState;
import org.elasticsearch.rest.BaseRestHandler;
import org.elasticsearch.rest.BytesRestResponse; import org.elasticsearch.rest.BytesRestResponse;
import org.elasticsearch.rest.RestController; import org.elasticsearch.rest.RestController;
import org.elasticsearch.rest.RestRequest; import org.elasticsearch.rest.RestRequest;
import org.elasticsearch.rest.RestResponse; import org.elasticsearch.rest.RestResponse;
import org.elasticsearch.rest.RestStatus; import org.elasticsearch.rest.RestStatus;
import org.elasticsearch.rest.action.RestBuilderListener; import org.elasticsearch.rest.action.RestBuilderListener;
import org.elasticsearch.xpack.XPackPlugin;
import org.elasticsearch.xpack.security.SecurityContext; import org.elasticsearch.xpack.security.SecurityContext;
import org.elasticsearch.xpack.security.action.user.AuthenticateAction; import org.elasticsearch.xpack.security.action.user.AuthenticateAction;
import org.elasticsearch.xpack.security.action.user.AuthenticateRequest; import org.elasticsearch.xpack.security.action.user.AuthenticateRequest;
@ -29,16 +26,14 @@ import java.io.IOException;
import static org.elasticsearch.rest.RestRequest.Method.GET; import static org.elasticsearch.rest.RestRequest.Method.GET;
public class RestAuthenticateAction extends BaseRestHandler { public class RestAuthenticateAction extends SecurityBaseRestHandler {
private final SecurityContext securityContext; private final SecurityContext securityContext;
private final XPackLicenseState licenseState;
public RestAuthenticateAction(Settings settings, RestController controller, SecurityContext securityContext, public RestAuthenticateAction(Settings settings, RestController controller, SecurityContext securityContext,
XPackLicenseState licenseState) { XPackLicenseState licenseState) {
super(settings); super(settings, licenseState);
this.securityContext = securityContext; this.securityContext = securityContext;
this.licenseState = licenseState;
controller.registerHandler(GET, "/_xpack/security/_authenticate", this); controller.registerHandler(GET, "/_xpack/security/_authenticate", this);
// @deprecated: Remove in 6.0 // @deprecated: Remove in 6.0
@ -49,15 +44,11 @@ public class RestAuthenticateAction extends BaseRestHandler {
} }
@Override @Override
public RestChannelConsumer prepareRequest(RestRequest request, NodeClient client) throws IOException { public RestChannelConsumer innerPrepareRequest(RestRequest request, NodeClient client) throws IOException {
// this API is a special case since we access the user here and we want it to fail with the proper error instead of a request
// validation error
if (licenseState.isAuthAllowed() == false) {
throw LicenseUtils.newComplianceException(XPackPlugin.SECURITY);
}
final User user = securityContext.getUser(); final User user = securityContext.getUser();
assert user != null; if (user == null) {
return restChannel -> { throw new IllegalStateException("we should never have a null user and invoke this consumer"); };
}
final String username = user.runAs() == null ? user.principal() : user.runAs().principal(); final String username = user.runAs() == null ? user.principal() : user.runAs().principal();
return channel -> client.execute(AuthenticateAction.INSTANCE, new AuthenticateRequest(username), return channel -> client.execute(AuthenticateAction.INSTANCE, new AuthenticateRequest(username),

View File

@ -0,0 +1,62 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/
package org.elasticsearch.xpack.security.rest.action;
import org.elasticsearch.client.node.NodeClient;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.license.LicenseUtils;
import org.elasticsearch.license.XPackLicenseState;
import org.elasticsearch.rest.BaseRestHandler;
import org.elasticsearch.rest.BytesRestResponse;
import org.elasticsearch.rest.RestRequest;
import java.io.IOException;
import static org.elasticsearch.xpack.XPackPlugin.SECURITY;
/**
* Base class for security rest handlers. This handler takes care of ensuring that the license
* level is valid so that security can be used!
*/
public abstract class SecurityBaseRestHandler extends BaseRestHandler {
protected final XPackLicenseState licenseState;
/**
* @param settings the node's settings
* @param licenseState the license state that will be used to determine if security is licensed
*/
protected SecurityBaseRestHandler(Settings settings, XPackLicenseState licenseState) {
super(settings);
this.licenseState = licenseState;
}
/**
* Calls the {@link #innerPrepareRequest(RestRequest, NodeClient)} method and then checks the
* license state. If the license state allows auth, the result from
* {@link #innerPrepareRequest(RestRequest, NodeClient)} is returned, otherwise a default error
* response will be returned indicating that security is not licensed.
*
* Note: the implementing rest handler is called before the license is checked so that we do not
* trip the unused parameters check
*/
protected final RestChannelConsumer prepareRequest(RestRequest request, NodeClient client) throws IOException {
RestChannelConsumer consumer = innerPrepareRequest(request, client);
if (licenseState.isAuthAllowed()) {
return consumer;
} else {
return channel -> channel.sendResponse(new BytesRestResponse(channel, LicenseUtils.newComplianceException(SECURITY)));
}
}
/**
* Implementers should implement this method as they normally would for
* {@link BaseRestHandler#prepareRequest(RestRequest, NodeClient)} and ensure that all request
* parameters are consumed prior to returning a value. The returned value is not guaranteed to
* be executed unless security is licensed and all request parameters are known
*/
protected abstract RestChannelConsumer innerPrepareRequest(RestRequest request, NodeClient client) throws IOException;
}

View File

@ -16,18 +16,16 @@ import org.elasticsearch.common.xcontent.ConstructingObjectParser;
import org.elasticsearch.common.xcontent.ObjectParser.ValueType; import org.elasticsearch.common.xcontent.ObjectParser.ValueType;
import org.elasticsearch.common.xcontent.XContentBuilder; import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.common.xcontent.XContentParser; import org.elasticsearch.common.xcontent.XContentParser;
import org.elasticsearch.license.LicenseUtils;
import org.elasticsearch.license.XPackLicenseState; import org.elasticsearch.license.XPackLicenseState;
import org.elasticsearch.rest.BaseRestHandler;
import org.elasticsearch.rest.BytesRestResponse; import org.elasticsearch.rest.BytesRestResponse;
import org.elasticsearch.rest.RestChannel; import org.elasticsearch.rest.RestChannel;
import org.elasticsearch.rest.RestController; import org.elasticsearch.rest.RestController;
import org.elasticsearch.rest.RestRequest; import org.elasticsearch.rest.RestRequest;
import org.elasticsearch.rest.RestStatus; import org.elasticsearch.rest.RestStatus;
import org.elasticsearch.xpack.XPackPlugin;
import org.elasticsearch.xpack.security.action.token.CreateTokenAction; import org.elasticsearch.xpack.security.action.token.CreateTokenAction;
import org.elasticsearch.xpack.security.action.token.CreateTokenRequest; import org.elasticsearch.xpack.security.action.token.CreateTokenRequest;
import org.elasticsearch.xpack.security.action.token.CreateTokenResponse; import org.elasticsearch.xpack.security.action.token.CreateTokenResponse;
import org.elasticsearch.xpack.security.rest.action.SecurityBaseRestHandler;
import java.io.IOException; import java.io.IOException;
import java.util.Arrays; import java.util.Arrays;
@ -42,7 +40,7 @@ import static org.elasticsearch.rest.RestRequest.Method.POST;
* specification as this aspect does not make the most sense since the response body is * specification as this aspect does not make the most sense since the response body is
* expected to be JSON * expected to be JSON
*/ */
public final class RestGetTokenAction extends BaseRestHandler { public final class RestGetTokenAction extends SecurityBaseRestHandler {
static final ConstructingObjectParser<CreateTokenRequest, Void> PARSER = new ConstructingObjectParser<>("token_request", static final ConstructingObjectParser<CreateTokenRequest, Void> PARSER = new ConstructingObjectParser<>("token_request",
a -> new CreateTokenRequest((String) a[0], (String) a[1], (SecureString) a[2], (String) a[3])); a -> new CreateTokenRequest((String) a[0], (String) a[1], (SecureString) a[2], (String) a[3]));
@ -55,22 +53,13 @@ public final class RestGetTokenAction extends BaseRestHandler {
PARSER.declareString(ConstructingObjectParser.optionalConstructorArg(), new ParseField("scope")); PARSER.declareString(ConstructingObjectParser.optionalConstructorArg(), new ParseField("scope"));
} }
private final XPackLicenseState licenseState; public RestGetTokenAction(Settings settings, RestController controller, XPackLicenseState xPackLicenseState) {
super(settings, xPackLicenseState);
public RestGetTokenAction(Settings settings, XPackLicenseState xPackLicenseState, RestController controller) {
super(settings);
this.licenseState = xPackLicenseState;
controller.registerHandler(POST, "/_xpack/security/oauth2/token", this); controller.registerHandler(POST, "/_xpack/security/oauth2/token", this);
} }
@Override @Override
protected RestChannelConsumer prepareRequest(RestRequest request, NodeClient client)throws IOException { protected RestChannelConsumer innerPrepareRequest(RestRequest request, NodeClient client)throws IOException {
// this API shouldn't be available if security is disabled by license
if (licenseState.isAuthAllowed() == false) {
return channel ->
channel.sendResponse(new BytesRestResponse(channel, LicenseUtils.newComplianceException(XPackPlugin.SECURITY)));
}
try (XContentParser parser = request.contentParser()) { try (XContentParser parser = request.contentParser()) {
final CreateTokenRequest tokenRequest = PARSER.parse(parser, null); final CreateTokenRequest tokenRequest = PARSER.parse(parser, null);
return channel -> client.execute(CreateTokenAction.INSTANCE, tokenRequest, return channel -> client.execute(CreateTokenAction.INSTANCE, tokenRequest,

View File

@ -11,19 +11,17 @@ import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.xcontent.ConstructingObjectParser; import org.elasticsearch.common.xcontent.ConstructingObjectParser;
import org.elasticsearch.common.xcontent.XContentBuilder; import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.common.xcontent.XContentParser; import org.elasticsearch.common.xcontent.XContentParser;
import org.elasticsearch.license.LicenseUtils;
import org.elasticsearch.license.XPackLicenseState; import org.elasticsearch.license.XPackLicenseState;
import org.elasticsearch.rest.BaseRestHandler;
import org.elasticsearch.rest.BytesRestResponse; import org.elasticsearch.rest.BytesRestResponse;
import org.elasticsearch.rest.RestController; import org.elasticsearch.rest.RestController;
import org.elasticsearch.rest.RestRequest; import org.elasticsearch.rest.RestRequest;
import org.elasticsearch.rest.RestResponse; import org.elasticsearch.rest.RestResponse;
import org.elasticsearch.rest.RestStatus; import org.elasticsearch.rest.RestStatus;
import org.elasticsearch.rest.action.RestBuilderListener; import org.elasticsearch.rest.action.RestBuilderListener;
import org.elasticsearch.xpack.XPackPlugin;
import org.elasticsearch.xpack.security.action.token.InvalidateTokenAction; import org.elasticsearch.xpack.security.action.token.InvalidateTokenAction;
import org.elasticsearch.xpack.security.action.token.InvalidateTokenRequest; import org.elasticsearch.xpack.security.action.token.InvalidateTokenRequest;
import org.elasticsearch.xpack.security.action.token.InvalidateTokenResponse; import org.elasticsearch.xpack.security.action.token.InvalidateTokenResponse;
import org.elasticsearch.xpack.security.rest.action.SecurityBaseRestHandler;
import java.io.IOException; import java.io.IOException;
@ -32,7 +30,7 @@ import static org.elasticsearch.rest.RestRequest.Method.DELETE;
/** /**
* Rest handler for handling access token invalidation requests * Rest handler for handling access token invalidation requests
*/ */
public final class RestInvalidateTokenAction extends BaseRestHandler { public final class RestInvalidateTokenAction extends SecurityBaseRestHandler {
static final ConstructingObjectParser<String, Void> PARSER = static final ConstructingObjectParser<String, Void> PARSER =
new ConstructingObjectParser<>("invalidate_token", a -> ((String) a[0])); new ConstructingObjectParser<>("invalidate_token", a -> ((String) a[0]));
@ -40,24 +38,13 @@ public final class RestInvalidateTokenAction extends BaseRestHandler {
PARSER.declareString(ConstructingObjectParser.constructorArg(), new ParseField("token")); PARSER.declareString(ConstructingObjectParser.constructorArg(), new ParseField("token"));
} }
private final XPackLicenseState licenseState; public RestInvalidateTokenAction(Settings settings, RestController controller, XPackLicenseState xPackLicenseState) {
super(settings, xPackLicenseState);
public RestInvalidateTokenAction(Settings settings, XPackLicenseState xPackLicenseState,
RestController controller) {
super(settings);
this.licenseState = xPackLicenseState;
controller.registerHandler(DELETE, "/_xpack/security/oauth2/token", this); controller.registerHandler(DELETE, "/_xpack/security/oauth2/token", this);
} }
@Override @Override
protected RestChannelConsumer prepareRequest(RestRequest request, protected RestChannelConsumer innerPrepareRequest(RestRequest request, NodeClient client) throws IOException {
NodeClient client)throws IOException {
// this API shouldn't be available if security is disabled by license
if (licenseState.isAuthAllowed() == false) {
return channel ->
channel.sendResponse(new BytesRestResponse(channel, LicenseUtils.newComplianceException(XPackPlugin.SECURITY)));
}
try (XContentParser parser = request.contentParser()) { try (XContentParser parser = request.contentParser()) {
final String token = PARSER.parse(parser, null); final String token = PARSER.parse(parser, null);
final InvalidateTokenRequest tokenRequest = new InvalidateTokenRequest(token); final InvalidateTokenRequest tokenRequest = new InvalidateTokenRequest(token);

View File

@ -7,20 +7,22 @@ package org.elasticsearch.xpack.security.rest.action.realm;
import org.elasticsearch.client.node.NodeClient; import org.elasticsearch.client.node.NodeClient;
import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.rest.BaseRestHandler; import org.elasticsearch.license.XPackLicenseState;
import org.elasticsearch.rest.RestController; import org.elasticsearch.rest.RestController;
import org.elasticsearch.rest.RestRequest; import org.elasticsearch.rest.RestRequest;
import org.elasticsearch.rest.action.RestActions.NodesResponseRestListener; import org.elasticsearch.rest.action.RestActions.NodesResponseRestListener;
import org.elasticsearch.xpack.security.action.realm.ClearRealmCacheRequest; import org.elasticsearch.xpack.security.action.realm.ClearRealmCacheRequest;
import org.elasticsearch.xpack.security.client.SecurityClient; import org.elasticsearch.xpack.security.client.SecurityClient;
import org.elasticsearch.xpack.security.rest.action.SecurityBaseRestHandler;
import java.io.IOException; import java.io.IOException;
import static org.elasticsearch.rest.RestRequest.Method.POST; import static org.elasticsearch.rest.RestRequest.Method.POST;
public class RestClearRealmCacheAction extends BaseRestHandler { public final class RestClearRealmCacheAction extends SecurityBaseRestHandler {
public RestClearRealmCacheAction(Settings settings, RestController controller) {
super(settings); public RestClearRealmCacheAction(Settings settings, RestController controller, XPackLicenseState licenseState) {
super(settings, licenseState);
controller.registerHandler(POST, "/_xpack/security/realm/{realms}/_clear_cache", this); controller.registerHandler(POST, "/_xpack/security/realm/{realms}/_clear_cache", this);
// @deprecated: Remove in 6.0 // @deprecated: Remove in 6.0
@ -35,8 +37,7 @@ public class RestClearRealmCacheAction extends BaseRestHandler {
} }
@Override @Override
public RestChannelConsumer prepareRequest(RestRequest request, NodeClient client) throws IOException { public RestChannelConsumer innerPrepareRequest(RestRequest request, NodeClient client) throws IOException {
String[] realms = request.paramAsStringArrayOrEmptyIfAll("realms"); String[] realms = request.paramAsStringArrayOrEmptyIfAll("realms");
String[] usernames = request.paramAsStringArrayOrEmptyIfAll("usernames"); String[] usernames = request.paramAsStringArrayOrEmptyIfAll("usernames");

View File

@ -7,20 +7,22 @@ package org.elasticsearch.xpack.security.rest.action.role;
import org.elasticsearch.client.node.NodeClient; import org.elasticsearch.client.node.NodeClient;
import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.rest.BaseRestHandler; import org.elasticsearch.license.XPackLicenseState;
import org.elasticsearch.rest.RestController; import org.elasticsearch.rest.RestController;
import org.elasticsearch.rest.RestRequest; import org.elasticsearch.rest.RestRequest;
import org.elasticsearch.rest.action.RestActions.NodesResponseRestListener; import org.elasticsearch.rest.action.RestActions.NodesResponseRestListener;
import org.elasticsearch.xpack.security.action.role.ClearRolesCacheRequest; import org.elasticsearch.xpack.security.action.role.ClearRolesCacheRequest;
import org.elasticsearch.xpack.security.client.SecurityClient; import org.elasticsearch.xpack.security.client.SecurityClient;
import org.elasticsearch.xpack.security.rest.action.SecurityBaseRestHandler;
import java.io.IOException; import java.io.IOException;
import static org.elasticsearch.rest.RestRequest.Method.POST; import static org.elasticsearch.rest.RestRequest.Method.POST;
public class RestClearRolesCacheAction extends BaseRestHandler { public final class RestClearRolesCacheAction extends SecurityBaseRestHandler {
public RestClearRolesCacheAction(Settings settings, RestController controller) {
super(settings); public RestClearRolesCacheAction(Settings settings, RestController controller, XPackLicenseState licenseState) {
super(settings, licenseState);
controller.registerHandler(POST, "/_xpack/security/role/{name}/_clear_cache", this); controller.registerHandler(POST, "/_xpack/security/role/{name}/_clear_cache", this);
// @deprecated: Remove in 6.0 // @deprecated: Remove in 6.0
@ -31,8 +33,7 @@ public class RestClearRolesCacheAction extends BaseRestHandler {
} }
@Override @Override
public RestChannelConsumer prepareRequest(RestRequest request, NodeClient client) throws IOException { public RestChannelConsumer innerPrepareRequest(RestRequest request, NodeClient client) throws IOException {
String[] roles = request.paramAsStringArrayOrEmptyIfAll("name"); String[] roles = request.paramAsStringArrayOrEmptyIfAll("name");
ClearRolesCacheRequest req = new ClearRolesCacheRequest().names(roles); ClearRolesCacheRequest req = new ClearRolesCacheRequest().names(roles);

View File

@ -8,7 +8,7 @@ package org.elasticsearch.xpack.security.rest.action.role;
import org.elasticsearch.client.node.NodeClient; import org.elasticsearch.client.node.NodeClient;
import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.xcontent.XContentBuilder; import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.rest.BaseRestHandler; import org.elasticsearch.license.XPackLicenseState;
import org.elasticsearch.rest.BytesRestResponse; import org.elasticsearch.rest.BytesRestResponse;
import org.elasticsearch.rest.RestController; import org.elasticsearch.rest.RestController;
import org.elasticsearch.rest.RestRequest; import org.elasticsearch.rest.RestRequest;
@ -17,6 +17,7 @@ import org.elasticsearch.rest.RestStatus;
import org.elasticsearch.rest.action.RestBuilderListener; import org.elasticsearch.rest.action.RestBuilderListener;
import org.elasticsearch.xpack.security.action.role.DeleteRoleResponse; import org.elasticsearch.xpack.security.action.role.DeleteRoleResponse;
import org.elasticsearch.xpack.security.client.SecurityClient; import org.elasticsearch.xpack.security.client.SecurityClient;
import org.elasticsearch.xpack.security.rest.action.SecurityBaseRestHandler;
import java.io.IOException; import java.io.IOException;
@ -25,9 +26,10 @@ import static org.elasticsearch.rest.RestRequest.Method.DELETE;
/** /**
* Rest endpoint to delete a Role from the security index * Rest endpoint to delete a Role from the security index
*/ */
public class RestDeleteRoleAction extends BaseRestHandler { public class RestDeleteRoleAction extends SecurityBaseRestHandler {
public RestDeleteRoleAction(Settings settings, RestController controller) {
super(settings); public RestDeleteRoleAction(Settings settings, RestController controller, XPackLicenseState licenseState) {
super(settings, licenseState);
controller.registerHandler(DELETE, "/_xpack/security/role/{name}", this); controller.registerHandler(DELETE, "/_xpack/security/role/{name}", this);
// @deprecated: Remove in 6.0 // @deprecated: Remove in 6.0
@ -38,7 +40,7 @@ public class RestDeleteRoleAction extends BaseRestHandler {
} }
@Override @Override
public RestChannelConsumer prepareRequest(RestRequest request, NodeClient client) throws IOException { public RestChannelConsumer innerPrepareRequest(RestRequest request, NodeClient client) throws IOException {
final String name = request.param("name"); final String name = request.param("name");
final String refresh = request.param("refresh"); final String refresh = request.param("refresh");

View File

@ -9,7 +9,7 @@ import org.elasticsearch.client.node.NodeClient;
import org.elasticsearch.common.Strings; import org.elasticsearch.common.Strings;
import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.xcontent.XContentBuilder; import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.rest.BaseRestHandler; import org.elasticsearch.license.XPackLicenseState;
import org.elasticsearch.rest.BytesRestResponse; import org.elasticsearch.rest.BytesRestResponse;
import org.elasticsearch.rest.RestController; import org.elasticsearch.rest.RestController;
import org.elasticsearch.rest.RestRequest; import org.elasticsearch.rest.RestRequest;
@ -19,6 +19,7 @@ import org.elasticsearch.rest.action.RestBuilderListener;
import org.elasticsearch.xpack.security.action.role.GetRolesResponse; import org.elasticsearch.xpack.security.action.role.GetRolesResponse;
import org.elasticsearch.xpack.security.authz.RoleDescriptor; import org.elasticsearch.xpack.security.authz.RoleDescriptor;
import org.elasticsearch.xpack.security.client.SecurityClient; import org.elasticsearch.xpack.security.client.SecurityClient;
import org.elasticsearch.xpack.security.rest.action.SecurityBaseRestHandler;
import java.io.IOException; import java.io.IOException;
@ -27,9 +28,9 @@ import static org.elasticsearch.rest.RestRequest.Method.GET;
/** /**
* Rest endpoint to retrieve a Role from the security index * Rest endpoint to retrieve a Role from the security index
*/ */
public class RestGetRolesAction extends BaseRestHandler { public class RestGetRolesAction extends SecurityBaseRestHandler {
public RestGetRolesAction(Settings settings, RestController controller) { public RestGetRolesAction(Settings settings, RestController controller, XPackLicenseState licenseState) {
super(settings); super(settings, licenseState);
controller.registerHandler(GET, "/_xpack/security/role/", this); controller.registerHandler(GET, "/_xpack/security/role/", this);
controller.registerHandler(GET, "/_xpack/security/role/{name}", this); controller.registerHandler(GET, "/_xpack/security/role/{name}", this);
@ -45,7 +46,7 @@ public class RestGetRolesAction extends BaseRestHandler {
} }
@Override @Override
public RestChannelConsumer prepareRequest(RestRequest request, NodeClient client) throws IOException { public RestChannelConsumer innerPrepareRequest(RestRequest request, NodeClient client) throws IOException {
final String[] roles = request.paramAsStringArray("name", Strings.EMPTY_ARRAY); final String[] roles = request.paramAsStringArray("name", Strings.EMPTY_ARRAY);
return channel -> new SecurityClient(client).prepareGetRoles(roles).execute(new RestBuilderListener<GetRolesResponse>(channel) { return channel -> new SecurityClient(client).prepareGetRoles(roles).execute(new RestBuilderListener<GetRolesResponse>(channel) {
@Override @Override

View File

@ -8,7 +8,7 @@ package org.elasticsearch.xpack.security.rest.action.role;
import org.elasticsearch.client.node.NodeClient; import org.elasticsearch.client.node.NodeClient;
import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.xcontent.XContentBuilder; import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.rest.BaseRestHandler; import org.elasticsearch.license.XPackLicenseState;
import org.elasticsearch.rest.BytesRestResponse; import org.elasticsearch.rest.BytesRestResponse;
import org.elasticsearch.rest.RestController; import org.elasticsearch.rest.RestController;
import org.elasticsearch.rest.RestRequest; import org.elasticsearch.rest.RestRequest;
@ -18,6 +18,7 @@ import org.elasticsearch.rest.action.RestBuilderListener;
import org.elasticsearch.xpack.security.action.role.PutRoleRequestBuilder; import org.elasticsearch.xpack.security.action.role.PutRoleRequestBuilder;
import org.elasticsearch.xpack.security.action.role.PutRoleResponse; import org.elasticsearch.xpack.security.action.role.PutRoleResponse;
import org.elasticsearch.xpack.security.client.SecurityClient; import org.elasticsearch.xpack.security.client.SecurityClient;
import org.elasticsearch.xpack.security.rest.action.SecurityBaseRestHandler;
import java.io.IOException; import java.io.IOException;
@ -27,9 +28,10 @@ import static org.elasticsearch.rest.RestRequest.Method.PUT;
/** /**
* Rest endpoint to add a Role to the security index * Rest endpoint to add a Role to the security index
*/ */
public class RestPutRoleAction extends BaseRestHandler { public class RestPutRoleAction extends SecurityBaseRestHandler {
public RestPutRoleAction(Settings settings, RestController controller) {
super(settings); public RestPutRoleAction(Settings settings, RestController controller, XPackLicenseState licenseState) {
super(settings, licenseState);
controller.registerHandler(POST, "/_xpack/security/role/{name}", this); controller.registerHandler(POST, "/_xpack/security/role/{name}", this);
controller.registerHandler(PUT, "/_xpack/security/role/{name}", this); controller.registerHandler(PUT, "/_xpack/security/role/{name}", this);
@ -45,7 +47,7 @@ public class RestPutRoleAction extends BaseRestHandler {
} }
@Override @Override
public RestChannelConsumer prepareRequest(RestRequest request, NodeClient client) throws IOException { public RestChannelConsumer innerPrepareRequest(RestRequest request, NodeClient client) throws IOException {
PutRoleRequestBuilder requestBuilder = new SecurityClient(client) PutRoleRequestBuilder requestBuilder = new SecurityClient(client)
.preparePutRole(request.param("name"), request.content(), request.getXContentType()) .preparePutRole(request.param("name"), request.content(), request.getXContentType())
.setRefreshPolicy(request.param("refresh")); .setRefreshPolicy(request.param("refresh"));

View File

@ -10,7 +10,7 @@ import java.io.IOException;
import org.elasticsearch.client.node.NodeClient; import org.elasticsearch.client.node.NodeClient;
import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.xcontent.XContentBuilder; import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.rest.BaseRestHandler; import org.elasticsearch.license.XPackLicenseState;
import org.elasticsearch.rest.BytesRestResponse; import org.elasticsearch.rest.BytesRestResponse;
import org.elasticsearch.rest.RestController; import org.elasticsearch.rest.RestController;
import org.elasticsearch.rest.RestRequest; import org.elasticsearch.rest.RestRequest;
@ -19,22 +19,22 @@ import org.elasticsearch.rest.RestStatus;
import org.elasticsearch.rest.action.RestBuilderListener; import org.elasticsearch.rest.action.RestBuilderListener;
import org.elasticsearch.xpack.security.action.rolemapping.DeleteRoleMappingResponse; import org.elasticsearch.xpack.security.action.rolemapping.DeleteRoleMappingResponse;
import org.elasticsearch.xpack.security.client.SecurityClient; import org.elasticsearch.xpack.security.client.SecurityClient;
import org.elasticsearch.xpack.security.rest.action.SecurityBaseRestHandler;
import static org.elasticsearch.rest.RestRequest.Method.DELETE; import static org.elasticsearch.rest.RestRequest.Method.DELETE;
/** /**
* Rest endpoint to delete a role-mapping from the {@link org.elasticsearch.xpack.security.authc.support.mapper.NativeRoleMappingStore} * Rest endpoint to delete a role-mapping from the {@link org.elasticsearch.xpack.security.authc.support.mapper.NativeRoleMappingStore}
*/ */
public class RestDeleteRoleMappingAction extends BaseRestHandler { public class RestDeleteRoleMappingAction extends SecurityBaseRestHandler {
public RestDeleteRoleMappingAction(Settings settings, RestController controller) { public RestDeleteRoleMappingAction(Settings settings, RestController controller, XPackLicenseState licenseState) {
super(settings); super(settings, licenseState);
controller.registerHandler(DELETE, "/_xpack/security/role_mapping/{name}", this); controller.registerHandler(DELETE, "/_xpack/security/role_mapping/{name}", this);
} }
@Override @Override
public RestChannelConsumer prepareRequest(RestRequest request, NodeClient client) public RestChannelConsumer innerPrepareRequest(RestRequest request, NodeClient client) throws IOException {
throws IOException {
final String name = request.param("name"); final String name = request.param("name");
final String refresh = request.param("refresh"); final String refresh = request.param("refresh");

View File

@ -8,10 +8,9 @@ package org.elasticsearch.xpack.security.rest.action.rolemapping;
import java.io.IOException; import java.io.IOException;
import org.elasticsearch.client.node.NodeClient; import org.elasticsearch.client.node.NodeClient;
import org.elasticsearch.common.Strings;
import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.xcontent.XContentBuilder; import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.rest.BaseRestHandler; import org.elasticsearch.license.XPackLicenseState;
import org.elasticsearch.rest.BytesRestResponse; import org.elasticsearch.rest.BytesRestResponse;
import org.elasticsearch.rest.RestController; import org.elasticsearch.rest.RestController;
import org.elasticsearch.rest.RestRequest; import org.elasticsearch.rest.RestRequest;
@ -21,22 +20,23 @@ import org.elasticsearch.rest.action.RestBuilderListener;
import org.elasticsearch.xpack.security.action.rolemapping.GetRoleMappingsResponse; import org.elasticsearch.xpack.security.action.rolemapping.GetRoleMappingsResponse;
import org.elasticsearch.xpack.security.authc.support.mapper.ExpressionRoleMapping; import org.elasticsearch.xpack.security.authc.support.mapper.ExpressionRoleMapping;
import org.elasticsearch.xpack.security.client.SecurityClient; import org.elasticsearch.xpack.security.client.SecurityClient;
import org.elasticsearch.xpack.security.rest.action.SecurityBaseRestHandler;
import static org.elasticsearch.rest.RestRequest.Method.GET; import static org.elasticsearch.rest.RestRequest.Method.GET;
/** /**
* Rest endpoint to retrieve a role-mapping from the {@link org.elasticsearch.xpack.security.authc.support.mapper.NativeRoleMappingStore} * Rest endpoint to retrieve a role-mapping from the {@link org.elasticsearch.xpack.security.authc.support.mapper.NativeRoleMappingStore}
*/ */
public class RestGetRoleMappingsAction extends BaseRestHandler { public class RestGetRoleMappingsAction extends SecurityBaseRestHandler {
public RestGetRoleMappingsAction(Settings settings, RestController controller) {
super(settings); public RestGetRoleMappingsAction(Settings settings, RestController controller, XPackLicenseState licenseState) {
super(settings, licenseState);
controller.registerHandler(GET, "/_xpack/security/role_mapping/", this); controller.registerHandler(GET, "/_xpack/security/role_mapping/", this);
controller.registerHandler(GET, "/_xpack/security/role_mapping/{name}", this); controller.registerHandler(GET, "/_xpack/security/role_mapping/{name}", this);
} }
@Override @Override
public RestChannelConsumer prepareRequest(RestRequest request, NodeClient client) public RestChannelConsumer innerPrepareRequest(RestRequest request, NodeClient client) throws IOException {
throws IOException {
final String[] names = request.paramAsStringArrayOrEmptyIfAll("name"); final String[] names = request.paramAsStringArrayOrEmptyIfAll("name");
return channel -> new SecurityClient(client).prepareGetRoleMappings(names) return channel -> new SecurityClient(client).prepareGetRoleMappings(names)
.execute(new RestBuilderListener<GetRoleMappingsResponse>(channel) { .execute(new RestBuilderListener<GetRoleMappingsResponse>(channel) {

View File

@ -10,7 +10,7 @@ import java.io.IOException;
import org.elasticsearch.client.node.NodeClient; import org.elasticsearch.client.node.NodeClient;
import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.xcontent.XContentBuilder; import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.rest.BaseRestHandler; import org.elasticsearch.license.XPackLicenseState;
import org.elasticsearch.rest.BytesRestResponse; import org.elasticsearch.rest.BytesRestResponse;
import org.elasticsearch.rest.RestController; import org.elasticsearch.rest.RestController;
import org.elasticsearch.rest.RestRequest; import org.elasticsearch.rest.RestRequest;
@ -20,6 +20,7 @@ import org.elasticsearch.rest.action.RestBuilderListener;
import org.elasticsearch.xpack.security.action.rolemapping.PutRoleMappingRequestBuilder; import org.elasticsearch.xpack.security.action.rolemapping.PutRoleMappingRequestBuilder;
import org.elasticsearch.xpack.security.action.rolemapping.PutRoleMappingResponse; import org.elasticsearch.xpack.security.action.rolemapping.PutRoleMappingResponse;
import org.elasticsearch.xpack.security.client.SecurityClient; import org.elasticsearch.xpack.security.client.SecurityClient;
import org.elasticsearch.xpack.security.rest.action.SecurityBaseRestHandler;
import static org.elasticsearch.rest.RestRequest.Method.POST; import static org.elasticsearch.rest.RestRequest.Method.POST;
import static org.elasticsearch.rest.RestRequest.Method.PUT; import static org.elasticsearch.rest.RestRequest.Method.PUT;
@ -29,17 +30,16 @@ import static org.elasticsearch.rest.RestRequest.Method.PUT;
* *
* @see org.elasticsearch.xpack.security.authc.support.mapper.NativeRoleMappingStore * @see org.elasticsearch.xpack.security.authc.support.mapper.NativeRoleMappingStore
*/ */
public class RestPutRoleMappingAction extends BaseRestHandler { public class RestPutRoleMappingAction extends SecurityBaseRestHandler {
public RestPutRoleMappingAction(Settings settings, RestController controller) {
super(settings); public RestPutRoleMappingAction(Settings settings, RestController controller, XPackLicenseState licenseState) {
super(settings, licenseState);
controller.registerHandler(POST, "/_xpack/security/role_mapping/{name}", this); controller.registerHandler(POST, "/_xpack/security/role_mapping/{name}", this);
controller.registerHandler(PUT, "/_xpack/security/role_mapping/{name}", this); controller.registerHandler(PUT, "/_xpack/security/role_mapping/{name}", this);
} }
@Override @Override
public RestChannelConsumer prepareRequest(RestRequest request, NodeClient client) public RestChannelConsumer innerPrepareRequest(RestRequest request, NodeClient client) throws IOException {
throws IOException {
final String name = request.param("name"); final String name = request.param("name");
PutRoleMappingRequestBuilder requestBuilder = new SecurityClient(client) PutRoleMappingRequestBuilder requestBuilder = new SecurityClient(client)
.preparePutRoleMapping(name, request.content(), request.getXContentType()) .preparePutRoleMapping(name, request.content(), request.getXContentType())

View File

@ -8,7 +8,7 @@ package org.elasticsearch.xpack.security.rest.action.user;
import org.elasticsearch.client.node.NodeClient; import org.elasticsearch.client.node.NodeClient;
import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.xcontent.XContentBuilder; import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.rest.BaseRestHandler; import org.elasticsearch.license.XPackLicenseState;
import org.elasticsearch.rest.BytesRestResponse; import org.elasticsearch.rest.BytesRestResponse;
import org.elasticsearch.rest.RestController; import org.elasticsearch.rest.RestController;
import org.elasticsearch.rest.RestRequest; import org.elasticsearch.rest.RestRequest;
@ -19,6 +19,7 @@ import org.elasticsearch.xpack.security.SecurityContext;
import org.elasticsearch.xpack.security.action.user.ChangePasswordResponse; import org.elasticsearch.xpack.security.action.user.ChangePasswordResponse;
import org.elasticsearch.xpack.security.client.SecurityClient; import org.elasticsearch.xpack.security.client.SecurityClient;
import org.elasticsearch.xpack.security.rest.RestRequestFilter; import org.elasticsearch.xpack.security.rest.RestRequestFilter;
import org.elasticsearch.xpack.security.rest.action.SecurityBaseRestHandler;
import org.elasticsearch.xpack.security.user.User; import org.elasticsearch.xpack.security.user.User;
import java.io.IOException; import java.io.IOException;
@ -28,12 +29,13 @@ import java.util.Set;
import static org.elasticsearch.rest.RestRequest.Method.POST; import static org.elasticsearch.rest.RestRequest.Method.POST;
import static org.elasticsearch.rest.RestRequest.Method.PUT; import static org.elasticsearch.rest.RestRequest.Method.PUT;
public class RestChangePasswordAction extends BaseRestHandler implements RestRequestFilter { public class RestChangePasswordAction extends SecurityBaseRestHandler implements RestRequestFilter {
private final SecurityContext securityContext; private final SecurityContext securityContext;
public RestChangePasswordAction(Settings settings, RestController controller, SecurityContext securityContext) { public RestChangePasswordAction(Settings settings, RestController controller, SecurityContext securityContext,
super(settings); XPackLicenseState licenseState) {
super(settings, licenseState);
this.securityContext = securityContext; this.securityContext = securityContext;
controller.registerHandler(POST, "/_xpack/security/user/{username}/_password", this); controller.registerHandler(POST, "/_xpack/security/user/{username}/_password", this);
controller.registerHandler(PUT, "/_xpack/security/user/{username}/_password", this); controller.registerHandler(PUT, "/_xpack/security/user/{username}/_password", this);
@ -42,7 +44,7 @@ public class RestChangePasswordAction extends BaseRestHandler implements RestReq
} }
@Override @Override
public RestChannelConsumer prepareRequest(RestRequest request, NodeClient client) throws IOException { public RestChannelConsumer innerPrepareRequest(RestRequest request, NodeClient client) throws IOException {
final User user = securityContext.getUser(); final User user = securityContext.getUser();
final String username; final String username;
if (request.param("username") == null) { if (request.param("username") == null) {
@ -58,10 +60,8 @@ public class RestChangePasswordAction extends BaseRestHandler implements RestReq
.setRefreshPolicy(refresh) .setRefreshPolicy(refresh)
.execute(new RestBuilderListener<ChangePasswordResponse>(channel) { .execute(new RestBuilderListener<ChangePasswordResponse>(channel) {
@Override @Override
public RestResponse buildResponse( public RestResponse buildResponse(ChangePasswordResponse changePasswordResponse,
ChangePasswordResponse changePasswordResponse, XContentBuilder builder) throws Exception {
XContentBuilder builder)
throws Exception {
return new BytesRestResponse(RestStatus.OK, builder.startObject().endObject()); return new BytesRestResponse(RestStatus.OK, builder.startObject().endObject());
} }
}); });

View File

@ -8,7 +8,7 @@ package org.elasticsearch.xpack.security.rest.action.user;
import org.elasticsearch.client.node.NodeClient; import org.elasticsearch.client.node.NodeClient;
import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.xcontent.XContentBuilder; import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.rest.BaseRestHandler; import org.elasticsearch.license.XPackLicenseState;
import org.elasticsearch.rest.BytesRestResponse; import org.elasticsearch.rest.BytesRestResponse;
import org.elasticsearch.rest.RestController; import org.elasticsearch.rest.RestController;
import org.elasticsearch.rest.RestRequest; import org.elasticsearch.rest.RestRequest;
@ -17,6 +17,7 @@ import org.elasticsearch.rest.RestStatus;
import org.elasticsearch.rest.action.RestBuilderListener; import org.elasticsearch.rest.action.RestBuilderListener;
import org.elasticsearch.xpack.security.action.user.DeleteUserResponse; import org.elasticsearch.xpack.security.action.user.DeleteUserResponse;
import org.elasticsearch.xpack.security.client.SecurityClient; import org.elasticsearch.xpack.security.client.SecurityClient;
import org.elasticsearch.xpack.security.rest.action.SecurityBaseRestHandler;
import java.io.IOException; import java.io.IOException;
@ -25,9 +26,10 @@ import static org.elasticsearch.rest.RestRequest.Method.DELETE;
/** /**
* Rest action to delete a user from the security index * Rest action to delete a user from the security index
*/ */
public class RestDeleteUserAction extends BaseRestHandler { public class RestDeleteUserAction extends SecurityBaseRestHandler {
public RestDeleteUserAction(Settings settings, RestController controller) {
super(settings); public RestDeleteUserAction(Settings settings, RestController controller, XPackLicenseState licenseState) {
super(settings, licenseState);
controller.registerHandler(DELETE, "/_xpack/security/user/{username}", this); controller.registerHandler(DELETE, "/_xpack/security/user/{username}", this);
// @deprecated: Remove in 6.0 // @deprecated: Remove in 6.0
@ -38,7 +40,7 @@ public class RestDeleteUserAction extends BaseRestHandler {
} }
@Override @Override
public RestChannelConsumer prepareRequest(RestRequest request, NodeClient client) throws IOException { public RestChannelConsumer innerPrepareRequest(RestRequest request, NodeClient client) throws IOException {
final String username = request.param("username"); final String username = request.param("username");
final String refresh = request.param("refresh"); final String refresh = request.param("refresh");
return channel -> new SecurityClient(client).prepareDeleteUser(username) return channel -> new SecurityClient(client).prepareDeleteUser(username)

View File

@ -9,7 +9,7 @@ import org.elasticsearch.client.node.NodeClient;
import org.elasticsearch.common.Strings; import org.elasticsearch.common.Strings;
import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.xcontent.XContentBuilder; import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.rest.BaseRestHandler; import org.elasticsearch.license.XPackLicenseState;
import org.elasticsearch.rest.BytesRestResponse; import org.elasticsearch.rest.BytesRestResponse;
import org.elasticsearch.rest.RestController; import org.elasticsearch.rest.RestController;
import org.elasticsearch.rest.RestRequest; import org.elasticsearch.rest.RestRequest;
@ -18,6 +18,7 @@ import org.elasticsearch.rest.RestStatus;
import org.elasticsearch.rest.action.RestBuilderListener; import org.elasticsearch.rest.action.RestBuilderListener;
import org.elasticsearch.xpack.security.action.user.GetUsersResponse; import org.elasticsearch.xpack.security.action.user.GetUsersResponse;
import org.elasticsearch.xpack.security.client.SecurityClient; import org.elasticsearch.xpack.security.client.SecurityClient;
import org.elasticsearch.xpack.security.rest.action.SecurityBaseRestHandler;
import org.elasticsearch.xpack.security.user.User; import org.elasticsearch.xpack.security.user.User;
import java.io.IOException; import java.io.IOException;
@ -27,9 +28,10 @@ import static org.elasticsearch.rest.RestRequest.Method.GET;
/** /**
* Rest action to retrieve a user from the security index * Rest action to retrieve a user from the security index
*/ */
public class RestGetUsersAction extends BaseRestHandler { public class RestGetUsersAction extends SecurityBaseRestHandler {
public RestGetUsersAction(Settings settings, RestController controller) {
super(settings); public RestGetUsersAction(Settings settings, RestController controller, XPackLicenseState licenseState) {
super(settings, licenseState);
controller.registerHandler(GET, "/_xpack/security/user/", this); controller.registerHandler(GET, "/_xpack/security/user/", this);
controller.registerHandler(GET, "/_xpack/security/user/{username}", this); controller.registerHandler(GET, "/_xpack/security/user/{username}", this);
@ -45,7 +47,7 @@ public class RestGetUsersAction extends BaseRestHandler {
} }
@Override @Override
public RestChannelConsumer prepareRequest(RestRequest request, NodeClient client) throws IOException { public RestChannelConsumer innerPrepareRequest(RestRequest request, NodeClient client) throws IOException {
String[] usernames = request.paramAsStringArray("username", Strings.EMPTY_ARRAY); String[] usernames = request.paramAsStringArray("username", Strings.EMPTY_ARRAY);
return channel -> new SecurityClient(client).prepareGetUsers(usernames).execute(new RestBuilderListener<GetUsersResponse>(channel) { return channel -> new SecurityClient(client).prepareGetUsers(usernames).execute(new RestBuilderListener<GetUsersResponse>(channel) {

View File

@ -10,7 +10,7 @@ import java.io.IOException;
import org.elasticsearch.client.node.NodeClient; import org.elasticsearch.client.node.NodeClient;
import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.xcontent.XContentBuilder; import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.rest.BaseRestHandler; import org.elasticsearch.license.XPackLicenseState;
import org.elasticsearch.rest.BytesRestResponse; import org.elasticsearch.rest.BytesRestResponse;
import org.elasticsearch.rest.RestChannel; import org.elasticsearch.rest.RestChannel;
import org.elasticsearch.rest.RestController; import org.elasticsearch.rest.RestController;
@ -22,6 +22,7 @@ import org.elasticsearch.xpack.security.SecurityContext;
import org.elasticsearch.xpack.security.action.user.HasPrivilegesRequestBuilder; import org.elasticsearch.xpack.security.action.user.HasPrivilegesRequestBuilder;
import org.elasticsearch.xpack.security.action.user.HasPrivilegesResponse; import org.elasticsearch.xpack.security.action.user.HasPrivilegesResponse;
import org.elasticsearch.xpack.security.client.SecurityClient; import org.elasticsearch.xpack.security.client.SecurityClient;
import org.elasticsearch.xpack.security.rest.action.SecurityBaseRestHandler;
import org.elasticsearch.xpack.security.user.User; import org.elasticsearch.xpack.security.user.User;
import static org.elasticsearch.rest.RestRequest.Method.GET; import static org.elasticsearch.rest.RestRequest.Method.GET;
@ -31,12 +32,13 @@ import static org.elasticsearch.rest.RestRequest.Method.POST;
* REST handler that tests whether a user has the specified * REST handler that tests whether a user has the specified
* {@link org.elasticsearch.xpack.security.authz.RoleDescriptor.IndicesPrivileges privileges} * {@link org.elasticsearch.xpack.security.authz.RoleDescriptor.IndicesPrivileges privileges}
*/ */
public class RestHasPrivilegesAction extends BaseRestHandler { public class RestHasPrivilegesAction extends SecurityBaseRestHandler {
private final SecurityContext securityContext; private final SecurityContext securityContext;
public RestHasPrivilegesAction(Settings settings, RestController controller, SecurityContext securityContext) { public RestHasPrivilegesAction(Settings settings, RestController controller, SecurityContext securityContext,
super(settings); XPackLicenseState licenseState) {
super(settings, licenseState);
this.securityContext = securityContext; this.securityContext = securityContext;
controller.registerHandler(GET, "/_xpack/security/user/{username}/_has_privileges", this); controller.registerHandler(GET, "/_xpack/security/user/{username}/_has_privileges", this);
controller.registerHandler(POST, "/_xpack/security/user/{username}/_has_privileges", this); controller.registerHandler(POST, "/_xpack/security/user/{username}/_has_privileges", this);
@ -45,7 +47,7 @@ public class RestHasPrivilegesAction extends BaseRestHandler {
} }
@Override @Override
public RestChannelConsumer prepareRequest(RestRequest request, NodeClient client) throws IOException { public RestChannelConsumer innerPrepareRequest(RestRequest request, NodeClient client) throws IOException {
final String username = getUsername(request); final String username = getUsername(request);
HasPrivilegesRequestBuilder requestBuilder = new SecurityClient(client) HasPrivilegesRequestBuilder requestBuilder = new SecurityClient(client)
.prepareHasPrivileges(username, request.content(), request.getXContentType()); .prepareHasPrivileges(username, request.content(), request.getXContentType());

View File

@ -9,7 +9,7 @@ import org.elasticsearch.client.node.NodeClient;
import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.util.set.Sets; import org.elasticsearch.common.util.set.Sets;
import org.elasticsearch.common.xcontent.XContentBuilder; import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.rest.BaseRestHandler; import org.elasticsearch.license.XPackLicenseState;
import org.elasticsearch.rest.BytesRestResponse; import org.elasticsearch.rest.BytesRestResponse;
import org.elasticsearch.rest.RestController; import org.elasticsearch.rest.RestController;
import org.elasticsearch.rest.RestRequest; import org.elasticsearch.rest.RestRequest;
@ -20,6 +20,7 @@ import org.elasticsearch.xpack.security.action.user.PutUserRequestBuilder;
import org.elasticsearch.xpack.security.action.user.PutUserResponse; import org.elasticsearch.xpack.security.action.user.PutUserResponse;
import org.elasticsearch.xpack.security.client.SecurityClient; import org.elasticsearch.xpack.security.client.SecurityClient;
import org.elasticsearch.xpack.security.rest.RestRequestFilter; import org.elasticsearch.xpack.security.rest.RestRequestFilter;
import org.elasticsearch.xpack.security.rest.action.SecurityBaseRestHandler;
import java.io.IOException; import java.io.IOException;
import java.util.Collections; import java.util.Collections;
@ -31,10 +32,10 @@ import static org.elasticsearch.rest.RestRequest.Method.PUT;
/** /**
* Rest endpoint to add a User to the security index * Rest endpoint to add a User to the security index
*/ */
public class RestPutUserAction extends BaseRestHandler implements RestRequestFilter { public class RestPutUserAction extends SecurityBaseRestHandler implements RestRequestFilter {
public RestPutUserAction(Settings settings, RestController controller) { public RestPutUserAction(Settings settings, RestController controller, XPackLicenseState licenseState) {
super(settings); super(settings, licenseState);
controller.registerHandler(POST, "/_xpack/security/user/{username}", this); controller.registerHandler(POST, "/_xpack/security/user/{username}", this);
controller.registerHandler(PUT, "/_xpack/security/user/{username}", this); controller.registerHandler(PUT, "/_xpack/security/user/{username}", this);
@ -50,7 +51,7 @@ public class RestPutUserAction extends BaseRestHandler implements RestRequestFil
} }
@Override @Override
public RestChannelConsumer prepareRequest(RestRequest request, NodeClient client) throws IOException { public RestChannelConsumer innerPrepareRequest(RestRequest request, NodeClient client) throws IOException {
PutUserRequestBuilder requestBuilder = new SecurityClient(client) PutUserRequestBuilder requestBuilder = new SecurityClient(client)
.preparePutUser(request.param("username"), request.content(), request.getXContentType()) .preparePutUser(request.param("username"), request.content(), request.getXContentType())
.setRefreshPolicy(request.param("refresh")); .setRefreshPolicy(request.param("refresh"));

View File

@ -8,6 +8,7 @@ package org.elasticsearch.xpack.security.rest.action.user;
import org.elasticsearch.client.node.NodeClient; import org.elasticsearch.client.node.NodeClient;
import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.xcontent.XContentBuilder; import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.license.XPackLicenseState;
import org.elasticsearch.rest.BaseRestHandler; import org.elasticsearch.rest.BaseRestHandler;
import org.elasticsearch.rest.BytesRestResponse; import org.elasticsearch.rest.BytesRestResponse;
import org.elasticsearch.rest.RestController; import org.elasticsearch.rest.RestController;
@ -17,6 +18,7 @@ import org.elasticsearch.rest.RestStatus;
import org.elasticsearch.rest.action.RestBuilderListener; import org.elasticsearch.rest.action.RestBuilderListener;
import org.elasticsearch.xpack.security.action.user.SetEnabledResponse; import org.elasticsearch.xpack.security.action.user.SetEnabledResponse;
import org.elasticsearch.xpack.security.client.SecurityClient; import org.elasticsearch.xpack.security.client.SecurityClient;
import org.elasticsearch.xpack.security.rest.action.SecurityBaseRestHandler;
import java.io.IOException; import java.io.IOException;
@ -27,9 +29,10 @@ import static org.elasticsearch.rest.RestRequest.Method.PUT;
* REST handler for enabling and disabling users. The username is required and we use the path to determine if the user is being * REST handler for enabling and disabling users. The username is required and we use the path to determine if the user is being
* enabled or disabled. * enabled or disabled.
*/ */
public class RestSetEnabledAction extends BaseRestHandler { public class RestSetEnabledAction extends SecurityBaseRestHandler {
public RestSetEnabledAction(Settings settings, RestController controller) {
super(settings); public RestSetEnabledAction(Settings settings, RestController controller, XPackLicenseState licenseState) {
super(settings, licenseState);
controller.registerHandler(POST, "/_xpack/security/user/{username}/_enable", this); controller.registerHandler(POST, "/_xpack/security/user/{username}/_enable", this);
controller.registerHandler(PUT, "/_xpack/security/user/{username}/_enable", this); controller.registerHandler(PUT, "/_xpack/security/user/{username}/_enable", this);
controller.registerHandler(POST, "/_xpack/security/user/{username}/_disable", this); controller.registerHandler(POST, "/_xpack/security/user/{username}/_disable", this);
@ -37,7 +40,7 @@ public class RestSetEnabledAction extends BaseRestHandler {
} }
@Override @Override
public RestChannelConsumer prepareRequest(RestRequest request, NodeClient client) throws IOException { public RestChannelConsumer innerPrepareRequest(RestRequest request, NodeClient client) throws IOException {
final boolean enabled = request.path().endsWith("_enable"); final boolean enabled = request.path().endsWith("_enable");
assert enabled || request.path().endsWith("_disable"); assert enabled || request.path().endsWith("_disable");
final String username = request.param("username"); final String username = request.param("username");

View File

@ -0,0 +1,60 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/
package org.elasticsearch.xpack.security.rest.action;
import org.elasticsearch.client.node.NodeClient;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.license.XPackLicenseState;
import org.elasticsearch.rest.RestRequest;
import org.elasticsearch.test.ESTestCase;
import org.elasticsearch.test.rest.FakeRestChannel;
import org.elasticsearch.test.rest.FakeRestRequest;
import java.io.IOException;
import java.util.concurrent.atomic.AtomicBoolean;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyZeroInteractions;
import static org.mockito.Mockito.when;
public class SecurityBaseRestHandlerTests extends ESTestCase {
public void testSecurityBaseRestHandlerChecksLicenseState() throws Exception {
final boolean securityEnabled = randomBoolean();
final AtomicBoolean consumerCalled = new AtomicBoolean(false);
final XPackLicenseState licenseState = mock(XPackLicenseState.class);
when(licenseState.isAuthAllowed()).thenReturn(securityEnabled);
SecurityBaseRestHandler handler = new SecurityBaseRestHandler(Settings.EMPTY, licenseState) {
@Override
protected RestChannelConsumer innerPrepareRequest(RestRequest request, NodeClient client) throws IOException {
return channel -> {
if (consumerCalled.compareAndSet(false, true) == false) {
fail("consumerCalled was not false");
}
};
}
};
FakeRestRequest fakeRestRequest = new FakeRestRequest();
FakeRestChannel fakeRestChannel = new FakeRestChannel(fakeRestRequest, randomBoolean(), securityEnabled ? 0 : 1);
NodeClient client = mock(NodeClient.class);
assertFalse(consumerCalled.get());
verifyZeroInteractions(licenseState);
handler.handleRequest(fakeRestRequest, fakeRestChannel, client);
verify(licenseState).isAuthAllowed();
if (securityEnabled) {
assertTrue(consumerCalled.get());
assertEquals(0, fakeRestChannel.responses().get());
assertEquals(0, fakeRestChannel.errors().get());
} else {
assertFalse(consumerCalled.get());
assertEquals(0, fakeRestChannel.responses().get());
assertEquals(1, fakeRestChannel.errors().get());
}
}
}