Procházet zdrojové kódy

[HLRC] Add support for get application privileges API (#35556)

This commits adds support for the Get Application Privileges
API to the HLRC

Relates: #29827
Ioannis Kakavas před 7 roky
rodič
revize
25f83ae08c

+ 43 - 3
client/rest-high-level/src/main/java/org/elasticsearch/client/SecurityClient.java

@@ -38,6 +38,8 @@ 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.GetPrivilegesRequest;
+import org.elasticsearch.client.security.GetPrivilegesResponse;
 import org.elasticsearch.client.security.GetRoleMappingsRequest;
 import org.elasticsearch.client.security.GetRoleMappingsResponse;
 import org.elasticsearch.client.security.GetSslCertificatesRequest;
@@ -505,10 +507,47 @@ public final class SecurityClient {
             InvalidateTokenResponse::fromXContent, listener, emptySet());
     }
 
+    /**
+     * Synchronously get application privilege(s).
+     * See <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/security-api-get-privileges.html">
+     * the docs</a> for more.
+     *
+     * @param request {@link GetPrivilegesRequest} with the application name and the privilege name.
+     *                If no application name is provided, information about all privileges for all applications is retrieved.
+     *                If no privilege name is provided, information about all privileges of the specified application is retrieved.
+     * @param options the request options (e.g. headers), use
+     *                {@link RequestOptions#DEFAULT} if nothing needs to be customized
+     * @return the response from the get privileges call
+     * @throws IOException in case there is a problem sending the request or
+     *                     parsing back the response
+     */
+    public GetPrivilegesResponse getPrivileges(final GetPrivilegesRequest request, final RequestOptions options) throws IOException {
+        return restHighLevelClient.performRequestAndParseEntity(request, SecurityRequestConverters::getPrivileges,
+            options, GetPrivilegesResponse::fromXContent, emptySet());
+    }
+
+    /**
+     * Asynchronously get application privilege(s).
+     * See <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/security-api-get-privileges.html">
+     * the docs</a> for more.
+     *
+     * @param request  {@link GetPrivilegesRequest} with the application name and the privilege name.
+     *                 If no application name is provided, information about all privileges for all applications is retrieved.
+     *                 If no privilege name is provided, information about all privileges of the specified application is retrieved.
+     * @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 getPrivilegesAsync(final GetPrivilegesRequest request, final RequestOptions options,
+                                   final ActionListener<GetPrivilegesResponse> listener) {
+        restHighLevelClient.performRequestAsyncAndParseEntity(request, SecurityRequestConverters::getPrivileges,
+            options, GetPrivilegesResponse::fromXContent, listener, emptySet());
+    }
+
     /**
      * Removes application privilege(s)
      * See <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/security-api-delete-privilege.html">
      * the docs</a> for more.
+     *
      * @param request the request with the application privilege to delete
      * @param options the request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
      * @return the response from the delete application privilege call
@@ -523,12 +562,13 @@ public final class SecurityClient {
      * Asynchronously removes an application privilege
      * See <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/security-api-delete-privilege.html">
      * the docs</a> for more.
-     * @param request the request with the application privilege to delete
-     * @param options the request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
+     *
+     * @param request  the request with the application privilege to delete
+     * @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 deletePrivilegesAsync(DeletePrivilegesRequest request, RequestOptions options,
-                                     ActionListener<DeletePrivilegesResponse> listener) {
+                                      ActionListener<DeletePrivilegesResponse> listener) {
         restHighLevelClient.performRequestAsyncAndParseEntity(request, SecurityRequestConverters::deletePrivileges, options,
             DeletePrivilegesResponse::fromXContent, listener, singleton(404));
     }

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

@@ -28,14 +28,15 @@ import org.elasticsearch.client.security.ClearRealmCacheRequest;
 import org.elasticsearch.client.security.ClearRolesCacheRequest;
 import org.elasticsearch.client.security.CreateTokenRequest;
 import org.elasticsearch.client.security.DeletePrivilegesRequest;
+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.PutRoleMappingRequest;
 import org.elasticsearch.client.security.HasPrivilegesRequest;
 import org.elasticsearch.client.security.DisableUserRequest;
 import org.elasticsearch.client.security.EnableUserRequest;
 import org.elasticsearch.client.security.GetRoleMappingsRequest;
-import org.elasticsearch.client.security.InvalidateTokenRequest;
-import org.elasticsearch.client.security.PutRoleMappingRequest;
 import org.elasticsearch.client.security.PutUserRequest;
 import org.elasticsearch.client.security.SetUserEnabledRequest;
 import org.elasticsearch.common.Strings;
@@ -181,6 +182,15 @@ final class SecurityRequestConverters {
         return request;
     }
 
+    static Request getPrivileges(GetPrivilegesRequest getPrivilegesRequest) {
+        String endpoint = new RequestConverters.EndpointBuilder()
+            .addPathPartAsIs("_xpack/security/privilege")
+            .addPathPart(getPrivilegesRequest.getApplicationName())
+            .addCommaSeparatedPathParts(getPrivilegesRequest.getPrivilegeNames())
+            .build();
+        return new Request(HttpGet.METHOD_NAME, endpoint);
+    }
+
     static Request deletePrivileges(DeletePrivilegesRequest deletePrivilegeRequest) {
         String endpoint = new RequestConverters.EndpointBuilder()
             .addPathPartAsIs("_xpack/security/privilege")

+ 93 - 0
client/rest-high-level/src/main/java/org/elasticsearch/client/security/GetPrivilegesRequest.java

@@ -0,0 +1,93 @@
+/*
+ * 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.Nullable;
+import org.elasticsearch.common.Strings;
+import org.elasticsearch.common.util.CollectionUtils;
+
+import java.util.Arrays;
+import java.util.Objects;
+
+/**
+ * Request object to get application privilege(s)
+ */
+public final class GetPrivilegesRequest implements Validatable {
+    private final String applicationName;
+    private final String[] privilegeNames;
+
+    public GetPrivilegesRequest(@Nullable final String applicationName, @Nullable final String... privilegeNames) {
+        if ((CollectionUtils.isEmpty(privilegeNames) == false) && Strings.isNullOrEmpty(applicationName)) {
+            throw new IllegalArgumentException("privilege cannot be specified when application is missing");
+        }
+        this.applicationName = applicationName;
+        this.privilegeNames = privilegeNames;
+    }
+
+    /**
+     * Constructs a {@link GetPrivilegesRequest} to request all the privileges defined for all applications
+     */
+    public static GetPrivilegesRequest getAllPrivileges() {
+        return new GetPrivilegesRequest(null);
+    }
+
+    /**
+     * Constructs a {@link GetPrivilegesRequest} to request all the privileges defined for the specified {@code applicationName}
+     *
+     * @param applicationName the name of the application for which the privileges are requested
+     */
+    public static GetPrivilegesRequest getApplicationPrivileges(String applicationName) {
+        if (Strings.isNullOrEmpty(applicationName)) {
+            throw new IllegalArgumentException("application name is required");
+        }
+        return new GetPrivilegesRequest(applicationName);
+    }
+
+    /**
+     * @return the name of the application for which to return certain privileges
+     */
+    public String getApplicationName() {
+        return applicationName;
+    }
+
+    /**
+     * @return an array of privilege names to return or null if all should be returned
+     */
+    public String[] getPrivilegeNames() {
+        return privilegeNames;
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) return true;
+        if (o == null || getClass() != o.getClass()) return false;
+        GetPrivilegesRequest that = (GetPrivilegesRequest) o;
+        return Objects.equals(applicationName, that.applicationName) &&
+            Arrays.equals(privilegeNames, that.privilegeNames);
+    }
+
+    @Override
+    public int hashCode() {
+        int result = Objects.hash(applicationName);
+        result = 31 * result + Arrays.hashCode(privilegeNames);
+        return result;
+    }
+}

