mirror of
https://github.com/honeymoose/OpenSearch.git
synced 2025-02-26 06:46:10 +00:00
HLRC: Add "_has_privileges" API to Security Client (#35479)
This adds the "hasPrivileges()" method to SecurityClient, including request, response & async variant of the method. Also includes API documentation.
This commit is contained in:
parent
0cdfc4cd0a
commit
87a8b99724
@ -42,6 +42,8 @@ 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.HasPrivilegesRequest;
|
||||
import org.elasticsearch.client.security.HasPrivilegesResponse;
|
||||
import org.elasticsearch.client.security.InvalidateTokenRequest;
|
||||
import org.elasticsearch.client.security.InvalidateTokenResponse;
|
||||
import org.elasticsearch.client.security.PutRoleMappingRequest;
|
||||
@ -244,6 +246,34 @@ public final class SecurityClient {
|
||||
AuthenticateResponse::fromXContent, listener, emptySet());
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine whether the current user has a specified list of privileges
|
||||
* See <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/security-api-has-privileges.html">
|
||||
* the docs</a> for more.
|
||||
*
|
||||
* @param request the request with the privileges to check
|
||||
* @param options the request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
|
||||
* @return the response from the has privileges call
|
||||
*/
|
||||
public HasPrivilegesResponse hasPrivileges(HasPrivilegesRequest request, RequestOptions options) throws IOException {
|
||||
return restHighLevelClient.performRequestAndParseEntity(request, SecurityRequestConverters::hasPrivileges, options,
|
||||
HasPrivilegesResponse::fromXContent, emptySet());
|
||||
}
|
||||
|
||||
/**
|
||||
* Asynchronously determine whether the current user has a specified list of privileges
|
||||
* See <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/security-api-has-privileges.html">
|
||||
* the docs</a> for more.
|
||||
*
|
||||
* @param request the request with the privileges to check
|
||||
* @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 hasPrivilegesAsync(HasPrivilegesRequest request, RequestOptions options, ActionListener<HasPrivilegesResponse> listener) {
|
||||
restHighLevelClient.performRequestAsyncAndParseEntity(request, SecurityRequestConverters::hasPrivileges, options,
|
||||
HasPrivilegesResponse::fromXContent, listener, emptySet());
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears the cache in one or more realms.
|
||||
* See <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/security-api-clear-cache.html">
|
||||
|
@ -30,6 +30,7 @@ import org.elasticsearch.client.security.CreateTokenRequest;
|
||||
import org.elasticsearch.client.security.DeletePrivilegesRequest;
|
||||
import org.elasticsearch.client.security.DeleteRoleMappingRequest;
|
||||
import org.elasticsearch.client.security.DeleteRoleRequest;
|
||||
import org.elasticsearch.client.security.HasPrivilegesRequest;
|
||||
import org.elasticsearch.client.security.DisableUserRequest;
|
||||
import org.elasticsearch.client.security.EnableUserRequest;
|
||||
import org.elasticsearch.client.security.GetRoleMappingsRequest;
|
||||
@ -114,6 +115,12 @@ final class SecurityRequestConverters {
|
||||
return request;
|
||||
}
|
||||
|
||||
static Request hasPrivileges(HasPrivilegesRequest hasPrivilegesRequest) throws IOException {
|
||||
Request request = new Request(HttpGet.METHOD_NAME, "/_xpack/security/user/_has_privileges");
|
||||
request.setEntity(createEntity(hasPrivilegesRequest, REQUEST_BODY_CONTENT_TYPE));
|
||||
return request;
|
||||
}
|
||||
|
||||
static Request clearRealmCache(ClearRealmCacheRequest clearRealmCacheRequest) {
|
||||
RequestConverters.EndpointBuilder builder = new RequestConverters.EndpointBuilder()
|
||||
.addPathPartAsIs("_xpack/security/realm");
|
||||
|
@ -0,0 +1,96 @@
|
||||
/*
|
||||
* 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.client.security.user.privileges.ApplicationResourcePrivileges;
|
||||
import org.elasticsearch.client.security.user.privileges.IndicesPrivileges;
|
||||
import org.elasticsearch.common.Nullable;
|
||||
import org.elasticsearch.common.xcontent.ToXContentObject;
|
||||
import org.elasticsearch.common.xcontent.XContentBuilder;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
|
||||
import static java.util.Collections.emptySet;
|
||||
import static java.util.Collections.unmodifiableSet;
|
||||
|
||||
/**
|
||||
* Request to determine whether the current user has a list of privileges.
|
||||
*/
|
||||
public final class HasPrivilegesRequest implements Validatable, ToXContentObject {
|
||||
|
||||
private final Set<String> clusterPrivileges;
|
||||
private final Set<IndicesPrivileges> indexPrivileges;
|
||||
private final Set<ApplicationResourcePrivileges> applicationPrivileges;
|
||||
|
||||
public HasPrivilegesRequest(@Nullable Set<String> clusterPrivileges,
|
||||
@Nullable Set<IndicesPrivileges> indexPrivileges,
|
||||
@Nullable Set<ApplicationResourcePrivileges> applicationPrivileges) {
|
||||
this.clusterPrivileges = clusterPrivileges == null ? emptySet() : unmodifiableSet(clusterPrivileges);
|
||||
this.indexPrivileges = indexPrivileges == null ? emptySet() : unmodifiableSet(indexPrivileges);
|
||||
this.applicationPrivileges = applicationPrivileges == null ? emptySet() : unmodifiableSet(applicationPrivileges);
|
||||
|
||||
if (this.clusterPrivileges.isEmpty() && this.indexPrivileges.isEmpty() && this.applicationPrivileges.isEmpty()) {
|
||||
throw new IllegalArgumentException("At last 1 privilege must be specified");
|
||||
}
|
||||
}
|
||||
|
||||
public Set<String> getClusterPrivileges() {
|
||||
return clusterPrivileges;
|
||||
}
|
||||
|
||||
public Set<IndicesPrivileges> getIndexPrivileges() {
|
||||
return indexPrivileges;
|
||||
}
|
||||
|
||||
public Set<ApplicationResourcePrivileges> getApplicationPrivileges() {
|
||||
return applicationPrivileges;
|
||||
}
|
||||
|
||||
@Override
|
||||
public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException {
|
||||
return builder.startObject()
|
||||
.field("cluster", clusterPrivileges)
|
||||
.field("index", indexPrivileges)
|
||||
.field("application", applicationPrivileges)
|
||||
.endObject();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) {
|
||||
return true;
|
||||
}
|
||||
if (o == null || getClass() != o.getClass()) {
|
||||
return false;
|
||||
}
|
||||
final HasPrivilegesRequest that = (HasPrivilegesRequest) o;
|
||||
return Objects.equals(clusterPrivileges, that.clusterPrivileges) &&
|
||||
Objects.equals(indexPrivileges, that.indexPrivileges) &&
|
||||
Objects.equals(applicationPrivileges, that.applicationPrivileges);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(clusterPrivileges, indexPrivileges, applicationPrivileges);
|
||||
}
|
||||
}
|
@ -0,0 +1,252 @@
|
||||
/*
|
||||
* 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.ParseField;
|
||||
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.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.function.BiConsumer;
|
||||
|
||||
import static org.elasticsearch.common.xcontent.ConstructingObjectParser.constructorArg;
|
||||
|
||||
/**
|
||||
* Response when checking whether the current user has a defined set of privileges.
|
||||
*/
|
||||
public final class HasPrivilegesResponse {
|
||||
|
||||
private static final ConstructingObjectParser<HasPrivilegesResponse, Void> PARSER = new ConstructingObjectParser<>(
|
||||
"has_privileges_response", true, args -> new HasPrivilegesResponse(
|
||||
(String) args[0], (Boolean) args[1], checkMap(args[2], 0), checkMap(args[3], 1), checkMap(args[4], 2)));
|
||||
|
||||
static {
|
||||
PARSER.declareString(constructorArg(), new ParseField("username"));
|
||||
PARSER.declareBoolean(constructorArg(), new ParseField("has_all_requested"));
|
||||
declareMap(constructorArg(), "cluster");
|
||||
declareMap(constructorArg(), "index");
|
||||
declareMap(constructorArg(), "application");
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private static <T> Map<String, T> checkMap(Object argument, int depth) {
|
||||
if (argument instanceof Map) {
|
||||
Map<String, T> map = (Map<String, T>) argument;
|
||||
if (depth == 0) {
|
||||
map.values().stream()
|
||||
.filter(val -> (val instanceof Boolean) == false)
|
||||
.forEach(val -> {
|
||||
throw new IllegalArgumentException("Map value [" + val + "] in [" + map + "] is not a Boolean");
|
||||
});
|
||||
} else {
|
||||
map.values().stream().forEach(val -> checkMap(val, depth - 1));
|
||||
}
|
||||
return map;
|
||||
}
|
||||
throw new IllegalArgumentException("Value [" + argument + "] is not an Object");
|
||||
}
|
||||
|
||||
private static void declareMap(BiConsumer<HasPrivilegesResponse, Map<String, Object>> arg, String name) {
|
||||
PARSER.declareField(arg, XContentParser::map, new ParseField(name), ObjectParser.ValueType.OBJECT);
|
||||
}
|
||||
|
||||
private final String username;
|
||||
private final boolean hasAllRequested;
|
||||
private final Map<String, Boolean> clusterPrivileges;
|
||||
private final Map<String, Map<String, Boolean>> indexPrivileges;
|
||||
private final Map<String, Map<String, Map<String, Boolean>>> applicationPrivileges;
|
||||
|
||||
public HasPrivilegesResponse(String username, boolean hasAllRequested,
|
||||
Map<String, Boolean> clusterPrivileges,
|
||||
Map<String, Map<String, Boolean>> indexPrivileges,
|
||||
Map<String, Map<String, Map<String, Boolean>>> applicationPrivileges) {
|
||||
this.username = username;
|
||||
this.hasAllRequested = hasAllRequested;
|
||||
this.clusterPrivileges = Collections.unmodifiableMap(clusterPrivileges);
|
||||
this.indexPrivileges = unmodifiableMap2(indexPrivileges);
|
||||
this.applicationPrivileges = unmodifiableMap3(applicationPrivileges);
|
||||
}
|
||||
|
||||
private static Map<String, Map<String, Boolean>> unmodifiableMap2(final Map<String, Map<String, Boolean>> map) {
|
||||
final Map<String, Map<String, Boolean>> copy = new HashMap<>(map);
|
||||
copy.replaceAll((k, v) -> Collections.unmodifiableMap(v));
|
||||
return Collections.unmodifiableMap(copy);
|
||||
}
|
||||
|
||||
private static Map<String, Map<String, Map<String, Boolean>>> unmodifiableMap3(
|
||||
final Map<String, Map<String, Map<String, Boolean>>> map) {
|
||||
final Map<String, Map<String, Map<String, Boolean>>> copy = new HashMap<>(map);
|
||||
copy.replaceAll((k, v) -> unmodifiableMap2(v));
|
||||
return Collections.unmodifiableMap(copy);
|
||||
}
|
||||
|
||||
public static HasPrivilegesResponse fromXContent(XContentParser parser) throws IOException {
|
||||
return PARSER.parse(parser, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* The username (principal) of the user for which the privileges check was executed.
|
||||
*/
|
||||
public String getUsername() {
|
||||
return username;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@code true} if the user has every privilege that was checked. Otherwise {@code false}.
|
||||
*/
|
||||
public boolean hasAllRequested() {
|
||||
return hasAllRequested;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param clusterPrivilegeName The name of a cluster privilege. This privilege must have been specified (verbatim) in the
|
||||
* {@link HasPrivilegesRequest#getClusterPrivileges() cluster privileges of the request}.
|
||||
* @return {@code true} if the user has the specified cluster privilege. {@code false} if the privilege was checked
|
||||
* but it has not been granted to the user.
|
||||
* @throws IllegalArgumentException if the response did not include a value for the specified privilege name.
|
||||
* The response only includes values for privileges that were
|
||||
* {@link HasPrivilegesRequest#getClusterPrivileges() included in the request}.
|
||||
*/
|
||||
public boolean hasClusterPrivilege(String clusterPrivilegeName) throws IllegalArgumentException {
|
||||
Boolean has = clusterPrivileges.get(clusterPrivilegeName);
|
||||
if (has == null) {
|
||||
throw new IllegalArgumentException("Cluster privilege [" + clusterPrivilegeName + "] was not included in this response");
|
||||
}
|
||||
return has;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param indexName The name of the index to check. This index must have been specified (verbatim) in the
|
||||
* {@link HasPrivilegesRequest#getIndexPrivileges() requested index privileges}.
|
||||
* @param privilegeName The name of the index privilege to check. This privilege must have been specified (verbatim), for the
|
||||
* given index, in the {@link HasPrivilegesRequest#getIndexPrivileges() requested index privileges}.
|
||||
* @return {@code true} if the user has the specified privilege on the specified index. {@code false} if the privilege was checked
|
||||
* for that index and was not granted to the user.
|
||||
* @throws IllegalArgumentException if the response did not include a value for the specified index and privilege name pair.
|
||||
* The response only includes values for indices and privileges that were
|
||||
* {@link HasPrivilegesRequest#getIndexPrivileges() included in the request}.
|
||||
*/
|
||||
public boolean hasIndexPrivilege(String indexName, String privilegeName) {
|
||||
Map<String, Boolean> indexPrivileges = this.indexPrivileges.get(indexName);
|
||||
if (indexPrivileges == null) {
|
||||
throw new IllegalArgumentException("No privileges for index [" + indexName + "] were included in this response");
|
||||
}
|
||||
Boolean has = indexPrivileges.get(privilegeName);
|
||||
if (has == null) {
|
||||
throw new IllegalArgumentException("Privilege [" + privilegeName + "] was not included in the response for index ["
|
||||
+ indexName + "]");
|
||||
}
|
||||
return has;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param applicationName The name of the application to check. This application must have been specified (verbatim) in the
|
||||
* {@link HasPrivilegesRequest#getApplicationPrivileges() requested application privileges}.
|
||||
* @param resourceName The name of the resource to check. This resource must have been specified (verbatim), for the given
|
||||
* application in the {@link HasPrivilegesRequest#getApplicationPrivileges() requested application privileges}.
|
||||
* @param privilegeName The name of the privilege to check. This privilege must have been specified (verbatim), for the given
|
||||
* application and resource, in the
|
||||
* {@link HasPrivilegesRequest#getApplicationPrivileges() requested application privileges}.
|
||||
* @return {@code true} if the user has the specified privilege on the specified resource in the specified application.
|
||||
* {@code false} if the privilege was checked for that application and resource, but was not granted to the user.
|
||||
* @throws IllegalArgumentException if the response did not include a value for the specified application, resource and privilege
|
||||
* triplet. The response only includes values for applications, resources and privileges that were
|
||||
* {@link HasPrivilegesRequest#getApplicationPrivileges() included in the request}.
|
||||
*/
|
||||
public boolean hasApplicationPrivilege(String applicationName, String resourceName, String privilegeName) {
|
||||
final Map<String, Map<String, Boolean>> appPrivileges = this.applicationPrivileges.get(applicationName);
|
||||
if (appPrivileges == null) {
|
||||
throw new IllegalArgumentException("No privileges for application [" + applicationName + "] were included in this response");
|
||||
}
|
||||
final Map<String, Boolean> resourcePrivileges = appPrivileges.get(resourceName);
|
||||
if (resourcePrivileges == null) {
|
||||
throw new IllegalArgumentException("No privileges for resource [" + resourceName +
|
||||
"] were included in the response for application [" + applicationName + "]");
|
||||
}
|
||||
Boolean has = resourcePrivileges.get(privilegeName);
|
||||
if (has == null) {
|
||||
throw new IllegalArgumentException("Privilege [" + privilegeName + "] was not included in the response for application [" +
|
||||
applicationName + "] and resource [" + resourceName + "]");
|
||||
}
|
||||
return has;
|
||||
}
|
||||
|
||||
/**
|
||||
* A {@code Map} from cluster-privilege-name to access. Each requested privilege is included as a key in the map, and the
|
||||
* associated value indicates whether the user was granted that privilege.
|
||||
* <p>
|
||||
* The {@link #hasClusterPrivilege} method should be used in preference to directly accessing this map.
|
||||
* </p>
|
||||
*/
|
||||
public Map<String, Boolean> getClusterPrivileges() {
|
||||
return clusterPrivileges;
|
||||
}
|
||||
|
||||
/**
|
||||
* A {@code Map} from index-name + privilege-name to access. Each requested index is a key in the outer map.
|
||||
* Each requested privilege is a key in the inner map. The inner most {@code Boolean} value indicates whether
|
||||
* the user was granted that privilege on that index.
|
||||
* <p>
|
||||
* The {@link #hasIndexPrivilege} method should be used in preference to directly accessing this map.
|
||||
* </p>
|
||||
*/
|
||||
public Map<String, Map<String, Boolean>> getIndexPrivileges() {
|
||||
return indexPrivileges;
|
||||
}
|
||||
|
||||
/**
|
||||
* A {@code Map} from application-name + resource-name + privilege-name to access. Each requested application is a key in the
|
||||
* outer-most map. Each requested resource is a key in the next-level map. The requested privileges form the keys in the inner-most map.
|
||||
* The {@code Boolean} value indicates whether the user was granted that privilege on that resource within that application.
|
||||
* <p>
|
||||
* The {@link #hasApplicationPrivilege} method should be used in preference to directly accessing this map.
|
||||
* </p>
|
||||
*/
|
||||
public Map<String, Map<String, Map<String, Boolean>>> getApplicationPrivileges() {
|
||||
return applicationPrivileges;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) {
|
||||
return true;
|
||||
}
|
||||
if (o == null || this.getClass() != o.getClass()) {
|
||||
return false;
|
||||
}
|
||||
final HasPrivilegesResponse that = (HasPrivilegesResponse) o;
|
||||
return this.hasAllRequested == that.hasAllRequested &&
|
||||
Objects.equals(this.username, that.username) &&
|
||||
Objects.equals(this.clusterPrivileges, that.clusterPrivileges) &&
|
||||
Objects.equals(this.indexPrivileges, that.indexPrivileges) &&
|
||||
Objects.equals(this.applicationPrivileges, that.applicationPrivileges);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(username, hasAllRequested, clusterPrivileges, indexPrivileges, applicationPrivileges);
|
||||
}
|
||||
}
|
||||
|
@ -51,6 +51,8 @@ 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.HasPrivilegesRequest;
|
||||
import org.elasticsearch.client.security.HasPrivilegesResponse;
|
||||
import org.elasticsearch.client.security.InvalidateTokenRequest;
|
||||
import org.elasticsearch.client.security.InvalidateTokenResponse;
|
||||
import org.elasticsearch.client.security.PutRoleMappingRequest;
|
||||
@ -63,7 +65,9 @@ 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.IndicesPrivileges;
|
||||
import org.elasticsearch.common.Strings;
|
||||
import org.elasticsearch.common.util.set.Sets;
|
||||
import org.elasticsearch.common.xcontent.XContentBuilder;
|
||||
import org.elasticsearch.rest.RestStatus;
|
||||
import org.hamcrest.Matchers;
|
||||
@ -80,6 +84,7 @@ import java.util.concurrent.TimeUnit;
|
||||
import static org.elasticsearch.common.xcontent.XContentFactory.jsonBuilder;
|
||||
import static org.hamcrest.Matchers.contains;
|
||||
import static org.hamcrest.Matchers.empty;
|
||||
import static org.hamcrest.Matchers.emptyIterable;
|
||||
import static org.hamcrest.Matchers.equalTo;
|
||||
import static org.hamcrest.Matchers.is;
|
||||
import static org.hamcrest.Matchers.isIn;
|
||||
@ -437,6 +442,67 @@ public class SecurityDocumentationIT extends ESRestHighLevelClientTestCase {
|
||||
}
|
||||
}
|
||||
|
||||
public void testHasPrivileges() throws Exception {
|
||||
RestHighLevelClient client = highLevelClient();
|
||||
{
|
||||
//tag::has-privileges-request
|
||||
HasPrivilegesRequest request = new HasPrivilegesRequest(
|
||||
Sets.newHashSet("monitor", "manage"),
|
||||
Sets.newHashSet(
|
||||
IndicesPrivileges.builder().indices("logstash-2018-10-05").privileges("read", "write").build(),
|
||||
IndicesPrivileges.builder().indices("logstash-2018-*").privileges("read").build()
|
||||
),
|
||||
null
|
||||
);
|
||||
//end::has-privileges-request
|
||||
|
||||
//tag::has-privileges-execute
|
||||
HasPrivilegesResponse response = client.security().hasPrivileges(request, RequestOptions.DEFAULT);
|
||||
//end::has-privileges-execute
|
||||
|
||||
//tag::has-privileges-response
|
||||
boolean hasMonitor = response.hasClusterPrivilege("monitor"); // <1>
|
||||
boolean hasWrite = response.hasIndexPrivilege("logstash-2018-10-05", "write"); // <2>
|
||||
boolean hasRead = response.hasIndexPrivilege("logstash-2018-*", "read"); // <3>
|
||||
//end::has-privileges-response
|
||||
|
||||
assertThat(response.getUsername(), is("test_user"));
|
||||
assertThat(response.hasAllRequested(), is(true));
|
||||
assertThat(hasMonitor, is(true));
|
||||
assertThat(hasWrite, is(true));
|
||||
assertThat(hasRead, is(true));
|
||||
assertThat(response.getApplicationPrivileges().entrySet(), emptyIterable());
|
||||
}
|
||||
|
||||
{
|
||||
HasPrivilegesRequest request = new HasPrivilegesRequest(Collections.singleton("monitor"),null,null);
|
||||
|
||||
// tag::has-privileges-execute-listener
|
||||
ActionListener<HasPrivilegesResponse> listener = new ActionListener<HasPrivilegesResponse>() {
|
||||
@Override
|
||||
public void onResponse(HasPrivilegesResponse response) {
|
||||
// <1>
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(Exception e) {
|
||||
// <2>
|
||||
}
|
||||
};
|
||||
// end::has-privileges-execute-listener
|
||||
|
||||
// Replace the empty listener by a blocking listener in test
|
||||
final CountDownLatch latch = new CountDownLatch(1);
|
||||
listener = new LatchedActionListener<>(listener, latch);
|
||||
|
||||
// tag::has-privileges-execute-async
|
||||
client.security().hasPrivilegesAsync(request, RequestOptions.DEFAULT, listener); // <1>
|
||||
// end::has-privileges-execute-async
|
||||
|
||||
assertTrue(latch.await(30L, TimeUnit.SECONDS));
|
||||
}
|
||||
}
|
||||
|
||||
public void testClearRealmCache() throws Exception {
|
||||
RestHighLevelClient client = highLevelClient();
|
||||
{
|
||||
|
@ -0,0 +1,111 @@
|
||||
/*
|
||||
* 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.ApplicationResourcePrivileges;
|
||||
import org.elasticsearch.client.security.user.privileges.IndicesPrivileges;
|
||||
import org.elasticsearch.common.Strings;
|
||||
import org.elasticsearch.common.util.set.Sets;
|
||||
import org.elasticsearch.common.xcontent.XContentHelper;
|
||||
import org.elasticsearch.common.xcontent.XContentType;
|
||||
import org.elasticsearch.test.ESTestCase;
|
||||
import org.elasticsearch.test.EqualsHashCodeTestUtils;
|
||||
import org.elasticsearch.test.XContentTestUtils;
|
||||
import org.hamcrest.Matchers;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Arrays;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
public class HasPrivilegesRequestTests extends ESTestCase {
|
||||
|
||||
public void testToXContent() throws IOException {
|
||||
final HasPrivilegesRequest request = new HasPrivilegesRequest(
|
||||
new LinkedHashSet<>(Arrays.asList("monitor", "manage_watcher", "manage_ml")),
|
||||
new LinkedHashSet<>(Arrays.asList(
|
||||
IndicesPrivileges.builder().indices("index-001", "index-002").privileges("all").build(),
|
||||
IndicesPrivileges.builder().indices("index-003").privileges("read").build()
|
||||
)),
|
||||
new LinkedHashSet<>(Arrays.asList(
|
||||
new ApplicationResourcePrivileges("myapp", Arrays.asList("read", "write"), Arrays.asList("*")),
|
||||
new ApplicationResourcePrivileges("myapp", Arrays.asList("admin"), Arrays.asList("/data/*"))
|
||||
))
|
||||
);
|
||||
String json = Strings.toString(request);
|
||||
final Map<String, Object> parsed = XContentHelper.convertToMap(XContentType.JSON.xContent(), json, false);
|
||||
|
||||
final Map<String, Object> expected = XContentHelper.convertToMap(XContentType.JSON.xContent(), "{" +
|
||||
" \"cluster\":[\"monitor\",\"manage_watcher\",\"manage_ml\"]," +
|
||||
" \"index\":[{" +
|
||||
" \"names\":[\"index-001\",\"index-002\"]," +
|
||||
" \"privileges\":[\"all\"]" +
|
||||
" },{" +
|
||||
" \"names\":[\"index-003\"]," +
|
||||
" \"privileges\":[\"read\"]" +
|
||||
" }]," +
|
||||
" \"application\":[{" +
|
||||
" \"application\":\"myapp\"," +
|
||||
" \"privileges\":[\"read\",\"write\"]," +
|
||||
" \"resources\":[\"*\"]" +
|
||||
" },{" +
|
||||
" \"application\":\"myapp\"," +
|
||||
" \"privileges\":[\"admin\"]," +
|
||||
" \"resources\":[\"/data/*\"]" +
|
||||
" }]" +
|
||||
"}", false);
|
||||
|
||||
assertThat(XContentTestUtils.differenceBetweenMapsIgnoringArrayOrder(parsed, expected), Matchers.nullValue());
|
||||
}
|
||||
|
||||
public void testEqualsAndHashCode() {
|
||||
final Set<String> cluster = Sets.newHashSet(randomArray(1, 3, String[]::new, () -> randomAlphaOfLengthBetween(3, 8)));
|
||||
final Set<IndicesPrivileges> indices = Sets.newHashSet(randomArray(1, 5, IndicesPrivileges[]::new,
|
||||
() -> IndicesPrivileges.builder()
|
||||
.indices(generateRandomStringArray(5, 12, false, false))
|
||||
.privileges(generateRandomStringArray(3, 8, false, false))
|
||||
.build()));
|
||||
final Set<ApplicationResourcePrivileges> application = Sets.newHashSet(randomArray(1, 5, ApplicationResourcePrivileges[]::new,
|
||||
() -> new ApplicationResourcePrivileges(
|
||||
randomAlphaOfLengthBetween(5, 12),
|
||||
Sets.newHashSet(generateRandomStringArray(3, 8, false, false)),
|
||||
Sets.newHashSet(generateRandomStringArray(2, 6, false, false))
|
||||
)));
|
||||
final HasPrivilegesRequest request = new HasPrivilegesRequest(cluster, indices, application);
|
||||
EqualsHashCodeTestUtils.checkEqualsAndHashCode(request, this::copy, this::mutate);
|
||||
}
|
||||
|
||||
private HasPrivilegesRequest copy(HasPrivilegesRequest request) {
|
||||
return new HasPrivilegesRequest(request.getClusterPrivileges(), request.getIndexPrivileges(), request.getApplicationPrivileges());
|
||||
}
|
||||
|
||||
private HasPrivilegesRequest mutate(HasPrivilegesRequest request) {
|
||||
switch (randomIntBetween(1, 3)) {
|
||||
case 1:
|
||||
return new HasPrivilegesRequest(null, request.getIndexPrivileges(), request.getApplicationPrivileges());
|
||||
case 2:
|
||||
return new HasPrivilegesRequest(request.getClusterPrivileges(), null, request.getApplicationPrivileges());
|
||||
case 3:
|
||||
return new HasPrivilegesRequest(request.getClusterPrivileges(), request.getIndexPrivileges(), null);
|
||||
}
|
||||
throw new IllegalStateException("The universe is broken (or the RNG is)");
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,262 @@
|
||||
/*
|
||||
* 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.collect.MapBuilder;
|
||||
import org.elasticsearch.common.xcontent.XContentParser;
|
||||
import org.elasticsearch.common.xcontent.XContentType;
|
||||
import org.elasticsearch.test.ESTestCase;
|
||||
import org.elasticsearch.test.EqualsHashCodeTestUtils;
|
||||
import org.hamcrest.Matchers;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
|
||||
import static java.util.Collections.emptyMap;
|
||||
|
||||
public class HasPrivilegesResponseTests extends ESTestCase {
|
||||
|
||||
public void testParseValidResponse() throws IOException {
|
||||
String json = "{" +
|
||||
" \"username\": \"namor\"," +
|
||||
" \"has_all_requested\": false," +
|
||||
" \"cluster\" : {" +
|
||||
" \"manage\" : false," +
|
||||
" \"monitor\" : true" +
|
||||
" }," +
|
||||
" \"index\" : {" +
|
||||
" \"index-01\": {" +
|
||||
" \"read\" : true," +
|
||||
" \"write\" : false" +
|
||||
" }," +
|
||||
" \"index-02\": {" +
|
||||
" \"read\" : true," +
|
||||
" \"write\" : true" +
|
||||
" }," +
|
||||
" \"index-03\": {" +
|
||||
" \"read\" : false," +
|
||||
" \"write\" : false" +
|
||||
" }" +
|
||||
" }," +
|
||||
" \"application\" : {" +
|
||||
" \"app01\" : {" +
|
||||
" \"/object/1\" : {" +
|
||||
" \"read\" : true," +
|
||||
" \"write\" : false" +
|
||||
" }," +
|
||||
" \"/object/2\" : {" +
|
||||
" \"read\" : true," +
|
||||
" \"write\" : true" +
|
||||
" }" +
|
||||
" }," +
|
||||
" \"app02\" : {" +
|
||||
" \"/object/1\" : {" +
|
||||
" \"read\" : false," +
|
||||
" \"write\" : false" +
|
||||
" }," +
|
||||
" \"/object/3\" : {" +
|
||||
" \"read\" : false," +
|
||||
" \"write\" : true" +
|
||||
" }" +
|
||||
" }" +
|
||||
" }" +
|
||||
"}";
|
||||
final XContentParser parser = createParser(XContentType.JSON.xContent(), json);
|
||||
HasPrivilegesResponse response = HasPrivilegesResponse.fromXContent(parser);
|
||||
|
||||
assertThat(response.getUsername(), Matchers.equalTo("namor"));
|
||||
assertThat(response.hasAllRequested(), Matchers.equalTo(false));
|
||||
|
||||
assertThat(response.getClusterPrivileges().keySet(), Matchers.containsInAnyOrder("monitor", "manage"));
|
||||
assertThat(response.hasClusterPrivilege("monitor"), Matchers.equalTo(true));
|
||||
assertThat(response.hasClusterPrivilege("manage"), Matchers.equalTo(false));
|
||||
|
||||
assertThat(response.getIndexPrivileges().keySet(), Matchers.containsInAnyOrder("index-01", "index-02", "index-03"));
|
||||
assertThat(response.hasIndexPrivilege("index-01", "read"), Matchers.equalTo(true));
|
||||
assertThat(response.hasIndexPrivilege("index-01", "write"), Matchers.equalTo(false));
|
||||
assertThat(response.hasIndexPrivilege("index-02", "read"), Matchers.equalTo(true));
|
||||
assertThat(response.hasIndexPrivilege("index-02", "write"), Matchers.equalTo(true));
|
||||
assertThat(response.hasIndexPrivilege("index-03", "read"), Matchers.equalTo(false));
|
||||
assertThat(response.hasIndexPrivilege("index-03", "write"), Matchers.equalTo(false));
|
||||
|
||||
assertThat(response.getApplicationPrivileges().keySet(), Matchers.containsInAnyOrder("app01", "app02"));
|
||||
assertThat(response.hasApplicationPrivilege("app01", "/object/1", "read"), Matchers.equalTo(true));
|
||||
assertThat(response.hasApplicationPrivilege("app01", "/object/1", "write"), Matchers.equalTo(false));
|
||||
assertThat(response.hasApplicationPrivilege("app01", "/object/2", "read"), Matchers.equalTo(true));
|
||||
assertThat(response.hasApplicationPrivilege("app01", "/object/2", "write"), Matchers.equalTo(true));
|
||||
assertThat(response.hasApplicationPrivilege("app02", "/object/1", "read"), Matchers.equalTo(false));
|
||||
assertThat(response.hasApplicationPrivilege("app02", "/object/1", "write"), Matchers.equalTo(false));
|
||||
assertThat(response.hasApplicationPrivilege("app02", "/object/3", "read"), Matchers.equalTo(false));
|
||||
assertThat(response.hasApplicationPrivilege("app02", "/object/3", "write"), Matchers.equalTo(true));
|
||||
}
|
||||
|
||||
public void testHasClusterPrivilege() {
|
||||
final Map<String, Boolean> cluster = MapBuilder.<String, Boolean>newMapBuilder()
|
||||
.put("a", true)
|
||||
.put("b", false)
|
||||
.put("c", false)
|
||||
.put("d", true)
|
||||
.map();
|
||||
final HasPrivilegesResponse response = new HasPrivilegesResponse("x", false, cluster, emptyMap(), emptyMap());
|
||||
assertThat(response.hasClusterPrivilege("a"), Matchers.is(true));
|
||||
assertThat(response.hasClusterPrivilege("b"), Matchers.is(false));
|
||||
assertThat(response.hasClusterPrivilege("c"), Matchers.is(false));
|
||||
assertThat(response.hasClusterPrivilege("d"), Matchers.is(true));
|
||||
|
||||
final IllegalArgumentException iae = expectThrows(IllegalArgumentException.class, () -> response.hasClusterPrivilege("e"));
|
||||
assertThat(iae.getMessage(), Matchers.containsString("[e]"));
|
||||
assertThat(iae.getMessage().toLowerCase(Locale.ROOT), Matchers.containsString("cluster privilege"));
|
||||
}
|
||||
|
||||
public void testHasIndexPrivilege() {
|
||||
final Map<String, Map<String, Boolean>> index = MapBuilder.<String, Map<String, Boolean>>newMapBuilder()
|
||||
.put("i1", Collections.singletonMap("read", true))
|
||||
.put("i2", Collections.singletonMap("read", false))
|
||||
.put("i3", MapBuilder.<String, Boolean>newMapBuilder().put("read", true).put("write", true).map())
|
||||
.put("i4", MapBuilder.<String, Boolean>newMapBuilder().put("read", true).put("write", false).map())
|
||||
.put("i*", MapBuilder.<String, Boolean>newMapBuilder().put("read", false).put("write", false).map())
|
||||
.map();
|
||||
final HasPrivilegesResponse response = new HasPrivilegesResponse("x", false, emptyMap(), index, emptyMap());
|
||||
assertThat(response.hasIndexPrivilege("i1", "read"), Matchers.is(true));
|
||||
assertThat(response.hasIndexPrivilege("i2", "read"), Matchers.is(false));
|
||||
assertThat(response.hasIndexPrivilege("i3", "read"), Matchers.is(true));
|
||||
assertThat(response.hasIndexPrivilege("i3", "write"), Matchers.is(true));
|
||||
assertThat(response.hasIndexPrivilege("i4", "read"), Matchers.is(true));
|
||||
assertThat(response.hasIndexPrivilege("i4", "write"), Matchers.is(false));
|
||||
assertThat(response.hasIndexPrivilege("i*", "read"), Matchers.is(false));
|
||||
assertThat(response.hasIndexPrivilege("i*", "write"), Matchers.is(false));
|
||||
|
||||
final IllegalArgumentException iae1 = expectThrows(IllegalArgumentException.class, () -> response.hasIndexPrivilege("i0", "read"));
|
||||
assertThat(iae1.getMessage(), Matchers.containsString("index [i0]"));
|
||||
|
||||
final IllegalArgumentException iae2 = expectThrows(IllegalArgumentException.class, () -> response.hasIndexPrivilege("i1", "write"));
|
||||
assertThat(iae2.getMessage().toLowerCase(Locale.ROOT), Matchers.containsString("privilege [write]"));
|
||||
assertThat(iae2.getMessage(), Matchers.containsString("index [i1]"));
|
||||
}
|
||||
|
||||
public void testHasApplicationPrivilege() {
|
||||
final Map<String, Map<String, Boolean>> app1 = MapBuilder.<String, Map<String, Boolean>>newMapBuilder()
|
||||
.put("/data/1", Collections.singletonMap("read", true))
|
||||
.put("/data/2", Collections.singletonMap("read", false))
|
||||
.put("/data/3", MapBuilder.<String, Boolean>newMapBuilder().put("read", true).put("write", true).map())
|
||||
.put("/data/4", MapBuilder.<String, Boolean>newMapBuilder().put("read", true).put("write", false).map())
|
||||
.map();
|
||||
final Map<String, Map<String, Boolean>> app2 = MapBuilder.<String, Map<String, Boolean>>newMapBuilder()
|
||||
.put("/action/1", Collections.singletonMap("execute", true))
|
||||
.put("/action/*", Collections.singletonMap("execute", false))
|
||||
.map();
|
||||
Map<String, Map<String, Map<String, Boolean>>> appPrivileges = new HashMap<>();
|
||||
appPrivileges.put("a1", app1);
|
||||
appPrivileges.put("a2", app2);
|
||||
final HasPrivilegesResponse response = new HasPrivilegesResponse("x", false, emptyMap(), emptyMap(), appPrivileges);
|
||||
assertThat(response.hasApplicationPrivilege("a1", "/data/1", "read"), Matchers.is(true));
|
||||
assertThat(response.hasApplicationPrivilege("a1", "/data/2", "read"), Matchers.is(false));
|
||||
assertThat(response.hasApplicationPrivilege("a1", "/data/3", "read"), Matchers.is(true));
|
||||
assertThat(response.hasApplicationPrivilege("a1", "/data/3", "write"), Matchers.is(true));
|
||||
assertThat(response.hasApplicationPrivilege("a1", "/data/4", "read"), Matchers.is(true));
|
||||
assertThat(response.hasApplicationPrivilege("a1", "/data/4", "write"), Matchers.is(false));
|
||||
assertThat(response.hasApplicationPrivilege("a2", "/action/1", "execute"), Matchers.is(true));
|
||||
assertThat(response.hasApplicationPrivilege("a2", "/action/*", "execute"), Matchers.is(false));
|
||||
|
||||
final IllegalArgumentException iae1 = expectThrows(IllegalArgumentException.class,
|
||||
() -> response.hasApplicationPrivilege("a0", "/data/1", "read"));
|
||||
assertThat(iae1.getMessage().toLowerCase(Locale.ROOT), Matchers.containsString("application [a0]"));
|
||||
|
||||
final IllegalArgumentException iae2 = expectThrows(IllegalArgumentException.class,
|
||||
() -> response.hasApplicationPrivilege("a1", "/data/0", "read"));
|
||||
assertThat(iae2.getMessage().toLowerCase(Locale.ROOT), Matchers.containsString("application [a1]"));
|
||||
assertThat(iae2.getMessage().toLowerCase(Locale.ROOT), Matchers.containsString("resource [/data/0]"));
|
||||
|
||||
final IllegalArgumentException iae3 = expectThrows(IllegalArgumentException.class,
|
||||
() -> response.hasApplicationPrivilege("a1", "/action/1", "execute"));
|
||||
assertThat(iae3.getMessage().toLowerCase(Locale.ROOT), Matchers.containsString("application [a1]"));
|
||||
assertThat(iae3.getMessage().toLowerCase(Locale.ROOT), Matchers.containsString("resource [/action/1]"));
|
||||
|
||||
final IllegalArgumentException iae4 = expectThrows(IllegalArgumentException.class,
|
||||
() -> response.hasApplicationPrivilege("a1", "/data/1", "write"));
|
||||
assertThat(iae4.getMessage().toLowerCase(Locale.ROOT), Matchers.containsString("application [a1]"));
|
||||
assertThat(iae4.getMessage().toLowerCase(Locale.ROOT), Matchers.containsString("resource [/data/1]"));
|
||||
assertThat(iae4.getMessage().toLowerCase(Locale.ROOT), Matchers.containsString("privilege [write]"));
|
||||
}
|
||||
|
||||
public void testEqualsAndHashCode() {
|
||||
final HasPrivilegesResponse response = randomResponse();
|
||||
EqualsHashCodeTestUtils.checkEqualsAndHashCode(response, this::copy, this::mutate);
|
||||
}
|
||||
|
||||
private HasPrivilegesResponse copy(HasPrivilegesResponse response) {
|
||||
return new HasPrivilegesResponse(response.getUsername(),
|
||||
response.hasAllRequested(),
|
||||
response.getClusterPrivileges(),
|
||||
response.getIndexPrivileges(),
|
||||
response.getApplicationPrivileges());
|
||||
}
|
||||
|
||||
private HasPrivilegesResponse mutate(HasPrivilegesResponse request) {
|
||||
switch (randomIntBetween(1, 5)) {
|
||||
case 1:
|
||||
return new HasPrivilegesResponse("_" + request.getUsername(), request.hasAllRequested(),
|
||||
request.getClusterPrivileges(), request.getIndexPrivileges(), request.getApplicationPrivileges());
|
||||
case 2:
|
||||
return new HasPrivilegesResponse(request.getUsername(), request.hasAllRequested() == false,
|
||||
request.getClusterPrivileges(), request.getIndexPrivileges(), request.getApplicationPrivileges());
|
||||
case 3:
|
||||
return new HasPrivilegesResponse(request.getUsername(), request.hasAllRequested(),
|
||||
emptyMap(), request.getIndexPrivileges(), request.getApplicationPrivileges());
|
||||
case 4:
|
||||
return new HasPrivilegesResponse(request.getUsername(), request.hasAllRequested(),
|
||||
request.getClusterPrivileges(), emptyMap(), request.getApplicationPrivileges());
|
||||
case 5:
|
||||
return new HasPrivilegesResponse(request.getUsername(), request.hasAllRequested(),
|
||||
request.getClusterPrivileges(), request.getIndexPrivileges(), emptyMap());
|
||||
}
|
||||
throw new IllegalStateException("The universe is broken (or the RNG is)");
|
||||
}
|
||||
|
||||
private HasPrivilegesResponse randomResponse() {
|
||||
final Map<String, Boolean> cluster = randomPrivilegeMap();
|
||||
final Map<String, Map<String, Boolean>> index = randomResourceMap();
|
||||
|
||||
final Map<String, Map<String, Map<String, Boolean>>> application = new HashMap<>();
|
||||
for (String app : randomArray(1, 3, String[]::new, () -> randomAlphaOfLengthBetween(3, 6).toLowerCase(Locale.ROOT))) {
|
||||
application.put(app, randomResourceMap());
|
||||
}
|
||||
return new HasPrivilegesResponse(randomAlphaOfLengthBetween(3, 8), randomBoolean(), cluster, index, application);
|
||||
}
|
||||
|
||||
private Map<String, Map<String, Boolean>> randomResourceMap() {
|
||||
final Map<String, Map<String, Boolean>> resource = new HashMap<>();
|
||||
for (String res : randomArray(1, 3, String[]::new, () -> randomAlphaOfLengthBetween(5, 8))) {
|
||||
resource.put(res, randomPrivilegeMap());
|
||||
}
|
||||
return resource;
|
||||
}
|
||||
|
||||
private Map<String, Boolean> randomPrivilegeMap() {
|
||||
final Map<String, Boolean> map = new HashMap<>();
|
||||
for (String privilege : randomArray(1, 6, String[]::new, () -> randomAlphaOfLengthBetween(3, 12))) {
|
||||
map.put(privilege, randomBoolean());
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
}
|
86
docs/java-rest/high-level/security/has-privileges.asciidoc
Normal file
86
docs/java-rest/high-level/security/has-privileges.asciidoc
Normal file
@ -0,0 +1,86 @@
|
||||
--
|
||||
:api: has-privileges
|
||||
:request: HasPrivilegesRequest
|
||||
:response: HasPrivilegesResponse
|
||||
--
|
||||
|
||||
[id="{upid}-{api}"]
|
||||
=== Has Privileges API
|
||||
|
||||
[id="{upid}-{api}-request"]
|
||||
==== Has Privileges Request
|
||||
The +{request}+ supports checking for any or all of the following privilege types:
|
||||
|
||||
* Cluster Privileges
|
||||
* Index Privileges
|
||||
* Application Privileges
|
||||
|
||||
Privileges types that you do not wish to check my be passed in as +null+, but as least
|
||||
one privilege must be specified.
|
||||
|
||||
["source","java",subs="attributes,callouts,macros"]
|
||||
--------------------------------------------------
|
||||
include-tagged::{doc-tests-file}[{api}-request]
|
||||
--------------------------------------------------
|
||||
include::../execution.asciidoc[]
|
||||
|
||||
[id="{upid}-{api}-response"]
|
||||
==== Has Privileges Response
|
||||
|
||||
The returned +{response}+ contains the following properties
|
||||
|
||||
`username`::
|
||||
The username (userid) of the current user (for whom the "has privileges"
|
||||
check was executed)
|
||||
|
||||
`hasAllRequested`::
|
||||
`true` if the user has all of the privileges that were specified in the
|
||||
+{request}+. Otherwise `false`.
|
||||
|
||||
`clusterPrivileges`::
|
||||
A `Map<String,Boolean>` where each key is the name of one of the cluster
|
||||
privileges specified in the request, and the value is `true` if the user
|
||||
has that privilege, and `false` otherwise.
|
||||
+
|
||||
The method `hasClusterPrivilege` can be used to retrieve this information
|
||||
in a more fluent manner. This method throws an `IllegalArgumentException`
|
||||
if the privilege was not included in the response (which will be the case
|
||||
if the privilege was not part of the request).
|
||||
|
||||
`indexPrivileges`::
|
||||
A `Map<String, Map<String, Boolean>>` where each key is the name of an
|
||||
index (as specified in the +{request}+) and the value is a `Map` from
|
||||
privilege name to a `Boolean`. The `Boolean` value is `true` if the user
|
||||
has that privilege on that index, and `false` otherwise.
|
||||
+
|
||||
The method `hasIndexPrivilege` can be used to retrieve this information
|
||||
in a more fluent manner. This method throws an `IllegalArgumentException`
|
||||
if the privilege was not included in the response (which will be the case
|
||||
if the privilege was not part of the request).
|
||||
|
||||
`applicationPrivileges`::
|
||||
A `Map<String, Map<String, Map<String, Boolean>>>>` where each key is the
|
||||
name of an application (as specified in the +{request}+).
|
||||
For each application, the value is a `Map` keyed by resource name, with
|
||||
each value being another `Map` from privilege name to a `Boolean`.
|
||||
The `Boolean` value is `true` if the user has that privilege on that
|
||||
resource for that application, and `false` otherwise.
|
||||
+
|
||||
The method `hasApplicationPrivilege` can be used to retrieve this
|
||||
information in a more fluent manner. This method throws an
|
||||
`IllegalArgumentException` if the privilege was not included in the
|
||||
response (which will be the case if the privilege was not part of the
|
||||
request).
|
||||
|
||||
["source","java",subs="attributes,callouts,macros"]
|
||||
--------------------------------------------------
|
||||
include-tagged::{doc-tests-file}[{api}-response]
|
||||
--------------------------------------------------
|
||||
<1> `hasMonitor` will be `true` if the user has the `"monitor"`
|
||||
cluster privilege.
|
||||
<2> `hasWrite` will be `true` if the user has the `"write"`
|
||||
privilege on the `"logstash-2018-10-05"` index.
|
||||
<3> `hasRead` will be `true` if the user has the `"read"`
|
||||
privilege on all possible indices that would match
|
||||
the `"logstash-2018-*"` pattern.
|
||||
|
@ -351,6 +351,7 @@ The Java High Level REST Client supports the following Security APIs:
|
||||
* <<{upid}-clear-roles-cache>>
|
||||
* <<{upid}-clear-realm-cache>>
|
||||
* <<{upid}-authenticate>>
|
||||
* <<{upid}-has-privileges>>
|
||||
* <<java-rest-high-security-get-certificates>>
|
||||
* <<java-rest-high-security-put-role-mapping>>
|
||||
* <<java-rest-high-security-get-role-mappings>>
|
||||
@ -368,6 +369,7 @@ include::security/delete-privileges.asciidoc[]
|
||||
include::security/clear-roles-cache.asciidoc[]
|
||||
include::security/clear-realm-cache.asciidoc[]
|
||||
include::security/authenticate.asciidoc[]
|
||||
include::security/has-privileges.asciidoc[]
|
||||
include::security/get-certificates.asciidoc[]
|
||||
include::security/put-role-mapping.asciidoc[]
|
||||
include::security/get-role-mappings.asciidoc[]
|
||||
|
Loading…
x
Reference in New Issue
Block a user