[HLRC] Add support for get roles API (#35787)

This commits adds support for the Get Roles API to the HLRC

Relates: #29827
This commit is contained in:
Ioannis Kakavas 2018-11-26 11:25:07 +02:00 committed by GitHub
parent dfd93deabe
commit 8daa854f90
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 676 additions and 53 deletions

View File

@ -42,6 +42,8 @@ import org.elasticsearch.client.security.GetPrivilegesRequest;
import org.elasticsearch.client.security.GetPrivilegesResponse;
import org.elasticsearch.client.security.GetRoleMappingsRequest;
import org.elasticsearch.client.security.GetRoleMappingsResponse;
import org.elasticsearch.client.security.GetRolesRequest;
import org.elasticsearch.client.security.GetRolesResponse;
import org.elasticsearch.client.security.GetSslCertificatesRequest;
import org.elasticsearch.client.security.GetSslCertificatesResponse;
import org.elasticsearch.client.security.HasPrivilegesRequest;
@ -407,6 +409,35 @@ public final class SecurityClient {
DeleteRoleMappingResponse::fromXContent, emptySet());
}
/**
* Asynchronously retrieves roles from the native roles store.
* See <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/security-api-get-role.html">
* the docs</a> for more.
*
* @param request the request with the roles to get
* @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 getRolesAsync(GetRolesRequest request, RequestOptions options, ActionListener<GetRolesResponse> listener) {
restHighLevelClient.performRequestAsyncAndParseEntity(request, SecurityRequestConverters::getRoles, options,
GetRolesResponse::fromXContent, listener, emptySet());
}
/**
* Retrieves roles from the native roles store.
* See <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/security-api-get-role.html">
* the docs</a> for more.
*
* @param request the request with the roles to get
* @param options the request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
* @return the response from the delete role call
* @throws IOException in case there is a problem sending the request or parsing back the response
*/
public GetRolesResponse getRoles(final GetRolesRequest request, final RequestOptions options) throws IOException {
return restHighLevelClient.performRequestAndParseEntity(request, SecurityRequestConverters::getRoles, options,
GetRolesResponse::fromXContent, emptySet());
}
/**
* Asynchronously delete a role mapping.
* See <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/security-api-delete-role-mapping.html">

View File

@ -32,6 +32,7 @@ import org.elasticsearch.client.security.GetPrivilegesRequest;
import org.elasticsearch.client.security.DeleteRoleMappingRequest;
import org.elasticsearch.client.security.DeleteRoleRequest;
import org.elasticsearch.client.security.InvalidateTokenRequest;
import org.elasticsearch.client.security.GetRolesRequest;
import org.elasticsearch.client.security.PutRoleMappingRequest;
import org.elasticsearch.client.security.HasPrivilegesRequest;
import org.elasticsearch.client.security.DisableUserRequest;
@ -170,6 +171,15 @@ final class SecurityRequestConverters {
return request;
}
static Request getRoles(GetRolesRequest getRolesRequest) {
RequestConverters.EndpointBuilder builder = new RequestConverters.EndpointBuilder();
builder.addPathPartAsIs("_xpack/security/role");
if (getRolesRequest.getRoleNames().size() > 0) {
builder.addPathPart(Strings.collectionToCommaDelimitedString(getRolesRequest.getRoleNames()));
}
return new Request(HttpGet.METHOD_NAME, builder.build());
}
static Request createToken(CreateTokenRequest createTokenRequest) throws IOException {
Request request = new Request(HttpPost.METHOD_NAME, "/_xpack/security/oauth2/token");
request.setEntity(createEntity(createTokenRequest, REQUEST_BODY_CONTENT_TYPE));

View File

@ -0,0 +1,64 @@
/*
* 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 roles from the native roles store
*/
public final class GetRolesRequest implements Validatable {
private final Set<String> roleNames;
public GetRolesRequest(final String... roleNames) {
if (roleNames != null) {
this.roleNames = Collections.unmodifiableSet(Sets.newHashSet(roleNames));
} else {
this.roleNames = Collections.emptySet();
}
}
public Set<String> getRoleNames() {
return roleNames;
}
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
final GetRolesRequest that = (GetRolesRequest) o;
return Objects.equals(roleNames, that.roleNames);
}
@Override
public int hashCode() {
return Objects.hash(roleNames);
}
}

