From 8c0bd41975419985c9698cd22ca351b5f6f6b0a9 Mon Sep 17 00:00:00 2001 From: Tim Vernum Date: Fri, 16 Nov 2018 17:14:44 +1100 Subject: [PATCH 1/2] Move XContent generation to HasPrivilegesResponse The RestHasPrivilegesAction previously handled its own XContent generation. This change moves that into HasPrivilegesResponse and makes the response implement ToXContent. This allows HasPrivilegesResponseTests to be used to test compatibility between HLRC and X-Pack internals. A serialization bug (cluster privs) was also fixed here. --- .../action/user/HasPrivilegesResponse.java | 107 +++++++++++++++++- .../user/HasPrivilegesResponseTests.java | 96 ++++++++++++++-- .../user/TransportHasPrivilegesAction.java | 2 +- .../action/user/RestHasPrivilegesAction.java | 54 ++------- .../TransportHasPrivilegesActionTests.java | 9 +- .../user/HasPrivilegesRestResponseTests.java | 57 ---------- 6 files changed, 207 insertions(+), 118 deletions(-) delete mode 100644 x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/rest/action/user/HasPrivilegesRestResponseTests.java diff --git a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/security/action/user/HasPrivilegesResponse.java b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/security/action/user/HasPrivilegesResponse.java index 8cd8b510c6499..6ae8c445327cf 100644 --- a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/security/action/user/HasPrivilegesResponse.java +++ b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/security/action/user/HasPrivilegesResponse.java @@ -9,11 +9,14 @@ import org.elasticsearch.action.ActionResponse; import org.elasticsearch.common.io.stream.StreamInput; import org.elasticsearch.common.io.stream.StreamOutput; +import org.elasticsearch.common.xcontent.ToXContentObject; +import org.elasticsearch.common.xcontent.XContentBuilder; import java.io.IOException; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; +import java.util.Comparator; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -22,24 +25,35 @@ /** * Response for a {@link HasPrivilegesRequest} */ -public class HasPrivilegesResponse extends ActionResponse { +public class HasPrivilegesResponse extends ActionResponse implements ToXContentObject { + private String username; private boolean completeMatch; private Map cluster; private List index; private Map> application; public HasPrivilegesResponse() { - this(true, Collections.emptyMap(), Collections.emptyList(), Collections.emptyMap()); + this("", true, Collections.emptyMap(), Collections.emptyList(), Collections.emptyMap()); } - public HasPrivilegesResponse(boolean completeMatch, Map cluster, Collection index, + public HasPrivilegesResponse(String username, boolean completeMatch, Map cluster, Collection index, Map> application) { super(); + this.username = username; this.completeMatch = completeMatch; this.cluster = new HashMap<>(cluster); - this.index = new ArrayList<>(index); + this.index = sorted(new ArrayList<>(index)); this.application = new HashMap<>(); - application.forEach((key, val) -> this.application.put(key, Collections.unmodifiableList(new ArrayList<>(val)))); + application.forEach((key, val) -> this.application.put(key, Collections.unmodifiableList(sorted(new ArrayList<>(val))))); + } + + private static List sorted(List resources) { + Collections.sort(resources, Comparator.comparing(o -> o.resource)); + return resources; + } + + public String getUsername() { + return username; } public boolean isCompleteMatch() { @@ -62,13 +76,47 @@ public Map> getApplicationPrivileges() { return Collections.unmodifiableMap(application); } + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + final HasPrivilegesResponse response = (HasPrivilegesResponse) o; + if (completeMatch == response.completeMatch) { + if (Objects.equals(username, response.username)) { + if (Objects.equals(cluster, response.cluster)) { + if (Objects.equals(index, response.index)) { + if (Objects.equals(application, response.application)) { + return true; + } + } + } + } + } + return false; + } + + @Override + public int hashCode() { + return Objects.hash(username, completeMatch, cluster, index, application); + } + public void readFrom(StreamInput in) throws IOException { super.readFrom(in); completeMatch = in.readBoolean(); + if (in.getVersion().onOrAfter(Version.V_7_0_0)) { + cluster = in.readMap(StreamInput::readString, StreamInput::readBoolean); + } index = readResourcePrivileges(in); if (in.getVersion().onOrAfter(Version.V_6_4_0)) { application = in.readMap(StreamInput::readString, HasPrivilegesResponse::readResourcePrivileges); } + if (in.getVersion().onOrAfter(Version.V_7_0_0)) { + username = in.readString(); + } } private static List readResourcePrivileges(StreamInput in) throws IOException { @@ -86,10 +134,16 @@ private static List readResourcePrivileges(StreamInput in) t public void writeTo(StreamOutput out) throws IOException { super.writeTo(out); out.writeBoolean(completeMatch); + if (out.getVersion().onOrAfter(Version.V_7_0_0)) { + out.writeMap(cluster, StreamOutput::writeString, StreamOutput::writeBoolean); + } writeResourcePrivileges(out, index); if (out.getVersion().onOrAfter(Version.V_6_4_0)) { out.writeMap(application, StreamOutput::writeString, HasPrivilegesResponse::writeResourcePrivileges); } + if (out.getVersion().onOrAfter(Version.V_7_0_0)) { + out.writeString(username); + } } private static void writeResourcePrivileges(StreamOutput out, List privileges) throws IOException { @@ -100,6 +154,49 @@ private static void writeResourcePrivileges(StreamOutput out, List privileges) + throws IOException { + builder.startObject(field); + for (HasPrivilegesResponse.ResourcePrivileges privilege : privileges) { + builder.field(privilege.getResource()); + builder.map(privilege.getPrivileges()); + } + builder.endObject(); + } + + public static class ResourcePrivileges { private final String resource; private final Map privileges; diff --git a/x-pack/plugin/core/src/test/java/org/elasticsearch/xpack/core/security/action/user/HasPrivilegesResponseTests.java b/x-pack/plugin/core/src/test/java/org/elasticsearch/xpack/core/security/action/user/HasPrivilegesResponseTests.java index 89c58945badd0..f9289113dc819 100644 --- a/x-pack/plugin/core/src/test/java/org/elasticsearch/xpack/core/security/action/user/HasPrivilegesResponseTests.java +++ b/x-pack/plugin/core/src/test/java/org/elasticsearch/xpack/core/security/action/user/HasPrivilegesResponseTests.java @@ -7,30 +7,42 @@ package org.elasticsearch.xpack.core.security.action.user; import org.elasticsearch.Version; +import org.elasticsearch.common.bytes.BytesReference; +import org.elasticsearch.common.collect.MapBuilder; import org.elasticsearch.common.io.stream.BytesStreamOutput; import org.elasticsearch.common.io.stream.StreamInput; -import org.elasticsearch.test.ESTestCase; +import org.elasticsearch.common.xcontent.ToXContent; +import org.elasticsearch.common.xcontent.XContentBuilder; +import org.elasticsearch.common.xcontent.XContentParser; +import org.elasticsearch.common.xcontent.XContentType; +import org.elasticsearch.protocol.AbstractHlrcStreamableXContentTestCase; import org.elasticsearch.test.VersionUtils; +import org.hamcrest.Matchers; import java.io.IOException; import java.util.ArrayList; +import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.HashMap; +import java.util.LinkedHashMap; +import java.util.List; import java.util.Locale; import java.util.Map; +import java.util.stream.Collectors; import static org.hamcrest.Matchers.equalTo; -public class HasPrivilegesResponseTests extends ESTestCase { +public class HasPrivilegesResponseTests + extends AbstractHlrcStreamableXContentTestCase { - public void testSerializationV64OrLater() throws IOException { + public void testSerializationV64OrV65() throws IOException { final HasPrivilegesResponse original = randomResponse(); - final Version version = VersionUtils.randomVersionBetween(random(), Version.V_6_4_0, Version.CURRENT); + final Version version = VersionUtils.randomVersionBetween(random(), Version.V_6_4_0, Version.V_6_5_1); final HasPrivilegesResponse copy = serializeAndDeserialize(original, version); assertThat(copy.isCompleteMatch(), equalTo(original.isCompleteMatch())); -// assertThat(copy.getClusterPrivileges(), equalTo(original.getClusterPrivileges())); + assertThat(copy.getClusterPrivileges().entrySet(), Matchers.emptyIterable()); assertThat(copy.getIndexPrivileges(), equalTo(original.getIndexPrivileges())); assertThat(copy.getApplicationPrivileges(), equalTo(original.getApplicationPrivileges())); } @@ -40,11 +52,79 @@ public void testSerializationV63() throws IOException { final HasPrivilegesResponse copy = serializeAndDeserialize(original, Version.V_6_3_0); assertThat(copy.isCompleteMatch(), equalTo(original.isCompleteMatch())); -// assertThat(copy.getClusterPrivileges(), equalTo(original.getClusterPrivileges())); + assertThat(copy.getClusterPrivileges().entrySet(), Matchers.emptyIterable()); assertThat(copy.getIndexPrivileges(), equalTo(original.getIndexPrivileges())); assertThat(copy.getApplicationPrivileges(), equalTo(Collections.emptyMap())); } + public void testToXContent() throws Exception { + final HasPrivilegesResponse response = new HasPrivilegesResponse("daredevil", false, + Collections.singletonMap("manage", true), + Arrays.asList( + new HasPrivilegesResponse.ResourcePrivileges("staff", + MapBuilder.newMapBuilder(new LinkedHashMap<>()) + .put("read", true).put("index", true).put("delete", false).put("manage", false).map()), + new HasPrivilegesResponse.ResourcePrivileges("customers", + MapBuilder.newMapBuilder(new LinkedHashMap<>()) + .put("read", true).put("index", true).put("delete", true).put("manage", false).map()) + ), Collections.emptyMap()); + + final XContentBuilder builder = XContentBuilder.builder(XContentType.JSON.xContent()); + response.toXContent(builder, ToXContent.EMPTY_PARAMS); + BytesReference bytes = BytesReference.bytes(builder); + + final String json = bytes.utf8ToString(); + assertThat(json, equalTo("{" + + "\"username\":\"daredevil\"," + + "\"has_all_requested\":false," + + "\"cluster\":{\"manage\":true}," + + "\"index\":{" + + "\"customers\":{\"read\":true,\"index\":true,\"delete\":true,\"manage\":false}," + + "\"staff\":{\"read\":true,\"index\":true,\"delete\":false,\"manage\":false}" + + "}," + + "\"application\":{}" + + "}")); + } + + @Override + protected boolean supportsUnknownFields() { + // Because we have nested objects with { string : boolean }, unknown fields cause parsing problems + return false; + } + + @Override + protected HasPrivilegesResponse createBlankInstance() { + return new HasPrivilegesResponse(); + } + + @Override + protected HasPrivilegesResponse createTestInstance() { + return randomResponse(); + } + + @Override + public org.elasticsearch.client.security.HasPrivilegesResponse doHlrcParseInstance(XContentParser parser) throws IOException { + return org.elasticsearch.client.security.HasPrivilegesResponse.fromXContent(parser); + } + + @Override + public HasPrivilegesResponse convertHlrcToInternal(org.elasticsearch.client.security.HasPrivilegesResponse hlrc) { + return new HasPrivilegesResponse( + hlrc.getUsername(), + hlrc.hasAllRequested(), + hlrc.getClusterPrivileges(), + toResourcePrivileges(hlrc.getIndexPrivileges()), + hlrc.getApplicationPrivileges().entrySet().stream() + .collect(Collectors.toMap(Map.Entry::getKey, e -> toResourcePrivileges(e.getValue()))) + ); + } + + private static List toResourcePrivileges(Map> map) { + return map.entrySet().stream() + .map(e -> new HasPrivilegesResponse.ResourcePrivileges(e.getKey(), e.getValue())) + .collect(Collectors.toList()); + } + private HasPrivilegesResponse serializeAndDeserialize(HasPrivilegesResponse original, Version version) throws IOException { logger.info("Test serialize/deserialize with version {}", version); final BytesStreamOutput out = new BytesStreamOutput(); @@ -60,6 +140,7 @@ private HasPrivilegesResponse serializeAndDeserialize(HasPrivilegesResponse orig } private HasPrivilegesResponse randomResponse() { + final String username = randomAlphaOfLengthBetween(4, 12); final Map cluster = new HashMap<>(); for (String priv : randomArray(1, 6, String[]::new, () -> randomAlphaOfLengthBetween(3, 12))) { cluster.put(priv, randomBoolean()); @@ -69,7 +150,7 @@ private HasPrivilegesResponse randomResponse() { for (String app : randomArray(1, 3, String[]::new, () -> randomAlphaOfLengthBetween(3, 6).toLowerCase(Locale.ROOT))) { application.put(app, randomResourcePrivileges()); } - return new HasPrivilegesResponse(randomBoolean(), cluster, index, application); + return new HasPrivilegesResponse(username, randomBoolean(), cluster, index, application); } private Collection randomResourcePrivileges() { @@ -83,5 +164,4 @@ private Collection randomResourcePrivi } return list; } - } diff --git a/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/action/user/TransportHasPrivilegesAction.java b/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/action/user/TransportHasPrivilegesAction.java index 37cd3478aa533..20fa9f522e710 100644 --- a/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/action/user/TransportHasPrivilegesAction.java +++ b/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/action/user/TransportHasPrivilegesAction.java @@ -168,7 +168,7 @@ private void checkPrivileges(HasPrivilegesRequest request, Role userRole, privilegesByApplication.put(applicationName, appPrivilegesByResource.values()); } - listener.onResponse(new HasPrivilegesResponse(allMatch, cluster, indices.values(), privilegesByApplication)); + listener.onResponse(new HasPrivilegesResponse(request.username(), allMatch, cluster, indices.values(), privilegesByApplication)); } private boolean testIndexMatch(String checkIndex, String checkPrivilegeName, Role userRole, diff --git a/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/rest/action/user/RestHasPrivilegesAction.java b/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/rest/action/user/RestHasPrivilegesAction.java index 5a47df39f0940..6ec8250420eed 100644 --- a/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/rest/action/user/RestHasPrivilegesAction.java +++ b/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/rest/action/user/RestHasPrivilegesAction.java @@ -10,11 +10,11 @@ import org.elasticsearch.common.bytes.BytesReference; import org.elasticsearch.common.collect.Tuple; import org.elasticsearch.common.settings.Settings; +import org.elasticsearch.common.xcontent.ToXContent; import org.elasticsearch.common.xcontent.XContentBuilder; import org.elasticsearch.common.xcontent.XContentType; import org.elasticsearch.license.XPackLicenseState; import org.elasticsearch.rest.BytesRestResponse; -import org.elasticsearch.rest.RestChannel; import org.elasticsearch.rest.RestController; import org.elasticsearch.rest.RestRequest; import org.elasticsearch.rest.RestResponse; @@ -29,8 +29,6 @@ import org.elasticsearch.xpack.security.rest.action.SecurityBaseRestHandler; import java.io.IOException; -import java.util.List; -import java.util.Map; import static org.elasticsearch.rest.RestRequest.Method.GET; import static org.elasticsearch.rest.RestRequest.Method.POST; @@ -66,7 +64,13 @@ public RestChannelConsumer innerPrepareRequest(RestRequest request, NodeClient c } final Tuple content = request.contentOrSourceParam(); HasPrivilegesRequestBuilder requestBuilder = new SecurityClient(client).prepareHasPrivileges(username, content.v2(), content.v1()); - return channel -> requestBuilder.execute(new HasPrivilegesRestResponseBuilder(username, channel)); + return channel -> requestBuilder.execute(new RestBuilderListener(channel) { + @Override + public RestResponse buildResponse(HasPrivilegesResponse response, XContentBuilder builder) throws Exception { + response.toXContent(builder, ToXContent.EMPTY_PARAMS); + return new BytesRestResponse(RestStatus.OK, builder); + } + }); } private String getUsername(RestRequest request) { @@ -80,46 +84,4 @@ private String getUsername(RestRequest request) { } return user.principal(); } - - static class HasPrivilegesRestResponseBuilder extends RestBuilderListener { - private String username; - - HasPrivilegesRestResponseBuilder(String username, RestChannel channel) { - super(channel); - this.username = username; - } - - @Override - public RestResponse buildResponse(HasPrivilegesResponse response, XContentBuilder builder) throws Exception { - builder.startObject() - .field("username", username) - .field("has_all_requested", response.isCompleteMatch()); - - builder.field("cluster"); - builder.map(response.getClusterPrivileges()); - - appendResources(builder, "index", response.getIndexPrivileges()); - - builder.startObject("application"); - final Map> appPrivileges = response.getApplicationPrivileges(); - for (String app : appPrivileges.keySet()) { - appendResources(builder, app, appPrivileges.get(app)); - } - builder.endObject(); - - builder.endObject(); - return new BytesRestResponse(RestStatus.OK, builder); - } - - private void appendResources(XContentBuilder builder, String field, List privileges) - throws IOException { - builder.startObject(field); - for (HasPrivilegesResponse.ResourcePrivileges privilege : privileges) { - builder.field(privilege.getResource()); - builder.map(privilege.getPrivileges()); - } - builder.endObject(); - } - - } } diff --git a/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/action/user/TransportHasPrivilegesActionTests.java b/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/action/user/TransportHasPrivilegesActionTests.java index 804412339e8a4..2da066b56eee1 100644 --- a/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/action/user/TransportHasPrivilegesActionTests.java +++ b/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/action/user/TransportHasPrivilegesActionTests.java @@ -111,7 +111,10 @@ public void setup() { * (in this case that {@link DeleteAction} and {@link IndexAction} are satisfied by {@link IndexPrivilege#WRITE}). */ public void testNamedIndexPrivilegesMatchApplicableActions() throws Exception { - role = Role.builder("test1").cluster(ClusterPrivilege.ALL).add(IndexPrivilege.WRITE, "academy").build(); + role = Role.builder("test1") + .cluster(Collections.singleton("all"), Collections.emptyList()) + .add(IndexPrivilege.WRITE, "academy") + .build(); final HasPrivilegesRequest request = new HasPrivilegesRequest(); request.username(user.principal()); @@ -126,6 +129,7 @@ public void testNamedIndexPrivilegesMatchApplicableActions() throws Exception { final HasPrivilegesResponse response = future.get(); assertThat(response, notNullValue()); + assertThat(response.getUsername(), is(user.principal())); assertThat(response.isCompleteMatch(), is(true)); assertThat(response.getClusterPrivileges().size(), equalTo(1)); @@ -163,6 +167,7 @@ public void testMatchSubsetOfPrivileges() throws Exception { final HasPrivilegesResponse response = future.get(); assertThat(response, notNullValue()); + assertThat(response.getUsername(), is(user.principal())); assertThat(response.isCompleteMatch(), is(false)); assertThat(response.getClusterPrivileges().size(), equalTo(2)); assertThat(response.getClusterPrivileges().get("monitor"), equalTo(true)); @@ -205,6 +210,7 @@ public void testMatchNothing() throws Exception { .indices("academy") .privileges("read", "write") .build(), Strings.EMPTY_ARRAY); + assertThat(response.getUsername(), is(user.principal())); assertThat(response.isCompleteMatch(), is(false)); assertThat(response.getIndexPrivileges(), Matchers.iterableWithSize(1)); final ResourcePrivileges result = response.getIndexPrivileges().get(0); @@ -289,6 +295,7 @@ public void testWildcardHandling() throws Exception { final HasPrivilegesResponse response = future.get(); assertThat(response, notNullValue()); + assertThat(response.getUsername(), is(user.principal())); assertThat(response.isCompleteMatch(), is(false)); assertThat(response.getIndexPrivileges(), Matchers.iterableWithSize(8)); assertThat(response.getIndexPrivileges(), containsInAnyOrder( diff --git a/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/rest/action/user/HasPrivilegesRestResponseTests.java b/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/rest/action/user/HasPrivilegesRestResponseTests.java deleted file mode 100644 index 645abbc8f1a6b..0000000000000 --- a/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/rest/action/user/HasPrivilegesRestResponseTests.java +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ -package org.elasticsearch.xpack.security.rest.action.user; - -import org.elasticsearch.common.collect.MapBuilder; -import org.elasticsearch.common.xcontent.XContentBuilder; -import org.elasticsearch.common.xcontent.XContentType; -import org.elasticsearch.rest.BytesRestResponse; -import org.elasticsearch.rest.RestChannel; -import org.elasticsearch.rest.RestResponse; -import org.elasticsearch.test.ESTestCase; -import org.elasticsearch.xpack.core.security.action.user.HasPrivilegesResponse; -import org.elasticsearch.xpack.security.rest.action.user.RestHasPrivilegesAction.HasPrivilegesRestResponseBuilder; - -import java.util.Arrays; -import java.util.Collections; -import java.util.LinkedHashMap; - -import static org.hamcrest.Matchers.equalTo; -import static org.hamcrest.Matchers.instanceOf; -import static org.mockito.Mockito.mock; - -public class HasPrivilegesRestResponseTests extends ESTestCase { - - public void testBuildValidJsonResponse() throws Exception { - final HasPrivilegesRestResponseBuilder response = new HasPrivilegesRestResponseBuilder("daredevil", mock(RestChannel.class)); - final HasPrivilegesResponse actionResponse = new HasPrivilegesResponse(false, - Collections.singletonMap("manage", true), - Arrays.asList( - new HasPrivilegesResponse.ResourcePrivileges("staff", - MapBuilder.newMapBuilder(new LinkedHashMap<>()) - .put("read", true).put("index", true).put("delete", false).put("manage", false).map()), - new HasPrivilegesResponse.ResourcePrivileges("customers", - MapBuilder.newMapBuilder(new LinkedHashMap<>()) - .put("read", true).put("index", true).put("delete", true).put("manage", false).map()) - ), Collections.emptyMap()); - final XContentBuilder builder = XContentBuilder.builder(XContentType.JSON.xContent()); - final RestResponse rest = response.buildResponse(actionResponse, builder); - - assertThat(rest, instanceOf(BytesRestResponse.class)); - - final String json = rest.content().utf8ToString(); - assertThat(json, equalTo("{" + - "\"username\":\"daredevil\"," + - "\"has_all_requested\":false," + - "\"cluster\":{\"manage\":true}," + - "\"index\":{" + - "\"staff\":{\"read\":true,\"index\":true,\"delete\":false,\"manage\":false}," + - "\"customers\":{\"read\":true,\"index\":true,\"delete\":true,\"manage\":false}" + - "}," + - "\"application\":{}" + - "}")); - } -} \ No newline at end of file From 061b509cfc2c6b5d70bc856dd9ca2a49c538b575 Mon Sep 17 00:00:00 2001 From: Tim Vernum Date: Tue, 20 Nov 2018 13:01:49 +1100 Subject: [PATCH 2/2] Switch nested "if" to "&&" --- .../action/user/HasPrivilegesResponse.java | 17 +++++------------ 1 file changed, 5 insertions(+), 12 deletions(-) diff --git a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/security/action/user/HasPrivilegesResponse.java b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/security/action/user/HasPrivilegesResponse.java index 6ae8c445327cf..0942ef053a818 100644 --- a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/security/action/user/HasPrivilegesResponse.java +++ b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/security/action/user/HasPrivilegesResponse.java @@ -85,18 +85,11 @@ public boolean equals(Object o) { return false; } final HasPrivilegesResponse response = (HasPrivilegesResponse) o; - if (completeMatch == response.completeMatch) { - if (Objects.equals(username, response.username)) { - if (Objects.equals(cluster, response.cluster)) { - if (Objects.equals(index, response.index)) { - if (Objects.equals(application, response.application)) { - return true; - } - } - } - } - } - return false; + return completeMatch == response.completeMatch + && Objects.equals(username, response.username) + && Objects.equals(cluster, response.cluster) + && Objects.equals(index, response.index) + && Objects.equals(application, response.application); } @Override