HLRC: Add get users action (#36332)

This commit adds get user action to the high level rest client.
This commit is contained in:
Nick Knize 2018-12-13 12:24:48 -06:00 committed by GitHub
parent b820d7c617
commit 4b17055035
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 607 additions and 12 deletions

View File

@ -50,6 +50,8 @@ import org.elasticsearch.client.security.GetSslCertificatesRequest;
import org.elasticsearch.client.security.GetSslCertificatesResponse;
import org.elasticsearch.client.security.GetUserPrivilegesRequest;
import org.elasticsearch.client.security.GetUserPrivilegesResponse;
import org.elasticsearch.client.security.GetUsersRequest;
import org.elasticsearch.client.security.GetUsersResponse;
import org.elasticsearch.client.security.HasPrivilegesRequest;
import org.elasticsearch.client.security.HasPrivilegesResponse;
import org.elasticsearch.client.security.InvalidateTokenRequest;
@ -81,6 +83,33 @@ public final class SecurityClient {
this.restHighLevelClient = restHighLevelClient;
}
/**
* Get a user, or list of users, in the native realm synchronously.
* See <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/security-api-get-user.html">
* the docs</a> for more information.
* @param request the request with the user's name
* @param options the request options (e.g., headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
* @return the response from the get users call
* @throws IOException in case there is a problem sending the request or parsing back the response
*/
public GetUsersResponse getUsers(GetUsersRequest request, RequestOptions options) throws IOException {
return restHighLevelClient.performRequestAndParseEntity(request, SecurityRequestConverters::getUsers, options,
GetUsersResponse::fromXContent, emptySet());
}
/**
* Get a user, or list of users, in the native realm asynchronously.
* See <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/security-api-get-user.html">
* the docs</a> for more information.
* @param request the request with the user's name
* @param options the request options (e.g., headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
* @param listener the listener to be notified upon request completion
*/
public void getUsersAsync(GetUsersRequest request, RequestOptions options, ActionListener<GetUsersResponse> listener) {
restHighLevelClient.performRequestAsyncAndParseEntity(request, SecurityRequestConverters::getUsers, options,
GetUsersResponse::fromXContent, listener, emptySet());
}
/**
* Create/update a user in the native realm synchronously.
* See <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/security-api-users.html">

View File

@ -36,6 +36,7 @@ import org.elasticsearch.client.security.EnableUserRequest;
import org.elasticsearch.client.security.GetPrivilegesRequest;
import org.elasticsearch.client.security.GetRoleMappingsRequest;
import org.elasticsearch.client.security.GetRolesRequest;
import org.elasticsearch.client.security.GetUsersRequest;
import org.elasticsearch.client.security.HasPrivilegesRequest;
import org.elasticsearch.client.security.InvalidateTokenRequest;
import org.elasticsearch.client.security.PutPrivilegesRequest;
@ -67,6 +68,15 @@ final class SecurityRequestConverters {
return request;
}
static Request getUsers(GetUsersRequest getUsersRequest) {
RequestConverters.EndpointBuilder builder = new RequestConverters.EndpointBuilder()
.addPathPartAsIs("_security/user");
if (getUsersRequest.getUsernames().size() > 0) {
builder.addPathPart(Strings.collectionToCommaDelimitedString(getUsersRequest.getUsernames()));
}
return new Request(HttpGet.METHOD_NAME, builder.build());
}
static Request putUser(PutUserRequest putUserRequest) throws IOException {
String endpoint = new RequestConverters.EndpointBuilder()
.addPathPartAsIs("_security/user")

View File

@ -0,0 +1,58 @@
/*
* Licensed to Elasticsearch under one or more contributor
* license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright
* ownership. Elasticsearch licenses this file to you under
* the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.elasticsearch.client.security;
import org.elasticsearch.client.Validatable;
import org.elasticsearch.common.util.set.Sets;
import java.util.Collections;
import java.util.Objects;
import java.util.Set;
/**
* Request object to retrieve users from the native realm
*/
public class GetUsersRequest implements Validatable {
private final Set<String> usernames;
public GetUsersRequest(final String... usernames) {
if (usernames != null) {
this.usernames = Collections.unmodifiableSet(Sets.newHashSet(usernames));
} else {
this.usernames = Collections.emptySet();
}
}
public Set<String> getUsernames() {
return usernames;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof GetUsersRequest)) return false;
GetUsersRequest that = (GetUsersRequest) o;
return Objects.equals(usernames, that.usernames);
}
@Override
public int hashCode() {
return Objects.hash(usernames);
}
}

