Handle 6.4.0+ BWC for Application Privileges (#32929)

When the application privileges feature was backported to 6.x/6.4 the
BWC version checks on the backport were updated to 6.4.0, but master
was not updated.

This commit updates all relevant version checks, and adds tests.
This commit is contained in:
Tim Vernum 2018-08-21 17:58:37 +10:00 committed by GitHub
parent 38886e8f23
commit b595b1a20c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 112 additions and 11 deletions

View File

@ -167,7 +167,7 @@ public class PutRoleRequest extends ActionRequest implements WriteRequest<PutRol
for (int i = 0; i < indicesSize; i++) { for (int i = 0; i < indicesSize; i++) {
indicesPrivileges.add(RoleDescriptor.IndicesPrivileges.createFrom(in)); indicesPrivileges.add(RoleDescriptor.IndicesPrivileges.createFrom(in));
} }
if (in.getVersion().onOrAfter(Version.V_7_0_0_alpha1)) { if (in.getVersion().onOrAfter(Version.V_6_4_0)) {
applicationPrivileges = in.readList(RoleDescriptor.ApplicationResourcePrivileges::createFrom); applicationPrivileges = in.readList(RoleDescriptor.ApplicationResourcePrivileges::createFrom);
conditionalClusterPrivileges = ConditionalClusterPrivileges.readArray(in); conditionalClusterPrivileges = ConditionalClusterPrivileges.readArray(in);
} }
@ -185,7 +185,7 @@ public class PutRoleRequest extends ActionRequest implements WriteRequest<PutRol
for (RoleDescriptor.IndicesPrivileges index : indicesPrivileges) { for (RoleDescriptor.IndicesPrivileges index : indicesPrivileges) {
index.writeTo(out); index.writeTo(out);
} }
if (out.getVersion().onOrAfter(Version.V_7_0_0_alpha1)) { if (out.getVersion().onOrAfter(Version.V_6_4_0)) {
out.writeStreamableList(applicationPrivileges); out.writeStreamableList(applicationPrivileges);
ConditionalClusterPrivileges.writeArray(out, this.conditionalClusterPrivileges); ConditionalClusterPrivileges.writeArray(out, this.conditionalClusterPrivileges);
} }

View File

@ -109,7 +109,7 @@ public class HasPrivilegesRequest extends ActionRequest implements UserRequest {
for (int i = 0; i < indexSize; i++) { for (int i = 0; i < indexSize; i++) {
indexPrivileges[i] = RoleDescriptor.IndicesPrivileges.createFrom(in); indexPrivileges[i] = RoleDescriptor.IndicesPrivileges.createFrom(in);
} }
if (in.getVersion().onOrAfter(Version.V_7_0_0_alpha1)) { if (in.getVersion().onOrAfter(Version.V_6_4_0)) {
applicationPrivileges = in.readArray(ApplicationResourcePrivileges::createFrom, ApplicationResourcePrivileges[]::new); applicationPrivileges = in.readArray(ApplicationResourcePrivileges::createFrom, ApplicationResourcePrivileges[]::new);
} }
} }
@ -123,7 +123,7 @@ public class HasPrivilegesRequest extends ActionRequest implements UserRequest {
for (RoleDescriptor.IndicesPrivileges priv : indexPrivileges) { for (RoleDescriptor.IndicesPrivileges priv : indexPrivileges) {
priv.writeTo(out); priv.writeTo(out);
} }
if (out.getVersion().onOrAfter(Version.V_7_0_0_alpha1)) { if (out.getVersion().onOrAfter(Version.V_6_4_0)) {
out.writeArray(ApplicationResourcePrivileges::write, applicationPrivileges); out.writeArray(ApplicationResourcePrivileges::write, applicationPrivileges);
} }
} }

View File

@ -66,7 +66,7 @@ public class HasPrivilegesResponse extends ActionResponse {
super.readFrom(in); super.readFrom(in);
completeMatch = in.readBoolean(); completeMatch = in.readBoolean();
index = readResourcePrivileges(in); index = readResourcePrivileges(in);
if (in.getVersion().onOrAfter(Version.V_7_0_0_alpha1)) { if (in.getVersion().onOrAfter(Version.V_6_4_0)) {
application = in.readMap(StreamInput::readString, HasPrivilegesResponse::readResourcePrivileges); application = in.readMap(StreamInput::readString, HasPrivilegesResponse::readResourcePrivileges);
} }
} }
@ -87,7 +87,7 @@ public class HasPrivilegesResponse extends ActionResponse {
super.writeTo(out); super.writeTo(out);
out.writeBoolean(completeMatch); out.writeBoolean(completeMatch);
writeResourcePrivileges(out, index); writeResourcePrivileges(out, index);
if (out.getVersion().onOrAfter(Version.V_7_0_0_alpha1)) { if (out.getVersion().onOrAfter(Version.V_6_4_0)) {
out.writeMap(application, StreamOutput::writeString, HasPrivilegesResponse::writeResourcePrivileges); out.writeMap(application, StreamOutput::writeString, HasPrivilegesResponse::writeResourcePrivileges);
} }
} }

