diff --git a/itests/hive-unit/src/test/java/org/apache/hadoop/hive/metastore/TestReplChangeManager.java b/itests/hive-unit/src/test/java/org/apache/hadoop/hive/metastore/TestReplChangeManager.java index 9b728b8693..2f8aec8ac1 100644 --- a/itests/hive-unit/src/test/java/org/apache/hadoop/hive/metastore/TestReplChangeManager.java +++ b/itests/hive-unit/src/test/java/org/apache/hadoop/hive/metastore/TestReplChangeManager.java @@ -19,8 +19,12 @@ package org.apache.hadoop.hive.metastore; import java.io.IOException; +import java.net.InetAddress; +import java.net.NetworkInterface; +import java.security.PrivilegedExceptionAction; import java.util.ArrayList; import java.util.Arrays; +import java.util.Enumeration; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -33,7 +37,9 @@ import org.apache.hadoop.hdfs.MiniDFSCluster; import org.apache.hadoop.hive.conf.HiveConf; import org.apache.hadoop.hive.metastore.ReplChangeManager.RecycleType; + import static org.apache.hadoop.hive.metastore.ReplChangeManager.SOURCE_OF_REPLICATION; + import org.apache.hadoop.hive.metastore.api.Database; import org.apache.hadoop.hive.metastore.api.FieldSchema; import org.apache.hadoop.hive.metastore.api.Partition; @@ -41,6 +47,10 @@ import org.apache.hadoop.hive.metastore.api.StorageDescriptor; import org.apache.hadoop.hive.metastore.api.Table; import org.apache.hadoop.hive.serde2.columnar.LazyBinaryColumnarSerDe; +import org.apache.hadoop.security.AccessControlException; +import org.apache.hadoop.security.UserGroupInformation; +import org.apache.hadoop.security.authorize.DefaultImpersonationProvider; +import org.apache.hadoop.security.authorize.ProxyUsers; import org.apache.hadoop.util.StringUtils; import org.junit.AfterClass; import org.junit.Assert; @@ -297,7 +307,6 @@ public void testClearer() throws Exception { Path part32 = new Path(dirTbl3, "part2"); createFile(part32, "testClearer32"); String fileChksum32 = ReplChangeManager.checksumFor(part32, fs); - ReplChangeManager.getInstance(hiveConf).recycle(dirTbl1, RecycleType.MOVE, false); ReplChangeManager.getInstance(hiveConf).recycle(dirTbl2, RecycleType.MOVE, false); ReplChangeManager.getInstance(hiveConf).recycle(dirTbl3, RecycleType.MOVE, true); @@ -340,6 +349,69 @@ public void testClearer() throws Exception { } while (!cleared); } + @Test + public void testRecycleUsingImpersonation() throws Exception { + FileSystem fs = warehouse.getWhRoot().getFileSystem(hiveConf); + Path dirDb = new Path(warehouse.getWhRoot(), "db3"); + fs.delete(dirDb, true); + fs.mkdirs(dirDb); + Path dirTbl1 = new Path(dirDb, "tbl1"); + fs.mkdirs(dirTbl1); + Path part11 = new Path(dirTbl1, "part1"); + createFile(part11, "testClearer11"); + Path part12 = new Path(dirTbl1, "part2"); + createFile(part12, "testClearer12"); + final UserGroupInformation proxyUserUgi = + UserGroupInformation.createRemoteUser("impala"); + setGroupsInConf(UserGroupInformation.getCurrentUser().getGroupNames(), + "impala", hiveConf); + //set owner of data path to impala + fs.setOwner(dirTbl1, "impala", "default"); + proxyUserUgi.doAs((PrivilegedExceptionAction) () -> { + try { + //impala doesn't have access. Should provide access control exception + ReplChangeManager.getInstance(hiveConf).recycle(dirTbl1, RecycleType.MOVE, false); + Assert.fail(); + } catch (AccessControlException e) { + assertTrue(e.getMessage().contains("Permission denied: user=impala, access=WRITE")); + } + return null; + }); + } + + private void setGroupsInConf(String[] groupNames, String proxyUserName, Configuration conf) + throws IOException { + conf.set( + DefaultImpersonationProvider.getTestProvider().getProxySuperuserGroupConfKey(proxyUserName), + StringUtils.join(",", Arrays.asList(groupNames))); + configureSuperUserIPAddresses(conf, proxyUserName); + ProxyUsers.refreshSuperUserGroupsConfiguration(conf); + } + + private void configureSuperUserIPAddresses(Configuration conf, + String superUserShortName) throws IOException { + List ipList = new ArrayList(); + Enumeration netInterfaceList = NetworkInterface + .getNetworkInterfaces(); + while (netInterfaceList.hasMoreElements()) { + NetworkInterface inf = netInterfaceList.nextElement(); + Enumeration addrList = inf.getInetAddresses(); + while (addrList.hasMoreElements()) { + InetAddress addr = addrList.nextElement(); + ipList.add(addr.getHostAddress()); + } + } + StringBuilder builder = new StringBuilder(); + for (String ip : ipList) { + builder.append(ip); + builder.append(','); + } + builder.append("127.0.1.1,"); + builder.append(InetAddress.getLocalHost().getCanonicalHostName()); + conf.setStrings(DefaultImpersonationProvider.getTestProvider().getProxySuperuserIpConfKey(superUserShortName), + builder.toString()); + } + @Test public void shouldIdentifyCMURIs() { assertTrue(ReplChangeManager diff --git a/standalone-metastore/metastore-common/src/main/java/org/apache/hadoop/hive/metastore/ReplChangeManager.java b/standalone-metastore/metastore-common/src/main/java/org/apache/hadoop/hive/metastore/ReplChangeManager.java index 338e351d0f..5b76acec64 100644 --- a/standalone-metastore/metastore-common/src/main/java/org/apache/hadoop/hive/metastore/ReplChangeManager.java +++ b/standalone-metastore/metastore-common/src/main/java/org/apache/hadoop/hive/metastore/ReplChangeManager.java @@ -287,9 +287,6 @@ public Boolean execute() throws IOException { // Ignore if a file with same content already exist in cmroot // We might want to setXAttr for the new location in the future if (success) { - // set the file owner to hive (or the id metastore run as) - fs.setOwner(cmPath, msUser, msGroup); - // tag the original file name so we know where the file comes from // Note we currently only track the last known trace as // xattr has limited capacity. We shall revisit and store all original