View File

@ -0,0 +1,134 @@
/*
* Licensed to Elasticsearch under one or more contributor
* license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright
* ownership. Elasticsearch licenses this file to you under
* the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.elasticsearch.client.security;
import org.elasticsearch.client.security.user.User;
import org.elasticsearch.common.Nullable;
import org.elasticsearch.common.ParseField;
import org.elasticsearch.common.xcontent.ConstructingObjectParser;
import org.elasticsearch.common.xcontent.XContentParser;
import org.elasticsearch.common.xcontent.XContentParser.Token;
import org.elasticsearch.common.xcontent.XContentParserUtils;
import java.io.IOException;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import static org.elasticsearch.common.xcontent.ConstructingObjectParser.constructorArg;
import static org.elasticsearch.common.xcontent.ConstructingObjectParser.optionalConstructorArg;
/**
* Response when requesting zero or more users.
* Returns a List of {@link User} objects
*/
public class GetUsersResponse {
private final Set<User> users;
private final Set<User> enabledUsers;
public GetUsersResponse(Set<User> users, Set<User> enabledUsers) {
this.users = Collections.unmodifiableSet(users);
this.enabledUsers = Collections.unmodifiableSet(enabledUsers);
}
public Set<User> getUsers() {
return users;
}
public Set<User> getEnabledUsers() {
return enabledUsers;
}
public static GetUsersResponse fromXContent(XContentParser parser) throws IOException {
XContentParserUtils.ensureExpectedToken(Token.START_OBJECT, parser.nextToken(), parser::getTokenLocation);
final Set<User> users = new HashSet<>();
final Set<User> enabledUsers = new HashSet<>();
Token token;
while ((token = parser.nextToken()) != Token.END_OBJECT) {
XContentParserUtils.ensureExpectedToken(Token.FIELD_NAME, token, parser::getTokenLocation);
ParsedUser parsedUser = USER_PARSER.parse(parser, parser.currentName());
users.add(parsedUser.user);
if (parsedUser.enabled) {
enabledUsers.add(parsedUser.user);
}
}
return new GetUsersResponse(users, enabledUsers);
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof GetUsersResponse)) return false;
GetUsersResponse that = (GetUsersResponse) o;
return Objects.equals(users, that.users);
}
@Override
public int hashCode() {
return Objects.hash(users);
}
public static final ParseField USERNAME = new ParseField("username");
public static final ParseField ROLES = new ParseField("roles");
public static final ParseField FULL_NAME = new ParseField("full_name");
public static final ParseField EMAIL = new ParseField("email");
public static final ParseField METADATA = new ParseField("metadata");
public static final ParseField ENABLED = new ParseField("enabled");
@SuppressWarnings("unchecked")
public static final ConstructingObjectParser<ParsedUser, String> USER_PARSER = new ConstructingObjectParser<>("user_info",
(constructorObjects) -> {
int i = 0;
final String username = (String) constructorObjects[i++];
final Collection<String> roles = (Collection<String>) constructorObjects[i++];
final Map<String, Object> metadata = (Map<String, Object>) constructorObjects[i++];
final Boolean enabled = (Boolean) constructorObjects[i++];
final String fullName = (String) constructorObjects[i++];
final String email = (String) constructorObjects[i++];
return new ParsedUser(username, roles, metadata, enabled, fullName, email);
});
static {
USER_PARSER.declareString(constructorArg(), USERNAME);
USER_PARSER.declareStringArray(constructorArg(), ROLES);
USER_PARSER.declareObject(constructorArg(), (parser, c) -> parser.map(), METADATA);
USER_PARSER.declareBoolean(constructorArg(), ENABLED);
USER_PARSER.declareStringOrNull(optionalConstructorArg(), FULL_NAME);
USER_PARSER.declareStringOrNull(optionalConstructorArg(), EMAIL);
}
protected static final class ParsedUser {
protected User user;
protected boolean enabled;
public ParsedUser(String username, Collection<String> roles, Map<String, Object> metadata, Boolean enabled,
@Nullable String fullName, @Nullable String email) {
String checkedUsername = username = Objects.requireNonNull(username, "`username` is required, cannot be null");
Collection<String> checkedRoles = Collections.unmodifiableSet(new HashSet<>(
Objects.requireNonNull(roles, "`roles` is required, cannot be null. Pass an empty Collection instead.")));
Map<String, Object> checkedMetadata = Collections
.unmodifiableMap(Objects.requireNonNull(metadata, "`metadata` is required, cannot be null. Pass an empty map instead."));
this.user = new User(checkedUsername, checkedRoles, checkedMetadata, fullName, email);
this.enabled = enabled;
}
}
}