+ 77 - 0
client/rest-high-level/src/main/java/org/elasticsearch/client/security/GetPrivilegesResponse.java

@@ -0,0 +1,77 @@
+/*
+ * 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.ApplicationPrivilege;
+import org.elasticsearch.common.xcontent.XContentParser;
+import org.elasticsearch.common.xcontent.XContentParserUtils;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Objects;
+import java.util.Set;
+
+/**
+ * Get application privileges response
+ */
+public final class GetPrivilegesResponse {
+
+    private Set<ApplicationPrivilege> privileges;
+
+    public Set<ApplicationPrivilege> getPrivileges() {
+        return privileges;
+    }
+
+    public GetPrivilegesResponse(Collection<ApplicationPrivilege> privileges) {
+        this.privileges = Collections.unmodifiableSet(new HashSet<>(privileges));
+    }
+
+    public static GetPrivilegesResponse fromXContent(XContentParser parser) throws IOException {
+        XContentParserUtils.ensureExpectedToken(XContentParser.Token.START_OBJECT, parser.nextToken(), parser::getTokenLocation);
+        List<ApplicationPrivilege> privileges = new ArrayList<>();
+        XContentParser.Token token;
+        while ((token = parser.nextToken()) != null) {
+            if (token == XContentParser.Token.FIELD_NAME) {
+                XContentParserUtils.ensureExpectedToken(XContentParser.Token.START_OBJECT, parser.nextToken(), parser::getTokenLocation);
+                while (parser.nextToken() != XContentParser.Token.END_OBJECT) {
+                    privileges.add(ApplicationPrivilege.PARSER.parse(parser, null));
+                }
+            }
+        }
+        return new GetPrivilegesResponse(new HashSet<>(privileges));
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) return true;
+        if (o == null || getClass() != o.getClass()) return false;
+        GetPrivilegesResponse that = (GetPrivilegesResponse) o;
+        return Objects.equals(privileges, that.privileges);
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(privileges);
+    }
+}

+ 174 - 0
client/rest-high-level/src/main/java/org/elasticsearch/client/security/user/privileges/ApplicationPrivilege.java

