diff --git a/common/src/java/org/apache/hadoop/hive/conf/HiveConf.java b/common/src/java/org/apache/hadoop/hive/conf/HiveConf.java index d97ac6b..d56ef16 100644 --- a/common/src/java/org/apache/hadoop/hive/conf/HiveConf.java +++ b/common/src/java/org/apache/hadoop/hive/conf/HiveConf.java @@ -770,6 +770,11 @@ private static void populateLlapDaemonVarsSet(Set llapDaemonVarsSetLocal "for operations like drop-partition (disallow the drop-partition if the user in\n" + "question doesn't have permissions to delete the corresponding directory\n" + "on the storage)."), + METASTORE_AUTHORIZATION_EXTERNALTABLE_DROP_CHECK("hive.metastore.authorization.storage.check.externaltable.drop", false, + "Should StorageBasedAuthorization check permission of the storage before dropping external table.\n" + + "StorageBasedAuthorization already does this check for managed table. For external table however,\n" + + "anyone has read permission of the directory could drop external table, which is surprising.\n" + + "The flag set to false by default to maintain backward compatibility."), METASTORE_EVENT_CLEAN_FREQ("hive.metastore.event.clean.freq", "0s", new TimeValidator(TimeUnit.SECONDS), "Frequency at which timer task runs to purge expired events in metastore."), diff --git a/itests/hive-unit/src/test/java/org/apache/hadoop/hive/ql/security/TestMetastoreAuthorizationProvider.java b/itests/hive-unit/src/test/java/org/apache/hadoop/hive/ql/security/TestMetastoreAuthorizationProvider.java index c228720..a536e92 100644 --- a/itests/hive-unit/src/test/java/org/apache/hadoop/hive/ql/security/TestMetastoreAuthorizationProvider.java +++ b/itests/hive-unit/src/test/java/org/apache/hadoop/hive/ql/security/TestMetastoreAuthorizationProvider.java @@ -261,6 +261,7 @@ public void testSimplePrivileges() throws Exception { assertEquals(1,ret.getResponseCode()); ttbl.setTableName(tblName+"mal"); + ttbl.setTableType("EXTERNAL_TABLE"); me = null; try { msc.createTable(ttbl); @@ -299,6 +300,7 @@ public void testSimplePrivileges() throws Exception { assertEquals(0,ret.getResponseCode()); allowDropOnTable(tblName, userName, tbl.getSd().getLocation()); + disallowDropOnTable(dbName,userName,db.getLocationUri()); allowDropOnDb(dbName,userName,db.getLocationUri()); driver.run("drop database if exists "+getTestDbName()+" cascade"); @@ -340,6 +342,11 @@ protected void allowDropOnTable(String tblName, String userName, String location driver.run("grant drop on table "+tblName+" to user "+userName); } + protected void disallowDropOnTable(String tblName, String userName, String location) + throws Exception { + driver.run("remoke drop on table "+tblName+" from user "+userName); + } + protected void allowDropOnDb(String dbName, String userName, String location) throws Exception { driver.run("grant drop on database "+dbName+" to user "+userName); diff --git a/itests/hive-unit/src/test/java/org/apache/hadoop/hive/ql/security/TestStorageBasedMetastoreAuthorizationProvider.java b/itests/hive-unit/src/test/java/org/apache/hadoop/hive/ql/security/TestStorageBasedMetastoreAuthorizationProvider.java index 78ff780..272c924 100644 --- a/itests/hive-unit/src/test/java/org/apache/hadoop/hive/ql/security/TestStorageBasedMetastoreAuthorizationProvider.java +++ b/itests/hive-unit/src/test/java/org/apache/hadoop/hive/ql/security/TestStorageBasedMetastoreAuthorizationProvider.java @@ -77,6 +77,12 @@ protected void allowDropOnTable(String tblName, String userName, String location } @Override + protected void disallowDropOnTable(String tblName, String userName, String location) + throws Exception { + setPermissions(location,"-r--r--r--"); + } + + @Override protected void allowDropOnDb(String dbName, String userName, String location) throws Exception { setPermissions(location,"-rwxr--r-t"); diff --git a/ql/src/java/org/apache/hadoop/hive/ql/security/authorization/StorageBasedAuthorizationProvider.java b/ql/src/java/org/apache/hadoop/hive/ql/security/authorization/StorageBasedAuthorizationProvider.java index 7992a70..e48fdef 100644 --- a/ql/src/java/org/apache/hadoop/hive/ql/security/authorization/StorageBasedAuthorizationProvider.java +++ b/ql/src/java/org/apache/hadoop/hive/ql/security/authorization/StorageBasedAuthorizationProvider.java @@ -35,6 +35,7 @@ import org.apache.hadoop.fs.Path; import org.apache.hadoop.fs.permission.FsAction; import org.apache.hadoop.hive.common.FileUtils; +import org.apache.hadoop.hive.conf.HiveConf; import org.apache.hadoop.hive.metastore.HiveMetaStore.HMSHandler; import org.apache.hadoop.hive.metastore.TableType; import org.apache.hadoop.hive.metastore.Warehouse; @@ -68,6 +69,7 @@ private Warehouse wh; private boolean isRunFromMetaStore = false; + private Configuration conf; private static Logger LOG = LoggerFactory.getLogger(StorageBasedAuthorizationProvider.class); @@ -100,6 +102,7 @@ private void initWh() throws MetaException, HiveException { @Override public void init(Configuration conf) throws HiveException { hive_db = new HiveProxy(); + this.conf = conf; } @Override @@ -177,8 +180,12 @@ public void authorize(Table table, Privilege[] readRequiredPriv, Privilege[] wri Path path = table.getDataLocation(); // authorize drops if there was a drop privilege requirement, and - // table is not external (external table data is not dropped) - if (privExtractor.hasDropPrivilege() && table.getTableType() != TableType.EXTERNAL_TABLE) { + // table is not external (external table data is not dropped) or + // "hive.metastore.authorization.storage.check.externaltable.drop" + // set to true + if (privExtractor.hasDropPrivilege() && (table.getTableType() != TableType.EXTERNAL_TABLE || + conf.getBoolean(HiveConf.ConfVars.METASTORE_AUTHORIZATION_EXTERNALTABLE_DROP_CHECK.varname, + false))) { checkDeletePermission(path, getConf(), authenticator.getUserName()); }