View File

@ -29,7 +29,6 @@ import java.util.Map;
import java.util.Objects;
import java.util.Set;
/**
* A user to be utilized with security APIs.
* Can be an existing authenticated user or it can be a new user to be enrolled to the native realm.

View File

@ -28,6 +28,8 @@ import org.elasticsearch.client.security.DeleteUserRequest;
import org.elasticsearch.client.security.DeleteUserResponse;
import org.elasticsearch.client.security.GetRolesRequest;
import org.elasticsearch.client.security.GetRolesResponse;
import org.elasticsearch.client.security.GetUsersRequest;
import org.elasticsearch.client.security.GetUsersResponse;
import org.elasticsearch.client.security.PutRoleRequest;
import org.elasticsearch.client.security.PutRoleResponse;
import org.elasticsearch.client.security.PutUserRequest;
@ -42,6 +44,7 @@ import org.elasticsearch.client.security.user.privileges.IndicesPrivilegesTests;
import org.elasticsearch.client.security.user.privileges.Role;
import org.elasticsearch.common.CharArrays;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Base64;
import java.util.HashMap;
@ -74,6 +77,22 @@ public class SecurityIT extends ESRestHighLevelClientTestCase {
highLevelClient().getLowLevelClient().performRequest(deleteUserRequest);
}
public void testGetUser() throws Exception {
final SecurityClient securityClient = highLevelClient().security();
// create user
final PutUserRequest putUserRequest = randomPutUserRequest(randomBoolean());
final PutUserResponse putUserResponse = execute(putUserRequest, securityClient::putUser, securityClient::putUserAsync);
// assert user created
assertThat(putUserResponse.isCreated(), is(true));
// get user
final GetUsersRequest getUsersRequest = new GetUsersRequest(putUserRequest.getUser().getUsername());
final GetUsersResponse getUsersResponse = execute(getUsersRequest, securityClient::getUsers, securityClient::getUsersAsync);
// assert user was correctly retrieved
ArrayList<User> users = new ArrayList<>();
users.addAll(getUsersResponse.getUsers());
assertThat(users.get(0), is(putUserRequest.getUser()));
}
public void testAuthenticate() throws Exception {
final SecurityClient securityClient = highLevelClient().security();
// test fixture: put enabled user
@ -89,6 +108,15 @@ public class SecurityIT extends ESRestHighLevelClientTestCase {
assertThat(authenticateResponse.getUser(), is(putUserRequest.getUser()));
assertThat(authenticateResponse.enabled(), is(true));
// get user
final GetUsersRequest getUsersRequest =
new GetUsersRequest(putUserRequest.getUser().getUsername());
final GetUsersResponse getUsersResponse =
execute(getUsersRequest, securityClient::getUsers, securityClient::getUsersAsync);
ArrayList<User> users = new ArrayList<>();
users.addAll(getUsersResponse.getUsers());
assertThat(users.get(0), is(putUserRequest.getUser()));
// delete user
final DeleteUserRequest deleteUserRequest =
new DeleteUserRequest(putUserRequest.getUser().getUsername(), putUserRequest.getRefreshPolicy());

View File

@ -34,6 +34,7 @@ import org.elasticsearch.client.security.EnableUserRequest;
import org.elasticsearch.client.security.GetPrivilegesRequest;
import org.elasticsearch.client.security.GetRoleMappingsRequest;
import org.elasticsearch.client.security.GetRolesRequest;
import org.elasticsearch.client.security.GetUsersRequest;
import org.elasticsearch.client.security.PutPrivilegesRequest;
import org.elasticsearch.client.security.PutRoleMappingRequest;
import org.elasticsearch.client.security.PutRoleRequest;
@ -101,6 +102,21 @@ public class SecurityRequestConvertersTests extends ESTestCase {
assertNull(request.getEntity());
}
public void testGetUsers() {
final String[] users = randomArray(0, 5, String[]::new, () -> randomAlphaOfLength(5));
GetUsersRequest getUsersRequest = new GetUsersRequest(users);
Request request = SecurityRequestConverters.getUsers(getUsersRequest);
assertEquals(HttpGet.METHOD_NAME, request.getMethod());
if (users.length == 0) {
assertEquals("/_security/user", request.getEndpoint());
} else {
assertEquals("/_security/user/" + Strings.collectionToCommaDelimitedString(getUsersRequest.getUsernames()),
request.getEndpoint());
}
assertNull(request.getEntity());
assertEquals(Collections.emptyMap(), request.getParameters());
}
public void testPutRoleMapping() throws IOException {
final String username = randomAlphaOfLengthBetween(4, 7);
final String rolename = randomAlphaOfLengthBetween(4, 7);

View File

@ -54,6 +54,8 @@ import org.elasticsearch.client.security.GetRolesRequest;
import org.elasticsearch.client.security.GetRolesResponse;
import org.elasticsearch.client.security.GetSslCertificatesResponse;
import org.elasticsearch.client.security.GetUserPrivilegesResponse;
import org.elasticsearch.client.security.GetUsersRequest;
import org.elasticsearch.client.security.GetUsersResponse;
import org.elasticsearch.client.security.HasPrivilegesRequest;
import org.elasticsearch.client.security.HasPrivilegesResponse;
import org.elasticsearch.client.security.InvalidateTokenRequest;
@ -109,6 +111,96 @@ import static org.hamcrest.Matchers.nullValue;
public class SecurityDocumentationIT extends ESRestHighLevelClientTestCase {
public void testGetUsers() throws Exception {
final RestHighLevelClient client = highLevelClient();
String[] usernames = new String[] {"user1", "user2", "user3"};
addUser(client, usernames[0], randomAlphaOfLength(4));
addUser(client, usernames[1], randomAlphaOfLength(4));
addUser(client, usernames[2], randomAlphaOfLength(4));
{
//tag::get-users-request
GetUsersRequest request = new GetUsersRequest(usernames[0]);
//end::get-users-request
//tag::get-users-execute
GetUsersResponse response = client.security().getUsers(request, RequestOptions.DEFAULT);
//end::get-users-execute
//tag::get-users-response
List<User> users = new ArrayList<>(1);
users.addAll(response.getUsers());
//end::get-users-response
assertNotNull(response);
assertThat(users.size(), equalTo(1));
assertThat(users.get(0), is(usernames[0]));
}
{
//tag::get-users-list-request
GetUsersRequest request = new GetUsersRequest(usernames);
GetUsersResponse response = client.security().getUsers(request, RequestOptions.DEFAULT);
//end::get-users-list-request
List<User> users = new ArrayList<>(3);
users.addAll(response.getUsers());
assertNotNull(response);
assertThat(users.size(), equalTo(3));
assertThat(users.get(0).getUsername(), equalTo(usernames[0]));
assertThat(users.get(1).getUsername(), equalTo(usernames[1]));
assertThat(users.get(2).getUsername(), equalTo(usernames[2]));
assertThat(users.size(), equalTo(3));
}
{
//tag::get-users-all-request
GetUsersRequest request = new GetUsersRequest();
GetUsersResponse response = client.security().getUsers(request, RequestOptions.DEFAULT);
//end::get-users-all-request
List<User> users = new ArrayList<>(3);
users.addAll(response.getUsers());
assertNotNull(response);
// 4 system users plus the three we created
assertThat(users.size(), equalTo(7));
}
{
GetUsersRequest request = new GetUsersRequest(usernames[0]);
ActionListener<GetUsersResponse> listener;
//tag::get-roles-execute-listener
listener = new ActionListener<GetUsersResponse>() {
@Override
public void onResponse(GetUsersResponse getRolesResponse) {
// <1>
}
@Override
public void onFailure(Exception e) {
// <2>
}
};
//end::get-users-execute-listener
assertNotNull(listener);
// Replace the empty listener by a blocking listener in test
final PlainActionFuture<GetUsersResponse> future = new PlainActionFuture<>();
listener = future;
//tag::get-users-execute-async
client.security().getUsersAsync(request, RequestOptions.DEFAULT, listener); // <1>
//end::get-users-execute-async
final GetUsersResponse response = future.get(30, TimeUnit.SECONDS);
List<User> users = new ArrayList<>(1);
users.addAll(response.getUsers());
assertNotNull(response);
assertThat(users.size(), equalTo(1));
assertThat(users.get(0).getUsername(), equalTo(usernames[0]));
}
}
public void testPutUser() throws Exception {
RestHighLevelClient client = highLevelClient();

View File

@ -38,12 +38,12 @@ public class AuthenticateResponseTests extends ESTestCase {
public void testFromXContent() throws IOException {
xContentTester(
this::createParser,
this::createTestInstance,
this::toXContent,
AuthenticateResponse::fromXContent)
.supportsUnknownFields(false)
.test();
this::createParser,
this::createTestInstance,
this::toXContent,
AuthenticateResponse::fromXContent)
.supportsUnknownFields(false)
.test();
}
public void testEqualsAndHashCode() {
@ -108,7 +108,7 @@ public class AuthenticateResponseTests extends ESTestCase {
private AuthenticateResponse copy(AuthenticateResponse response) {
final User originalUser = response.getUser();
final User copyUser = new User(originalUser.getUsername(), originalUser.getRoles(), originalUser.getMetadata(),
originalUser.getFullName(), originalUser.getEmail());
originalUser.getFullName(), originalUser.getEmail());
return new AuthenticateResponse(copyUser, response.enabled(), response.getAuthenticationRealm(),
response.getLookupRealm());
}
@ -117,9 +117,9 @@ public class AuthenticateResponseTests extends ESTestCase {
final User originalUser = response.getUser();
switch (randomIntBetween(1, 8)) {
case 1:
return new AuthenticateResponse(new User(originalUser.getUsername() + "wrong", originalUser.getRoles(),
return new AuthenticateResponse(new User(originalUser.getUsername() + "wrong", originalUser.getRoles(),
originalUser.getMetadata(), originalUser.getFullName(), originalUser.getEmail()), response.enabled(),
response.getAuthenticationRealm(), response.getLookupRealm());
response.getAuthenticationRealm(), response.getLookupRealm());
case 2:
final Collection<String> wrongRoles = new ArrayList<>(originalUser.getRoles());
wrongRoles.add(randomAlphaOfLengthBetween(1, 4));
@ -134,11 +134,11 @@ public class AuthenticateResponseTests extends ESTestCase {
response.getLookupRealm());
case 4:
return new AuthenticateResponse(new User(originalUser.getUsername(), originalUser.getRoles(), originalUser.getMetadata(),
originalUser.getFullName() + "wrong", originalUser.getEmail()), response.enabled(),
originalUser.getFullName() + "wrong", originalUser.getEmail()), response.enabled(),
response.getAuthenticationRealm(), response.getLookupRealm());
case 5:
return new AuthenticateResponse(new User(originalUser.getUsername(), originalUser.getRoles(), originalUser.getMetadata(),
originalUser.getFullName(), originalUser.getEmail() + "wrong"), response.enabled(),
originalUser.getFullName(), originalUser.getEmail() + "wrong"), response.enabled(),
response.getAuthenticationRealm(), response.getLookupRealm());
case 6:
return new AuthenticateResponse(new User(originalUser.getUsername(), originalUser.getRoles(), originalUser.getMetadata(),

View File

@ -0,0 +1,53 @@
/*
* Licensed to Elasticsearch under one or more contributor
* license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright
* ownership. Elasticsearch licenses this file to you under
* the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.elasticsearch.client.security;
import org.elasticsearch.test.ESTestCase;
import org.elasticsearch.test.EqualsHashCodeTestUtils;
import static org.hamcrest.Matchers.containsInAnyOrder;
import static org.hamcrest.Matchers.equalTo;
public class GetUsersRequestTests extends ESTestCase {
public void testGetUsersRequest() {
final String[] users = randomArray(0, 5, String[]::new, () -> randomAlphaOfLength(5));
GetUsersRequest getUsersRequest = new GetUsersRequest(users);
assertThat(getUsersRequest.getUsernames().size(), equalTo(users.length));
assertThat(getUsersRequest.getUsernames(), containsInAnyOrder(users));
}
public void testEqualsHashCode() {
final String[] users = randomArray(0, 5, String[]::new, () -> randomAlphaOfLength(5));
final GetUsersRequest getUsersRequest = new GetUsersRequest(users);
assertNotNull(getUsersRequest);
EqualsHashCodeTestUtils.checkEqualsAndHashCode(getUsersRequest, (original) -> {
return new GetUsersRequest(original.getUsernames().toArray(new String[0]));
});
EqualsHashCodeTestUtils.checkEqualsAndHashCode(getUsersRequest, (original) -> {
return new GetUsersRequest(original.getUsernames().toArray(new String[0]));
}, GetUsersRequestTests::mutateTestItem);
}
private static GetUsersRequest mutateTestItem(GetUsersRequest original) {
final int minRoles = original.getUsernames().isEmpty() ? 1 : 0;
return new GetUsersRequest(randomArray(minRoles, 5, String[]::new, () -> randomAlphaOfLength(6)));
}
}

View File

@ -0,0 +1,126 @@
/*
* Licensed to Elasticsearch under one or more contributor
* license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright
* ownership. Elasticsearch licenses this file to you under
* the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.elasticsearch.client.security;
import org.elasticsearch.client.security.user.User;
import org.elasticsearch.common.xcontent.DeprecationHandler;
import org.elasticsearch.common.xcontent.NamedXContentRegistry;
import org.elasticsearch.common.xcontent.XContentType;
import org.elasticsearch.test.ESTestCase;
import org.elasticsearch.test.EqualsHashCodeTestUtils;
import java.io.IOException;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;
import static org.hamcrest.Matchers.equalTo;
/** tests the Response for getting users from the security HLRC */
public class GetUsersResponseTests extends ESTestCase {
public void testFromXContent() throws IOException {
String json =
"{\n" +
" \"jacknich\": {\n" +
" \"username\": \"jacknich\",\n" +
" \"roles\": [\n" +
" \"admin\", \"other_role1\"\n" +
" ],\n" +
" \"full_name\": \"Jack Nicholson\",\n" +
" \"email\": \"jacknich@example.com\",\n" +
" \"metadata\": { \"intelligence\" : 7 },\n" +
" \"enabled\": true\n" +
" }\n" +
"}";
final GetUsersResponse response = GetUsersResponse.fromXContent((XContentType.JSON.xContent().createParser(
new NamedXContentRegistry(Collections.emptyList()), new DeprecationHandler() {
@Override
public void usedDeprecatedName(String usedName, String modernName) {
}
@Override
public void usedDeprecatedField(String usedName, String replacedWith) {
}
}, json)));
assertThat(response.getUsers().size(), equalTo(1));
final User user = response.getUsers().iterator().next();
assertThat(user.getUsername(), equalTo("jacknich"));
assertThat(user.getRoles().size(), equalTo(2));
assertThat(user.getFullName(), equalTo("Jack Nicholson"));
assertThat(user.getEmail(), equalTo("jacknich@example.com"));
final Map<String, Object> metadata = new HashMap<>();
metadata.put("intelligence", 7);
assertThat(metadata, equalTo(user.getMetadata()));
}
public void testEqualsHashCode() {
final Set<User> users = new HashSet<>();
final Set<User> enabledUsers = new HashSet<>();
Map<String, Object> metadata = new HashMap<>();
metadata.put("intelligence", 1);
final User user1 = new User("testUser1", Arrays.asList(new String[] {"admin", "other_role1"}),
metadata, "Test User 1", null);
users.add(user1);
enabledUsers.add(user1);
Map<String, Object> metadata2 = new HashMap<>();
metadata2.put("intelligence", 9);
metadata2.put("specialty", "geo");
final User user2 = new User("testUser2", Arrays.asList(new String[] {"admin"}),
metadata, "Test User 2", "testuser2@example.com");
users.add(user2);
enabledUsers.add(user2);
final GetUsersResponse getUsersResponse = new GetUsersResponse(users, enabledUsers);
assertNotNull(getUsersResponse);
EqualsHashCodeTestUtils.checkEqualsAndHashCode(getUsersResponse, (original) -> {
return new GetUsersResponse(original.getUsers(), original.getEnabledUsers());
});
EqualsHashCodeTestUtils.checkEqualsAndHashCode(getUsersResponse, (original) -> {
return new GetUsersResponse(original.getUsers(), original.getEnabledUsers());
}, GetUsersResponseTests::mutateTestItem);
}
private static GetUsersResponse mutateTestItem(GetUsersResponse original) {
if (randomBoolean()) {
final Set<User> users = new HashSet<>();
final Set<User> enabledUsers = new HashSet<>();
Map<String, Object> metadata = new HashMap<>();
metadata.put("intelligence", 1);
final User user1 = new User("testUser1", Arrays.asList(new String[] {"admin", "other_role1"}),
metadata, "Test User 1", null);
users.add(user1);
enabledUsers.add(user1);
return new GetUsersResponse(users, enabledUsers);
}
Map<String, Object> metadata = new HashMap<>();
metadata.put("intelligence", 5); // change intelligence
final User user1 = new User("testUser1", Arrays.asList(new String[] {"admin", "other_role1"}),
metadata, "Test User 1", null);
Set<User> newUsers = original.getUsers().stream().collect(Collectors.toSet());
Set<User> enabledUsers = original.getEnabledUsers().stream().collect(Collectors.toSet());
newUsers.clear();
enabledUsers.clear();
newUsers.add(user1);
enabledUsers.add(user1);
return new GetUsersResponse(newUsers, enabledUsers);
}
}

