Browse Source

[HLRC] Add support for get role mappings API (#34637)

This commit adds support for get role mappings API
in HLRC.
Yogesh Gaikwad 7 years ago
parent
commit
a5ee134c40

+ 36 - 0
client/rest-high-level/src/main/java/org/elasticsearch/client/SecurityClient.java

@@ -29,6 +29,8 @@ import org.elasticsearch.client.security.PutRoleMappingResponse;
 import org.elasticsearch.client.security.DisableUserRequest;
 import org.elasticsearch.client.security.EmptyResponse;
 import org.elasticsearch.client.security.EnableUserRequest;
+import org.elasticsearch.client.security.GetRoleMappingsRequest;
+import org.elasticsearch.client.security.GetRoleMappingsResponse;
 import org.elasticsearch.client.security.GetSslCertificatesRequest;
 import org.elasticsearch.client.security.GetSslCertificatesResponse;
 import org.elasticsearch.client.security.PutUserRequest;
@@ -112,6 +114,40 @@ public final class SecurityClient {
                 PutRoleMappingResponse::fromXContent, listener, emptySet());
     }
 
+    /**
+     * Synchronously get role mapping(s).
+     * See <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/security-api-get-role-mapping.html">
+     * the docs</a> for more.
+     *
+     * @param request {@link GetRoleMappingsRequest} with role mapping name(s).
+     * If no role mapping name is provided then retrieves all role mappings.
+     * @param options the request options (e.g. headers), use
+     * {@link RequestOptions#DEFAULT} if nothing needs to be customized
+     * @return the response from the get role mapping call
+     * @throws IOException in case there is a problem sending the request or
+     * parsing back the response
+     */
+    public GetRoleMappingsResponse getRoleMappings(final GetRoleMappingsRequest request, final RequestOptions options) throws IOException {
+        return restHighLevelClient.performRequestAndParseEntity(request, SecurityRequestConverters::getRoleMappings,
+            options, GetRoleMappingsResponse::fromXContent, emptySet());
+    }
+
+    /**
+     * Asynchronously get role mapping(s).
+     * See <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/security-api-get-role-mapping.html">
+     * the docs</a> for more.
+     *
+     * @param request {@link GetRoleMappingsRequest} with role mapping name(s).
+     * If no role mapping name is provided then retrieves all role mappings.
+     * @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 getRoleMappingsAsync(final GetRoleMappingsRequest request, final RequestOptions options,
+            final ActionListener<GetRoleMappingsResponse> listener) {
+        restHighLevelClient.performRequestAsyncAndParseEntity(request, SecurityRequestConverters::getRoleMappings,
+                options, GetRoleMappingsResponse::fromXContent, listener, emptySet());
+    }
+
     /**
      * Enable a native realm or built-in user synchronously.
      * See <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/security-api-enable-user.html">

+ 12 - 0
client/rest-high-level/src/main/java/org/elasticsearch/client/SecurityRequestConverters.java

@@ -19,6 +19,7 @@
 
 package org.elasticsearch.client;
 
+import org.apache.http.client.methods.HttpGet;
 import org.apache.http.client.methods.HttpDelete;
 import org.apache.http.client.methods.HttpPost;
 import org.apache.http.client.methods.HttpPut;
@@ -28,9 +29,11 @@ import org.elasticsearch.client.security.DeleteRoleRequest;
 import org.elasticsearch.client.security.PutRoleMappingRequest;
 import org.elasticsearch.client.security.DisableUserRequest;
 import org.elasticsearch.client.security.EnableUserRequest;
+import org.elasticsearch.client.security.GetRoleMappingsRequest;
 import org.elasticsearch.client.security.ChangePasswordRequest;
 import org.elasticsearch.client.security.PutUserRequest;
 import org.elasticsearch.client.security.SetUserEnabledRequest;
+import org.elasticsearch.common.Strings;
 
 import java.io.IOException;
 
@@ -78,6 +81,15 @@ final class SecurityRequestConverters {
         return request;
     }
 
+    static Request getRoleMappings(final GetRoleMappingsRequest getRoleMappingRequest) throws IOException {
+        RequestConverters.EndpointBuilder builder = new RequestConverters.EndpointBuilder();
+        builder.addPathPartAsIs("_xpack/security/role_mapping");
+        if (getRoleMappingRequest.getRoleMappingNames().size() > 0) {
+            builder.addPathPart(Strings.collectionToCommaDelimitedString(getRoleMappingRequest.getRoleMappingNames()));
+        }
+        return new Request(HttpGet.METHOD_NAME, builder.build());
+    }
+
     static Request enableUser(EnableUserRequest enableUserRequest) {
         return setUserEnabled(enableUserRequest);
     }

+ 153 - 0
client/rest-high-level/src/main/java/org/elasticsearch/client/security/ExpressionRoleMapping.java

@@ -0,0 +1,153 @@
+/*
+ * 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.support.expressiondsl.RoleMapperExpression;
+import org.elasticsearch.client.security.support.expressiondsl.parser.RoleMapperExpressionParser;
+import org.elasticsearch.common.ParseField;
+import org.elasticsearch.common.xcontent.ConstructingObjectParser;
+import org.elasticsearch.common.xcontent.ObjectParser;
+import org.elasticsearch.common.xcontent.XContentParser;
+
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+
+import static org.elasticsearch.common.xcontent.ConstructingObjectParser.constructorArg;
+
+/**
+ * A representation of a single role-mapping.
+ *
+ * @see RoleMapperExpression
+ * @see RoleMapperExpressionParser
+ */
+public final class ExpressionRoleMapping {
+
+    @SuppressWarnings("unchecked")
+    static final ConstructingObjectParser<ExpressionRoleMapping, String> PARSER = new ConstructingObjectParser<>("role-mapping", true,
+            (args, name) -> new ExpressionRoleMapping(name, (RoleMapperExpression) args[0], (List<String>) args[1],
+                    (Map<String, Object>) args[2], (boolean) args[3]));
+
+    static {
+        PARSER.declareField(constructorArg(), (parser, context) -> RoleMapperExpressionParser.fromXContent(parser), Fields.RULES,
+                ObjectParser.ValueType.OBJECT);
+        PARSER.declareStringArray(constructorArg(), Fields.ROLES);
+        PARSER.declareField(constructorArg(), XContentParser::map, Fields.METADATA, ObjectParser.ValueType.OBJECT);
+        PARSER.declareBoolean(constructorArg(), Fields.ENABLED);
+    }
+
+    private final String name;
+    private final RoleMapperExpression expression;
+    private final List<String> roles;
+    private final Map<String, Object> metadata;
+    private final boolean enabled;
+
+    /**
+     * Constructor for role mapping
+     *
+     * @param name role mapping name
+     * @param expr {@link RoleMapperExpression} Expression used for role mapping
+     * @param roles list of roles to be associated with the user
+     * @param metadata metadata that helps to identify which roles are assigned
+     * to the user
+     * @param enabled a flag when {@code true} signifies the role mapping is active
+     */
+    public ExpressionRoleMapping(final String name, final RoleMapperExpression expr, final List<String> roles,
+            final Map<String, Object> metadata, boolean enabled) {
+        this.name = name;
+        this.expression = expr;
+        this.roles = Collections.unmodifiableList(roles);
+        this.metadata = (metadata == null) ? Collections.emptyMap() : Collections.unmodifiableMap(metadata);
+        this.enabled = enabled;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public RoleMapperExpression getExpression() {
+        return expression;
+    }
+
+    public List<String> getRoles() {
+        return roles;
+    }
+
+    public Map<String, Object> getMetadata() {
+        return metadata;
+    }
+
+    public boolean isEnabled() {
+        return enabled;
+    }
+
+    @Override
+    public int hashCode() {
+        final int prime = 31;
+        int result = 1;
+        result = prime * result + (enabled ? 1231 : 1237);
+        result = prime * result + ((expression == null) ? 0 : expression.hashCode());
+        result = prime * result + ((metadata == null) ? 0 : metadata.hashCode());
+        result = prime * result + ((name == null) ? 0 : name.hashCode());
+        result = prime * result + ((roles == null) ? 0 : roles.hashCode());
+        return result;
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj)
+            return true;
+        if (obj == null)
+            return false;
+        if (getClass() != obj.getClass())
+            return false;
+        final ExpressionRoleMapping other = (ExpressionRoleMapping) obj;
+        if (enabled != other.enabled)
+            return false;
+        if (expression == null) {
+            if (other.expression != null)
+                return false;
+        } else if (!expression.equals(other.expression))
+            return false;
+        if (metadata == null) {
+            if (other.metadata != null)
+                return false;
+        } else if (!metadata.equals(other.metadata))
+            return false;
+        if (name == null) {
+            if (other.name != null)
+                return false;
+        } else if (!name.equals(other.name))
+            return false;
+        if (roles == null) {
+            if (other.roles != null)
+                return false;
+        } else if (!roles.equals(other.roles))
+            return false;
+        return true;
+    }
+
+    public interface Fields {
+        ParseField ROLES = new ParseField("roles");
+        ParseField ENABLED = new ParseField("enabled");
+        ParseField RULES = new ParseField("rules");
+        ParseField METADATA = new ParseField("metadata");
+    }
+}

