diff --git a/elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/action/role/DeleteRoleRequest.java b/elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/action/role/DeleteRoleRequest.java index fc542fb5c16..20b4812c724 100644 --- a/elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/action/role/DeleteRoleRequest.java +++ b/elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/action/role/DeleteRoleRequest.java @@ -20,6 +20,7 @@ import static org.elasticsearch.action.ValidateActions.addValidationError; public class DeleteRoleRequest extends ActionRequest { private String name; + private boolean refresh = true; public DeleteRoleRequest() { } @@ -41,15 +42,25 @@ public class DeleteRoleRequest extends ActionRequest { 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); } } diff --git a/elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/action/role/DeleteRoleRequestBuilder.java b/elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/action/role/DeleteRoleRequestBuilder.java index 4eec0b7a105..fb509d99fba 100644 --- a/elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/action/role/DeleteRoleRequestBuilder.java +++ b/elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/action/role/DeleteRoleRequestBuilder.java @@ -25,4 +25,9 @@ public class DeleteRoleRequestBuilder extends ActionRequestBuilder { private String[] clusterPrivileges = Strings.EMPTY_ARRAY; private List indicesPrivileges = new ArrayList<>(); private String[] runAs = Strings.EMPTY_ARRAY; - + private boolean refresh = true; + public PutRoleRequest() { } @@ -68,6 +69,10 @@ public class PutRoleRequest extends ActionRequest { 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 { 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 { indicesPrivileges.add(RoleDescriptor.IndicesPrivileges.createFrom(in)); } runAs = in.readStringArray(); + refresh = in.readBoolean(); } @Override @@ -107,6 +117,7 @@ public class PutRoleRequest extends ActionRequest { index.writeTo(out); } out.writeStringArray(runAs); + out.writeBoolean(refresh); } RoleDescriptor roleDescriptor() { diff --git a/elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/action/role/PutRoleRequestBuilder.java b/elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/action/role/PutRoleRequestBuilder.java index 7c251556cc9..5bfe5bc6ea8 100644 --- a/elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/action/role/PutRoleRequestBuilder.java +++ b/elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/action/role/PutRoleRequestBuilder.java @@ -53,4 +53,9 @@ public class PutRoleRequestBuilder extends ActionRequestBuilder listener) { - rolesStore.putRole(request.roleDescriptor(), new ActionListener() { + rolesStore.putRole(request, request.roleDescriptor(), new ActionListener() { @Override public void onResponse(Boolean created) { if (created) { diff --git a/elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/action/user/DeleteUserRequest.java b/elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/action/user/DeleteUserRequest.java index 148e9e30749..082edd7aa17 100644 --- a/elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/action/user/DeleteUserRequest.java +++ b/elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/action/user/DeleteUserRequest.java @@ -20,6 +20,7 @@ import static org.elasticsearch.action.ValidateActions.addValidationError; public class DeleteUserRequest extends ActionRequest { private String username; + private boolean refresh = true; public DeleteUserRequest() { } @@ -41,20 +42,30 @@ public class DeleteUserRequest extends ActionRequest { 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); } } diff --git a/elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/action/user/DeleteUserRequestBuilder.java b/elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/action/user/DeleteUserRequestBuilder.java index 81703eca582..c82dd47f6d6 100644 --- a/elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/action/user/DeleteUserRequestBuilder.java +++ b/elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/action/user/DeleteUserRequestBuilder.java @@ -22,4 +22,9 @@ public class DeleteUserRequestBuilder extends ActionRequestBuilder { private String email; private Map metadata; private char[] passwordHash; + private boolean refresh = true; public PutUserRequest() { } @@ -70,6 +71,10 @@ public class PutUserRequest extends ActionRequest { 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 { 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 { 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 { out.writeBoolean(true); out.writeMap(metadata); } + out.writeBoolean(refresh); } } diff --git a/elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/action/user/PutUserRequestBuilder.java b/elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/action/user/PutUserRequestBuilder.java index a4ba772c92c..6a0b42481d5 100644 --- a/elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/action/user/PutUserRequestBuilder.java +++ b/elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/action/user/PutUserRequestBuilder.java @@ -64,6 +64,11 @@ public class PutUserRequestBuilder extends ActionRequestBuilder() { @@ -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() { @Override public void onResponse(DeleteResponse deleteResponse) { diff --git a/elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/authz/esnative/ESNativeRolesStore.java b/elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/authz/esnative/ESNativeRolesStore.java index ece071259e7..792c7710e4a 100644 --- a/elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/authz/esnative/ESNativeRolesStore.java +++ b/elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/authz/esnative/ESNativeRolesStore.java @@ -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() { @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 listener) { + public void putRole(final PutRoleRequest request, final RoleDescriptor role, final ActionListener 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() { @Override public void onResponse(IndexResponse indexResponse) { @@ -363,8 +369,11 @@ public class ESNativeRolesStore extends AbstractComponent implements RolesStore, private void executeGetRoleRequest(String role, ActionListener 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); diff --git a/elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/rest/action/role/RestDeleteRoleAction.java b/elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/rest/action/role/RestDeleteRoleAction.java index ed63c5ef5d0..9ed99f57604 100644 --- a/elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/rest/action/role/RestDeleteRoleAction.java +++ b/elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/rest/action/role/RestDeleteRoleAction.java @@ -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(channel) { + DeleteRoleRequestBuilder requestBuilder = new SecurityClient(client).prepareDeleteRole(request.param("name")); + if (request.hasParam("refresh")) { + requestBuilder.refresh(request.paramAsBoolean("refresh", true)); + } + requestBuilder.execute(new RestBuilderListener(channel) { @Override public RestResponse buildResponse(DeleteRoleResponse response, XContentBuilder builder) throws Exception { return new BytesRestResponse(response.found() ? RestStatus.OK : RestStatus.NOT_FOUND, diff --git a/elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/rest/action/role/RestPutRoleAction.java b/elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/rest/action/role/RestPutRoleAction.java index 3d662ef19d0..dd44d51d3eb 100644 --- a/elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/rest/action/role/RestPutRoleAction.java +++ b/elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/rest/action/role/RestPutRoleAction.java @@ -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,15 +35,18 @@ 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(channel) { - @Override - public RestResponse buildResponse(PutRoleResponse putRoleResponse, XContentBuilder builder) throws Exception { - return new BytesRestResponse(RestStatus.OK, - builder.startObject() - .field("role", putRoleResponse) - .endObject()); - } - }); + 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(channel) { + @Override + public RestResponse buildResponse(PutRoleResponse putRoleResponse, XContentBuilder builder) throws Exception { + return new BytesRestResponse(RestStatus.OK, + builder.startObject() + .field("role", putRoleResponse) + .endObject()); + } + }); } } diff --git a/elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/rest/action/user/RestDeleteUserAction.java b/elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/rest/action/user/RestDeleteUserAction.java index e5d9f8d2a69..a31d30e1ffb 100644 --- a/elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/rest/action/user/RestDeleteUserAction.java +++ b/elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/rest/action/user/RestDeleteUserAction.java @@ -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(channel) { + DeleteUserRequestBuilder requestBuilder = new SecurityClient(client).prepareDeleteUser(username); + if (request.hasParam("refresh")) { + requestBuilder.refresh(request.paramAsBoolean("refresh", true)); + } + requestBuilder.execute(new RestBuilderListener(channel) { @Override public RestResponse buildResponse(DeleteUserResponse response, XContentBuilder builder) throws Exception { return new BytesRestResponse(response.found() ? RestStatus.OK : RestStatus.NOT_FOUND, diff --git a/elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/rest/action/user/RestPutUserAction.java b/elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/rest/action/user/RestPutUserAction.java index 1b2abae4a44..fa348ba66f9 100644 --- a/elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/rest/action/user/RestPutUserAction.java +++ b/elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/rest/action/user/RestPutUserAction.java @@ -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,15 +35,18 @@ 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(channel) { - @Override - public RestResponse buildResponse(PutUserResponse putUserResponse, XContentBuilder builder) throws Exception { - return new BytesRestResponse(RestStatus.OK, - builder.startObject() - .field("user", putUserResponse) - .endObject()); - } - }); + 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(channel) { + @Override + public RestResponse buildResponse(PutUserResponse putUserResponse, XContentBuilder builder) throws Exception { + return new BytesRestResponse(RestStatus.OK, + builder.startObject() + .field("user", putUserResponse) + .endObject()); + } + }); } } diff --git a/elasticsearch/x-pack/shield/src/test/java/org/elasticsearch/shield/authc/esnative/ESNativeTests.java b/elasticsearch/x-pack/shield/src/test/java/org/elasticsearch/shield/authc/esnative/ESNativeTests.java index fa6158660e5..0c9ceba6f3e 100644 --- a/elasticsearch/x-pack/shield/src/test/java/org/elasticsearch/shield/authc/esnative/ESNativeTests.java +++ b/elasticsearch/x-pack/shield/src/test/java/org/elasticsearch/shield/authc/esnative/ESNativeTests.java @@ -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);