From 2eb7fa44d3a552c8389b6a1eac3b5c5303a97108 Mon Sep 17 00:00:00 2001 From: Andrew Purtell Date: Tue, 17 Nov 2015 11:35:32 -0800 Subject: [PATCH] HBASE-14799 Commons-collections object deserialization remote command execution vulnerability --- .../java/org/apache/hadoop/hbase/HConstants.java | 5 + .../java/org/apache/hadoop/hbase/util/Base64.java | 127 -------- .../access/HbaseObjectWritableFor96Migration.java | 11 + .../TestHbaseObjectWritableFor96Migration.java | 334 +++++++++++++++++++++ .../security/access/TestTablePermissions.java | 13 +- pom.xml | 3 +- 6 files changed, 360 insertions(+), 133 deletions(-) create mode 100644 hbase-server/src/test/java/org/apache/hadoop/hbase/security/access/TestHbaseObjectWritableFor96Migration.java diff --git a/hbase-common/src/main/java/org/apache/hadoop/hbase/HConstants.java b/hbase-common/src/main/java/org/apache/hadoop/hbase/HConstants.java index 2a18f70..4f54c33 100644 --- a/hbase-common/src/main/java/org/apache/hadoop/hbase/HConstants.java +++ b/hbase-common/src/main/java/org/apache/hadoop/hbase/HConstants.java @@ -1144,6 +1144,11 @@ public final class HConstants { public static final String ZK_SERVER_KERBEROS_PRINCIPAL = "hbase.zookeeper.server.kerberos.principal"; + /** + * Allow legacy object serialization. Disabled by default because it is a security risk */ + public static final String ALLOW_LEGACY_OBJECT_SERIALIZATION_KEY = + "hbase.allow.legacy.object.serialization"; + private HConstants() { // Can't be instantiated with this ctor. } diff --git a/hbase-common/src/main/java/org/apache/hadoop/hbase/util/Base64.java b/hbase-common/src/main/java/org/apache/hadoop/hbase/util/Base64.java index 6677520..dadc70c 100644 --- a/hbase-common/src/main/java/org/apache/hadoop/hbase/util/Base64.java +++ b/hbase-common/src/main/java/org/apache/hadoop/hbase/util/Base64.java @@ -35,10 +35,7 @@ import java.io.FilterInputStream; import java.io.FilterOutputStream; import java.io.IOException; import java.io.InputStream; -import java.io.ObjectInputStream; -import java.io.ObjectOutputStream; import java.io.OutputStream; -import java.io.Serializable; import java.io.UnsupportedEncodingException; import java.util.zip.GZIPInputStream; import java.util.zip.GZIPOutputStream; @@ -513,93 +510,6 @@ public class Base64 { return destination; } // end switch } // end encode3to4 - - /** - * Serializes an object and returns the Base64-encoded version of that - * serialized object. If the object cannot be serialized or there is another - * error, the method will return null. The object is not - * GZip-compressed before being encoded. - * - * @param serializableObject The object to encode - * @return The Base64-encoded object - * @since 1.4 - */ - public static String encodeObject(Serializable serializableObject) { - return encodeObject(serializableObject, NO_OPTIONS); - } // end encodeObject - - /** - * Serializes an object and returns the Base64-encoded version of that - * serialized object. If the object cannot be serialized or there is another - * error, the method will return null. - *

- * Valid options: - *

- *

- * Example: encodeObject( myObj, Base64.GZIP ) or - *

- * Example: - * encodeObject( myObj, Base64.GZIP | Base64.DONT_BREAK_LINES ) - * - * @param serializableObject The object to encode - * @param options Specified options - * @see Base64#GZIP - * @see Base64#DONT_BREAK_LINES - * @return The Base64-encoded object - * @since 2.0 - */ - @SuppressWarnings({"ConstantConditions"}) - public static String encodeObject(Serializable serializableObject, - int options) { - - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - OutputStream b64os = null; - ObjectOutputStream oos = null; - try { - // ObjectOutputStream -> (GZIP) -> Base64 -> ByteArrayOutputStream - b64os = new Base64OutputStream(baos, ENCODE | options); - - oos = ((options & GZIP) == GZIP) ? - new ObjectOutputStream(new GZIPOutputStream(b64os)) : - new ObjectOutputStream(b64os); - - oos.writeObject(serializableObject); - return new String(baos.toByteArray(), PREFERRED_ENCODING); - - } catch (UnsupportedEncodingException uue) { - return new String(baos.toByteArray()); - - } catch (IOException e) { - LOG.error("error encoding object", e); - return null; - - } finally { - if (oos != null) { - try { - oos.close(); - } catch (Exception e) { - LOG.error("error closing ObjectOutputStream", e); - } - } - if (b64os != null) { - try { - b64os.close(); - } catch (Exception e) { - LOG.error("error closing Base64OutputStream", e); - } - } - try { - baos.close(); - } catch (Exception e) { - LOG.error("error closing ByteArrayOutputStream", e); - } - } // end finally - } // end encode - /** * Encodes a byte array into Base64 notation. Does not GZip-compress data. * @@ -978,43 +888,6 @@ public class Base64 { } // end decode /** - * Attempts to decode Base64 data and deserialize a Java Object within. - * Returns null if there was an error. - * - * @param encodedObject The Base64 data to decode - * @return The decoded and deserialized object - * @since 1.5 - */ - public static Object decodeToObject(String encodedObject) { - // Decode and gunzip if necessary - byte[] objBytes = decode(encodedObject); - - Object obj = null; - ObjectInputStream ois = null; - try { - ois = new ObjectInputStream(new ByteArrayInputStream(objBytes)); - obj = ois.readObject(); - - } catch (IOException e) { - LOG.error("error decoding object", e); - - } catch (ClassNotFoundException e) { - LOG.error("error decoding object", e); - - } finally { - if (ois != null) { - try { - ois.close(); - } catch (Exception e) { - LOG.error("error closing ObjectInputStream", e); - } - } - } // end finally - - return obj; - } // end decodeObject - - /** * Convenience method for encoding data to a file. * * @param dataToEncode byte array of data to encode in base64 form diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/security/access/HbaseObjectWritableFor96Migration.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/security/access/HbaseObjectWritableFor96Migration.java index 4fd0a61..1f418bd 100644 --- a/hbase-server/src/main/java/org/apache/hadoop/hbase/security/access/HbaseObjectWritableFor96Migration.java +++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/security/access/HbaseObjectWritableFor96Migration.java @@ -60,6 +60,7 @@ import org.apache.hadoop.hbase.client.Result; import org.apache.hadoop.hbase.client.Row; import org.apache.hadoop.hbase.client.RowMutations; import org.apache.hadoop.hbase.client.Scan; +import org.apache.hadoop.hbase.exceptions.DeserializationException; import org.apache.hadoop.hbase.filter.BinaryComparator; import org.apache.hadoop.hbase.filter.BitComparator; import org.apache.hadoop.hbase.filter.ByteArrayComparable; @@ -514,6 +515,11 @@ class HbaseObjectWritableFor96Migration implements Writable, WritableWithSize, C } ((Writable)instanceObj).write(out); } else if (Serializable.class.isAssignableFrom(declClass)) { + if (!conf.getBoolean(HConstants.ALLOW_LEGACY_OBJECT_SERIALIZATION_KEY, false)) { + throw new IOException( + "Legacy object serialization support is disabled by default." + + " Change '" + HConstants.ALLOW_LEGACY_OBJECT_SERIALIZATION_KEY + "' to enable."); + } Class c = instanceObj.getClass(); Integer code = CLASS_TO_CODE.get(c); if (code == null) { @@ -698,6 +704,11 @@ class HbaseObjectWritableFor96Migration implements Writable, WritableWithSize, C instance = null; } } else { + if (!conf.getBoolean(HConstants.ALLOW_LEGACY_OBJECT_SERIALIZATION_KEY, false)) { + throw new IOException( + "Legacy object deserialization support is disabled by default." + + " Change '" + HConstants.ALLOW_LEGACY_OBJECT_SERIALIZATION_KEY + "' to enable."); + } int length = in.readInt(); byte[] objectBytes = new byte[length]; in.readFully(objectBytes); diff --git a/hbase-server/src/test/java/org/apache/hadoop/hbase/security/access/TestHbaseObjectWritableFor96Migration.java b/hbase-server/src/test/java/org/apache/hadoop/hbase/security/access/TestHbaseObjectWritableFor96Migration.java new file mode 100644 index 0000000..ec65231 --- /dev/null +++ b/hbase-server/src/test/java/org/apache/hadoop/hbase/security/access/TestHbaseObjectWritableFor96Migration.java @@ -0,0 +1,334 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF 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.apache.hadoop.hbase.security.access; + +import static org.junit.Assert.*; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.DataInput; +import java.io.DataInputStream; +import java.io.DataOutput; +import java.io.DataOutputStream; +import java.io.IOException; +import java.io.Serializable; +import java.lang.reflect.Array; +import java.util.List; +import java.util.NavigableSet; + +import org.apache.hadoop.conf.Configuration; +import org.apache.hadoop.hbase.ClusterStatus; +import org.apache.hadoop.hbase.HBaseConfiguration; +import org.apache.hadoop.hbase.HColumnDescriptor; +import org.apache.hadoop.hbase.HConstants; +import org.apache.hadoop.hbase.HRegionInfo; +import org.apache.hadoop.hbase.HTableDescriptor; +import org.apache.hadoop.hbase.KeyValue; +import org.apache.hadoop.hbase.client.Action; +import org.apache.hadoop.hbase.client.Append; +import org.apache.hadoop.hbase.client.Delete; +import org.apache.hadoop.hbase.client.Get; +import org.apache.hadoop.hbase.client.Increment; +import org.apache.hadoop.hbase.client.MultiAction; +import org.apache.hadoop.hbase.client.MultiResponse; +import org.apache.hadoop.hbase.client.Put; +import org.apache.hadoop.hbase.client.Result; +import org.apache.hadoop.hbase.client.Row; +import org.apache.hadoop.hbase.client.RowMutations; +import org.apache.hadoop.hbase.client.Scan; +import org.apache.hadoop.hbase.filter.BinaryComparator; +import org.apache.hadoop.hbase.filter.BitComparator; +import org.apache.hadoop.hbase.filter.ColumnCountGetFilter; +import org.apache.hadoop.hbase.filter.ColumnPrefixFilter; +import org.apache.hadoop.hbase.filter.ColumnRangeFilter; +import org.apache.hadoop.hbase.filter.CompareFilter; +import org.apache.hadoop.hbase.filter.CompareFilter.CompareOp; +import org.apache.hadoop.hbase.filter.DependentColumnFilter; +import org.apache.hadoop.hbase.filter.FirstKeyOnlyFilter; +import org.apache.hadoop.hbase.filter.InclusiveStopFilter; +import org.apache.hadoop.hbase.filter.KeyOnlyFilter; +import org.apache.hadoop.hbase.filter.PageFilter; +import org.apache.hadoop.hbase.filter.PrefixFilter; +import org.apache.hadoop.hbase.filter.QualifierFilter; +import org.apache.hadoop.hbase.filter.RandomRowFilter; +import org.apache.hadoop.hbase.filter.RowFilter; +import org.apache.hadoop.hbase.filter.SingleColumnValueExcludeFilter; +import org.apache.hadoop.hbase.filter.SingleColumnValueFilter; +import org.apache.hadoop.hbase.filter.SkipFilter; +import org.apache.hadoop.hbase.filter.ValueFilter; +import org.apache.hadoop.hbase.filter.WhileMatchFilter; +import org.apache.hadoop.hbase.regionserver.HRegion; +import org.apache.hadoop.hbase.regionserver.RegionOpeningState; +import org.apache.hadoop.hbase.regionserver.wal.HLog; +import org.apache.hadoop.hbase.regionserver.wal.HLogKey; +import org.apache.hadoop.io.MapWritable; +import org.apache.hadoop.io.Text; +import org.apache.hadoop.io.Writable; +import org.junit.Test; + +import com.google.protobuf.Message; + +public class TestHbaseObjectWritableFor96Migration { + + @Test + public void testCustomWritable() throws Exception { + Configuration conf = HBaseConfiguration.create(); + // test proper serialization of un-encoded custom writables + CustomWritable custom = new CustomWritable("test phrase"); + Object obj = doType(conf, custom, CustomWritable.class); + assertTrue(obj instanceof Writable); + assertTrue(obj instanceof CustomWritable); + assertEquals("test phrase", ((CustomWritable)obj).getValue()); + } + + @Test + public void testCustomSerializable() throws Exception { + Configuration conf = HBaseConfiguration.create(); + + Configuration legacyConf = HBaseConfiguration.create(); + legacyConf.setBoolean(HConstants.ALLOW_LEGACY_OBJECT_SERIALIZATION_KEY, true); + + CustomSerializable custom = new CustomSerializable("test phrase"); + + // check that we can't write by default + try { + writeType(conf, custom, CustomSerializable.class); + fail("IOException expected"); + } catch (IOException e) { + // expected + } + + // check that we can't read by default + byte[] data = writeType(legacyConf, custom, CustomSerializable.class); + try { + readType(conf, data); + fail("IOException expected"); + } catch (IOException e) { + // expected + } + } + + @Test + public void testLegacyCustomSerializable() throws Exception { + Configuration conf = HBaseConfiguration.create(); + conf.setBoolean(HConstants.ALLOW_LEGACY_OBJECT_SERIALIZATION_KEY, true); + // test proper serialization of un-encoded serialized java objects + CustomSerializable custom = new CustomSerializable("test phrase"); + byte[] data = writeType(conf, custom, CustomSerializable.class); + Object obj = readType(conf, data); + assertTrue(obj instanceof Serializable); + assertTrue(obj instanceof CustomSerializable); + assertEquals("test phrase", ((CustomSerializable)obj).getValue()); + } + + private Object doType(final Configuration conf, final Object value, + final Class clazz) + throws IOException { + return readType(conf, writeType(conf, value, clazz)); + } + + @SuppressWarnings("deprecation") + private byte[] writeType(final Configuration conf, final Object value, + final Class clazz) throws IOException { + ByteArrayOutputStream byteStream = new ByteArrayOutputStream(); + DataOutputStream out = new DataOutputStream(byteStream); + HbaseObjectWritableFor96Migration.writeObject(out, value, clazz, conf); + out.close(); + return byteStream.toByteArray(); + } + + @SuppressWarnings("deprecation") + private Object readType(final Configuration conf, final byte[] value) + throws IOException { + DataInputStream dis = new DataInputStream(new ByteArrayInputStream(value)); + Object product = HbaseObjectWritableFor96Migration.readObject(dis, conf); + dis.close(); + return product; + } + + public static class CustomSerializable implements Serializable { + private static final long serialVersionUID = 1048445561865740632L; + private String value = null; + + public CustomSerializable() { + } + + public CustomSerializable(String value) { + this.value = value; + } + + public String getValue() { + return value; + } + + public void setValue(String value) { + this.value = value; + } + + } + + public static class CustomWritable implements Writable { + private String value = null; + + public CustomWritable() { + } + + public CustomWritable(String val) { + this.value = val; + } + + public String getValue() { return value; } + + @Override + public void write(DataOutput out) throws IOException { + Text.writeString(out, this.value); + } + + @Override + public void readFields(DataInput in) throws IOException { + this.value = Text.readString(in); + } + } + + /** + * Test case to ensure ordering of CODE_TO_CLASS and CLASS_TO_CODE. In the + * past, and item was added in the middle of the static initializer, and that + * threw off all of the codes after the addition. This unintentionally broke + * the wire protocol for clients. The idea behind this test case is that if + * you unintentionally change the order, you will get a test failure. If you + * are actually intentionally change the order, just update the test case. + * This should be a clue to the reviewer that you are doing something to + * change the wire protocol. + */ + @SuppressWarnings("deprecation") + @Test + public void testGetClassCode() throws IOException{ + // Primitive types + assertEquals(1,HbaseObjectWritableFor96Migration.getClassCode(Boolean.TYPE).intValue()); + assertEquals(2,HbaseObjectWritableFor96Migration.getClassCode(Byte.TYPE).intValue()); + assertEquals(3,HbaseObjectWritableFor96Migration.getClassCode(Character.TYPE).intValue()); + assertEquals(4,HbaseObjectWritableFor96Migration.getClassCode(Short.TYPE).intValue()); + assertEquals(5,HbaseObjectWritableFor96Migration.getClassCode(Integer.TYPE).intValue()); + assertEquals(6,HbaseObjectWritableFor96Migration.getClassCode(Long.TYPE).intValue()); + assertEquals(7,HbaseObjectWritableFor96Migration.getClassCode(Float.TYPE).intValue()); + assertEquals(8,HbaseObjectWritableFor96Migration.getClassCode(Double.TYPE).intValue()); + assertEquals(9,HbaseObjectWritableFor96Migration.getClassCode(Void.TYPE).intValue()); + + // Other java types + assertEquals(10,HbaseObjectWritableFor96Migration.getClassCode(String.class).intValue()); + assertEquals(11,HbaseObjectWritableFor96Migration.getClassCode(byte [].class).intValue()); + assertEquals(12,HbaseObjectWritableFor96Migration.getClassCode(byte [][].class).intValue()); + + // Hadoop types + assertEquals(13,HbaseObjectWritableFor96Migration.getClassCode(Text.class).intValue()); + assertEquals(14,HbaseObjectWritableFor96Migration.getClassCode(Writable.class).intValue()); + assertEquals(15,HbaseObjectWritableFor96Migration.getClassCode(Writable [].class).intValue()); + //assertEquals(16,HbaseObjectWritableFor96Migration.getClassCode(HbaseMapWritable.class).intValue()); + // 17 is NullInstance which isn't visible from here + + // Hbase types + assertEquals(18,HbaseObjectWritableFor96Migration.getClassCode(HColumnDescriptor.class).intValue()); + assertEquals(19,HbaseObjectWritableFor96Migration.getClassCode(HConstants.Modify.class).intValue()); + // 20 and 21 are place holders for HMsg + // 22: Not pushed over the wire + // 23: Not pushed over the wire + assertEquals(24,HbaseObjectWritableFor96Migration.getClassCode(HRegionInfo.class).intValue()); + assertEquals(25,HbaseObjectWritableFor96Migration.getClassCode(HRegionInfo[].class).intValue()); + // 26: Removed + // 27: Removed + assertEquals(28,HbaseObjectWritableFor96Migration.getClassCode(HTableDescriptor.class).intValue()); + assertEquals(29,HbaseObjectWritableFor96Migration.getClassCode(MapWritable.class).intValue()); + + // HBASE-880 + assertEquals(30,HbaseObjectWritableFor96Migration.getClassCode(ClusterStatus.class).intValue()); + assertEquals(31,HbaseObjectWritableFor96Migration.getClassCode(Delete.class).intValue()); + assertEquals(32,HbaseObjectWritableFor96Migration.getClassCode(Get.class).intValue()); + assertEquals(33,HbaseObjectWritableFor96Migration.getClassCode(KeyValue.class).intValue()); + assertEquals(34,HbaseObjectWritableFor96Migration.getClassCode(KeyValue[].class).intValue()); + assertEquals(35,HbaseObjectWritableFor96Migration.getClassCode(Put.class).intValue()); + assertEquals(36,HbaseObjectWritableFor96Migration.getClassCode(Put[].class).intValue()); + assertEquals(37,HbaseObjectWritableFor96Migration.getClassCode(Result.class).intValue()); + assertEquals(38,HbaseObjectWritableFor96Migration.getClassCode(Result[].class).intValue()); + assertEquals(39,HbaseObjectWritableFor96Migration.getClassCode(Scan.class).intValue()); + + assertEquals(40,HbaseObjectWritableFor96Migration.getClassCode(WhileMatchFilter.class).intValue()); + assertEquals(41,HbaseObjectWritableFor96Migration.getClassCode(PrefixFilter.class).intValue()); + assertEquals(42,HbaseObjectWritableFor96Migration.getClassCode(PageFilter.class).intValue()); + assertEquals(43,HbaseObjectWritableFor96Migration.getClassCode(InclusiveStopFilter.class).intValue()); + assertEquals(44,HbaseObjectWritableFor96Migration.getClassCode(ColumnCountGetFilter.class).intValue()); + assertEquals(45,HbaseObjectWritableFor96Migration.getClassCode(SingleColumnValueFilter.class).intValue()); + assertEquals(46,HbaseObjectWritableFor96Migration.getClassCode(SingleColumnValueExcludeFilter.class).intValue()); + assertEquals(47,HbaseObjectWritableFor96Migration.getClassCode(BinaryComparator.class).intValue()); + assertEquals(48,HbaseObjectWritableFor96Migration.getClassCode(BitComparator.class).intValue()); + assertEquals(49,HbaseObjectWritableFor96Migration.getClassCode(CompareFilter.class).intValue()); + assertEquals(50,HbaseObjectWritableFor96Migration.getClassCode(RowFilter.class).intValue()); + assertEquals(51,HbaseObjectWritableFor96Migration.getClassCode(ValueFilter.class).intValue()); + assertEquals(52,HbaseObjectWritableFor96Migration.getClassCode(QualifierFilter.class).intValue()); + assertEquals(53,HbaseObjectWritableFor96Migration.getClassCode(SkipFilter.class).intValue()); + // assertEquals(54,HbaseObjectWritableFor96Migration.getClassCode(WritableByteArrayComparable.class).intValue()); + assertEquals(55,HbaseObjectWritableFor96Migration.getClassCode(FirstKeyOnlyFilter.class).intValue()); + assertEquals(56,HbaseObjectWritableFor96Migration.getClassCode(DependentColumnFilter.class).intValue()); + + assertEquals(57,HbaseObjectWritableFor96Migration.getClassCode(Delete [].class).intValue()); + + assertEquals(58,HbaseObjectWritableFor96Migration.getClassCode(HLog.Entry.class).intValue()); + assertEquals(59,HbaseObjectWritableFor96Migration.getClassCode(HLog.Entry[].class).intValue()); + assertEquals(60,HbaseObjectWritableFor96Migration.getClassCode(HLogKey.class).intValue()); + + assertEquals(61,HbaseObjectWritableFor96Migration.getClassCode(List.class).intValue()); + + assertEquals(62,HbaseObjectWritableFor96Migration.getClassCode(NavigableSet.class).intValue()); + assertEquals(63,HbaseObjectWritableFor96Migration.getClassCode(ColumnPrefixFilter.class).intValue()); + + // Multi + assertEquals(64,HbaseObjectWritableFor96Migration.getClassCode(Row.class).intValue()); + assertEquals(65,HbaseObjectWritableFor96Migration.getClassCode(Action.class).intValue()); + assertEquals(66,HbaseObjectWritableFor96Migration.getClassCode(MultiAction.class).intValue()); + assertEquals(67,HbaseObjectWritableFor96Migration.getClassCode(MultiResponse.class).intValue()); + + // coprocessor execution + // assertEquals(68,HbaseObjectWritableFor96Migration.getClassCode(Exec.class).intValue()); + assertEquals(69,HbaseObjectWritableFor96Migration.getClassCode(Increment.class).intValue()); + + assertEquals(70,HbaseObjectWritableFor96Migration.getClassCode(KeyOnlyFilter.class).intValue()); + + // serializable + assertEquals(71,HbaseObjectWritableFor96Migration.getClassCode(Serializable.class).intValue()); + assertEquals(72,HbaseObjectWritableFor96Migration.getClassCode(RandomRowFilter.class).intValue()); + assertEquals(73,HbaseObjectWritableFor96Migration.getClassCode(CompareOp.class).intValue()); + assertEquals(74,HbaseObjectWritableFor96Migration.getClassCode(ColumnRangeFilter.class).intValue()); + // assertEquals(75,HbaseObjectWritableFor96Migration.getClassCode(HServerLoad.class).intValue()); + assertEquals(76,HbaseObjectWritableFor96Migration.getClassCode(RegionOpeningState.class).intValue()); + assertEquals(77,HbaseObjectWritableFor96Migration.getClassCode(HTableDescriptor[].class).intValue()); + assertEquals(78,HbaseObjectWritableFor96Migration.getClassCode(Append.class).intValue()); + assertEquals(79,HbaseObjectWritableFor96Migration.getClassCode(RowMutations.class).intValue()); + assertEquals(80,HbaseObjectWritableFor96Migration.getClassCode(Message.class).intValue()); + + assertEquals(81,HbaseObjectWritableFor96Migration.getClassCode(Array.class).intValue()); + } + + /** + * This test verifies that additional objects have not been added to the end of the list. + * If you are legitimately adding objects, this test will need to be updated, but see the + * note on the test above. + */ + public void testGetNextObjectCode(){ + assertEquals(83,HbaseObjectWritableFor96Migration.getNextClassCode()); + } + +} diff --git a/hbase-server/src/test/java/org/apache/hadoop/hbase/security/access/TestTablePermissions.java b/hbase-server/src/test/java/org/apache/hadoop/hbase/security/access/TestTablePermissions.java index cbb720a..de11fa5 100644 --- a/hbase-server/src/test/java/org/apache/hadoop/hbase/security/access/TestTablePermissions.java +++ b/hbase-server/src/test/java/org/apache/hadoop/hbase/security/access/TestTablePermissions.java @@ -23,6 +23,7 @@ import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; import java.io.ByteArrayOutputStream; import java.io.DataOutput; @@ -38,6 +39,7 @@ import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.apache.hadoop.conf.Configuration; import org.apache.hadoop.hbase.Abortable; +import org.apache.hadoop.hbase.HConstants; import org.apache.hadoop.hbase.TableName; import org.apache.hadoop.hbase.exceptions.DeserializationException; import org.apache.hadoop.hbase.HBaseTestingUtility; @@ -125,9 +127,10 @@ public class TestTablePermissions { */ @Test public void testMigration() throws DeserializationException { - Configuration conf = UTIL.getConfiguration(); + Configuration conf = new Configuration(UTIL.getConfiguration()); + conf.setBoolean(HConstants.ALLOW_LEGACY_OBJECT_SERIALIZATION_KEY, true); ListMultimap permissions = createPermissions(); - byte [] bytes = writePermissionsAsBytes(permissions, conf); + byte [] bytes = writePermissionsAsLegacyBytes(permissions, conf); AccessControlLists.readPermissions(bytes, conf); } @@ -136,11 +139,11 @@ public class TestTablePermissions { * and returns the resulting byte array. Used to verify we can read stuff written * with Writable. */ - public static byte[] writePermissionsAsBytes(ListMultimap perms, + public static byte[] writePermissionsAsLegacyBytes(ListMultimap perms, Configuration conf) { try { ByteArrayOutputStream bos = new ByteArrayOutputStream(); - writePermissions(new DataOutputStream(bos), perms, conf); + writeLegacyPermissions(new DataOutputStream(bos), perms, conf); return bos.toByteArray(); } catch (IOException ioe) { // shouldn't happen here @@ -156,7 +159,7 @@ public class TestTablePermissions { * @param conf * @throws IOException */ - public static void writePermissions(DataOutput out, + public static void writeLegacyPermissions(DataOutput out, ListMultimap perms, Configuration conf) throws IOException { Set keys = perms.keySet(); diff --git a/pom.xml b/pom.xml index 7b3aeae..bafdf18 100644 --- a/pom.xml +++ b/pom.xml @@ -1074,7 +1074,8 @@ 2.6 1.1.1 2.1 - 3.2.1 + + 3.2.2 3.1 2.2.0 12.0.1 -- 2.4.9 (Apple Git-60)