Browse Source

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.
Tim Vernum 7 years ago
parent
commit
b595b1a20c

+ 2 - 2
x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/security/action/role/PutRoleRequest.java

@@ -167,7 +167,7 @@ public class PutRoleRequest extends ActionRequest implements WriteRequest<PutRol
         for (int i = 0; i < indicesSize; i++) {
             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);
             conditionalClusterPrivileges = ConditionalClusterPrivileges.readArray(in);
         }
@@ -185,7 +185,7 @@ public class PutRoleRequest extends ActionRequest implements WriteRequest<PutRol
         for (RoleDescriptor.IndicesPrivileges index : indicesPrivileges) {
             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);
             ConditionalClusterPrivileges.writeArray(out, this.conditionalClusterPrivileges);
         }

+ 2 - 2
x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/security/action/user/HasPrivilegesRequest.java

@@ -109,7 +109,7 @@ public class HasPrivilegesRequest extends ActionRequest implements UserRequest {
         for (int i = 0; i < indexSize; i++) {
             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);
         }
     }
@@ -123,7 +123,7 @@ public class HasPrivilegesRequest extends ActionRequest implements UserRequest {
         for (RoleDescriptor.IndicesPrivileges priv : indexPrivileges) {
             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);
         }
     }

+ 2 - 2
x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/security/action/user/HasPrivilegesResponse.java

@@ -66,7 +66,7 @@ public class HasPrivilegesResponse extends ActionResponse {
         super.readFrom(in);
         completeMatch = in.readBoolean();
         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);
         }
     }
@@ -87,7 +87,7 @@ public class HasPrivilegesResponse extends ActionResponse {
         super.writeTo(out);
         out.writeBoolean(completeMatch);
         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);
         }
     }

+ 2 - 2
x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/security/authz/RoleDescriptor.java

@@ -252,7 +252,7 @@ public class RoleDescriptor implements ToXContentObject {
 
         final ApplicationResourcePrivileges[] applicationPrivileges;
         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);
             conditionalClusterPrivileges = ConditionalClusterPrivileges.readArray(in);
         } else {
@@ -276,7 +276,7 @@ public class RoleDescriptor implements ToXContentObject {
         if (out.getVersion().onOrAfter(Version.V_5_2_0)) {
             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);
             ConditionalClusterPrivileges.writeArray(out, descriptor.getConditionalClusterPrivileges());
         }

+ 6 - 0
x-pack/plugin/core/src/test/java/org/elasticsearch/xpack/core/security/action/role/PutRoleRequestTests.java

@@ -58,11 +58,17 @@ public class PutRoleRequestTests extends ESTestCase {
         final PutRoleRequest original = buildRandomRequest();
 
         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);
 
         final PutRoleRequest copy = new PutRoleRequest();
         final NamedWriteableRegistry registry = new NamedWriteableRegistry(new XPackClientPlugin(Settings.EMPTY).getNamedWriteables());
         StreamInput in = new NamedWriteableAwareStreamInput(ByteBufferStreamInput.wrap(BytesReference.toBytes(out.bytes())), registry);
+        in.setVersion(out.getVersion());
         copy.readFrom(in);
 
         assertThat(copy.roleDescriptor(), equalTo(original.roleDescriptor()));

+ 4 - 2
x-pack/plugin/core/src/test/java/org/elasticsearch/xpack/core/security/action/user/HasPrivilegesRequestTests.java

@@ -12,6 +12,7 @@ import org.elasticsearch.common.Strings;
 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 org.elasticsearch.xpack.core.security.authz.RoleDescriptor.ApplicationResourcePrivileges;
 import org.elasticsearch.xpack.core.security.authz.RoleDescriptor.IndicesPrivileges;
 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 void testSerializationV7() throws IOException {
+    public void testSerializationV64OrLater() throws IOException {
         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.clusterPrivileges(), equalTo(original.clusterPrivileges()));

+ 87 - 0
x-pack/plugin/core/src/test/java/org/elasticsearch/xpack/core/security/action/user/HasPrivilegesResponseTests.java

@@ -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;
+    }
+
+}

+ 7 - 1
x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authz/RoleDescriptorTests.java

@@ -5,6 +5,7 @@
  */
 package org.elasticsearch.xpack.security.authz;
 
+import org.elasticsearch.Version;
 import org.elasticsearch.common.Strings;
 import org.elasticsearch.common.bytes.BytesArray;
 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.XContentType;
 import org.elasticsearch.test.ESTestCase;
+import org.elasticsearch.test.VersionUtils;
 import org.elasticsearch.xpack.core.XPackClientPlugin;
 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.ConditionalClusterPrivileges;
 import org.elasticsearch.xpack.core.security.support.MetadataUtils;
 import org.hamcrest.Matchers;
 
@@ -208,7 +210,10 @@ public class RoleDescriptorTests extends ESTestCase {
     }
 
     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();
+        output.setVersion(version);
         RoleDescriptor.IndicesPrivileges[] groups = new RoleDescriptor.IndicesPrivileges[] {
                 RoleDescriptor.IndicesPrivileges.builder()
                         .indices("i1", "i2")
@@ -235,6 +240,7 @@ public class RoleDescriptorTests extends ESTestCase {
         final NamedWriteableRegistry registry = new NamedWriteableRegistry(new XPackClientPlugin(Settings.EMPTY).getNamedWriteables());
         StreamInput streamInput = new NamedWriteableAwareStreamInput(ByteBufferStreamInput.wrap(BytesReference.toBytes(output.bytes())),
             registry);
+        streamInput.setVersion(version);
         final RoleDescriptor serialized = RoleDescriptor.readFrom(streamInput);
         assertEquals(descriptor, serialized);
     }