shield: refresh on user and role modifications by default
This commit introduces the default refresh on user and role update and delete operations. The behavior can be controlled via the `refresh` parameter on the REST API and the refresh option in the Java API. Closes elastic/elasticsearch#1494 Original commit: elastic/x-pack-elasticsearch@aff4d13886
This commit is contained in:
parent
ab3ee46104
commit
d46f465ddb
|
@ -20,6 +20,7 @@ import static org.elasticsearch.action.ValidateActions.addValidationError;
|
|||
public class DeleteRoleRequest extends ActionRequest<DeleteRoleRequest> {
|
||||
|
||||
private String name;
|
||||
private boolean refresh = true;
|
||||
|
||||
public DeleteRoleRequest() {
|
||||
}
|
||||
|
@ -41,15 +42,25 @@ public class DeleteRoleRequest extends ActionRequest<DeleteRoleRequest> {
|
|||
return name;
|
||||
}
|
||||
|
||||
public void refresh(boolean refresh) {
|
||||
this.refresh = refresh;
|
||||
}
|
||||
|
||||
public boolean refresh() {
|
||||
return refresh;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void readFrom(StreamInput in) throws IOException {
|
||||
super.readFrom(in);
|
||||
name = in.readString();
|
||||
refresh = in.readBoolean();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeTo(StreamOutput out) throws IOException {
|
||||
super.writeTo(out);
|
||||
out.writeString(name);
|
||||
out.writeBoolean(refresh);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -25,4 +25,9 @@ public class DeleteRoleRequestBuilder extends ActionRequestBuilder<DeleteRoleReq
|
|||
request.name(name);
|
||||
return this;
|
||||
}
|
||||
|
||||
public DeleteRoleRequestBuilder refresh(boolean refresh) {
|
||||
request.refresh(refresh);
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -30,6 +30,7 @@ public class PutRoleRequest extends ActionRequest<PutRoleRequest> {
|
|||
private String[] clusterPrivileges = Strings.EMPTY_ARRAY;
|
||||
private List<RoleDescriptor.IndicesPrivileges> indicesPrivileges = new ArrayList<>();
|
||||
private String[] runAs = Strings.EMPTY_ARRAY;
|
||||
private boolean refresh = true;
|
||||
|
||||
public PutRoleRequest() {
|
||||
}
|
||||
|
@ -68,6 +69,10 @@ public class PutRoleRequest extends ActionRequest<PutRoleRequest> {
|
|||
this.runAs = usernames;
|
||||
}
|
||||
|
||||
public void refresh(boolean refresh) {
|
||||
this.refresh = refresh;
|
||||
}
|
||||
|
||||
public String name() {
|
||||
return name;
|
||||
}
|
||||
|
@ -84,6 +89,10 @@ public class PutRoleRequest extends ActionRequest<PutRoleRequest> {
|
|||
return runAs;
|
||||
}
|
||||
|
||||
public boolean refresh() {
|
||||
return refresh;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void readFrom(StreamInput in) throws IOException {
|
||||
super.readFrom(in);
|
||||
|
@ -95,6 +104,7 @@ public class PutRoleRequest extends ActionRequest<PutRoleRequest> {
|
|||
indicesPrivileges.add(RoleDescriptor.IndicesPrivileges.createFrom(in));
|
||||
}
|
||||
runAs = in.readStringArray();
|
||||
refresh = in.readBoolean();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -107,6 +117,7 @@ public class PutRoleRequest extends ActionRequest<PutRoleRequest> {
|
|||
index.writeTo(out);
|
||||
}
|
||||
out.writeStringArray(runAs);
|
||||
out.writeBoolean(refresh);
|
||||
}
|
||||
|
||||
RoleDescriptor roleDescriptor() {
|
||||
|
|
|
@ -53,4 +53,9 @@ public class PutRoleRequestBuilder extends ActionRequestBuilder<PutRoleRequest,
|
|||
request.addIndex(indices, privileges, fields, query);
|
||||
return this;
|
||||
}
|
||||
|
||||
public PutRoleRequestBuilder refresh(boolean refresh) {
|
||||
request.refresh(refresh);
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -29,7 +29,7 @@ public class TransportPutRoleAction extends HandledTransportAction<PutRoleReques
|
|||
|
||||
@Override
|
||||
protected void doExecute(final PutRoleRequest request, final ActionListener<PutRoleResponse> listener) {
|
||||
rolesStore.putRole(request.roleDescriptor(), new ActionListener<Boolean>() {
|
||||
rolesStore.putRole(request, request.roleDescriptor(), new ActionListener<Boolean>() {
|
||||
@Override
|
||||
public void onResponse(Boolean created) {
|
||||
if (created) {
|
||||
|
|
|
@ -20,6 +20,7 @@ import static org.elasticsearch.action.ValidateActions.addValidationError;
|
|||
public class DeleteUserRequest extends ActionRequest<DeleteUserRequest> {
|
||||
|
||||
private String username;
|
||||
private boolean refresh = true;
|
||||
|
||||
public DeleteUserRequest() {
|
||||
}
|
||||
|
@ -41,20 +42,30 @@ public class DeleteUserRequest extends ActionRequest<DeleteUserRequest> {
|
|||
return this.username;
|
||||
}
|
||||
|
||||
public boolean refresh() {
|
||||
return refresh;
|
||||
}
|
||||
|
||||
public void username(String username) {
|
||||
this.username = username;
|
||||
}
|
||||
|
||||
public void refresh(boolean refresh) {
|
||||
this.refresh = refresh;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void readFrom(StreamInput in) throws IOException {
|
||||
super.readFrom(in);
|
||||
username = in.readString();
|
||||
refresh = in.readBoolean();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeTo(StreamOutput out) throws IOException {
|
||||
super.writeTo(out);
|
||||
out.writeString(username);
|
||||
out.writeBoolean(refresh);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -22,4 +22,9 @@ public class DeleteUserRequestBuilder extends ActionRequestBuilder<DeleteUserReq
|
|||
request.username(username);
|
||||
return this;
|
||||
}
|
||||
|
||||
public DeleteUserRequestBuilder refresh(boolean refresh) {
|
||||
request.refresh(refresh);
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -27,6 +27,7 @@ public class PutUserRequest extends ActionRequest<PutUserRequest> {
|
|||
private String email;
|
||||
private Map<String, Object> metadata;
|
||||
private char[] passwordHash;
|
||||
private boolean refresh = true;
|
||||
|
||||
public PutUserRequest() {
|
||||
}
|
||||
|
@ -70,6 +71,10 @@ public class PutUserRequest extends ActionRequest<PutUserRequest> {
|
|||
this.passwordHash = passwordHash;
|
||||
}
|
||||
|
||||
public void refresh(boolean refresh) {
|
||||
this.refresh = refresh;
|
||||
}
|
||||
|
||||
public String username() {
|
||||
return username;
|
||||
}
|
||||
|
@ -94,6 +99,10 @@ public class PutUserRequest extends ActionRequest<PutUserRequest> {
|
|||
return passwordHash;
|
||||
}
|
||||
|
||||
public boolean refresh() {
|
||||
return refresh;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void readFrom(StreamInput in) throws IOException {
|
||||
super.readFrom(in);
|
||||
|
@ -103,6 +112,7 @@ public class PutUserRequest extends ActionRequest<PutUserRequest> {
|
|||
fullName = in.readOptionalString();
|
||||
email = in.readOptionalString();
|
||||
metadata = in.readBoolean() ? in.readMap() : null;
|
||||
refresh = in.readBoolean();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -119,5 +129,6 @@ public class PutUserRequest extends ActionRequest<PutUserRequest> {
|
|||
out.writeBoolean(true);
|
||||
out.writeMap(metadata);
|
||||
}
|
||||
out.writeBoolean(refresh);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -64,6 +64,11 @@ public class PutUserRequestBuilder extends ActionRequestBuilder<PutUserRequest,
|
|||
return this;
|
||||
}
|
||||
|
||||
public PutUserRequestBuilder refresh(boolean refresh) {
|
||||
request.refresh(refresh);
|
||||
return this;
|
||||
}
|
||||
|
||||
public PutUserRequestBuilder source(String username, BytesReference source) throws IOException {
|
||||
username(username);
|
||||
try (XContentParser parser = XContentHelper.createParser(source)) {
|
||||
|
|
|
@ -302,6 +302,7 @@ public class ESNativeUsersStore extends AbstractComponent implements ClusterStat
|
|||
User.Fields.FULL_NAME.getPreferredName(), request.fullName(),
|
||||
User.Fields.EMAIL.getPreferredName(), request.email(),
|
||||
User.Fields.METADATA.getPreferredName(), request.metadata())
|
||||
.setRefresh(request.refresh())
|
||||
.request();
|
||||
|
||||
client.index(indexRequest, new ActionListener<IndexResponse>() {
|
||||
|
@ -337,6 +338,7 @@ public class ESNativeUsersStore extends AbstractComponent implements ClusterStat
|
|||
DeleteRequest request = client.prepareDelete(ShieldTemplateService.SECURITY_INDEX_NAME,
|
||||
USER_DOC_TYPE, deleteUserRequest.username()).request();
|
||||
request.indicesOptions().ignoreUnavailable();
|
||||
request.refresh(deleteUserRequest.refresh());
|
||||
client.delete(request, new ActionListener<DeleteResponse>() {
|
||||
@Override
|
||||
public void onResponse(DeleteResponse deleteResponse) {
|
||||
|
|
|
@ -34,6 +34,7 @@ import org.elasticsearch.common.util.concurrent.FutureUtils;
|
|||
import org.elasticsearch.common.xcontent.ToXContent;
|
||||
import org.elasticsearch.gateway.GatewayService;
|
||||
import org.elasticsearch.index.IndexNotFoundException;
|
||||
import org.elasticsearch.index.get.GetResult;
|
||||
import org.elasticsearch.index.query.QueryBuilder;
|
||||
import org.elasticsearch.index.query.QueryBuilders;
|
||||
import org.elasticsearch.search.SearchHit;
|
||||
|
@ -42,6 +43,7 @@ import org.elasticsearch.shield.ShieldTemplateService;
|
|||
import org.elasticsearch.shield.action.role.ClearRolesCacheRequest;
|
||||
import org.elasticsearch.shield.action.role.ClearRolesCacheResponse;
|
||||
import org.elasticsearch.shield.action.role.DeleteRoleRequest;
|
||||
import org.elasticsearch.shield.action.role.PutRoleRequest;
|
||||
import org.elasticsearch.shield.authc.AuthenticationService;
|
||||
import org.elasticsearch.shield.authz.RoleDescriptor;
|
||||
import org.elasticsearch.shield.authz.permission.Role;
|
||||
|
@ -257,7 +259,7 @@ public class ESNativeRolesStore extends AbstractComponent implements RolesStore,
|
|||
try {
|
||||
DeleteRequest request = client.prepareDelete(ShieldTemplateService.SECURITY_INDEX_NAME,
|
||||
ROLE_DOC_TYPE, deleteRoleRequest.name()).request();
|
||||
request.indicesOptions().ignoreUnavailable();
|
||||
request.refresh(deleteRoleRequest.refresh());
|
||||
client.delete(request, new ActionListener<DeleteResponse>() {
|
||||
@Override
|
||||
public void onResponse(DeleteResponse deleteResponse) {
|
||||
|
@ -270,13 +272,16 @@ public class ESNativeRolesStore extends AbstractComponent implements RolesStore,
|
|||
listener.onFailure(e);
|
||||
}
|
||||
});
|
||||
} catch (IndexNotFoundException e) {
|
||||
logger.trace("security index does not exist", e);
|
||||
listener.onResponse(false);
|
||||
} catch (Exception e) {
|
||||
logger.error("unable to remove role", e);
|
||||
listener.onFailure(e);
|
||||
}
|
||||
}
|
||||
|
||||
public void putRole(final RoleDescriptor role, final ActionListener<Boolean> listener) {
|
||||
public void putRole(final PutRoleRequest request, final RoleDescriptor role, final ActionListener<Boolean> listener) {
|
||||
if (state() != State.STARTED) {
|
||||
logger.trace("attempted to put role before service was started");
|
||||
listener.onResponse(false);
|
||||
|
@ -284,6 +289,7 @@ public class ESNativeRolesStore extends AbstractComponent implements RolesStore,
|
|||
try {
|
||||
client.prepareIndex(ShieldTemplateService.SECURITY_INDEX_NAME, ROLE_DOC_TYPE, role.getName())
|
||||
.setSource(role.toXContent(jsonBuilder(), ToXContent.EMPTY_PARAMS))
|
||||
.setRefresh(request.refresh())
|
||||
.execute(new ActionListener<IndexResponse>() {
|
||||
@Override
|
||||
public void onResponse(IndexResponse indexResponse) {
|
||||
|
@ -363,8 +369,11 @@ public class ESNativeRolesStore extends AbstractComponent implements RolesStore,
|
|||
private void executeGetRoleRequest(String role, ActionListener<GetResponse> listener) {
|
||||
try {
|
||||
GetRequest request = client.prepareGet(ShieldTemplateService.SECURITY_INDEX_NAME, ROLE_DOC_TYPE, role).request();
|
||||
request.indicesOptions().ignoreUnavailable();
|
||||
client.get(request, listener);
|
||||
} catch (IndexNotFoundException e) {
|
||||
logger.trace("security index does not exist", e);
|
||||
listener.onResponse(new GetResponse(
|
||||
new GetResult(ShieldTemplateService.SECURITY_INDEX_NAME, ROLE_DOC_TYPE, role, -1, false, null, null)));
|
||||
} catch (Exception e) {
|
||||
logger.error("unable to retrieve role", e);
|
||||
listener.onFailure(e);
|
||||
|
|
|
@ -17,6 +17,7 @@ import org.elasticsearch.rest.RestRequest;
|
|||
import org.elasticsearch.rest.RestResponse;
|
||||
import org.elasticsearch.rest.RestStatus;
|
||||
import org.elasticsearch.rest.action.support.RestBuilderListener;
|
||||
import org.elasticsearch.shield.action.role.DeleteRoleRequestBuilder;
|
||||
import org.elasticsearch.shield.action.role.DeleteRoleResponse;
|
||||
import org.elasticsearch.shield.client.SecurityClient;
|
||||
|
||||
|
@ -33,7 +34,11 @@ public class RestDeleteRoleAction extends BaseRestHandler {
|
|||
|
||||
@Override
|
||||
protected void handleRequest(RestRequest request, final RestChannel channel, Client client) throws Exception {
|
||||
new SecurityClient(client).prepareDeleteRole(request.param("name")).execute(new RestBuilderListener<DeleteRoleResponse>(channel) {
|
||||
DeleteRoleRequestBuilder requestBuilder = new SecurityClient(client).prepareDeleteRole(request.param("name"));
|
||||
if (request.hasParam("refresh")) {
|
||||
requestBuilder.refresh(request.paramAsBoolean("refresh", true));
|
||||
}
|
||||
requestBuilder.execute(new RestBuilderListener<DeleteRoleResponse>(channel) {
|
||||
@Override
|
||||
public RestResponse buildResponse(DeleteRoleResponse response, XContentBuilder builder) throws Exception {
|
||||
return new BytesRestResponse(response.found() ? RestStatus.OK : RestStatus.NOT_FOUND,
|
||||
|
|
|
@ -17,6 +17,7 @@ import org.elasticsearch.rest.RestRequest;
|
|||
import org.elasticsearch.rest.RestResponse;
|
||||
import org.elasticsearch.rest.RestStatus;
|
||||
import org.elasticsearch.rest.action.support.RestBuilderListener;
|
||||
import org.elasticsearch.shield.action.role.PutRoleRequestBuilder;
|
||||
import org.elasticsearch.shield.action.role.PutRoleResponse;
|
||||
import org.elasticsearch.shield.client.SecurityClient;
|
||||
|
||||
|
@ -34,8 +35,11 @@ public class RestPutRoleAction extends BaseRestHandler {
|
|||
|
||||
@Override
|
||||
protected void handleRequest(RestRequest request, final RestChannel channel, Client client) throws Exception {
|
||||
new SecurityClient(client).preparePutRole(request.param("name"), request.content()).execute(
|
||||
new RestBuilderListener<PutRoleResponse>(channel) {
|
||||
PutRoleRequestBuilder requestBuilder = new SecurityClient(client).preparePutRole(request.param("name"), request.content());
|
||||
if (request.hasParam("refresh")) {
|
||||
requestBuilder.refresh(request.paramAsBoolean("refresh", true));
|
||||
}
|
||||
requestBuilder.execute(new RestBuilderListener<PutRoleResponse>(channel) {
|
||||
@Override
|
||||
public RestResponse buildResponse(PutRoleResponse putRoleResponse, XContentBuilder builder) throws Exception {
|
||||
return new BytesRestResponse(RestStatus.OK,
|
||||
|
|
|
@ -18,6 +18,7 @@ import org.elasticsearch.rest.RestResponse;
|
|||
import org.elasticsearch.rest.RestStatus;
|
||||
import org.elasticsearch.rest.action.support.RestBuilderListener;
|
||||
import org.elasticsearch.shield.action.user.DeleteUserRequest;
|
||||
import org.elasticsearch.shield.action.user.DeleteUserRequestBuilder;
|
||||
import org.elasticsearch.shield.action.user.DeleteUserResponse;
|
||||
import org.elasticsearch.shield.client.SecurityClient;
|
||||
|
||||
|
@ -36,7 +37,11 @@ public class RestDeleteUserAction extends BaseRestHandler {
|
|||
protected void handleRequest(RestRequest request, final RestChannel channel, Client client) throws Exception {
|
||||
String username = request.param("username");
|
||||
|
||||
new SecurityClient(client).prepareDeleteUser(username).execute(new RestBuilderListener<DeleteUserResponse>(channel) {
|
||||
DeleteUserRequestBuilder requestBuilder = new SecurityClient(client).prepareDeleteUser(username);
|
||||
if (request.hasParam("refresh")) {
|
||||
requestBuilder.refresh(request.paramAsBoolean("refresh", true));
|
||||
}
|
||||
requestBuilder.execute(new RestBuilderListener<DeleteUserResponse>(channel) {
|
||||
@Override
|
||||
public RestResponse buildResponse(DeleteUserResponse response, XContentBuilder builder) throws Exception {
|
||||
return new BytesRestResponse(response.found() ? RestStatus.OK : RestStatus.NOT_FOUND,
|
||||
|
|
|
@ -17,6 +17,7 @@ import org.elasticsearch.rest.RestRequest;
|
|||
import org.elasticsearch.rest.RestResponse;
|
||||
import org.elasticsearch.rest.RestStatus;
|
||||
import org.elasticsearch.rest.action.support.RestBuilderListener;
|
||||
import org.elasticsearch.shield.action.user.PutUserRequestBuilder;
|
||||
import org.elasticsearch.shield.action.user.PutUserResponse;
|
||||
import org.elasticsearch.shield.client.SecurityClient;
|
||||
|
||||
|
@ -34,8 +35,11 @@ public class RestPutUserAction extends BaseRestHandler {
|
|||
|
||||
@Override
|
||||
protected void handleRequest(RestRequest request, final RestChannel channel, Client client) throws Exception {
|
||||
new SecurityClient(client).preparePutUser(request.param("username"), request.content())
|
||||
.execute(new RestBuilderListener<PutUserResponse>(channel) {
|
||||
PutUserRequestBuilder requestBuilder = new SecurityClient(client).preparePutUser(request.param("username"), request.content());
|
||||
if (request.hasParam("refresh")) {
|
||||
requestBuilder.refresh(request.paramAsBoolean("refresh", true));
|
||||
}
|
||||
requestBuilder.execute(new RestBuilderListener<PutUserResponse>(channel) {
|
||||
@Override
|
||||
public RestResponse buildResponse(PutUserResponse putUserResponse, XContentBuilder builder) throws Exception {
|
||||
return new BytesRestResponse(RestStatus.OK,
|
||||
|
|
|
@ -74,8 +74,6 @@ public class ESNativeTests extends ShieldIntegTestCase {
|
|||
logger.info("--> adding two more users");
|
||||
c.preparePutUser("joe2", "s3kirt2".toCharArray(), "role2", "user").get();
|
||||
c.preparePutUser("joe3", "s3kirt3".toCharArray(), "role3", "user").get();
|
||||
// Since getting multiple users relies on them being visible to search, perform a refresh
|
||||
refresh();
|
||||
GetUsersResponse allUsersResp = c.prepareGetUsers().get();
|
||||
assertTrue("users should exist", allUsersResp.hasUsers());
|
||||
assertEquals("should be 3 users total", 3, allUsersResp.users().length);
|
||||
|
@ -134,9 +132,6 @@ public class ESNativeTests extends ShieldIntegTestCase {
|
|||
new String[]{"body", "title"}, new BytesArray("{\"query\": {\"match_all\": {}}}"))
|
||||
.get();
|
||||
|
||||
// Refresh to make new roles visible
|
||||
refresh();
|
||||
|
||||
logger.info("--> retrieving all roles");
|
||||
GetRolesResponse allRolesResp = c.prepareGetRoles().get();
|
||||
assertTrue("roles should exist", allRolesResp.hasRoles());
|
||||
|
@ -165,7 +160,6 @@ public class ESNativeTests extends ShieldIntegTestCase {
|
|||
.get();
|
||||
logger.error("--> creating user");
|
||||
c.preparePutUser("joe", "s3krit".toCharArray(), "test_role").get();
|
||||
refresh();
|
||||
logger.error("--> waiting for .shield index");
|
||||
ensureGreen(ShieldTemplateService.SECURITY_INDEX_NAME);
|
||||
logger.info("--> retrieving user");
|
||||
|
@ -187,7 +181,6 @@ public class ESNativeTests extends ShieldIntegTestCase {
|
|||
SecurityClient c = securityClient();
|
||||
logger.error("--> creating user");
|
||||
c.preparePutUser("joe", "s3krit".toCharArray(), ShieldSettingsSource.DEFAULT_ROLE).get();
|
||||
refresh();
|
||||
logger.error("--> waiting for .shield index");
|
||||
ensureGreen(ShieldTemplateService.SECURITY_INDEX_NAME);
|
||||
logger.info("--> retrieving user");
|
||||
|
@ -223,7 +216,6 @@ public class ESNativeTests extends ShieldIntegTestCase {
|
|||
SecurityClient c = securityClient();
|
||||
logger.error("--> creating user");
|
||||
c.preparePutUser("joe", "s3krit".toCharArray(), ShieldSettingsSource.DEFAULT_ROLE).get();
|
||||
refresh();
|
||||
logger.error("--> waiting for .shield index");
|
||||
ensureGreen(ShieldTemplateService.SECURITY_INDEX_NAME);
|
||||
logger.info("--> retrieving user");
|
||||
|
@ -262,7 +254,6 @@ public class ESNativeTests extends ShieldIntegTestCase {
|
|||
.get();
|
||||
logger.error("--> creating user");
|
||||
c.preparePutUser("joe", "s3krit".toCharArray(), "test_role").get();
|
||||
refresh();
|
||||
logger.error("--> waiting for .shield index");
|
||||
ensureGreen(ShieldTemplateService.SECURITY_INDEX_NAME);
|
||||
|
||||
|
@ -310,7 +301,6 @@ public class ESNativeTests extends ShieldIntegTestCase {
|
|||
new String[]{"body", "title"}, new BytesArray("{\"match_all\": {}}"))
|
||||
.get();
|
||||
c.preparePutUser("joe", "s3krit".toCharArray(), "test_role").get();
|
||||
refresh();
|
||||
logger.error("--> waiting for .shield index");
|
||||
ensureGreen(ShieldTemplateService.SECURITY_INDEX_NAME);
|
||||
|
||||
|
|
Loading…
Reference in New Issue