@@ -0,0 +1,174 @@
+/*
+ * 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.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.ObjectParser;
+import org.elasticsearch.common.xcontent.XContentParser;
+
+import java.io.IOException;
+
+import java.util.Arrays;
+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;
+
+/**
+ * Represents an application specific privilege. The application name, privilege name,
+ * actions and metadata are completely managed by the client and can contain arbitrary
+ * string values.
+ */
+public final class ApplicationPrivilege {
+
+    private static final ParseField APPLICATION = new ParseField("application");
+    private static final ParseField NAME = new ParseField("name");
+    private static final ParseField ACTIONS = new ParseField("actions");
+    private static final ParseField METADATA = new ParseField("metadata");
+
+    private final String application;
+    private final String name;
+    private final Set<String> actions;
+    private final Map<String, Object> metadata;
+
+    public ApplicationPrivilege(String application, String name, Collection<String> actions, @Nullable Map<String, Object> metadata) {
+        if (Strings.isNullOrEmpty(application)) {
+            throw new IllegalArgumentException("application name must be provided");
+        } else {
+            this.application = application;
+        }
+        if (Strings.isNullOrEmpty(name)) {
+            throw new IllegalArgumentException("privilege name must be provided");
+        } else {
+            this.name = name;
+        }
+        if (actions == null || actions.isEmpty()) {
+            throw new IllegalArgumentException("actions must be provided");
+        } else {
+            this.actions = Collections.unmodifiableSet(new HashSet<>(actions));
+        }
+        if (metadata == null || metadata.isEmpty()) {
+            this.metadata = Collections.emptyMap();
+        } else {
+            this.metadata = Collections.unmodifiableMap(metadata);
+        }
+    }
+
+    public String getApplication() {
+        return application;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public Set<String> getActions() {
+        return actions;
+    }
+
+    public Map<String, Object> getMetadata() {
+        return metadata;
+    }
+
+    @SuppressWarnings("unchecked")
+    public static final ConstructingObjectParser<ApplicationPrivilege, String> PARSER = new ConstructingObjectParser<>(
+        "application_privilege",
+        true, args -> new ApplicationPrivilege((String) args[0], (String) args[1], (Collection<String>) args[2],
+        (Map<String, Object>) args[3]));
+
+    static {
+        PARSER.declareString(constructorArg(), APPLICATION);
+        PARSER.declareString(constructorArg(), NAME);
+        PARSER.declareStringArray(constructorArg(), ACTIONS);
+        PARSER.declareField(optionalConstructorArg(), XContentParser::map, ApplicationPrivilege.METADATA, ObjectParser.ValueType.OBJECT);
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) return true;
+        if (o == null || getClass() != o.getClass()) return false;
+        ApplicationPrivilege that = (ApplicationPrivilege) o;
+        return Objects.equals(application, that.application) &&
+            Objects.equals(name, that.name) &&
+            Objects.equals(actions, that.actions) &&
+            Objects.equals(metadata, that.metadata);
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(application, name, actions, metadata);
+    }
+
+    static ApplicationPrivilege fromXContent(XContentParser parser) throws IOException {
+        return PARSER.parse(parser, null);
+    }
+
+    public static Builder builder() {
+        return new Builder();
+    }
+
+    public static final class Builder {
+        private String applicationName = null;
+        private String privilegeName = null;
+        private Collection<String> actions = null;
+        private Map<String, Object> metadata = null;
+
+        private Builder() {
+        }
+
+        public Builder application(String applicationName) {
+            this.applicationName = Objects.requireNonNull(applicationName, "application name must be provided");
+            return this;
+        }
+
+        public Builder privilege(String privilegeName) {
+            this.privilegeName = Objects.requireNonNull(privilegeName, "privilege name must be provided");
+            return this;
+        }
+
+        public Builder actions(String... actions) {
+            this.actions = Arrays.asList(Objects.requireNonNull(actions));
+            return this;
+        }
+
+        public Builder actions(Collection<String> actions) {
+            this.actions = Objects.requireNonNull(actions);
+            return this;
+        }
+
+        public Builder metadata(Map<String, Object> metadata) {
+            this.metadata = metadata;
+            return this;
+        }
+
+        public ApplicationPrivilege build() {
+            return new ApplicationPrivilege(applicationName, privilegeName, actions, metadata);
+        }
+    }
+
+}

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

@@ -29,6 +29,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.GetPrivilegesRequest;
 import org.elasticsearch.client.security.GetRoleMappingsRequest;
 import org.elasticsearch.client.security.ChangePasswordRequest;
 import org.elasticsearch.client.security.PutRoleMappingRequest;
@@ -243,6 +244,50 @@ public class SecurityRequestConvertersTests extends ESTestCase {
         assertToXContentBody(createTokenRequest, request.getEntity());
     }
 