View File

@ -0,0 +1,71 @@
/*
* 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.privileges.Role;
import org.elasticsearch.common.xcontent.XContentParser;
import org.elasticsearch.common.xcontent.XContentParserUtils;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
/**
* Response when requesting one or more roles.
* Returns a List of {@link Role} objects
*/
public final class GetRolesResponse {
private final List<Role> roles;
public GetRolesResponse(List<Role> roles) {
this.roles = Collections.unmodifiableList(roles);
}
public List<Role> getRoles() {
return roles;
}
public static GetRolesResponse fromXContent(XContentParser parser) throws IOException {
XContentParserUtils.ensureExpectedToken(XContentParser.Token.START_OBJECT, parser.nextToken(), parser::getTokenLocation);
final List<Role> roles = new ArrayList<>();
XContentParser.Token token;
while ((token = parser.nextToken()) != XContentParser.Token.END_OBJECT) {
XContentParserUtils.ensureExpectedToken(XContentParser.Token.FIELD_NAME, token, parser::getTokenLocation);
roles.add(Role.PARSER.parse(parser, parser.currentName()));
}
return new GetRolesResponse(roles);
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
GetRolesResponse response = (GetRolesResponse) o;
return Objects.equals(roles, response.roles);
}
@Override
public int hashCode() {
return Objects.hash(roles);
}
}

View File

