changed the User API

- Now it's more aligned with other APIs in ES (e.g. index template API)
- the "get user" API now returns an object as a response. The users are keyed by their username. If none of the requested users is found, an empty object will be returned with a 404 response status.
- the body of "put user" request doesn't require "username" anymore (as it's defined as part of the URL)

Original commit: elastic/x-pack-elasticsearch@f7c12648b1
This commit is contained in:
uboness 2016-02-28 03:47:28 +01:00 committed by jaymode
parent 1f113e07f4
commit 759d99de9c
14 changed files with 126 additions and 116 deletions

View File

@ -34,8 +34,8 @@ import java.util.concurrent.atomic.AtomicBoolean;
*/
public class ShieldTemplateService extends AbstractComponent implements ClusterStateListener {
public static final String SHIELD_ADMIN_INDEX_NAME = ".security";
public static final String SHIELD_TEMPLATE_NAME = "security-index-template";
public static final String SECURITY_INDEX_NAME = ".security";
public static final String SECURITY_TEMPLATE_NAME = "security-index-template";
private final ThreadPool threadPool;
private final Provider<InternalClient> clientProvider;
@ -52,22 +52,22 @@ public class ShieldTemplateService extends AbstractComponent implements ClusterS
private void createShieldTemplate() {
final Client client = clientProvider.get();
try (InputStream is = getClass().getResourceAsStream("/" + SHIELD_TEMPLATE_NAME + ".json")) {
try (InputStream is = getClass().getResourceAsStream("/" + SECURITY_TEMPLATE_NAME + ".json")) {
ByteArrayOutputStream out = new ByteArrayOutputStream();
Streams.copy(is, out);
final byte[] template = out.toByteArray();
logger.info("--> putting the shield index template");
PutIndexTemplateRequest putTemplateRequest = client.admin().indices()
.preparePutTemplate(SHIELD_TEMPLATE_NAME).setSource(template).request();
.preparePutTemplate(SECURITY_TEMPLATE_NAME).setSource(template).request();
PutIndexTemplateResponse templateResponse = client.admin().indices().putTemplate(putTemplateRequest).get();
if (templateResponse.isAcknowledged() == false) {
throw new ElasticsearchException("adding template for shield admin index was not acknowledged");
}
} catch (Exception e) {
logger.error("failed to create shield admin index template [{}]",
e, SHIELD_ADMIN_INDEX_NAME);
e, SECURITY_INDEX_NAME);
throw new IllegalStateException("failed to create shield admin index template [" +
SHIELD_ADMIN_INDEX_NAME + "]", e);
SECURITY_INDEX_NAME + "]", e);
}
}
@ -80,13 +80,13 @@ public class ShieldTemplateService extends AbstractComponent implements ClusterS
return;
}
IndexRoutingTable shieldIndexRouting = event.state().routingTable().index(SHIELD_ADMIN_INDEX_NAME);
IndexRoutingTable shieldIndexRouting = event.state().routingTable().index(SECURITY_INDEX_NAME);
if (shieldIndexRouting == null) {
if (event.localNodeMaster()) {
ClusterState state = event.state();
// TODO for the future need to add some checking in the event the template needs to be updated...
IndexTemplateMetaData templateMeta = state.metaData().templates().get(SHIELD_TEMPLATE_NAME);
IndexTemplateMetaData templateMeta = state.metaData().templates().get(SECURITY_TEMPLATE_NAME);
final boolean createTemplate = (templateMeta == null);
if (createTemplate && templateCreationPending.compareAndSet(false, true)) {

View File

@ -158,13 +158,12 @@ public class User implements ToXContent {
@Override
public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException {
builder.startObject();
builder.field(Fields.USERNAME.getPreferredName(), principal());
builder.array(Fields.ROLES.getPreferredName(), roles());
builder.field(Fields.USERNAME.getPreferredName(), username);
builder.array(Fields.ROLES.getPreferredName(), roles);
builder.field(Fields.FULL_NAME.getPreferredName(), fullName);
builder.field(Fields.EMAIL.getPreferredName(), email);
builder.field(Fields.METADATA.getPreferredName(), metadata);
builder.endObject();
return builder;
return builder.endObject();
}
public static User readFrom(StreamInput input) throws IOException {

View File

@ -43,7 +43,7 @@ public class XPackUser extends User {
// these will be the index permissions required by shield (will uncomment once we optimize watcher permissions)
// .add(IndexPrivilege.ALL, ShieldTemplateService.SHIELD_ADMIN_INDEX_NAME)
// .add(IndexPrivilege.ALL, ShieldTemplateService.SECURITY_INDEX_NAME)
// .add(IndexPrivilege.ALL, IndexAuditTrail.INDEX_NAME_PREFIX + "*")

View File

@ -64,7 +64,8 @@ public class PutUserRequestBuilder extends ActionRequestBuilder<PutUserRequest,
return this;
}
public PutUserRequestBuilder source(BytesReference source) throws IOException {
public PutUserRequestBuilder source(String username, BytesReference source) throws IOException {
username(username);
try (XContentParser parser = XContentHelper.createParser(source)) {
XContentUtils.verifyObject(parser);
XContentParser.Token token;
@ -73,11 +74,9 @@ public class PutUserRequestBuilder extends ActionRequestBuilder<PutUserRequest,
if (token == XContentParser.Token.FIELD_NAME) {
currentFieldName = parser.currentName();
} else if (ParseFieldMatcher.STRICT.match(currentFieldName, User.Fields.USERNAME)) {
if (token == XContentParser.Token.VALUE_STRING) {
username(parser.text());
} else {
throw new ElasticsearchParseException(
"expected field [{}] to be of type string, but found [{}] instead", currentFieldName, token);
if (username.equals(parser.text()) == false) {
throw new ElasticsearchParseException("failed to parse user [{}]. username doesn't match user id [{}]",
username, parser.text());
}
} else if (ParseFieldMatcher.STRICT.match(currentFieldName, User.Fields.PASSWORD)) {
if (token == XContentParser.Token.VALUE_STRING) {

View File

@ -88,7 +88,7 @@ public class ESNativeUsersStore extends AbstractComponent implements ClusterStat
}
// TODO - perhaps separate indices for users/roles instead of types?
public static final String INDEX_USER_TYPE = "user";
public static final String USER_DOC_TYPE = "user";
// this map contains the mapping for username -> version, which is used when polling the index to easily detect of
// any changes that may have been missed since the last update.
@ -168,12 +168,13 @@ public class ESNativeUsersStore extends AbstractComponent implements ClusterStat
final List<User> users = new ArrayList<>();
QueryBuilder query;
if (usernames == null || usernames.length == 0) {
query = QueryBuilders.boolQuery().filter(QueryBuilders.termQuery("_type", INDEX_USER_TYPE));
query = QueryBuilders.matchAllQuery();
} else {
query = QueryBuilders.boolQuery().filter(QueryBuilders.idsQuery(INDEX_USER_TYPE).addIds(usernames));
query = QueryBuilders.boolQuery().filter(QueryBuilders.idsQuery(USER_DOC_TYPE).addIds(usernames));
}
SearchRequest request = client.prepareSearch(ShieldTemplateService.SHIELD_ADMIN_INDEX_NAME)
SearchRequest request = client.prepareSearch(ShieldTemplateService.SECURITY_INDEX_NAME)
.setScroll(scrollKeepAlive)
.setTypes(USER_DOC_TYPE)
.setQuery(query)
.setSize(scrollSize)
.setFetchSource(true)
@ -187,7 +188,7 @@ public class ESNativeUsersStore extends AbstractComponent implements ClusterStat
boolean hasHits = resp.getHits().getHits().length > 0;
if (hasHits) {
for (SearchHit hit : resp.getHits().getHits()) {
UserAndPassword u = transformUser(hit.getSource());
UserAndPassword u = transformUser(hit.getId(), hit.getSource());
if (u != null) {
users.add(u.user());
}
@ -257,12 +258,12 @@ public class ESNativeUsersStore extends AbstractComponent implements ClusterStat
private void getUserAndPassword(String user, final ActionListener<UserAndPassword> listener) {
try {
GetRequest request = client.prepareGet(ShieldTemplateService.SHIELD_ADMIN_INDEX_NAME, INDEX_USER_TYPE, user).request();
GetRequest request = client.prepareGet(ShieldTemplateService.SECURITY_INDEX_NAME, USER_DOC_TYPE, user).request();
request.indicesOptions().ignoreUnavailable();
client.get(request, new ActionListener<GetResponse>() {
@Override
public void onResponse(GetResponse getFields) {
listener.onResponse(transformUser(getFields.getSource()));
public void onResponse(GetResponse response) {
listener.onResponse(transformUser(response.getId(), response.getSource()));
}
@Override
@ -286,24 +287,24 @@ public class ESNativeUsersStore extends AbstractComponent implements ClusterStat
}
}
public void putUser(final PutUserRequest putUserRequest, final ActionListener<Boolean> listener) {
public void putUser(final PutUserRequest request, final ActionListener<Boolean> listener) {
if (state() != State.STARTED) {
listener.onFailure(new IllegalStateException("user cannot be added as native user service has not been started"));
return;
}
try {
IndexRequest request = client.prepareIndex(ShieldTemplateService.SHIELD_ADMIN_INDEX_NAME,
INDEX_USER_TYPE, putUserRequest.username())
.setSource(User.Fields.USERNAME.getPreferredName(), putUserRequest.username(),
User.Fields.PASSWORD.getPreferredName(), String.valueOf(putUserRequest.passwordHash()),
User.Fields.ROLES.getPreferredName(), putUserRequest.roles(),
User.Fields.FULL_NAME.getPreferredName(), putUserRequest.fullName(),
User.Fields.EMAIL.getPreferredName(), putUserRequest.email(),
User.Fields.METADATA.getPreferredName(), putUserRequest.metadata())
IndexRequest indexRequest = client.prepareIndex(ShieldTemplateService.SECURITY_INDEX_NAME, USER_DOC_TYPE, request.username())
// we still index the username for more intuitive searchability (e.g. using queries like "username: joe")
.setSource(User.Fields.USERNAME.getPreferredName(), request.username(),
User.Fields.PASSWORD.getPreferredName(), String.valueOf(request.passwordHash()),
User.Fields.ROLES.getPreferredName(), request.roles(),
User.Fields.FULL_NAME.getPreferredName(), request.fullName(),
User.Fields.EMAIL.getPreferredName(), request.email(),
User.Fields.METADATA.getPreferredName(), request.metadata())
.request();
client.index(request, new ActionListener<IndexResponse>() {
client.index(indexRequest, new ActionListener<IndexResponse>() {
@Override
public void onResponse(IndexResponse indexResponse) {
// if the document was just created, then we don't need to clear cache
@ -312,7 +313,7 @@ public class ESNativeUsersStore extends AbstractComponent implements ClusterStat
return;
}
clearRealmCache(putUserRequest.username(), listener, indexResponse.isCreated());
clearRealmCache(request.username(), listener, indexResponse.isCreated());
}
@Override
@ -333,8 +334,8 @@ public class ESNativeUsersStore extends AbstractComponent implements ClusterStat
}
try {
DeleteRequest request = client.prepareDelete(ShieldTemplateService.SHIELD_ADMIN_INDEX_NAME,
INDEX_USER_TYPE, deleteUserRequest.username()).request();
DeleteRequest request = client.prepareDelete(ShieldTemplateService.SECURITY_INDEX_NAME,
USER_DOC_TYPE, deleteUserRequest.username()).request();
request.indicesOptions().ignoreUnavailable();
client.delete(request, new ActionListener<DeleteResponse>() {
@Override
@ -366,21 +367,21 @@ public class ESNativeUsersStore extends AbstractComponent implements ClusterStat
return false;
}
if (clusterState.metaData().templates().get(ShieldTemplateService.SHIELD_TEMPLATE_NAME) == null) {
if (clusterState.metaData().templates().get(ShieldTemplateService.SECURITY_TEMPLATE_NAME) == null) {
logger.debug("native users template [{}] does not exist, so service cannot start",
ShieldTemplateService.SHIELD_TEMPLATE_NAME);
ShieldTemplateService.SECURITY_TEMPLATE_NAME);
return false;
}
IndexMetaData metaData = clusterState.metaData().index(ShieldTemplateService.SHIELD_ADMIN_INDEX_NAME);
IndexMetaData metaData = clusterState.metaData().index(ShieldTemplateService.SECURITY_INDEX_NAME);
if (metaData == null) {
logger.debug("shield user index [{}] does not exist, so service can start", ShieldTemplateService.SHIELD_ADMIN_INDEX_NAME);
logger.debug("shield user index [{}] does not exist, so service can start", ShieldTemplateService.SECURITY_INDEX_NAME);
return true;
}
if (clusterState.routingTable().index(ShieldTemplateService.SHIELD_ADMIN_INDEX_NAME).allPrimaryShardsActive()) {
if (clusterState.routingTable().index(ShieldTemplateService.SECURITY_INDEX_NAME).allPrimaryShardsActive()) {
logger.debug("shield user index [{}] all primary shards started, so service can start",
ShieldTemplateService.SHIELD_ADMIN_INDEX_NAME);
ShieldTemplateService.SECURITY_INDEX_NAME);
return true;
}
return false;
@ -472,11 +473,11 @@ public class ESNativeUsersStore extends AbstractComponent implements ClusterStat
@Override
public void clusterChanged(ClusterChangedEvent event) {
final boolean exists = event.state().metaData().indices().get(ShieldTemplateService.SHIELD_ADMIN_INDEX_NAME) != null;
final boolean exists = event.state().metaData().indices().get(ShieldTemplateService.SECURITY_INDEX_NAME) != null;
// make sure all the primaries are active
if (exists && event.state().routingTable().index(ShieldTemplateService.SHIELD_ADMIN_INDEX_NAME).allPrimaryShardsActive()) {
if (exists && event.state().routingTable().index(ShieldTemplateService.SECURITY_INDEX_NAME).allPrimaryShardsActive()) {
logger.debug("shield user index [{}] all primary shards started, so polling can start",
ShieldTemplateService.SHIELD_ADMIN_INDEX_NAME);
ShieldTemplateService.SECURITY_INDEX_NAME);
shieldIndexExists = true;
} else {
// always set the value - it may have changed...
@ -502,12 +503,11 @@ public class ESNativeUsersStore extends AbstractComponent implements ClusterStat
}
@Nullable
private UserAndPassword transformUser(Map<String, Object> sourceMap) {
private UserAndPassword transformUser(String username, Map<String, Object> sourceMap) {
if (sourceMap == null) {
return null;
}
try {
String username = (String) sourceMap.get(User.Fields.USERNAME.getPreferredName());
String password = (String) sourceMap.get(User.Fields.PASSWORD.getPreferredName());
String[] roles = ((List<String>) sourceMap.get(User.Fields.ROLES.getPreferredName())).toArray(Strings.EMPTY_ARRAY);
String fullName = (String) sourceMap.get(User.Fields.FULL_NAME.getPreferredName());
@ -529,7 +529,7 @@ public class ESNativeUsersStore extends AbstractComponent implements ClusterStat
}
if (shieldIndexExists == false) {
logger.trace("cannot poll for user changes since shield admin index [{}] does not exist", ShieldTemplateService
.SHIELD_ADMIN_INDEX_NAME);
.SECURITY_INDEX_NAME);
return;
}
@ -609,9 +609,9 @@ public class ESNativeUsersStore extends AbstractComponent implements ClusterStat
final ObjectLongMap<String> map = new ObjectLongHashMap<>();
SearchResponse response = null;
try {
SearchRequest request = client.prepareSearch(ShieldTemplateService.SHIELD_ADMIN_INDEX_NAME)
SearchRequest request = client.prepareSearch(ShieldTemplateService.SECURITY_INDEX_NAME)
.setScroll(scrollKeepAlive)
.setQuery(QueryBuilders.typeQuery(INDEX_USER_TYPE))
.setQuery(QueryBuilders.typeQuery(USER_DOC_TYPE))
.setSize(scrollSize)
.setVersion(true)
.setFetchSource(true)

View File

@ -134,7 +134,7 @@ public class ESNativeRolesStore extends AbstractComponent implements RolesStore,
} else {
query = QueryBuilders.boolQuery().filter(QueryBuilders.idsQuery(INDEX_ROLE_TYPE).addIds(rolesToGet));
}
SearchRequest request = client.prepareSearch(ShieldTemplateService.SHIELD_ADMIN_INDEX_NAME)
SearchRequest request = client.prepareSearch(ShieldTemplateService.SECURITY_INDEX_NAME)
.setScroll(scrollKeepAlive)
.setQuery(query)
.setSize(scrollSize)
@ -205,7 +205,7 @@ public class ESNativeRolesStore extends AbstractComponent implements RolesStore,
private void executeGetRoleRequest(String role, ActionListener<GetResponse> listener) {
try {
GetRequest request = client.prepareGet(ShieldTemplateService.SHIELD_ADMIN_INDEX_NAME, INDEX_ROLE_TYPE, role).request();
GetRequest request = client.prepareGet(ShieldTemplateService.SECURITY_INDEX_NAME, INDEX_ROLE_TYPE, role).request();
request.indicesOptions().ignoreUnavailable();
client.get(request, listener);
} catch (Exception e) {
@ -220,7 +220,7 @@ public class ESNativeRolesStore extends AbstractComponent implements RolesStore,
listener.onResponse(false);
}
try {
DeleteRequest request = client.prepareDelete(ShieldTemplateService.SHIELD_ADMIN_INDEX_NAME,
DeleteRequest request = client.prepareDelete(ShieldTemplateService.SECURITY_INDEX_NAME,
INDEX_ROLE_TYPE, deleteRoleRequest.role()).request();
request.indicesOptions().ignoreUnavailable();
client.delete(request, new ActionListener<DeleteResponse>() {
@ -294,7 +294,7 @@ public class ESNativeRolesStore extends AbstractComponent implements RolesStore,
listener.onResponse(false);
}
try {
IndexRequest request = client.prepareIndex(ShieldTemplateService.SHIELD_ADMIN_INDEX_NAME,
IndexRequest request = client.prepareIndex(ShieldTemplateService.SECURITY_INDEX_NAME,
INDEX_ROLE_TYPE, putRoleRequest.name())
.setSource(putRoleRequest.toXContent(jsonBuilder(), ToXContent.EMPTY_PARAMS))
.request();
@ -340,9 +340,9 @@ public class ESNativeRolesStore extends AbstractComponent implements RolesStore,
return false;
}
if (clusterState.metaData().templates().get(ShieldTemplateService.SHIELD_TEMPLATE_NAME) == null) {
if (clusterState.metaData().templates().get(ShieldTemplateService.SECURITY_TEMPLATE_NAME) == null) {
logger.debug("native roles template [{}] does not exist, so service cannot start",
ShieldTemplateService.SHIELD_TEMPLATE_NAME);
ShieldTemplateService.SECURITY_TEMPLATE_NAME);
return false;
}
// Okay to start...
@ -362,7 +362,7 @@ public class ESNativeRolesStore extends AbstractComponent implements RolesStore,
poller.doRun();
} catch (Exception e) {
logger.warn("failed to perform initial poll of roles index [{}]. scheduling again in [{}]", e,
ShieldTemplateService.SHIELD_ADMIN_INDEX_NAME, pollInterval);
ShieldTemplateService.SECURITY_INDEX_NAME, pollInterval);
}
versionChecker = threadPool.scheduleWithFixedDelay(poller, pollInterval);
state.set(State.STARTED);
@ -426,11 +426,11 @@ public class ESNativeRolesStore extends AbstractComponent implements RolesStore,
// TODO abstract this code rather than duplicating...
@Override
public void clusterChanged(ClusterChangedEvent event) {
final boolean exists = event.state().metaData().indices().get(ShieldTemplateService.SHIELD_ADMIN_INDEX_NAME) != null;
final boolean exists = event.state().metaData().indices().get(ShieldTemplateService.SECURITY_INDEX_NAME) != null;
// make sure all the primaries are active
if (exists && event.state().routingTable().index(ShieldTemplateService.SHIELD_ADMIN_INDEX_NAME).allPrimaryShardsActive()) {
if (exists && event.state().routingTable().index(ShieldTemplateService.SECURITY_INDEX_NAME).allPrimaryShardsActive()) {
logger.debug("shield roles index [{}] all primary shards started, so polling can start",
ShieldTemplateService.SHIELD_ADMIN_INDEX_NAME);
ShieldTemplateService.SECURITY_INDEX_NAME);
shieldIndexExists = true;
} else {
// always set the value - it may have changed...
@ -460,7 +460,7 @@ public class ESNativeRolesStore extends AbstractComponent implements RolesStore,
}
if (shieldIndexExists == false) {
logger.trace("cannot poll for role changes since shield admin index [{}] does not exist",
ShieldTemplateService.SHIELD_ADMIN_INDEX_NAME);
ShieldTemplateService.SECURITY_INDEX_NAME);
return;
}
@ -473,7 +473,7 @@ public class ESNativeRolesStore extends AbstractComponent implements RolesStore,
// create a copy of the keys in the cache since we will be modifying this list
final Set<String> existingRoles = new HashSet<>(roleCache.keySet());
try {
SearchRequest request = client.prepareSearch(ShieldTemplateService.SHIELD_ADMIN_INDEX_NAME)
SearchRequest request = client.prepareSearch(ShieldTemplateService.SECURITY_INDEX_NAME)
.setScroll(scrollKeepAlive)
.setQuery(QueryBuilders.typeQuery(INDEX_ROLE_TYPE))
.setSize(scrollSize)

View File

@ -119,8 +119,8 @@ public class SecurityClient {
/** User Management */
public GetUsersRequestBuilder prepareGetUsers() {
return new GetUsersRequestBuilder(client);
public GetUsersRequestBuilder prepareGetUsers(String... usernames) {
return new GetUsersRequestBuilder(client).usernames(usernames);
}
public void getUsers(GetUsersRequest request, ActionListener<GetUsersResponse> listener) {
@ -136,7 +136,7 @@ public class SecurityClient {
}
public PutUserRequestBuilder preparePutUser(String username, BytesReference source) throws IOException {
return new PutUserRequestBuilder(client).username(username).source(source);
return new PutUserRequestBuilder(client).source(username, source);
}
public PutUserRequestBuilder preparePutUser(String username, char[] password, String... roles) {

View File

@ -39,17 +39,23 @@ public class RestGetUsersAction extends BaseRestHandler {
protected void handleRequest(RestRequest request, final RestChannel channel, Client client) throws Exception {
String[] usernames = request.paramAsStringArray("username", Strings.EMPTY_ARRAY);
new SecurityClient(client).prepareGetUsers().usernames(usernames).execute(new RestBuilderListener<GetUsersResponse>(channel) {
new SecurityClient(client).prepareGetUsers(usernames).execute(new RestBuilderListener<GetUsersResponse>(channel) {
@Override
public RestResponse buildResponse(GetUsersResponse getUsersResponse, XContentBuilder builder) throws Exception {
public RestResponse buildResponse(GetUsersResponse response, XContentBuilder builder) throws Exception {
builder.startObject();
builder.field("found", getUsersResponse.hasUsers());
builder.startArray("users");
for (User user : getUsersResponse.users()) {
user.toXContent(builder, ToXContent.EMPTY_PARAMS);
for (User user : response.users()) {
builder.field(user.principal(), user);
}
builder.endArray();
builder.endObject();
// if the user asked for specific users, but none of them were found
// we'll return an empty result and 404 status code
if (usernames.length != 0 && response.users().length == 0) {
return new BytesRestResponse(RestStatus.NOT_FOUND, builder);
}
// either the user asked for all users, or at least one of the users
// was found
return new BytesRestResponse(RestStatus.OK, builder);
}
});

View File

@ -88,7 +88,7 @@ public class ClearRolesCacheTests extends ShieldIntegTestCase {
logger.debug("--> created role [{}]", role);
}
ensureGreen(ShieldTemplateService.SHIELD_ADMIN_INDEX_NAME);
ensureGreen(ShieldTemplateService.SECURITY_INDEX_NAME);
// warm up the caches on every node
for (ESNativeRolesStore rolesStore : internalCluster().getInstances(ESNativeRolesStore.class)) {
@ -134,7 +134,7 @@ public class ClearRolesCacheTests extends ShieldIntegTestCase {
List<String> toModify = randomSubsetOf(modifiedRolesCount, roles);
logger.debug("--> modifying roles {} to have run_as", toModify);
for (String role : toModify) {
UpdateResponse response = client.prepareUpdate().setId(role).setIndex(ShieldTemplateService.SHIELD_ADMIN_INDEX_NAME)
UpdateResponse response = client.prepareUpdate().setId(role).setIndex(ShieldTemplateService.SECURITY_INDEX_NAME)
.setType(ESNativeRolesStore.INDEX_ROLE_TYPE)
.setDoc("run_as", new String[] { role })
.get();
@ -177,7 +177,7 @@ public class ClearRolesCacheTests extends ShieldIntegTestCase {
List<RoleDescriptor> foundRoles = securityClient.prepareGetRoles().names(role).get().roles();
assertThat(foundRoles.size(), is(1));
logger.debug("--> deleting role [{}]", role);
DeleteResponse response = client.prepareDelete(ShieldTemplateService.SHIELD_ADMIN_INDEX_NAME,
DeleteResponse response = client.prepareDelete(ShieldTemplateService.SECURITY_INDEX_NAME,
ESNativeRolesStore.INDEX_ROLE_TYPE, role).get();
assertThat(response.isFound(), is(true));

View File

@ -52,7 +52,7 @@ public class ESNativeTests extends ShieldIntegTestCase {
public void testGettingUserThatDoesntExist() throws Exception {
SecurityClient c = securityClient();
GetUsersResponse resp = c.prepareGetUsers().usernames("joe").get();
GetUsersResponse resp = c.prepareGetUsers("joe").get();
assertFalse("user should not exist", resp.hasUsers());
GetRolesResponse resp2 = c.prepareGetRoles().names("role").get();
assertFalse("role should not exist", resp2.isExists());
@ -63,9 +63,9 @@ public class ESNativeTests extends ShieldIntegTestCase {
logger.error("--> creating user");
c.preparePutUser("joe", "s3kirt".toCharArray(), "role1", "user").get();
logger.error("--> waiting for .shield index");
ensureGreen(ShieldTemplateService.SHIELD_ADMIN_INDEX_NAME);
ensureGreen(ShieldTemplateService.SECURITY_INDEX_NAME);
logger.info("--> retrieving user");
GetUsersResponse resp = c.prepareGetUsers().usernames("joe").get();
GetUsersResponse resp = c.prepareGetUsers("joe").get();
assertTrue("user should exist", resp.hasUsers());
User joe = resp.users()[0];
assertEquals(joe.principal(), "joe");
@ -86,7 +86,7 @@ public class ESNativeTests extends ShieldIntegTestCase {
CollectionUtil.timSort(names);
assertArrayEquals(new String[] { "joe", "joe2", "joe3" }, names.toArray(Strings.EMPTY_ARRAY));
GetUsersResponse someUsersResp = c.prepareGetUsers().usernames("joe", "joe3").get();
GetUsersResponse someUsersResp = c.prepareGetUsers("joe", "joe3").get();
assertTrue("users should exist", someUsersResp.hasUsers());
assertEquals("should be 2 users returned", 2, someUsersResp.users().length);
names = new ArrayList<>(2);
@ -100,7 +100,7 @@ public class ESNativeTests extends ShieldIntegTestCase {
DeleteUserResponse delResp = c.prepareDeleteUser("joe").get();
assertTrue(delResp.found());
logger.info("--> retrieving user");
resp = c.prepareGetUsers().usernames("joe").get();
resp = c.prepareGetUsers("joe").get();
assertFalse("user should not exist after being deleted", resp.hasUsers());
}
@ -114,7 +114,7 @@ public class ESNativeTests extends ShieldIntegTestCase {
new String[]{"body", "title"}, new BytesArray("{\"query\": {\"match_all\": {}}}"))
.get();
logger.error("--> waiting for .shield index");
ensureGreen(ShieldTemplateService.SHIELD_ADMIN_INDEX_NAME);
ensureGreen(ShieldTemplateService.SECURITY_INDEX_NAME);
logger.info("--> retrieving role");
GetRolesResponse resp = c.prepareGetRoles().names("test_role").get();
assertTrue("role should exist", resp.isExists());
@ -167,9 +167,9 @@ public class ESNativeTests extends ShieldIntegTestCase {
c.preparePutUser("joe", "s3krit".toCharArray(), "test_role").get();
refresh();
logger.error("--> waiting for .shield index");
ensureGreen(ShieldTemplateService.SHIELD_ADMIN_INDEX_NAME);
ensureGreen(ShieldTemplateService.SECURITY_INDEX_NAME);
logger.info("--> retrieving user");
GetUsersResponse resp = c.prepareGetUsers().usernames("joe").get();
GetUsersResponse resp = c.prepareGetUsers("joe").get();
assertTrue("user should exist", resp.hasUsers());
createIndex("idx");
@ -189,9 +189,9 @@ public class ESNativeTests extends ShieldIntegTestCase {
c.preparePutUser("joe", "s3krit".toCharArray(), ShieldSettingsSource.DEFAULT_ROLE).get();
refresh();
logger.error("--> waiting for .shield index");
ensureGreen(ShieldTemplateService.SHIELD_ADMIN_INDEX_NAME);
ensureGreen(ShieldTemplateService.SECURITY_INDEX_NAME);
logger.info("--> retrieving user");
GetUsersResponse resp = c.prepareGetUsers().usernames("joe").get();
GetUsersResponse resp = c.prepareGetUsers("joe").get();
assertTrue("user should exist", resp.hasUsers());
assertThat(resp.users()[0].roles(), arrayContaining(ShieldSettingsSource.DEFAULT_ROLE));
@ -225,9 +225,9 @@ public class ESNativeTests extends ShieldIntegTestCase {
c.preparePutUser("joe", "s3krit".toCharArray(), ShieldSettingsSource.DEFAULT_ROLE).get();
refresh();
logger.error("--> waiting for .shield index");
ensureGreen(ShieldTemplateService.SHIELD_ADMIN_INDEX_NAME);
ensureGreen(ShieldTemplateService.SECURITY_INDEX_NAME);
logger.info("--> retrieving user");
GetUsersResponse resp = c.prepareGetUsers().usernames("joe").get();
GetUsersResponse resp = c.prepareGetUsers("joe").get();
assertTrue("user should exist", resp.hasUsers());
assertThat(resp.users()[0].roles(), arrayContaining(ShieldSettingsSource.DEFAULT_ROLE));
@ -264,7 +264,7 @@ public class ESNativeTests extends ShieldIntegTestCase {
c.preparePutUser("joe", "s3krit".toCharArray(), "test_role").get();
refresh();
logger.error("--> waiting for .shield index");
ensureGreen(ShieldTemplateService.SHIELD_ADMIN_INDEX_NAME);
ensureGreen(ShieldTemplateService.SECURITY_INDEX_NAME);
if (authenticate) {
final String token = basicAuthHeaderValue("joe", new SecuredString("s3krit".toCharArray()));
@ -311,7 +311,7 @@ public class ESNativeTests extends ShieldIntegTestCase {
c.preparePutUser("joe", "s3krit".toCharArray(), "test_role").get();
refresh();
logger.error("--> waiting for .shield index");
ensureGreen(ShieldTemplateService.SHIELD_ADMIN_INDEX_NAME);
ensureGreen(ShieldTemplateService.SECURITY_INDEX_NAME);
final String token = basicAuthHeaderValue("joe", new SecuredString("s3krit".toCharArray()));
ClusterHealthResponse response = client().filterWithHeader(Collections.singletonMap("Authorization", token)).admin().cluster()

View File

@ -7,8 +7,8 @@
"paths": [ "/_shield/user/{username}" ],
"parts": {
"username": {
"type" : "string",
"description" : "The username of the User",
"type" : "list",
"description" : "A comma-separated list of usernames",
"required" : false
}
},

View File

@ -12,7 +12,6 @@
username: "joe"
body: >
{
"username" : "joe",
"password" : "s3krit",
"roles" : [ "admin" ],
"full_name" : "Bazooka Joe",
@ -33,10 +32,9 @@
- do:
shield.get_user:
username: "joe"
- match: { found: true }
- match: { users.0.username: "joe" }
- match: { users.0.roles.0: "admin" }
- match: { users.0.full_name: "Bazooka Joe" }
- match: { users.0.email: "joe@bazooka.gum" }
- match: { users.0.metadata.key1: "val1" }
- match: { users.0.metadata.key2: "val2" }
- match: { joe.username: "joe" }
- match: { joe.roles.0: "admin" }
- match: { joe.full_name: "Bazooka Joe" }
- match: { joe.email: "joe@bazooka.gum" }
- match: { joe.metadata.key1: "val1" }
- match: { joe.metadata.key2: "val2" }

View File

@ -12,7 +12,6 @@
username: "joe"
body: >
{
"username": "joe",
"password": "s3krit",
"roles" : [ "admin" ]
}
@ -21,9 +20,8 @@
- do:
shield.get_user:
username: "joe"
- match: { found: true }
- match: { users.0.username: "joe" }
- match: { users.0.roles.0: "admin" }
- match: { joe.username: "joe" }
- match: { joe.roles.0: "admin" }
- do:
headers:
@ -36,7 +34,6 @@
username: "joe"
body: >
{
"username" : "joe",
"password" : "s3krit2",
"roles" : [ "admin", "foo" ],
"full_name" : "Bazooka Joe",
@ -51,14 +48,13 @@
- do:
shield.get_user:
username: "joe"
- match: { found: true }
- match: { users.0.username: "joe" }
- match: { users.0.roles.0: "admin" }
- match: { users.0.roles.1: "foo" }
- match: { users.0.full_name: "Bazooka Joe" }
- match: { users.0.email: "joe@bazooka.gum" }
- match: { users.0.metadata.key1: "val1" }
- match: { users.0.metadata.key2: "val2" }
- match: { joe.username: "joe" }
- match: { joe.roles.0: "admin" }
- match: { joe.roles.1: "foo" }
- match: { joe.full_name: "Bazooka Joe" }
- match: { joe.email: "joe@bazooka.gum" }
- match: { joe.metadata.key1: "val1" }
- match: { joe.metadata.key2: "val2" }
- do:
headers:

View File

@ -0,0 +1,12 @@
"Get missing user":
- do:
catch: missing
shield.get_user:
username: 'foo'
---
"Get missing (multiple) users":
- do:
catch: missing
shield.get_user:
username: [ 'foo', 'bar' ]