+    public void testGetApplicationPrivilege() throws Exception {
+        final String application = randomAlphaOfLength(6);
+        final String privilege = randomAlphaOfLength(4);
+        GetPrivilegesRequest getPrivilegesRequest = new GetPrivilegesRequest(application, privilege);
+        Request request = SecurityRequestConverters.getPrivileges(getPrivilegesRequest);
+        assertEquals(HttpGet.METHOD_NAME, request.getMethod());
+        assertEquals("/_xpack/security/privilege/" + application + "/" + privilege, request.getEndpoint());
+        assertEquals(Collections.emptyMap(), request.getParameters());
+        assertNull(request.getEntity());
+    }
+
+    public void testGetAllApplicationPrivileges() throws Exception {
+        final String application = randomAlphaOfLength(6);
+        GetPrivilegesRequest getPrivilegesRequest = GetPrivilegesRequest.getApplicationPrivileges(application);
+        Request request = SecurityRequestConverters.getPrivileges(getPrivilegesRequest);
+        assertEquals(HttpGet.METHOD_NAME, request.getMethod());
+        assertEquals("/_xpack/security/privilege/" + application, request.getEndpoint());
+        assertEquals(Collections.emptyMap(), request.getParameters());
+        assertNull(request.getEntity());
+    }
+
+    public void testGetMultipleApplicationPrivileges() throws Exception {
+        final String application = randomAlphaOfLength(6);
+        final int numberOfPrivileges = randomIntBetween(1, 5);
+        final String[] privilegeNames =
+            randomArray(numberOfPrivileges, numberOfPrivileges, String[]::new, () -> randomAlphaOfLength(5));
+        GetPrivilegesRequest getPrivilegesRequest = new GetPrivilegesRequest(application, privilegeNames);
+        Request request = SecurityRequestConverters.getPrivileges(getPrivilegesRequest);
+        assertEquals(HttpGet.METHOD_NAME, request.getMethod());
+        assertEquals("/_xpack/security/privilege/" + application + "/" + Strings.arrayToCommaDelimitedString(privilegeNames),
+            request.getEndpoint());
+        assertEquals(Collections.emptyMap(), request.getParameters());
+        assertNull(request.getEntity());
+    }
+
+    public void testGetAllPrivileges() throws Exception {
+        GetPrivilegesRequest getPrivilegesRequest = GetPrivilegesRequest.getAllPrivileges();
+        Request request = SecurityRequestConverters.getPrivileges(getPrivilegesRequest);
+        assertEquals(HttpGet.METHOD_NAME, request.getMethod());
+        assertEquals("/_xpack/security/privilege", request.getEndpoint());
+        assertEquals(Collections.emptyMap(), request.getParameters());
+        assertNull(request.getEntity());
+    }
+
     public void testDeletePrivileges() {
         final String application = randomAlphaOfLengthBetween(1, 12);
         final List<String> privileges = randomSubsetOf(randomIntBetween(1, 3), "read", "write", "all");

+ 148 - 1
client/rest-high-level/src/test/java/org/elasticsearch/client/documentation/SecurityDocumentationIT.java

@@ -48,6 +48,8 @@ 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.GetPrivilegesRequest;
+import org.elasticsearch.client.security.GetPrivilegesResponse;
 import org.elasticsearch.client.security.GetRoleMappingsRequest;
 import org.elasticsearch.client.security.GetRoleMappingsResponse;
 import org.elasticsearch.client.security.GetSslCertificatesResponse;
@@ -65,6 +67,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.ApplicationPrivilege;
 import org.elasticsearch.client.security.user.privileges.IndicesPrivileges;
 import org.elasticsearch.common.Strings;
 import org.elasticsearch.common.util.set.Sets;
@@ -73,16 +76,19 @@ import org.elasticsearch.rest.RestStatus;
 import org.hamcrest.Matchers;
 
 import java.io.IOException;
+import java.util.Arrays;
 import java.util.Collections;
 import java.util.HashMap;
 import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
+import java.util.Set;
 import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.TimeUnit;
 
 import static org.elasticsearch.common.xcontent.XContentFactory.jsonBuilder;
 import static org.hamcrest.Matchers.contains;
+import static org.hamcrest.Matchers.containsInAnyOrder;
 import static org.hamcrest.Matchers.empty;
 import static org.hamcrest.Matchers.emptyIterable;
 import static org.hamcrest.Matchers.equalTo;
@@ -475,7 +481,7 @@ public class SecurityDocumentationIT extends ESRestHighLevelClientTestCase {
         }
 
         {
-            HasPrivilegesRequest request = new HasPrivilegesRequest(Collections.singleton("monitor"),null,null);
+            HasPrivilegesRequest request = new HasPrivilegesRequest(Collections.singleton("monitor"), null, null);
 
             // tag::has-privileges-execute-listener
             ActionListener<HasPrivilegesResponse> listener = new ActionListener<HasPrivilegesResponse>() {
@@ -987,6 +993,146 @@ public class SecurityDocumentationIT extends ESRestHighLevelClientTestCase {
         }
     }
 
+    public void testGetPrivileges() throws Exception {
+        final RestHighLevelClient client = highLevelClient();
+        final ApplicationPrivilege readTestappPrivilege =
+            new ApplicationPrivilege("testapp", "read", Arrays.asList("action:login", "data:read/*"), null);
+        final Map<String, Object> metadata = new HashMap<>();
+        metadata.put("key1", "value1");
+        final ApplicationPrivilege writeTestappPrivilege =
+            new ApplicationPrivilege("testapp", "write", Arrays.asList("action:login", "data:write/*"), metadata);
+        final ApplicationPrivilege allTestappPrivilege =
+            new ApplicationPrivilege("testapp", "all", Arrays.asList("action:login", "data:write/*", "manage:*"), null);
+        final Map<String, Object> metadata2 = new HashMap<>();
+        metadata2.put("key2", "value2");
+        final ApplicationPrivilege readTestapp2Privilege =
+            new ApplicationPrivilege("testapp2", "read", Arrays.asList("action:login", "data:read/*"), metadata2);
+        final ApplicationPrivilege writeTestapp2Privilege =
+            new ApplicationPrivilege("testapp2", "write", Arrays.asList("action:login", "data:write/*"), null);
+        final ApplicationPrivilege allTestapp2Privilege =
+            new ApplicationPrivilege("testapp2", "all", Arrays.asList("action:login", "data:write/*", "manage:*"), null);
+
+        {
+            //TODO Replace this with a call to PutPrivileges once it is implemented
+            final Request createPrivilegeRequest = new Request("POST", "/_xpack/security/privilege");
+            createPrivilegeRequest.setJsonEntity("{" +
+                "  \"testapp\": {" +
+                "    \"read\": {" +
+                "      \"actions\": [ \"action:login\", \"data:read/*\" ]" +
+                "    }," +
+                "    \"write\": {" +
+                "      \"actions\": [ \"action:login\", \"data:write/*\" ]," +
+                "      \"metadata\": { \"key1\": \"value1\" }" +
+                "    }," +
+                "    \"all\": {" +
+                "      \"actions\": [ \"action:login\", \"data:write/*\" , \"manage:*\"]" +
+                "    }" +
+                "  }," +
+                "  \"testapp2\": {" +
+                "    \"read\": {" +
+                "      \"actions\": [ \"action:login\", \"data:read/*\" ]," +
+                "      \"metadata\": { \"key2\": \"value2\" }" +
+                "    }," +
+                "    \"write\": {" +
+                "      \"actions\": [ \"action:login\", \"data:write/*\" ]" +
+                "    }," +
+                "    \"all\": {" +
+                "      \"actions\": [ \"action:login\", \"data:write/*\" , \"manage:*\"]" +
+                "    }" +
+                "  }" +
+                "}");
+            final Response createPrivilegeResponse = client.getLowLevelClient().performRequest(createPrivilegeRequest);
+            assertEquals(RestStatus.OK.getStatus(), createPrivilegeResponse.getStatusLine().getStatusCode());
+        }
+
+        {
+            //tag::get-privileges-request
+            GetPrivilegesRequest request = new GetPrivilegesRequest("testapp", "write");
+            //end::get-privileges-request
+            //tag::get-privileges-execute
+            GetPrivilegesResponse response = client.security().getPrivileges(request, RequestOptions.DEFAULT);
+            //end::get-privileges-execute
+            assertNotNull(response);
+            assertThat(response.getPrivileges().size(), equalTo(1));
+            assertThat(response.getPrivileges().contains(writeTestappPrivilege), equalTo(true));
+        }
+
+        {
+            //tag::get-all-application-privileges-request
+            GetPrivilegesRequest request = GetPrivilegesRequest.getApplicationPrivileges("testapp");
+            //end::get-all-application-privileges-request
+            GetPrivilegesResponse response = client.security().getPrivileges(request, RequestOptions.DEFAULT);
+
+            assertNotNull(response);
+            assertThat(response.getPrivileges().size(), equalTo(3));
+            final GetPrivilegesResponse exptectedResponse =
+                new GetPrivilegesResponse(Arrays.asList(readTestappPrivilege, writeTestappPrivilege, allTestappPrivilege));
+            assertThat(response, equalTo(exptectedResponse));
+            Set<ApplicationPrivilege> privileges = response.getPrivileges();
+            for (ApplicationPrivilege privilege : privileges) {
+                assertThat(privilege.getApplication(), equalTo("testapp"));
+                if (privilege.getName().equals("read")) {
+                    assertThat(privilege.getActions(), containsInAnyOrder("action:login", "data:read/*"));
+                    assertThat(privilege.getMetadata().isEmpty(), equalTo(true));
+                } else if (privilege.getName().equals("write")) {
+                    assertThat(privilege.getActions(), containsInAnyOrder("action:login", "data:write/*"));
+                    assertThat(privilege.getMetadata().isEmpty(), equalTo(false));
+                    assertThat(privilege.getMetadata().get("key1"), equalTo("value1"));
+                } else if (privilege.getName().equals("all")) {
+                    assertThat(privilege.getActions(), containsInAnyOrder("action:login", "data:write/*", "manage:*"));
+                    assertThat(privilege.getMetadata().isEmpty(), equalTo(true));
+                }
+            }
+        }
+
+        {
+            //tag::get-all-privileges-request
+            GetPrivilegesRequest request = GetPrivilegesRequest.getAllPrivileges();
+            //end::get-all-privileges-request
+            GetPrivilegesResponse response = client.security().getPrivileges(request, RequestOptions.DEFAULT);
+
+            assertNotNull(response);
+            assertThat(response.getPrivileges().size(), equalTo(6));
+            final GetPrivilegesResponse exptectedResponse =
+                new GetPrivilegesResponse(Arrays.asList(readTestappPrivilege, writeTestappPrivilege, allTestappPrivilege,
+                    readTestapp2Privilege, writeTestapp2Privilege, allTestapp2Privilege));
+            assertThat(response, equalTo(exptectedResponse));
+        }
+
+        {
+            GetPrivilegesRequest request = new GetPrivilegesRequest("testapp", "read");
+            //tag::get-privileges-execute-listener
+            ActionListener<GetPrivilegesResponse> listener = new ActionListener<GetPrivilegesResponse>() {
+                @Override
+                public void onResponse(GetPrivilegesResponse getPrivilegesResponse) {
+                    // <1>
+                }
+
+                @Override
+                public void onFailure(Exception e) {
+                    // <2>
+                }
+            };
+            //end::get-privileges-execute-listener
+
+            // Avoid unused variable warning
+            assertNotNull(listener);
+
+            // Replace the empty listener by a blocking listener in test
+            final PlainActionFuture<GetPrivilegesResponse> future = new PlainActionFuture<>();
+            listener = future;
+
+            //tag::get-privileges-execute-async
+            client.security().getPrivilegesAsync(request, RequestOptions.DEFAULT, listener); // <1>
+            //end::get-privileges-execute-async
+
+            final GetPrivilegesResponse response = future.get(30, TimeUnit.SECONDS);
+            assertNotNull(response);
+            assertThat(response.getPrivileges().size(), equalTo(1));
+            assertThat(response.getPrivileges().contains(readTestappPrivilege), equalTo(true));
+        }
+    }
+
     public void testDeletePrivilege() throws Exception {
         RestHighLevelClient client = highLevelClient();
         {
@@ -1061,3 +1207,4 @@ public class SecurityDocumentationIT extends ESRestHighLevelClientTestCase {
         }
     }
 }
+

+ 65 - 0
client/rest-high-level/src/test/java/org/elasticsearch/client/security/GetPrivilegesRequestTests.java

@@ -0,0 +1,65 @@
+/*
+ * 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.equalTo;
+
+public class GetPrivilegesRequestTests extends ESTestCase {
+
+    public void testGetPrivilegesRequest() {
+        final String applicationName = randomAlphaOfLength(5);
+        final int numberOfPrivileges = randomIntBetween(0, 5);
+        final String[] privilegeNames = randomBoolean() ? null : randomArray(numberOfPrivileges, numberOfPrivileges, String[]::new,
+            () -> randomAlphaOfLength(5));
+        final GetPrivilegesRequest getPrivilegesRequest = new GetPrivilegesRequest(applicationName, privilegeNames);
+        assertThat(getPrivilegesRequest.getApplicationName(), equalTo(applicationName));
+        assertThat(getPrivilegesRequest.getPrivilegeNames(), equalTo(privilegeNames));
+    }
+    
+    public void testPrivilegeWithoutApplication() {
+        IllegalArgumentException e = expectThrows(IllegalArgumentException.class, () -> {
+            new GetPrivilegesRequest(null, randomAlphaOfLength(5));
+        });
+        assertThat(e.getMessage(), equalTo("privilege cannot be specified when application is missing"));
+    }
+
+    public void testEqualsAndHashCode() {
+        final String applicationName = randomAlphaOfLength(5);
+        final int numberOfPrivileges = randomIntBetween(0, 5);
+        final String[] privilegeNames =
+            randomArray(numberOfPrivileges, numberOfPrivileges, String[]::new, () -> randomAlphaOfLength(5));
+        final GetPrivilegesRequest getPrivilegesRequest = new GetPrivilegesRequest(applicationName, privilegeNames);
+        final EqualsHashCodeTestUtils.MutateFunction<GetPrivilegesRequest> mutate = r -> {
+            if (randomBoolean()) {
+                final int numberOfNewPrivileges = randomIntBetween(1, 5);
+                final String[] newPrivilegeNames =
+                    randomArray(numberOfNewPrivileges, numberOfNewPrivileges, String[]::new, () -> randomAlphaOfLength(5));
+                return new GetPrivilegesRequest(applicationName, newPrivilegeNames);
+            } else {
+                return GetPrivilegesRequest.getApplicationPrivileges(randomAlphaOfLength(6));
+            }
+        };
+        EqualsHashCodeTestUtils.checkEqualsAndHashCode(getPrivilegesRequest,
+            r -> new GetPrivilegesRequest(r.getApplicationName(), r.getPrivilegeNames()), mutate);
+    }
+}

+ 154 - 0
client/rest-high-level/src/test/java/org/elasticsearch/client/security/GetPrivilegesResponseTests.java

@@ -0,0 +1,154 @@
+/*
+ * 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.ApplicationPrivilege;
+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.Arrays;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import static org.hamcrest.Matchers.equalTo;
+
+public class GetPrivilegesResponseTests extends ESTestCase {
+
+    public void testFromXContent() throws IOException {
+        final String json = "{" +
+            "  \"testapp\": {" +
+            "    \"read\": {" +
+            "      \"application\": \"testapp\"," +
+            "      \"name\": \"read\"," +
+            "      \"actions\": [ \"action:login\", \"data:read/*\" ]" +
+            "    }," +
+            "    \"write\": {" +
+            "      \"application\": \"testapp\"," +
+            "      \"name\": \"write\"," +
+            "      \"actions\": [ \"action:login\", \"data:write/*\" ]," +
+            "      \"metadata\": { \"key1\": \"value1\" }" +
+            "    }," +
+            "    \"all\": {" +
+            "      \"application\": \"testapp\"," +
+            "      \"name\": \"all\"," +
+            "      \"actions\": [ \"action:login\", \"data:write/*\" , \"manage:*\"]" +
+            "    }" +
+            "  }," +
+            "  \"testapp2\": {" +
+            "    \"read\": {" +
+            "      \"application\": \"testapp2\"," +
+            "      \"name\": \"read\"," +
+            "      \"actions\": [ \"action:login\", \"data:read/*\" ]," +
+            "      \"metadata\": { \"key2\": \"value2\" }" +
+            "    }," +
+            "    \"write\": {" +
+            "      \"application\": \"testapp2\"," +
+            "      \"name\": \"write\"," +
+            "      \"actions\": [ \"action:login\", \"data:write/*\" ]" +
+            "    }," +
+            "    \"all\": {" +
+            "      \"application\": \"testapp2\"," +
+            "      \"name\": \"all\"," +
+            "      \"actions\": [ \"action:login\", \"data:write/*\" , \"manage:*\"]" +
+            "    }" +
+            "  }" +
+            "}";
+
+        final GetPrivilegesResponse response = GetPrivilegesResponse.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 ApplicationPrivilege readTestappPrivilege =
+            new ApplicationPrivilege("testapp", "read", Arrays.asList("action:login", "data:read/*"), null);
+        final Map<String, Object> metadata = new HashMap<>();
+        metadata.put("key1", "value1");
+        final ApplicationPrivilege writeTestappPrivilege =
+            new ApplicationPrivilege("testapp", "write", Arrays.asList("action:login", "data:write/*"), metadata);
+        final ApplicationPrivilege allTestappPrivilege =
+            new ApplicationPrivilege("testapp", "all", Arrays.asList("action:login", "data:write/*", "manage:*"), null);
+        final Map<String, Object> metadata2 = new HashMap<>();
+        metadata2.put("key2", "value2");
+        final ApplicationPrivilege readTestapp2Privilege =
+            new ApplicationPrivilege("testapp2", "read", Arrays.asList("action:login", "data:read/*"), metadata2);
+        final ApplicationPrivilege writeTestapp2Privilege =
+            new ApplicationPrivilege("testapp2", "write", Arrays.asList("action:login", "data:write/*"), null);
+        final ApplicationPrivilege allTestapp2Privilege =
+            new ApplicationPrivilege("testapp2", "all", Arrays.asList("action:login", "data:write/*", "manage:*"), null);
+        final GetPrivilegesResponse exptectedResponse =
+            new GetPrivilegesResponse(Arrays.asList(readTestappPrivilege, writeTestappPrivilege, allTestappPrivilege,
+                readTestapp2Privilege, writeTestapp2Privilege, allTestapp2Privilege));
+        assertThat(response, equalTo(exptectedResponse));
+    }
+
+    public void testEqualsHashCode() {
+        final List<ApplicationPrivilege> privileges = new ArrayList<>();
+        final List<ApplicationPrivilege> privileges2 = new ArrayList<>();
+        final Map<String, Object> metadata = new HashMap<>();
+        metadata.put("key1", "value1");
+        final ApplicationPrivilege writePrivilege =
+            new ApplicationPrivilege("testapp", "write", Arrays.asList("action:login", "data:write/*"),
+                metadata);
+        final ApplicationPrivilege readPrivilege =
+            new ApplicationPrivilege("testapp", "read", Arrays.asList("data:read/*", "action:login"),
+                metadata);
+        privileges.add(readPrivilege);
+        privileges.add(writePrivilege);
+        privileges2.add(writePrivilege);
+        privileges2.add(readPrivilege);
+        final GetPrivilegesResponse response = new GetPrivilegesResponse(privileges);
+        EqualsHashCodeTestUtils.checkEqualsAndHashCode(response, (original) -> {
+            return new GetPrivilegesResponse(original.getPrivileges());
+        });
+        EqualsHashCodeTestUtils.checkEqualsAndHashCode(response, (original) -> {
+            return new GetPrivilegesResponse(original.getPrivileges());
+        }, GetPrivilegesResponseTests::mutateTestItem);
+    }
+
+    private static GetPrivilegesResponse mutateTestItem(GetPrivilegesResponse original) {
+        if (randomBoolean()) {
+            Set<ApplicationPrivilege> originalPrivileges = original.getPrivileges();
+            List<ApplicationPrivilege> privileges = new ArrayList<>();
+            privileges.addAll(originalPrivileges);
+            privileges.add(new ApplicationPrivilege("testapp", "all", Arrays.asList("action:login", "data:read/*", "manage:*"), null));
+            return new GetPrivilegesResponse(privileges);
+        } else {
+            final List<ApplicationPrivilege> privileges = new ArrayList<>();
+            final ApplicationPrivilege privilege =
+                new ApplicationPrivilege("testapp", "all", Arrays.asList("action:login", "data:write/*", "manage:*"), null);
+            privileges.add(privilege);
+            return new GetPrivilegesResponse(privileges);
+        }
+    }
+}

+ 110 - 0
client/rest-high-level/src/test/java/org/elasticsearch/client/security/user/privileges/ApplicationPrivilegeTests.java

@@ -0,0 +1,110 @@
+/*
+ * 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.user.privileges;
+
+import org.elasticsearch.common.xcontent.DeprecationHandler;
+import org.elasticsearch.common.xcontent.NamedXContentRegistry;
+import org.elasticsearch.common.xcontent.XContentType;
+import org.elasticsearch.test.ESTestCase;
+
+import java.io.IOException;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import static org.hamcrest.Matchers.containsInAnyOrder;
+import static org.hamcrest.Matchers.equalTo;
+
+public class ApplicationPrivilegeTests extends ESTestCase {
+
+    public void testFromXContent() throws IOException {
+        String json =
+            "    {" +
+                "      \"application\": \"myapp\"," +
+                "      \"name\": \"read\"," +
+                "      \"actions\": [" +
+                "        \"data:read/*\"," +
+                "        \"action:login\"" +
+                "      ],\n" +
+                "      \"metadata\": {" +
+                "        \"description\": \"Read access to myapp\"" +
+                "      }" +
+                "    }";
+        final ApplicationPrivilege privilege = ApplicationPrivilege.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 Map<String, Object> metadata = new HashMap<>();
+        metadata.put("description", "Read access to myapp");
+        final ApplicationPrivilege expectedPrivilege =
+            new ApplicationPrivilege("myapp", "read", Arrays.asList("data:read/*", "action:login"), metadata);
+        assertThat(privilege, equalTo(expectedPrivilege));
+    }
+
+    public void testEmptyApplicationName() {
+        final Map<String, Object> metadata = new HashMap<>();
+        metadata.put("description", "Read access to myapp");
+        final String applicationName = randomBoolean() ? null : "";
+        final IllegalArgumentException e = expectThrows(IllegalArgumentException.class, () ->
+            new ApplicationPrivilege(applicationName, "read", Arrays.asList("data:read/*", "action:login"), metadata));
+        assertThat(e.getMessage(), equalTo("application name must be provided"));
+    }
+
+    public void testEmptyPrivilegeName() {
+        final Map<String, Object> metadata = new HashMap<>();
+        metadata.put("description", "Read access to myapp");
+        final String privilegenName = randomBoolean() ? null : "";
+        final IllegalArgumentException e = expectThrows(IllegalArgumentException.class, () ->
+            new ApplicationPrivilege("myapp", privilegenName, Arrays.asList("data:read/*", "action:login"), metadata));
+        assertThat(e.getMessage(), equalTo("privilege name must be provided"));
+    }
+
+    public void testEmptyActions() {
+        final Map<String, Object> metadata = new HashMap<>();
+        metadata.put("description", "Read access to myapp");
+        final List<String> actions = randomBoolean() ? null : Collections.emptyList();
+        final IllegalArgumentException e = expectThrows(IllegalArgumentException.class, () ->
+            new ApplicationPrivilege("myapp", "read", actions, metadata));
+        assertThat(e.getMessage(), equalTo("actions must be provided"));
+    }
+
+    public void testBuilder() {
+        final Map<String, Object> metadata = new HashMap<>();
+        metadata.put("description", "Read access to myapp");
+        ApplicationPrivilege privilege = ApplicationPrivilege.builder()
+            .application("myapp")
+            .privilege("read")
+            .actions("data:read/*", "action:login")
+            .metadata(metadata)
+            .build();
+        assertThat(privilege.getApplication(), equalTo("myapp"));
+        assertThat(privilege.getName(), equalTo("read"));
+        assertThat(privilege.getActions(), containsInAnyOrder("data:read/*", "action:login"));
+        assertThat(privilege.getMetadata(), equalTo(metadata));
+    }
+}

+ 47 - 0
docs/java-rest/high-level/security/get-privileges.asciidoc

@@ -0,0 +1,47 @@
+
+--
+:api: get-privileges
+:request: GetPrivilegesRequest
+:respnse: GetPrivilegesResponse
+--
+
+[id="{upid}-{api}"]
+=== Get Privileges API
+
+[id="{upid}-{api}-request"]
+==== Get Privileges Request
+
+The +{request}+ supports getting privilege(s) for all or for specific applications.
+
+===== Specific privilege of a specific application
+
+["source","java",subs="attributes,callouts,macros"]
+--------------------------------------------------
+include-tagged::{doc-tests-file}[{api}-request]
+--------------------------------------------------
+
+===== All privileges of a specific application
+
+["source","java",subs="attributes,callouts,macros"]
+--------------------------------------------------
+include-tagged::{doc-tests-file}[get-all-application-privileges-request]
+--------------------------------------------------
+
+===== All privileges of all applications
+
+["source","java",subs="attributes,callouts,macros"]
+--------------------------------------------------
+include-tagged::{doc-tests-file}[get-all-privileges-request]
+--------------------------------------------------
+
+include::../execution.asciidoc[]
+
+[id="{upid}-{api}-response"]
+==== Get Privileges Response
+
+The returned +{response}+ allows to get information about the retrieved privileges as follows.
+
+["source","java",subs="attributes,callouts,macros"]
+--------------------------------------------------
+include-tagged::{doc-tests-file}[{api}-response]
+--------------------------------------------------

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

@@ -375,6 +375,7 @@ The Java High Level REST Client supports the following Security APIs:
 * <<java-rest-high-security-delete-role-mapping>>
 * <<java-rest-high-security-create-token>>
 * <<{upid}-invalidate-token>>
+* <<{upid}-get-privileges>>
 * <<{upid}-delete-privileges>>
 
 include::security/put-user.asciidoc[]
@@ -383,6 +384,7 @@ include::security/disable-user.asciidoc[]
 include::security/change-password.asciidoc[]
 include::security/delete-role.asciidoc[]
 include::security/delete-privileges.asciidoc[]
+include::security/get-privileges.asciidoc[]
 include::security/clear-roles-cache.asciidoc[]
 include::security/clear-realm-cache.asciidoc[]
 include::security/authenticate.asciidoc[]