View File

@ -252,7 +252,7 @@ public class RoleDescriptor implements ToXContentObject {
final ApplicationResourcePrivileges[] applicationPrivileges; final ApplicationResourcePrivileges[] applicationPrivileges;
final ConditionalClusterPrivilege[] conditionalClusterPrivileges; final ConditionalClusterPrivilege[] conditionalClusterPrivileges;
if (in.getVersion().onOrAfter(Version.V_7_0_0_alpha1)) { if (in.getVersion().onOrAfter(Version.V_6_4_0)) {
applicationPrivileges = in.readArray(ApplicationResourcePrivileges::createFrom, ApplicationResourcePrivileges[]::new); applicationPrivileges = in.readArray(ApplicationResourcePrivileges::createFrom, ApplicationResourcePrivileges[]::new);
conditionalClusterPrivileges = ConditionalClusterPrivileges.readArray(in); conditionalClusterPrivileges = ConditionalClusterPrivileges.readArray(in);
} else { } else {
@ -276,7 +276,7 @@ public class RoleDescriptor implements ToXContentObject {
if (out.getVersion().onOrAfter(Version.V_5_2_0)) { if (out.getVersion().onOrAfter(Version.V_5_2_0)) {
out.writeMap(descriptor.transientMetadata); out.writeMap(descriptor.transientMetadata);
} }
if (out.getVersion().onOrAfter(Version.V_7_0_0_alpha1)) { if (out.getVersion().onOrAfter(Version.V_6_4_0)) {
out.writeArray(ApplicationResourcePrivileges::write, descriptor.applicationPrivileges); out.writeArray(ApplicationResourcePrivileges::write, descriptor.applicationPrivileges);
ConditionalClusterPrivileges.writeArray(out, descriptor.getConditionalClusterPrivileges()); ConditionalClusterPrivileges.writeArray(out, descriptor.getConditionalClusterPrivileges());
} }

View File

@ -58,11 +58,17 @@ public class PutRoleRequestTests extends ESTestCase {
final PutRoleRequest original = buildRandomRequest(); final PutRoleRequest original = buildRandomRequest();
final BytesStreamOutput out = new BytesStreamOutput(); final BytesStreamOutput out = new BytesStreamOutput();
if (randomBoolean()) {
final Version version = VersionUtils.randomVersionBetween(random(), Version.V_6_4_0, Version.CURRENT);
logger.info("Serializing with version {}", version);
out.setVersion(version);
}
original.writeTo(out); original.writeTo(out);
final PutRoleRequest copy = new PutRoleRequest(); final PutRoleRequest copy = new PutRoleRequest();
final NamedWriteableRegistry registry = new NamedWriteableRegistry(new XPackClientPlugin(Settings.EMPTY).getNamedWriteables()); final NamedWriteableRegistry registry = new NamedWriteableRegistry(new XPackClientPlugin(Settings.EMPTY).getNamedWriteables());
StreamInput in = new NamedWriteableAwareStreamInput(ByteBufferStreamInput.wrap(BytesReference.toBytes(out.bytes())), registry); StreamInput in = new NamedWriteableAwareStreamInput(ByteBufferStreamInput.wrap(BytesReference.toBytes(out.bytes())), registry);
in.setVersion(out.getVersion());
copy.readFrom(in); copy.readFrom(in);
assertThat(copy.roleDescriptor(), equalTo(original.roleDescriptor())); assertThat(copy.roleDescriptor(), equalTo(original.roleDescriptor()));

View File

@ -12,6 +12,7 @@ import org.elasticsearch.common.Strings;
import org.elasticsearch.common.io.stream.BytesStreamOutput; import org.elasticsearch.common.io.stream.BytesStreamOutput;
import org.elasticsearch.common.io.stream.StreamInput; import org.elasticsearch.common.io.stream.StreamInput;
import org.elasticsearch.test.ESTestCase; import org.elasticsearch.test.ESTestCase;
import org.elasticsearch.test.VersionUtils;
import org.elasticsearch.xpack.core.security.authz.RoleDescriptor.ApplicationResourcePrivileges; import org.elasticsearch.xpack.core.security.authz.RoleDescriptor.ApplicationResourcePrivileges;
import org.elasticsearch.xpack.core.security.authz.RoleDescriptor.IndicesPrivileges; import org.elasticsearch.xpack.core.security.authz.RoleDescriptor.IndicesPrivileges;
import org.elasticsearch.xpack.core.security.authz.privilege.ClusterPrivilege; import org.elasticsearch.xpack.core.security.authz.privilege.ClusterPrivilege;
@ -28,9 +29,10 @@ import static org.hamcrest.Matchers.nullValue;
public class HasPrivilegesRequestTests extends ESTestCase { public class HasPrivilegesRequestTests extends ESTestCase {
public void testSerializationV7() throws IOException { public void testSerializationV64OrLater() throws IOException {
final HasPrivilegesRequest original = randomRequest(); final HasPrivilegesRequest original = randomRequest();
final HasPrivilegesRequest copy = serializeAndDeserialize(original, Version.V_7_0_0_alpha1); final Version version = VersionUtils.randomVersionBetween(random(), Version.V_6_4_0, Version.CURRENT);
final HasPrivilegesRequest copy = serializeAndDeserialize(original, version);
assertThat(copy.username(), equalTo(original.username())); assertThat(copy.username(), equalTo(original.username()));
assertThat(copy.clusterPrivileges(), equalTo(original.clusterPrivileges())); assertThat(copy.clusterPrivileges(), equalTo(original.clusterPrivileges()));

View File

@ -0,0 +1,87 @@
/*
* 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.core.security.action.user;
import org.elasticsearch.Version;
import org.elasticsearch.common.io.stream.BytesStreamOutput;
import org.elasticsearch.common.io.stream.StreamInput;
import org.elasticsearch.test.ESTestCase;
import org.elasticsearch.test.VersionUtils;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
import static org.hamcrest.Matchers.equalTo;
public class HasPrivilegesResponseTests extends ESTestCase {
public void testSerializationV64OrLater() throws IOException {
final HasPrivilegesResponse original = randomResponse();
final Version version = VersionUtils.randomVersionBetween(random(), Version.V_6_4_0, Version.CURRENT);
final HasPrivilegesResponse copy = serializeAndDeserialize(original, version);
assertThat(copy.isCompleteMatch(), equalTo(original.isCompleteMatch()));
// assertThat(copy.getClusterPrivileges(), equalTo(original.getClusterPrivileges()));
assertThat(copy.getIndexPrivileges(), equalTo(original.getIndexPrivileges()));
assertThat(copy.getApplicationPrivileges(), equalTo(original.getApplicationPrivileges()));
}
public void testSerializationV63() throws IOException {
final HasPrivilegesResponse original = randomResponse();
final HasPrivilegesResponse copy = serializeAndDeserialize(original, Version.V_6_3_0);
assertThat(copy.isCompleteMatch(), equalTo(original.isCompleteMatch()));
// assertThat(copy.getClusterPrivileges(), equalTo(original.getClusterPrivileges()));
assertThat(copy.getIndexPrivileges(), equalTo(original.getIndexPrivileges()));
assertThat(copy.getApplicationPrivileges(), equalTo(Collections.emptyMap()));
}
private HasPrivilegesResponse serializeAndDeserialize(HasPrivilegesResponse original, Version version) throws IOException {
logger.info("Test serialize/deserialize with version {}", version);
final BytesStreamOutput out = new BytesStreamOutput();
out.setVersion(version);
original.writeTo(out);
final HasPrivilegesResponse copy = new HasPrivilegesResponse();
final StreamInput in = out.bytes().streamInput();
in.setVersion(version);
copy.readFrom(in);
assertThat(in.read(), equalTo(-1));
return copy;
}
private HasPrivilegesResponse randomResponse() {
final Map<String, Boolean> cluster = new HashMap<>();
for (String priv : randomArray(1, 6, String[]::new, () -> randomAlphaOfLengthBetween(3, 12))) {
cluster.put(priv, randomBoolean());
}
final Collection<HasPrivilegesResponse.ResourcePrivileges> index = randomResourcePrivileges();
final Map<String, Collection<HasPrivilegesResponse.ResourcePrivileges>> application = new HashMap<>();
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);
}
private Collection<HasPrivilegesResponse.ResourcePrivileges> randomResourcePrivileges() {
final Collection<HasPrivilegesResponse.ResourcePrivileges> list = new ArrayList<>();
for (String resource : randomArray(1, 3, String[]::new, () -> randomAlphaOfLengthBetween(2, 6))) {
final Map<String, Boolean> privileges = new HashMap<>();
for (String priv : randomArray(1, 5, String[]::new, () -> randomAlphaOfLengthBetween(3, 8))) {
privileges.put(priv, randomBoolean());
}
list.add(new HasPrivilegesResponse.ResourcePrivileges(resource, privileges));
}
return list;
}
}

View File

@ -5,6 +5,7 @@
*/ */
package org.elasticsearch.xpack.security.authz; package org.elasticsearch.xpack.security.authz;
import org.elasticsearch.Version;
import org.elasticsearch.common.Strings; import org.elasticsearch.common.Strings;
import org.elasticsearch.common.bytes.BytesArray; import org.elasticsearch.common.bytes.BytesArray;
import org.elasticsearch.common.bytes.BytesReference; import org.elasticsearch.common.bytes.BytesReference;
@ -18,10 +19,11 @@ import org.elasticsearch.common.xcontent.ToXContent;
import org.elasticsearch.common.xcontent.XContentBuilder; import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.common.xcontent.XContentType; import org.elasticsearch.common.xcontent.XContentType;
import org.elasticsearch.test.ESTestCase; import org.elasticsearch.test.ESTestCase;
import org.elasticsearch.test.VersionUtils;
import org.elasticsearch.xpack.core.XPackClientPlugin; import org.elasticsearch.xpack.core.XPackClientPlugin;
import org.elasticsearch.xpack.core.security.authz.RoleDescriptor; import org.elasticsearch.xpack.core.security.authz.RoleDescriptor;
import org.elasticsearch.xpack.core.security.authz.privilege.ConditionalClusterPrivileges;
import org.elasticsearch.xpack.core.security.authz.privilege.ConditionalClusterPrivilege; import org.elasticsearch.xpack.core.security.authz.privilege.ConditionalClusterPrivilege;
import org.elasticsearch.xpack.core.security.authz.privilege.ConditionalClusterPrivileges;
import org.elasticsearch.xpack.core.security.support.MetadataUtils; import org.elasticsearch.xpack.core.security.support.MetadataUtils;
import org.hamcrest.Matchers; import org.hamcrest.Matchers;
@ -208,7 +210,10 @@ public class RoleDescriptorTests extends ESTestCase {
} }
public void testSerialization() throws Exception { public void testSerialization() throws Exception {
final Version version = VersionUtils.randomVersionBetween(random(), Version.V_6_4_0, null);
logger.info("Testing serialization with version {}", version);
BytesStreamOutput output = new BytesStreamOutput(); BytesStreamOutput output = new BytesStreamOutput();
output.setVersion(version);
RoleDescriptor.IndicesPrivileges[] groups = new RoleDescriptor.IndicesPrivileges[] { RoleDescriptor.IndicesPrivileges[] groups = new RoleDescriptor.IndicesPrivileges[] {
RoleDescriptor.IndicesPrivileges.builder() RoleDescriptor.IndicesPrivileges.builder()
.indices("i1", "i2") .indices("i1", "i2")
@ -235,6 +240,7 @@ public class RoleDescriptorTests extends ESTestCase {
final NamedWriteableRegistry registry = new NamedWriteableRegistry(new XPackClientPlugin(Settings.EMPTY).getNamedWriteables()); final NamedWriteableRegistry registry = new NamedWriteableRegistry(new XPackClientPlugin(Settings.EMPTY).getNamedWriteables());
StreamInput streamInput = new NamedWriteableAwareStreamInput(ByteBufferStreamInput.wrap(BytesReference.toBytes(output.bytes())), StreamInput streamInput = new NamedWriteableAwareStreamInput(ByteBufferStreamInput.wrap(BytesReference.toBytes(output.bytes())),
registry); registry);
streamInput.setVersion(version);
final RoleDescriptor serialized = RoleDescriptor.readFrom(streamInput); final RoleDescriptor serialized = RoleDescriptor.readFrom(streamInput);
assertEquals(descriptor, serialized); assertEquals(descriptor, serialized);
} }