+ 68 - 0
client/rest-high-level/src/main/java/org/elasticsearch/client/security/GetRoleMappingsRequest.java

@@ -0,0 +1,68 @@
+/*
+ * 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 get role mappings
+ */
+public final class GetRoleMappingsRequest implements Validatable {
+    private final Set<String> roleMappingNames;
+
+    public GetRoleMappingsRequest(final String... roleMappingNames) {
+        if (roleMappingNames != null) {
+           this.roleMappingNames = Collections.unmodifiableSet(Sets.newHashSet(roleMappingNames));
+        } else {
+           this.roleMappingNames = Collections.emptySet();
+        }
+    }
+
+    public Set<String> getRoleMappingNames() {
+        return roleMappingNames;
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(roleMappingNames);
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj) {
+            return true;
+        }
+        if (obj == null) {
+            return false;
+        }
+        if (getClass() != obj.getClass()) {
+            return false;
+        }
+        final GetRoleMappingsRequest other = (GetRoleMappingsRequest) obj;
+
+        return Objects.equals(roleMappingNames, other.roleMappingNames);
+    }
+
+}

+ 70 - 0
client/rest-high-level/src/main/java/org/elasticsearch/client/security/GetRoleMappingsResponse.java

@@ -0,0 +1,70 @@
+/*
+ * 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.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;
+
+/**
+ * Get role mappings response
+ */
+public final class GetRoleMappingsResponse {
+
+    private final List<ExpressionRoleMapping> mappings;
+
+    public GetRoleMappingsResponse(List<ExpressionRoleMapping> mappings) {
+        this.mappings = Collections.unmodifiableList(mappings);
+    }
+
+    public List<ExpressionRoleMapping> getMappings() {
+        return mappings;
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) return true;
+        if (o == null || getClass() != o.getClass()) return false;
+        final GetRoleMappingsResponse that = (GetRoleMappingsResponse) o;
+        return this.mappings.equals(that.mappings);
+    }
+
+    @Override
+    public int hashCode() {
+        return mappings.hashCode();
+    }
+
+    public static GetRoleMappingsResponse fromXContent(XContentParser parser) throws IOException {
+        final List<ExpressionRoleMapping> roleMappings = new ArrayList<>();
+
+        XContentParserUtils.ensureExpectedToken(XContentParser.Token.START_OBJECT, parser.nextToken(), parser::getTokenLocation);
+        XContentParser.Token token;
+        while ((token = parser.nextToken()) != XContentParser.Token.END_OBJECT) {
+            XContentParserUtils.ensureExpectedToken(XContentParser.Token.FIELD_NAME, token, parser::getTokenLocation);
+            roleMappings.add(ExpressionRoleMapping.PARSER.parse(parser, parser.currentName()));
+        }
+
+        return new GetRoleMappingsResponse(roleMappings);
+    }
+}