@ -249,7 +249,7 @@ public final class IndicesPrivileges implements ToXContentObject {
private @Nullable Collection<String> deniedFields = null;
private @Nullable String query = null;
private Builder() {
public Builder() {
}
public Builder indices(String... indices) {

View File

@ -21,15 +21,11 @@ package org.elasticsearch.client.security.user.privileges;
import org.elasticsearch.common.Nullable;
import org.elasticsearch.common.ParseField;
import org.elasticsearch.common.Strings;
import org.elasticsearch.common.xcontent.ConstructingObjectParser;
import org.elasticsearch.common.xcontent.ToXContentObject;
import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.common.xcontent.XContentHelper;
import org.elasticsearch.common.xcontent.XContentParser;
import org.elasticsearch.common.xcontent.XContentType;
import org.elasticsearch.common.xcontent.ObjectParser.ValueType;
import java.io.IOException;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
@ -42,10 +38,9 @@ import static org.elasticsearch.common.xcontent.ConstructingObjectParser.constru
import static org.elasticsearch.common.xcontent.ConstructingObjectParser.optionalConstructorArg;
/**
* Represents an aggregation of privileges. This does not have a name
* identifier.
* Represents an aggregation of privileges.
*/
public final class Role implements ToXContentObject {
public final class Role {
public static final ParseField CLUSTER = new ParseField("cluster");
public static final ParseField GLOBAL = new ParseField("global");
@ -53,10 +48,11 @@ public final class Role implements ToXContentObject {
public static final ParseField APPLICATIONS = new ParseField("applications");
public static final ParseField RUN_AS = new ParseField("run_as");
public static final ParseField METADATA = new ParseField("metadata");
public static final ParseField TRANSIENT_METADATA = new ParseField("transient_metadata");
@SuppressWarnings("unchecked")
private static final ConstructingObjectParser<Role, Void> PARSER = new ConstructingObjectParser<>("role_descriptor", false,
constructorObjects -> {
public static final ConstructingObjectParser<Role, String> PARSER = new ConstructingObjectParser<>("role_descriptor", false,
(constructorObjects, roleName) -> {
// Don't ignore unknown fields. It is dangerous if the object we parse is also
// part of a request that we build later on, and the fields that we now ignore
// will end up being implicitly set to null in that request.
@ -67,31 +63,44 @@ public final class Role implements ToXContentObject {
final Collection<ApplicationResourcePrivileges> applicationResourcePrivileges =
(Collection<ApplicationResourcePrivileges>) constructorObjects[i++];
final Collection<String> runAsPrivilege = (Collection<String>) constructorObjects[i++];
final Map<String, Object> metadata = (Map<String, Object>) constructorObjects[i];
return new Role(clusterPrivileges, globalApplicationPrivileges, indicesPrivileges, applicationResourcePrivileges,
runAsPrivilege, metadata);
final Map<String, Object> metadata = (Map<String, Object>) constructorObjects[i++];
final Map<String, Object> transientMetadata = (Map<String, Object>) constructorObjects[i];
return new Role(roleName, clusterPrivileges, globalApplicationPrivileges, indicesPrivileges, applicationResourcePrivileges,
runAsPrivilege, metadata, transientMetadata);
});
static {
PARSER.declareStringArray(optionalConstructorArg(), CLUSTER);
PARSER.declareObject(optionalConstructorArg(), GlobalPrivileges.PARSER, GLOBAL);
PARSER.declareFieldArray(optionalConstructorArg(), IndicesPrivileges.PARSER, INDICES, ValueType.OBJECT_ARRAY);
PARSER.declareFieldArray(optionalConstructorArg(), ApplicationResourcePrivileges.PARSER, APPLICATIONS, ValueType.OBJECT_ARRAY);
PARSER.declareObject(optionalConstructorArg(), (parser,c)-> GlobalPrivileges.PARSER.parse(parser,null), GLOBAL);
PARSER.declareFieldArray(optionalConstructorArg(), (parser,c)->IndicesPrivileges.PARSER.parse(parser,null), INDICES,
ValueType.OBJECT_ARRAY);
PARSER.declareFieldArray(optionalConstructorArg(), (parser,c)->ApplicationResourcePrivileges.PARSER.parse(parser,null),
APPLICATIONS, ValueType.OBJECT_ARRAY);
PARSER.declareStringArray(optionalConstructorArg(), RUN_AS);
PARSER.declareObject(constructorArg(), (parser, c) -> parser.map(), METADATA);
PARSER.declareObject(constructorArg(), (parser, c) -> parser.map(), TRANSIENT_METADATA);
}
private final String name;
private final Set<String> clusterPrivileges;
private final @Nullable GlobalPrivileges globalApplicationPrivileges;
private final Set<IndicesPrivileges> indicesPrivileges;
private final Set<ApplicationResourcePrivileges> applicationResourcePrivileges;
private final Set<String> runAsPrivilege;
private final Map<String, Object> metadata;
private final Map<String, Object> transientMetadata;
private Role(@Nullable Collection<String> clusterPrivileges, @Nullable GlobalPrivileges globalApplicationPrivileges,
@Nullable Collection<IndicesPrivileges> indicesPrivileges,
@Nullable Collection<ApplicationResourcePrivileges> applicationResourcePrivileges, @Nullable Collection<String> runAsPrivilege,
@Nullable Map<String, Object> metadata) {
private Role(String name, @Nullable Collection<String> clusterPrivileges,
@Nullable GlobalPrivileges globalApplicationPrivileges,
@Nullable Collection<IndicesPrivileges> indicesPrivileges,
@Nullable Collection<ApplicationResourcePrivileges> applicationResourcePrivileges,
@Nullable Collection<String> runAsPrivilege, @Nullable Map<String, Object> metadata,
@Nullable Map<String, Object> transientMetadata) {
if (Strings.hasText(name) == false){
throw new IllegalArgumentException("role name must be provided");
} else {
this.name = name;
}
// no cluster privileges are granted unless otherwise specified
this.clusterPrivileges = Collections
.unmodifiableSet(clusterPrivileges != null ? new HashSet<>(clusterPrivileges) : Collections.emptySet());
@ -105,6 +114,11 @@ public final class Role implements ToXContentObject {
// no run as privileges are granted unless otherwise specified
this.runAsPrivilege = Collections.unmodifiableSet(runAsPrivilege != null ? new HashSet<>(runAsPrivilege) : Collections.emptySet());
this.metadata = metadata != null ? Collections.unmodifiableMap(metadata) : Collections.emptyMap();
this.transientMetadata = transientMetadata != null ? Collections.unmodifiableMap(transientMetadata) : Collections.emptyMap();
}
public String getName() {
return name;
}
public Set<String> getClusterPrivileges() {
@ -136,55 +150,67 @@ public final class Role implements ToXContentObject {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Role that = (Role) o;
return clusterPrivileges.equals(that.clusterPrivileges)
&& Objects.equals(globalApplicationPrivileges, that.globalApplicationPrivileges)
&& indicesPrivileges.equals(that.indicesPrivileges)
&& applicationResourcePrivileges.equals(that.applicationResourcePrivileges)
&& runAsPrivilege.equals(that.runAsPrivilege)
&& metadata.equals(that.metadata);
return name.equals(that.name)
&& clusterPrivileges.equals(that.clusterPrivileges)
&& Objects.equals(globalApplicationPrivileges, that.globalApplicationPrivileges)
&& indicesPrivileges.equals(that.indicesPrivileges)
&& applicationResourcePrivileges.equals(that.applicationResourcePrivileges)
&& runAsPrivilege.equals(that.runAsPrivilege)
&& metadata.equals(that.metadata)
&& transientMetadata.equals(that.transientMetadata);
}
@Override
public int hashCode() {
return Objects.hash(clusterPrivileges, globalApplicationPrivileges, indicesPrivileges, applicationResourcePrivileges,
runAsPrivilege, metadata);
return Objects.hash(name, clusterPrivileges, globalApplicationPrivileges, indicesPrivileges, applicationResourcePrivileges,
runAsPrivilege, metadata, transientMetadata);
}
@Override
public String toString() {
try {
return XContentHelper.toXContent(this, XContentType.JSON, true).utf8ToString();
} catch (IOException e) {
throw new RuntimeException("Unexpected", e);
}
}
@Override
public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException {
builder.startObject();
StringBuilder sb = new StringBuilder("{");
sb.append("Name=").append(name).append(",");
if (false == clusterPrivileges.isEmpty()) {
builder.field(CLUSTER.getPreferredName(), clusterPrivileges);
sb.append("ClusterPrivileges=");
sb.append(clusterPrivileges.toString());
sb.append(", ");
}
if (null != globalApplicationPrivileges) {
builder.field(GLOBAL.getPreferredName(), globalApplicationPrivileges);
if (globalApplicationPrivileges != null) {
sb.append("GlobalApplcationPrivileges=");
sb.append(globalApplicationPrivileges.toString());
sb.append(", ");
}
if (false == indicesPrivileges.isEmpty()) {
builder.field(INDICES.getPreferredName(), indicesPrivileges);
sb.append("IndicesPrivileges=");
sb.append(indicesPrivileges.toString());
sb.append(", ");
}
if (false == applicationResourcePrivileges.isEmpty()) {
builder.field(APPLICATIONS.getPreferredName(), applicationResourcePrivileges);
sb.append("ApplicationPrivileges=");
sb.append(applicationResourcePrivileges.toString());
sb.append(", ");
}
if (false == runAsPrivilege.isEmpty()) {
builder.field(RUN_AS.getPreferredName(), runAsPrivilege);
sb.append("RunAsPrivilege=");
sb.append(runAsPrivilege.toString());
sb.append(", ");
}
if (false == metadata.isEmpty()) {
builder.field(METADATA.getPreferredName(), metadata);
sb.append("Metadata=[");
sb.append(metadata.toString());
sb.append("], ");
}
return builder.endObject();
if (false == transientMetadata.isEmpty()) {
sb.append("TransientMetadata=[");
sb.append(transientMetadata.toString());
sb.append("] ");
}
sb.append("}");
return sb.toString();
}
public static Role fromXContent(XContentParser parser) {
return PARSER.apply(parser, null);
public static Role fromXContent(XContentParser parser, String name) {
return PARSER.apply(parser, name);
}
public static Builder builder() {
@ -193,16 +219,27 @@ public final class Role implements ToXContentObject {
public static final class Builder {
private @Nullable String name = null;
private @Nullable Collection<String> clusterPrivileges = null;
private @Nullable GlobalPrivileges globalApplicationPrivileges = null;
private @Nullable Collection<IndicesPrivileges> indicesPrivileges = null;
private @Nullable Collection<ApplicationResourcePrivileges> applicationResourcePrivileges = null;
private @Nullable Collection<String> runAsPrivilege = null;
private @Nullable Map<String, Object> metadata = null;
private @Nullable Map<String, Object> transientMetadata = null;
private Builder() {
}
public Builder name(String name) {
if (Strings.hasText(name) == false){
throw new IllegalArgumentException("role name must be provided");
} else {
this.name = name;
}
return this;
}
public Builder clusterPrivileges(String... clusterPrivileges) {
return clusterPrivileges(Arrays
.asList(Objects.requireNonNull(clusterPrivileges, "Cluster privileges cannot be null. Pass an empty array instead.")));
@ -214,7 +251,7 @@ public final class Role implements ToXContentObject {
return this;
}
public Builder glabalApplicationPrivileges(GlobalPrivileges globalApplicationPrivileges) {
public Builder globalApplicationPrivileges(GlobalPrivileges globalApplicationPrivileges) {
this.globalApplicationPrivileges = globalApplicationPrivileges;
return this;
}
@ -257,9 +294,15 @@ public final class Role implements ToXContentObject {
return this;
}
public Builder transientMetadata(Map<String, Object> transientMetadata) {
this.transientMetadata =
Objects.requireNonNull(transientMetadata, "Transient metadata cannot be null. Pass an empty map instead.");
return this;
}
public Role build() {
return new Role(clusterPrivileges, globalApplicationPrivileges, indicesPrivileges, applicationResourcePrivileges,
runAsPrivilege, metadata);
return new Role(name, clusterPrivileges, globalApplicationPrivileges, indicesPrivileges, applicationResourcePrivileges,
runAsPrivilege, metadata, transientMetadata);
}
}
@ -282,6 +325,7 @@ public final class Role implements ToXContentObject {
public static final String TRANSPORT_CLIENT = "transport_client";
public static final String MANAGE_SECURITY = "manage_security";
public static final String MANAGE_SAML = "manage_saml";
public static final String MANAGE_TOKEN = "manage_token";
public static final String MANAGE_PIPELINE = "manage_pipeline";
public static final String MANAGE_CCR = "manage_ccr";
public static final String READ_CCR = "read_ccr";

View File

@ -32,6 +32,7 @@ import org.elasticsearch.client.security.EnableUserRequest;
import org.elasticsearch.client.security.GetPrivilegesRequest;
import org.elasticsearch.client.security.GetRoleMappingsRequest;
import org.elasticsearch.client.security.ChangePasswordRequest;
import org.elasticsearch.client.security.GetRolesRequest;
import org.elasticsearch.client.security.PutRoleMappingRequest;
import org.elasticsearch.client.security.PutUserRequest;
import org.elasticsearch.client.security.RefreshPolicy;
@ -202,6 +203,22 @@ public class SecurityRequestConvertersTests extends ESTestCase {
assertNull(request.getEntity());
}
public void testGetRoles() {
final String[] roles = randomArray(0, 5, String[]::new, () -> randomAlphaOfLength(5));
final GetRolesRequest getRolesRequest = new GetRolesRequest(roles);
final Request request = SecurityRequestConverters.getRoles(getRolesRequest);
assertEquals(HttpGet.METHOD_NAME, request.getMethod());
if (roles.length == 0) {
assertEquals("/_xpack/security/role", request.getEndpoint());
} else {
assertEquals("/_xpack/security/role/" + Strings.collectionToCommaDelimitedString(getRolesRequest.getRoleNames()),
request.getEndpoint());
}
assertNull(request.getEntity());
assertEquals(Collections.emptyMap(), request.getParameters());
}
public void testDeleteRole() {
final String name = randomAlphaOfLengthBetween(1, 12);
final RefreshPolicy refreshPolicy = randomFrom(RefreshPolicy.values());

View File

@ -52,6 +52,8 @@ import org.elasticsearch.client.security.GetPrivilegesRequest;
import org.elasticsearch.client.security.GetPrivilegesResponse;
import org.elasticsearch.client.security.GetRoleMappingsRequest;
import org.elasticsearch.client.security.GetRoleMappingsResponse;
import org.elasticsearch.client.security.GetRolesRequest;
import org.elasticsearch.client.security.GetRolesResponse;
import org.elasticsearch.client.security.GetSslCertificatesResponse;
import org.elasticsearch.client.security.HasPrivilegesRequest;
import org.elasticsearch.client.security.HasPrivilegesResponse;
@ -67,6 +69,7 @@ import org.elasticsearch.client.security.support.expressiondsl.RoleMapperExpress
import org.elasticsearch.client.security.support.expressiondsl.expressions.AnyRoleMapperExpression;
import org.elasticsearch.client.security.support.expressiondsl.fields.FieldRoleMapperExpression;
import org.elasticsearch.client.security.user.User;
import org.elasticsearch.client.security.user.privileges.Role;
import org.elasticsearch.client.security.user.privileges.ApplicationPrivilege;
import org.elasticsearch.client.security.user.privileges.IndicesPrivileges;
import org.elasticsearch.common.Strings;
@ -401,6 +404,89 @@ public class SecurityDocumentationIT extends ESRestHighLevelClientTestCase {
}
}
public void testGetRoles() throws Exception {
final RestHighLevelClient client = highLevelClient();
addRole("my_role");
addRole("my_role2");
addRole("my_role3");
{
//tag::get-roles-request
GetRolesRequest request = new GetRolesRequest("my_role");
//end::get-roles-request
//tag::get-roles-execute
GetRolesResponse response = client.security().getRoles(request, RequestOptions.DEFAULT);
//end::get-roles-execute
//tag::get-roles-response
List<Role> roles = response.getRoles();
//end::get-roles-response
assertNotNull(response);
assertThat(roles.size(), equalTo(1));
assertThat(roles.get(0).getName(), equalTo("my_role"));
assertThat(roles.get(0).getClusterPrivileges().contains("all"), equalTo(true));
}
{
//tag::get-roles-list-request
GetRolesRequest request = new GetRolesRequest("my_role", "my_role2");
GetRolesResponse response = client.security().getRoles(request, RequestOptions.DEFAULT);
//end::get-roles-list-request
List<Role> roles = response.getRoles();
assertNotNull(response);
assertThat(roles.size(), equalTo(2));
assertThat(roles.get(0).getClusterPrivileges().contains("all"), equalTo(true));
assertThat(roles.get(1).getClusterPrivileges().contains("all"), equalTo(true));
}
{
//tag::get-roles-all-request
GetRolesRequest request = new GetRolesRequest();
GetRolesResponse response = client.security().getRoles(request, RequestOptions.DEFAULT);
//end::get-roles-all-request
List<Role> roles = response.getRoles();
assertNotNull(response);
// 21 system roles plus the three we created
assertThat(roles.size(), equalTo(24));
}
{
GetRolesRequest request = new GetRolesRequest("my_role");
ActionListener<GetRolesResponse> listener;
//tag::get-roles-execute-listener
listener = new ActionListener<GetRolesResponse>() {
@Override
public void onResponse(GetRolesResponse getRolesResponse) {
// <1>
}
@Override
public void onFailure(Exception e) {
// <2>
}
};
//end::get-roles-execute-listener
assertNotNull(listener);
// Replace the empty listener by a blocking listener in test
final PlainActionFuture<GetRolesResponse> future = new PlainActionFuture<>();
listener = future;
//tag::get-roles-execute-async
client.security().getRolesAsync(request, RequestOptions.DEFAULT, listener); // <1>
//end::get-roles-execute-async
final GetRolesResponse response = future.get(30, TimeUnit.SECONDS);
assertNotNull(response);
assertThat(response.getRoles().size(), equalTo(1));
assertThat(response.getRoles().get(0).getName(), equalTo("my_role"));
assertThat(response.getRoles().get(0).getClusterPrivileges().contains("all"), equalTo(true));
}
}
public void testAuthenticate() throws Exception {
RestHighLevelClient client = highLevelClient();
{
@ -414,7 +500,7 @@ public class SecurityDocumentationIT extends ESRestHighLevelClientTestCase {
//end::authenticate-response
assertThat(user.getUsername(), is("test_user"));
assertThat(user.getRoles(), contains(new String[] {"superuser"}));
assertThat(user.getRoles(), contains(new String[]{"superuser"}));
assertThat(user.getFullName(), nullValue());
assertThat(user.getEmail(), nullValue());
assertThat(user.getMetadata().isEmpty(), is(true));

View File

@ -0,0 +1,52 @@
/*
* 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 GetRolesRequestTests extends ESTestCase {
public void testGetRolesRequest() {
final String[] roles = randomArray(0, 5, String[]::new, () -> randomAlphaOfLength(5));
final GetRolesRequest getRolesRequest = new GetRolesRequest(roles);
assertThat(getRolesRequest.getRoleNames().size(), equalTo(roles.length));
assertThat(getRolesRequest.getRoleNames(), containsInAnyOrder(roles));
}
public void testEqualsHashCode() {
final String[] roles = randomArray(0, 5, String[]::new, () -> randomAlphaOfLength(5));
final GetRolesRequest getRolesRequest = new GetRolesRequest(roles);
assertNotNull(getRolesRequest);
EqualsHashCodeTestUtils.checkEqualsAndHashCode(getRolesRequest, (original) -> {
return new GetRolesRequest(original.getRoleNames().toArray(new String[0]));
});
EqualsHashCodeTestUtils.checkEqualsAndHashCode(getRolesRequest, (original) -> {
return new GetRolesRequest(original.getRoleNames().toArray(new String[0]));
}, GetRolesRequestTests::mutateTestItem);
}
private static GetRolesRequest mutateTestItem(GetRolesRequest original) {
return new GetRolesRequest(randomArray(0, 5, String[]::new, () -> randomAlphaOfLength(5)));
}
}

View File

@ -0,0 +1,199 @@
/*
* 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.privileges.IndicesPrivileges;
import org.elasticsearch.client.security.user.privileges.Role;
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.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import static org.hamcrest.Matchers.equalTo;
public class GetRolesResponseTests extends ESTestCase {
public void testFromXContent() throws IOException {
String json =
"{\n" +
" \"my_admin_role\": {\n" +
" \"cluster\" : [ \"all\" ],\n" +
" \"indices\" : [\n" +
" {\n" +
" \"names\" : [ \"index1\", \"index2\" ],\n" +
" \"privileges\" : [ \"all\" ],\n" +
" \"field_security\" : {\n" +
" \"grant\" : [ \"title\", \"body\" ]}\n" +
" }\n" +
" ],\n" +
" \"applications\" : [ ],\n" +
" \"run_as\" : [ \"other_user\" ],\n" +
" \"metadata\" : {\n" +
" \"version\" : 1\n" +
" },\n" +
" \"transient_metadata\" : {\n" +
" \"enabled\" : true\n" +
" }\n" +
" }\n" +
"}";
final GetRolesResponse response = GetRolesResponse.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.getRoles().size(), equalTo(1));
final Role role = response.getRoles().get(0);
assertThat(role.getName(), equalTo("my_admin_role"));
assertThat(role.getClusterPrivileges().size(), equalTo(1));
IndicesPrivileges expectedIndicesPrivileges = new IndicesPrivileges.Builder()
.indices("index1", "index2")
.privileges("all")
.grantedFields("title", "body")
.build();
assertThat(role.getIndicesPrivileges().contains(expectedIndicesPrivileges), equalTo(true));
final Map<String, Object> expectedMetadata = new HashMap<>();
expectedMetadata.put("version", 1);
final Map<String, Object> expectedTransientMetadata = new HashMap<>();
expectedTransientMetadata.put("enabled", true);
final Role expectedRole = Role.builder()
.name("my_admin_role")
.clusterPrivileges("all")
.indicesPrivileges(expectedIndicesPrivileges)
.runAsPrivilege("other_user")
.metadata(expectedMetadata)
.transientMetadata(expectedTransientMetadata)
.build();
assertThat(role, equalTo(expectedRole));
}
public void testEqualsHashCode() {
final List<Role> roles = new ArrayList<>();
IndicesPrivileges indicesPrivileges = new IndicesPrivileges.Builder()
.indices("index1", "index2")
.privileges("write", "monitor", "delete")
.grantedFields("field1", "field2")
.deniedFields("field3", "field4")
.build();
Map<String, Object> metadata = new HashMap<>();
metadata.put("key", "value");
Map<String, Object> transientMetadata = new HashMap<>();
transientMetadata.put("transient_key", "transient_value");
final Role role = Role.builder()
.name("role_name")
.clusterPrivileges("monitor", "manage", "manage_saml")
.indicesPrivileges(indicesPrivileges)
.runAsPrivilege("run_as_user")
.metadata(metadata)
.transientMetadata(transientMetadata)
.build();
roles.add(role);
IndicesPrivileges indicesPrivileges2 = new IndicesPrivileges.Builder()
.indices("other_index1", "other_index2")
.privileges("write", "monitor", "delete")
.grantedFields("other_field1", "other_field2")
.deniedFields("other_field3", "other_field4")
.build();
Map<String, Object> metadata2 = new HashMap<>();
metadata.put("other_key", "other_value");
Map<String, Object> transientMetadata2 = new HashMap<>();
transientMetadata2.put("other_transient_key", "other_transient_value");
final Role role2 = Role.builder()
.name("role2_name")
.clusterPrivileges("monitor", "manage", "manage_saml")
.indicesPrivileges(indicesPrivileges2)
.runAsPrivilege("other_run_as_user")
.metadata(metadata2)
.transientMetadata(transientMetadata2)
.build();
roles.add(role2);
final GetRolesResponse getRolesResponse = new GetRolesResponse(roles);
assertNotNull(getRolesResponse);
EqualsHashCodeTestUtils.checkEqualsAndHashCode(getRolesResponse, (original) -> {
return new GetRolesResponse(original.getRoles());
});
EqualsHashCodeTestUtils.checkEqualsAndHashCode(getRolesResponse, (original) -> {
return new GetRolesResponse(original.getRoles());
}, GetRolesResponseTests::mutateTestItem);
}
private static GetRolesResponse mutateTestItem(GetRolesResponse original) {
if (randomBoolean()) {
final List<Role> roles = new ArrayList<>();
IndicesPrivileges indicesPrivileges = new IndicesPrivileges.Builder()
.indices("index1", "index2")
.privileges("write", "monitor", "delete")
.grantedFields("field1", "field2")
.deniedFields("field3", "field4")
.build();
Map<String, Object> metadata = new HashMap<String, Object>();
metadata.put("key", "value");
Map<String, Object> transientMetadata = new HashMap<>();
transientMetadata.put("transient_key", "transient_value");
final Role role = Role.builder()
.name("role_name")
.clusterPrivileges("monitor", "manage", "manage_saml")
.indicesPrivileges(indicesPrivileges)
.runAsPrivilege("run_as_user")
.metadata(metadata)
.transientMetadata(transientMetadata)
.build();
roles.add(role);
return new GetRolesResponse(roles);
} else {
IndicesPrivileges indicesPrivileges = new IndicesPrivileges.Builder()
.indices("index1_changed", "index2")
.privileges("write", "monitor", "delete")
.grantedFields("field1", "field2")
.deniedFields("field3", "field4")
.build();
Map<String, Object> metadata = new HashMap<String, Object>();
metadata.put("key", "value");
Map<String, Object> transientMetadata = new HashMap<>();
transientMetadata.put("transient_key", "transient_value");
final Role role = Role.builder()
.name("role_name")
.clusterPrivileges("monitor", "manage", "manage_saml")
.indicesPrivileges(indicesPrivileges)
.runAsPrivilege("run_as_user")
.metadata(metadata)
.transientMetadata(transientMetadata)
.build();
List<Role> newRoles = original.getRoles().stream().collect(Collectors.toList());
newRoles.remove(0);
newRoles.add(role);
return new GetRolesResponse(newRoles);
}
}
}

View File

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

View File

@ -366,6 +366,7 @@ The Java High Level REST Client supports the following Security APIs:
* <<java-rest-high-security-enable-user>>
* <<java-rest-high-security-disable-user>>
* <<java-rest-high-security-change-password>>
* <<{upid}-get-roles>>
* <<java-rest-high-security-delete-role>>
* <<{upid}-clear-roles-cache>>
* <<{upid}-clear-realm-cache>>