View File

@ -0,0 +1,48 @@
--
:api: get-users
:request: GetUsersRequest
:respnse: GetUsersResponse
--
[id="{upid}-{api}"]
=== Get Users API
[id="{upid}-{api}-request"]
==== Get Users Request
Retrieving a user can be performed using the `security().getUsers()`
method and by setting the username on +{request}+:
["source","java",subs="attributes,callouts,macros"]
--------------------------------------------------
include-tagged::{doc-tests-file}[{api}-request]
--------------------------------------------------
Retrieving multiple users can be performed using the `security().getUsers()`
method and by setting multiple usernames on +{request}+:
["source","java",subs="attributes,callouts,macros"]
--------------------------------------------------
include-tagged::{doc-tests-file}[{api}-list-request]
--------------------------------------------------
Retrieving all users can be performed using the `security().getUsers()`
method without specifying any usernames on +{request}+:
["source","java",subs="attributes,callouts,macros"]
--------------------------------------------------
include-tagged::{doc-tests-file}[{api}-all-request]
--------------------------------------------------
include::../execution.asciidoc[]
[id="{upid}-{api}-response"]
==== Get Users Response
The returned +{response}+ allows getting information about the retrieved users as follows.
["source","java",subs="attributes,callouts,macros"]
--------------------------------------------------
include-tagged::{doc-tests-file}[{api}-response]
--------------------------------------------------

View File

@ -387,6 +387,7 @@ include::rollup/get_rollup_index_caps.asciidoc[]
The Java High Level REST Client supports the following Security APIs:
* <<java-rest-high-security-put-user>>
* <<{upid}-get-users>>
* <<{upid}-delete-user>>
* <<java-rest-high-security-enable-user>>
* <<java-rest-high-security-disable-user>>
@ -410,6 +411,7 @@ The Java High Level REST Client supports the following Security APIs:
* <<{upid}-delete-privileges>>
include::security/put-user.asciidoc[]
include::security/get-users.asciidoc[]
include::security/delete-user.asciidoc[]
include::security/enable-user.asciidoc[]
include::security/disable-user.asciidoc[]