+ 12 - 0
client/rest-high-level/src/main/java/org/elasticsearch/client/security/support/expressiondsl/parser/RoleMapperExpressionParser.java

@@ -45,6 +45,18 @@ import java.util.List;
 public final class RoleMapperExpressionParser {
     public static final ParseField FIELD = new ParseField("field");
 
+    public static RoleMapperExpression fromXContent(final XContentParser parser) throws IOException {
+        return new RoleMapperExpressionParser().parse("rules", parser);
+    }
+
+    /**
+     * This function exists to be compatible with
+     * {@link org.elasticsearch.common.xcontent.ContextParser#parse(XContentParser, Object)}
+     */
+    public static RoleMapperExpression parseObject(XContentParser parser, String id) throws IOException {
+        return new RoleMapperExpressionParser().parse(id, parser);
+    }
+
     /**
      * @param name The name of the expression tree within its containing object.
      * Used to provide descriptive error messages.

+ 22 - 0
client/rest-high-level/src/test/java/org/elasticsearch/client/SecurityRequestConvertersTests.java

@@ -19,6 +19,7 @@
 
 package org.elasticsearch.client;
 
+import org.apache.http.client.methods.HttpGet;
 import org.apache.http.client.methods.HttpDelete;
 import org.apache.http.client.methods.HttpPost;
 import org.apache.http.client.methods.HttpPut;
@@ -26,6 +27,7 @@ import org.elasticsearch.client.security.DeleteRoleMappingRequest;
 import org.elasticsearch.client.security.DeleteRoleRequest;
 import org.elasticsearch.client.security.DisableUserRequest;
 import org.elasticsearch.client.security.EnableUserRequest;
+import org.elasticsearch.client.security.GetRoleMappingsRequest;
 import org.elasticsearch.client.security.ChangePasswordRequest;
 import org.elasticsearch.client.security.PutRoleMappingRequest;
 import org.elasticsearch.client.security.PutUserRequest;
@@ -33,6 +35,7 @@ import org.elasticsearch.client.security.RefreshPolicy;
 import org.elasticsearch.client.security.support.expressiondsl.RoleMapperExpression;
 import org.elasticsearch.client.security.support.expressiondsl.expressions.AnyRoleMapperExpression;
 import org.elasticsearch.client.security.support.expressiondsl.fields.FieldRoleMapperExpression;
+import org.elasticsearch.common.Strings;
 import org.elasticsearch.test.ESTestCase;
 
 import java.io.IOException;
@@ -102,6 +105,25 @@ public class SecurityRequestConvertersTests extends ESTestCase {
         assertToXContentBody(putRoleMappingRequest, request.getEntity());
     }
 
+    public void testGetRoleMappings() throws IOException {
+        int noOfRoleMappingNames = randomIntBetween(0, 2);
+        final String[] roleMappingNames =
+                randomArray(noOfRoleMappingNames, noOfRoleMappingNames, String[]::new, () -> randomAlphaOfLength(5));
+        final GetRoleMappingsRequest getRoleMappingsRequest = new GetRoleMappingsRequest(roleMappingNames);
+
+        final Request request = SecurityRequestConverters.getRoleMappings(getRoleMappingsRequest);
+
+        assertEquals(HttpGet.METHOD_NAME, request.getMethod());
+        if (noOfRoleMappingNames == 0) {
+            assertEquals("/_xpack/security/role_mapping", request.getEndpoint());
+        } else {
+            assertEquals("/_xpack/security/role_mapping/" +
+                    Strings.collectionToCommaDelimitedString(getRoleMappingsRequest.getRoleMappingNames()), request.getEndpoint());
+        }
+        assertEquals(Collections.emptyMap(), request.getParameters());
+        assertNull(request.getEntity());
+    }
+
     public void testEnableUser() {
         final String username = randomAlphaOfLengthBetween(1, 12);
         final RefreshPolicy refreshPolicy = randomFrom(RefreshPolicy.values());

+ 122 - 0
client/rest-high-level/src/test/java/org/elasticsearch/client/documentation/SecurityDocumentationIT.java

@@ -38,6 +38,9 @@ import org.elasticsearch.client.security.DeleteRoleResponse;
 import org.elasticsearch.client.security.DisableUserRequest;
 import org.elasticsearch.client.security.EmptyResponse;
 import org.elasticsearch.client.security.EnableUserRequest;
+import org.elasticsearch.client.security.ExpressionRoleMapping;
+import org.elasticsearch.client.security.GetRoleMappingsRequest;
+import org.elasticsearch.client.security.GetRoleMappingsResponse;
 import org.elasticsearch.client.security.GetSslCertificatesResponse;
 import org.elasticsearch.client.security.PutRoleMappingRequest;
 import org.elasticsearch.client.security.PutRoleMappingResponse;
@@ -54,14 +57,20 @@ import org.hamcrest.Matchers;
 
 import java.io.IOException;
 import java.util.Collections;
+import java.util.HashMap;
 import java.util.Iterator;
 import java.util.List;
+import java.util.Map;
 import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.TimeUnit;
 
 import static org.hamcrest.Matchers.empty;
 import static org.hamcrest.Matchers.not;
 import static org.elasticsearch.common.xcontent.XContentFactory.jsonBuilder;
+import static org.hamcrest.Matchers.contains;
+import static org.hamcrest.Matchers.equalTo;
+import static org.hamcrest.Matchers.is;
+import static org.hamcrest.Matchers.isIn;
 
 public class SecurityDocumentationIT extends ESRestHighLevelClientTestCase {
 
@@ -165,6 +174,119 @@ public class SecurityDocumentationIT extends ESRestHighLevelClientTestCase {
         }
     }
 
+    public void testGetRoleMappings() throws Exception {
+        final RestHighLevelClient client = highLevelClient();
+
+        final RoleMapperExpression rules1 = AnyRoleMapperExpression.builder().addExpression(FieldRoleMapperExpression.ofUsername("*"))
+                .addExpression(FieldRoleMapperExpression.ofGroups("cn=admins,dc=example,dc=com")).build();
+        final PutRoleMappingRequest putRoleMappingRequest1 = new PutRoleMappingRequest("mapping-example-1", true, Collections.singletonList(
+                "superuser"), rules1, null, RefreshPolicy.NONE);
+        final PutRoleMappingResponse putRoleMappingResponse1 = client.security().putRoleMapping(putRoleMappingRequest1,
+                RequestOptions.DEFAULT);
+        boolean isCreated1 = putRoleMappingResponse1.isCreated();
+        assertTrue(isCreated1);
+        final RoleMapperExpression rules2 = AnyRoleMapperExpression.builder().addExpression(FieldRoleMapperExpression.ofGroups(
+                "cn=admins,dc=example,dc=com")).build();
+        final Map<String, Object> metadata2 = new HashMap<>();
+        metadata2.put("k1", "v1");
+        final PutRoleMappingRequest putRoleMappingRequest2 = new PutRoleMappingRequest("mapping-example-2", true, Collections.singletonList(
+                "monitoring"), rules2, metadata2, RefreshPolicy.NONE);
+        final PutRoleMappingResponse putRoleMappingResponse2 = client.security().putRoleMapping(putRoleMappingRequest2,
+                RequestOptions.DEFAULT);
+        boolean isCreated2 = putRoleMappingResponse2.isCreated();
+        assertTrue(isCreated2);
+
+        {
+            // tag::get-role-mappings-execute
+            final GetRoleMappingsRequest request = new GetRoleMappingsRequest("mapping-example-1");
+            final GetRoleMappingsResponse response = client.security().getRoleMappings(request, RequestOptions.DEFAULT);
+            // end::get-role-mappings-execute
+            // tag::get-role-mappings-response
+            List<ExpressionRoleMapping> mappings = response.getMappings();
+            // end::get-role-mappings-response
+            assertNotNull(mappings);
+            assertThat(mappings.size(), is(1));
+            assertThat(mappings.get(0).isEnabled(), is(true));
+            assertThat(mappings.get(0).getName(), is("mapping-example-1"));
+            assertThat(mappings.get(0).getExpression(), equalTo(rules1));
+            assertThat(mappings.get(0).getMetadata(), equalTo(Collections.emptyMap()));
+            assertThat(mappings.get(0).getRoles(), contains("superuser"));
+        }
+
+        {
+            // tag::get-role-mappings-list-execute
+            final GetRoleMappingsRequest request = new GetRoleMappingsRequest("mapping-example-1", "mapping-example-2");
+            final GetRoleMappingsResponse response = client.security().getRoleMappings(request, RequestOptions.DEFAULT);
+            // end::get-role-mappings-all-execute
+            List<ExpressionRoleMapping> mappings = response.getMappings();
+            assertNotNull(mappings);
+            assertThat(mappings.size(), is(2));
+            for (ExpressionRoleMapping roleMapping : mappings) {
+                assertThat(roleMapping.isEnabled(), is(true));
+                assertThat(roleMapping.getName(), isIn(new String[] { "mapping-example-1", "mapping-example-2" }));
+                if (roleMapping.getName().equals("mapping-example-1")) {
+                    assertThat(roleMapping.getMetadata(), equalTo(Collections.emptyMap()));
+                    assertThat(roleMapping.getExpression(), equalTo(rules1));
+                    assertThat(roleMapping.getRoles(), contains("superuser"));
+                } else {
+                    assertThat(roleMapping.getMetadata(), equalTo(metadata2));
+                    assertThat(roleMapping.getExpression(), equalTo(rules2));
+                    assertThat(roleMapping.getRoles(), contains("monitoring"));
+                }
+            }
+        }
+
+        {
+            // tag::get-role-mappings-all-execute
+            final GetRoleMappingsRequest request = new GetRoleMappingsRequest();
+            final GetRoleMappingsResponse response = client.security().getRoleMappings(request, RequestOptions.DEFAULT);
+            // end::get-role-mappings-all-execute
+            List<ExpressionRoleMapping> mappings = response.getMappings();
+            assertNotNull(mappings);
+            assertThat(mappings.size(), is(2));
+            for (ExpressionRoleMapping roleMapping : mappings) {
+                assertThat(roleMapping.isEnabled(), is(true));
+                assertThat(roleMapping.getName(), isIn(new String[] { "mapping-example-1", "mapping-example-2" }));
+                if (roleMapping.getName().equals("mapping-example-1")) {
+                    assertThat(roleMapping.getMetadata(), equalTo(Collections.emptyMap()));
+                    assertThat(roleMapping.getExpression(), equalTo(rules1));
+                    assertThat(roleMapping.getRoles(), contains("superuser"));
+                } else {
+                    assertThat(roleMapping.getMetadata(), equalTo(metadata2));
+                    assertThat(roleMapping.getExpression(), equalTo(rules2));
+                    assertThat(roleMapping.getRoles(), contains("monitoring"));
+                }
+            }
+        }
+
+        {
+            final GetRoleMappingsRequest request = new GetRoleMappingsRequest();
+            // tag::get-role-mappings-execute-listener
+            ActionListener<GetRoleMappingsResponse> listener = new ActionListener<GetRoleMappingsResponse>() {
+                @Override
+                public void onResponse(GetRoleMappingsResponse response) {
+                    // <1>
+                }
+
+                @Override
+                public void onFailure(Exception e) {
+                    // <2>
+                }
+            };
+            // end::get-role-mappings-execute-listener
+
+            // Replace the empty listener by a blocking listener in test
+            final CountDownLatch latch = new CountDownLatch(1);
+            listener = new LatchedActionListener<>(listener, latch);
+
+            // tag::get-role-mappings-execute-async
+            client.security().getRoleMappingsAsync(request, RequestOptions.DEFAULT, listener); // <1>
+            // end::get-role-mappings-execute-async
+
+            assertTrue(latch.await(30L, TimeUnit.SECONDS));
+        }
+    }
+
     public void testEnableUser() throws Exception {
         RestHighLevelClient client = highLevelClient();
         char[] password = new char[]{'p', 'a', 's', 's', 'w', 'o', 'r', 'd'};

+ 108 - 0
client/rest-high-level/src/test/java/org/elasticsearch/client/security/ExpressionRoleMappingTests.java

@@ -0,0 +1,108 @@
+/*
+ * 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.support.expressiondsl.fields.FieldRoleMapperExpression;
+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.Collections;
+import java.util.HashMap;
+import java.util.Map;
+
+import static org.hamcrest.Matchers.equalTo;
+
+public class ExpressionRoleMappingTests extends ESTestCase {
+
+    public void testExpressionRoleMappingParser() throws IOException {
+        final String json = 
+                "{\n" + 
+                "   \"enabled\" : true,\n" + 
+                "   \"roles\" : [\n" + 
+                "     \"superuser\"\n" + 
+                "   ],\n" + 
+                "   \"rules\" : {\n" + 
+                "     \"field\" : {\n" + 
+                "       \"realm.name\" : \"kerb1\"\n" + 
+                "     }\n" + 
+                "   },\n" + 
+                "   \"metadata\" : { }\n" + 
+                " }";
+        final ExpressionRoleMapping expressionRoleMapping = ExpressionRoleMapping.PARSER.parse(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), "example-role-mapping");
+        final ExpressionRoleMapping expectedRoleMapping = new ExpressionRoleMapping("example-role-mapping", FieldRoleMapperExpression
+                .ofKeyValues("realm.name", "kerb1"), Collections.singletonList("superuser"), null, true);
+        assertThat(expressionRoleMapping, equalTo(expectedRoleMapping));
+    }
+
+    public void testEqualsHashCode() {
+        final ExpressionRoleMapping expressionRoleMapping = new ExpressionRoleMapping("kerberosmapping", FieldRoleMapperExpression
+                .ofKeyValues("realm.name", "kerb1"), Collections.singletonList("superuser"), null, true);
+        EqualsHashCodeTestUtils.checkEqualsAndHashCode(expressionRoleMapping, (original) -> {
+            return new ExpressionRoleMapping(original.getName(), original.getExpression(), original.getRoles(), original.getMetadata(),
+                    original.isEnabled());
+        });
+        EqualsHashCodeTestUtils.checkEqualsAndHashCode(expressionRoleMapping, (original) -> {
+            return new ExpressionRoleMapping(original.getName(), original.getExpression(), original.getRoles(), original.getMetadata(),
+                    original.isEnabled());
+        }, ExpressionRoleMappingTests::mutateTestItem);
+    }
+
+    private static ExpressionRoleMapping mutateTestItem(ExpressionRoleMapping original) {
+        ExpressionRoleMapping mutated = null;
+        switch (randomIntBetween(0, 4)) {
+        case 0:
+            mutated = new ExpressionRoleMapping("namechanged", FieldRoleMapperExpression.ofKeyValues("realm.name", "kerb1"), Collections
+                    .singletonList("superuser"), null, true);
+            break;
+        case 1:
+            mutated = new ExpressionRoleMapping("kerberosmapping", FieldRoleMapperExpression.ofKeyValues("changed", "changed"), Collections
+                    .singletonList("superuser"), null, true);
+            break;
+        case 2:
+            mutated = new ExpressionRoleMapping("kerberosmapping", FieldRoleMapperExpression.ofKeyValues("realm.name", "kerb1"), Collections
+                    .singletonList("changed"), null, true);
+            break;
+        case 3:
+            Map<String, Object> metadata = new HashMap<>();
+            metadata.put("a", "b");
+            mutated = new ExpressionRoleMapping("kerberosmapping", FieldRoleMapperExpression.ofKeyValues("realm.name", "kerb1"), Collections
+                    .singletonList("superuser"), metadata, true);
+            break;
+        case 4:
+            mutated = new ExpressionRoleMapping("kerberosmapping", FieldRoleMapperExpression.ofKeyValues("realm.name", "kerb1"), Collections
+                    .singletonList("superuser"), null, false);
+            break;
+        }
+        return mutated;
+    }
+}

+ 55 - 0
client/rest-high-level/src/test/java/org/elasticsearch/client/security/GetRoleMappingsRequestTests.java

@@ -0,0 +1,55 @@
+/*
+ * 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.is;
+
+public class GetRoleMappingsRequestTests extends ESTestCase {
+
+    public void testGetRoleMappingsRequest() {
+        int noOfRoleMappingNames = randomIntBetween(0, 2);
+        final String[] roleMappingNames = randomArray(noOfRoleMappingNames, noOfRoleMappingNames, String[]::new, () -> randomAlphaOfLength(
+                5));
+        final GetRoleMappingsRequest getRoleMappingsRequest = new GetRoleMappingsRequest(roleMappingNames);
+        assertThat(getRoleMappingsRequest.getRoleMappingNames().size(), is(noOfRoleMappingNames));
+        assertThat(getRoleMappingsRequest.getRoleMappingNames(), containsInAnyOrder(roleMappingNames));
+    }
+
+    public void testEqualsHashCode() {
+        int noOfRoleMappingNames = randomIntBetween(0, 2);
+        final String[] roleMappingNames = randomArray(noOfRoleMappingNames, String[]::new, () -> randomAlphaOfLength(5));
+        final GetRoleMappingsRequest getRoleMappingsRequest = new GetRoleMappingsRequest(roleMappingNames);
+        assertNotNull(getRoleMappingsRequest);
+        EqualsHashCodeTestUtils.checkEqualsAndHashCode(getRoleMappingsRequest, (original) -> {
+            return new GetRoleMappingsRequest(original.getRoleMappingNames().toArray(new String[0]));
+        });
+        EqualsHashCodeTestUtils.checkEqualsAndHashCode(getRoleMappingsRequest, (original) -> {
+            return new GetRoleMappingsRequest(original.getRoleMappingNames().toArray(new String[0]));
+        }, GetRoleMappingsRequestTests::mutateTestItem);
+    }
+
+    private static GetRoleMappingsRequest mutateTestItem(GetRoleMappingsRequest original) {
+        return new GetRoleMappingsRequest(randomAlphaOfLength(8));
+    }
+}

+ 118 - 0
client/rest-high-level/src/test/java/org/elasticsearch/client/security/GetRoleMappingsResponseTests.java

@@ -0,0 +1,118 @@
+/*
+ * 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.support.expressiondsl.fields.FieldRoleMapperExpression;
+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.List;
+
+import static org.hamcrest.Matchers.equalTo;
+
+public class GetRoleMappingsResponseTests extends ESTestCase {
+
+    public void testFromXContent() throws IOException {
+        final String json = "{\n" + 
+                " \"kerberosmapping\" : {\n" + 
+                "   \"enabled\" : true,\n" + 
+                "   \"roles\" : [\n" + 
+                "     \"superuser\"\n" + 
+                "   ],\n" + 
+                "   \"rules\" : {\n" + 
+                "     \"field\" : {\n" + 
+                "       \"realm.name\" : \"kerb1\"\n" + 
+                "     }\n" + 
+                "   },\n" + 
+                "   \"metadata\" : { }\n" + 
+                " },\n" + 
+                " \"ldapmapping\" : {\n" + 
+                "   \"enabled\" : false,\n" + 
+                "   \"roles\" : [\n" + 
+                "     \"monitoring\"\n" + 
+                "   ],\n" + 
+                "   \"rules\" : {\n" + 
+                "     \"field\" : {\n" + 
+                "       \"groups\" : \"cn=ipausers,cn=groups,cn=accounts,dc=ipademo,dc=local\"\n" + 
+                "     }\n" + 
+                "   },\n" + 
+                "   \"metadata\" : { }\n" + 
+                " }\n" + 
+                "}";
+        final GetRoleMappingsResponse response = GetRoleMappingsResponse.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));
+        final List<ExpressionRoleMapping> expectedRoleMappingsList = new ArrayList<>();
+        expectedRoleMappingsList.add(new ExpressionRoleMapping("kerberosmapping", FieldRoleMapperExpression.ofKeyValues("realm.name",
+                "kerb1"), Collections.singletonList("superuser"), null, true));
+        expectedRoleMappingsList.add(new ExpressionRoleMapping("ldapmapping", FieldRoleMapperExpression.ofGroups(
+                "cn=ipausers,cn=groups,cn=accounts,dc=ipademo,dc=local"), Collections.singletonList("monitoring"), null, false));
+        final GetRoleMappingsResponse expectedResponse = new GetRoleMappingsResponse(expectedRoleMappingsList);
+        assertThat(response, equalTo(expectedResponse));
+    }
+
+    public void testEqualsHashCode() {
+        final List<ExpressionRoleMapping> roleMappingsList = new ArrayList<>();
+        roleMappingsList.add(new ExpressionRoleMapping("kerberosmapping", FieldRoleMapperExpression.ofKeyValues("realm.name",
+                "kerb1"), Collections.singletonList("superuser"), null, true));
+        final GetRoleMappingsResponse response = new GetRoleMappingsResponse(roleMappingsList);
+        assertNotNull(response);
+        EqualsHashCodeTestUtils.checkEqualsAndHashCode(response, (original) -> {
+            return new GetRoleMappingsResponse(original.getMappings());
+        });
+        EqualsHashCodeTestUtils.checkEqualsAndHashCode(response, (original) -> {
+            return new GetRoleMappingsResponse(original.getMappings());
+        }, GetRoleMappingsResponseTests::mutateTestItem);
+    }
+
+    private static GetRoleMappingsResponse mutateTestItem(GetRoleMappingsResponse original) {
+        GetRoleMappingsResponse mutated = null;
+        switch(randomIntBetween(0, 1)) {
+        case 0:
+            final List<ExpressionRoleMapping> roleMappingsList1 = new ArrayList<>();
+            roleMappingsList1.add(new ExpressionRoleMapping("ldapmapping", FieldRoleMapperExpression.ofGroups(
+                "cn=ipausers,cn=groups,cn=accounts,dc=ipademo,dc=local"), Collections.singletonList("monitoring"), null, false));
+            mutated = new GetRoleMappingsResponse(roleMappingsList1);
+            break;
+        case 1:
+            final List<ExpressionRoleMapping> roleMappingsList2 = new ArrayList<>();
+            ExpressionRoleMapping orginialRoleMapping = original.getMappings().get(0);
+            roleMappingsList2.add(new ExpressionRoleMapping(orginialRoleMapping.getName(), FieldRoleMapperExpression.ofGroups(
+                    "cn=ipausers,cn=groups,cn=accounts,dc=ipademo,dc=local"),
+                    orginialRoleMapping.getRoles(), orginialRoleMapping.getMetadata(), !orginialRoleMapping.isEnabled()));
+            mutated = new GetRoleMappingsResponse(roleMappingsList2);
+            break;
+        }
+        return mutated;
+    }
+}

+ 67 - 0
docs/java-rest/high-level/security/get-role-mappings.asciidoc

@@ -0,0 +1,67 @@
+[[java-rest-high-security-get-role-mappings]]
+=== Get Role Mappings API
+
+[[java-rest-high-security-get-role-mappings-execution]]
+==== Execution
+
+Retrieving a role mapping can be performed using the `security().getRoleMappings()`
+method and by setting role mapping name on `GetRoleMappingsRequest`:
+
+["source","java",subs="attributes,callouts,macros"]
+--------------------------------------------------
+include-tagged::{doc-tests}/SecurityDocumentationIT.java[get-role-mappings-execute]
+--------------------------------------------------
+
+Retrieving multiple role mappings can be performed using the `security.getRoleMappings()`
+method and by setting role mapping names on `GetRoleMappingsRequest`:
+
+["source","java",subs="attributes,callouts,macros"]
+--------------------------------------------------
+include-tagged::{doc-tests}/SecurityDocumentationIT.java[get-role-mappings-list-execute]
+--------------------------------------------------
+
+Retrieving all role mappings can be performed using the `security.getRoleMappings()`
+method and with no role mapping name on `GetRoleMappingsRequest`:
+
+["source","java",subs="attributes,callouts,macros"]
+--------------------------------------------------
+include-tagged::{doc-tests}/SecurityDocumentationIT.java[get-role-mappings-all-execute]
+--------------------------------------------------
+
+[[java-rest-high-security-get-role-mappings-response]]
+==== Response
+
+The returned `GetRoleMappingsResponse` contains the list of role mapping(s).
+
+["source","java",subs="attributes,callouts,macros"]
+--------------------------------------------------
+include-tagged::{doc-tests}/SecurityDocumentationIT.java[get-role-mappings-response]
+--------------------------------------------------
+
+[[java-rest-high-security-get-role-mappings-async]]
+==== Asynchronous Execution
+
+This request can be executed asynchronously using the `security().getRoleMappingsAsync()`
+method:
+
+["source","java",subs="attributes,callouts,macros"]
+--------------------------------------------------
+include-tagged::{doc-tests}/SecurityDocumentationIT.java[get-role-mappings-execute-async]
+--------------------------------------------------
+<1> The `GetRoleMappingsRequest` to execute and the `ActionListener` to use when
+the execution completes
+
+The asynchronous method does not block and returns immediately. Once the request
+has completed the `ActionListener` is called back using the `onResponse` method
+if the execution successfully completed or using the `onFailure` method if
+it failed.
+
+A typical listener for a `GetRoleMappingsResponse` looks like:
+
+["source","java",subs="attributes,callouts,macros"]
+--------------------------------------------------
+include-tagged::{doc-tests}/SecurityDocumentationIT.java[get-role-mappings-execute-listener]
+--------------------------------------------------
+<1> Called when the execution is successfully completed. The response is
+provided as an argument
+<2> Called in case of failure. The raised exception is provided as an argument

+ 2 - 0
docs/java-rest/high-level/supported-apis.asciidoc

@@ -327,6 +327,7 @@ The Java High Level REST Client supports the following Security APIs:
 * <<{upid}-clear-roles-cache>>
 * <<java-rest-high-security-get-certificates>>
 * <<java-rest-high-security-put-role-mapping>>
+* <<java-rest-high-security-get-role-mapping>>
 * <<java-rest-high-security-delete-role-mapping>>
 
 include::security/put-user.asciidoc[]
@@ -337,6 +338,7 @@ include::security/delete-role.asciidoc[]
 include::security/clear-roles-cache.asciidoc[]
 include::security/get-certificates.asciidoc[]
 include::security/put-role-mapping.asciidoc[]
+include::security/get-role-mapping.asciidoc[]
 include::security/delete-role-mapping.asciidoc[]
 
 == Watcher APIs