This is an automated email from the ASF dual-hosted git repository.

kgyrtkirk pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/hive.git


The following commit(s) were added to refs/heads/master by this push:
     new 78b20c8  HIVE-25680 : Authorize #get_table_meta HiveMetastore Server 
API to use any of the HiveMetastore Authorization model (#2770) (Syed Shameerur 
Rahman reviewed by Zoltan Haindrich)
78b20c8 is described below

commit 78b20c803ef2e75a7fe830325df2c19c15b203a3
Author: Syed Shameerur Rahman <rhma...@amazon.com>
AuthorDate: Tue Nov 23 13:31:36 2021 +0530

    HIVE-25680 : Authorize #get_table_meta HiveMetastore Server API to use any 
of the HiveMetastore Authorization model (#2770) (Syed Shameerur Rahman 
reviewed by Zoltan Haindrich)
---
 ...stMetastoreClientSideAuthorizationProvider.java | 145 +++++++++++++++++++++
 .../apache/hadoop/hive/metastore/HMSHandler.java   |  52 ++++++++
 2 files changed, 197 insertions(+)

diff --git 
a/itests/hive-unit/src/test/java/org/apache/hadoop/hive/ql/security/TestMetastoreClientSideAuthorizationProvider.java
 
b/itests/hive-unit/src/test/java/org/apache/hadoop/hive/ql/security/TestMetastoreClientSideAuthorizationProvider.java
new file mode 100644
index 0000000..dbd71cb
--- /dev/null
+++ 
b/itests/hive-unit/src/test/java/org/apache/hadoop/hive/ql/security/TestMetastoreClientSideAuthorizationProvider.java
@@ -0,0 +1,145 @@
+/*
+ * 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.hive.ql.security;
+
+import com.google.common.collect.Lists;
+import org.apache.hadoop.hive.cli.CliSessionState;
+import org.apache.hadoop.hive.conf.HiveConf;
+import org.apache.hadoop.hive.metastore.HiveMetaStoreClient;
+import org.apache.hadoop.hive.metastore.MetaStoreTestUtils;
+import org.apache.hadoop.hive.metastore.api.TableMeta;
+import org.apache.hadoop.hive.ql.DriverFactory;
+import org.apache.hadoop.hive.ql.IDriver;
+import 
org.apache.hadoop.hive.ql.security.authorization.DefaultHiveAuthorizationProvider;
+import org.apache.hadoop.hive.ql.session.SessionState;
+import org.apache.hadoop.hive.shims.Utils;
+import org.apache.hadoop.security.UserGroupInformation;
+import static org.junit.Assert.assertEquals;
+
+import org.junit.Before;
+import org.junit.Test;
+
+import java.util.List;
+
+/**
+ * TestMetastoreClientSideAuthorizationProvider : Simple base test for 
Metastore client side
+ * Authorization Providers. By default, tests DefaultHiveAuthorizationProvider
+ */
+public class TestMetastoreClientSideAuthorizationProvider {
+    private HiveConf clientHiveConf;
+    private HiveMetaStoreClient msc;
+    private IDriver driver;
+    private UserGroupInformation ugi;
+
+    @Before
+    public void setUp() throws Exception {
+        
System.setProperty(HiveConf.ConfVars.METASTORE_PRE_EVENT_LISTENERS.varname,
+                
"org.apache.hadoop.hive.ql.security.authorization.AuthorizationPreEventListener");
+
+        int port = MetaStoreTestUtils.startMetaStoreWithRetry();
+
+        clientHiveConf = new HiveConf(this.getClass());
+
+        // Turn on client-side authorization
+        
clientHiveConf.setBoolVar(HiveConf.ConfVars.HIVE_AUTHORIZATION_ENABLED,true);
+        
clientHiveConf.set(HiveConf.ConfVars.HIVE_AUTHORIZATION_MANAGER.varname,
+                getAuthorizationProvider());
+        
clientHiveConf.set(HiveConf.ConfVars.HIVE_AUTHENTICATOR_MANAGER.varname,
+                InjectableDummyAuthenticator.class.getName());
+        
clientHiveConf.set(HiveConf.ConfVars.HIVE_AUTHORIZATION_TABLE_OWNER_GRANTS.varname,
 "");
+        clientHiveConf.setVar(HiveConf.ConfVars.HIVEMAPREDMODE, "nonstrict");
+        clientHiveConf.setVar(HiveConf.ConfVars.METASTOREURIS, 
"thrift://localhost:" + port);
+        
clientHiveConf.setIntVar(HiveConf.ConfVars.METASTORETHRIFTCONNECTIONRETRIES, 3);
+        clientHiveConf.set(HiveConf.ConfVars.HIVE_SUPPORT_CONCURRENCY.varname, 
"false");
+
+        clientHiveConf.set(HiveConf.ConfVars.PREEXECHOOKS.varname, "");
+        clientHiveConf.set(HiveConf.ConfVars.POSTEXECHOOKS.varname, "");
+
+        ugi = Utils.getUGI();
+
+        SessionState.start(new CliSessionState(clientHiveConf));
+        msc = new HiveMetaStoreClient(clientHiveConf);
+        driver = DriverFactory.newDriver(clientHiveConf);
+    }
+
+    private String getAuthorizationProvider(){
+        return DefaultHiveAuthorizationProvider.class.getName();
+    }
+
+    private void allowCreateDatabase(String userName) throws Exception {
+        driver.run("grant create to user " + userName);
+    }
+
+    private void allowSelect(String userName) throws Exception {
+        driver.run("grant select to user " + userName);
+    }
+
+    private void revokeSelect(String userName) throws Exception {
+        driver.run("revoke select from user " + userName);
+    }
+
+    protected void allowCreateInDb(String dbName, String userName) throws 
Exception {
+        driver.run("grant create on database "+ dbName +" to user " + 
userName);
+    }
+
+    private void allowSelectInDb(String dbName, String userName) throws 
Exception {
+        driver.run("grant select on database " + dbName + " to user " + 
userName);
+    }
+
+
+    private void disallowSelectDatabase(String dbName, String userName) throws 
Exception {
+        driver.run("revoke select on database " + dbName + " from user " + 
userName);
+    }
+
+    @Test
+    public void testGetTableMeta() throws Exception {
+        String dbName1 = "database1";
+        String tblName1 = "table1";
+
+        String userName = ugi.getUserName();
+        allowCreateDatabase(userName);
+        allowSelect(userName);
+        driver.run("create database " + dbName1);
+        allowCreateInDb(dbName1, userName);
+        driver.run("use " + dbName1);
+        driver.run(String.format("create table %s (a string) partitioned by (b 
string)", tblName1));
+        allowSelectInDb(dbName1, userName);
+
+        String dbName2 = "database2";
+        String tblName2 = "table2";
+        driver.run("create database " + dbName2);
+        allowSelectInDb(dbName2, userName);
+        driver.run("use " + dbName2);
+        driver.run(String.format("create table %s (a string) partitioned by (b 
string)", tblName2));
+
+        List<TableMeta> tableMetas = msc.getTableMeta("*", "*", 
Lists.newArrayList());
+        assertEquals(2, tableMetas.size());
+
+        revokeSelect(userName);
+        disallowSelectDatabase(dbName1, userName);
+        tableMetas = msc.getTableMeta("*", "*", Lists.newArrayList());
+        assertEquals(1, tableMetas.size());
+        assertEquals(dbName2, tableMetas.get(0).getDbName());
+        assertEquals(tblName2, tableMetas.get(0).getTableName());
+
+        disallowSelectDatabase(dbName2, userName);
+        tableMetas = msc.getTableMeta("*", "*", Lists.newArrayList());
+        assertEquals(0, tableMetas.size());
+    }
+}
diff --git 
a/standalone-metastore/metastore-server/src/main/java/org/apache/hadoop/hive/metastore/HMSHandler.java
 
b/standalone-metastore/metastore-server/src/main/java/org/apache/hadoop/hive/metastore/HMSHandler.java
index a2211a4..f849745 100644
--- 
a/standalone-metastore/metastore-server/src/main/java/org/apache/hadoop/hive/metastore/HMSHandler.java
+++ 
b/standalone-metastore/metastore-server/src/main/java/org/apache/hadoop/hive/metastore/HMSHandler.java
@@ -3641,6 +3641,7 @@ public class HMSHandler extends FacebookBase implements 
IHMSHandler {
       t = getMS().getTableMeta(parsedDbName[CAT_NAME], parsedDbName[DB_NAME], 
tblNames, tblTypes);
       t = FilterUtils.filterTableMetasIfEnabled(isServerFilterEnabled, 
filterHook,
           parsedDbName[CAT_NAME], parsedDbName[DB_NAME], t);
+      t = filterReadableTables(parsedDbName[CAT_NAME], t);
     } catch (Exception e) {
       ex = e;
       throw newMetaException(e);
@@ -5488,6 +5489,57 @@ public class HMSHandler extends FacebookBase implements 
IHMSHandler {
     }
   }
 
+  /**
+   * filters out the table meta for which read database access is not granted
+   * @param catName catalog name
+   * @param tableMetas list of table metas
+   * @return filtered list of table metas
+   * @throws RuntimeException
+   * @throws NoSuchObjectException
+   */
+  private List<TableMeta> filterReadableTables(String catName, List<TableMeta> 
tableMetas)
+          throws RuntimeException, NoSuchObjectException {
+    List<TableMeta> finalT = new ArrayList<>();
+    Map<String, Boolean> databaseNames = new HashMap();
+    for (TableMeta tableMeta : tableMetas) {
+      String fullDbName = prependCatalogToDbName(catName, 
tableMeta.getDbName(), conf);
+      if (databaseNames.get(fullDbName) == null) {
+        boolean isExecptionThrown = false;
+        try {
+          fireReadDatabasePreEvent(fullDbName);
+        } catch (MetaException e) {
+          isExecptionThrown = true;
+        }
+        databaseNames.put(fullDbName, isExecptionThrown);
+      }
+      if (!databaseNames.get(fullDbName)) {
+        finalT.add(tableMeta);
+      }
+    }
+    return finalT;
+  }
+
+  /**
+   * Fire a pre-event for read database operation, if there are any
+   * pre-event listeners registered
+   */
+  private void fireReadDatabasePreEvent(final String name)
+          throws MetaException, RuntimeException, NoSuchObjectException {
+    if(preListeners.size() > 0) {
+      String[] parsedDbName = parseDbName(name, conf);
+      Database db = null;
+      try {
+        db = get_database_core(parsedDbName[CAT_NAME], parsedDbName[DB_NAME]);
+        if (db == null) {
+          throw new NoSuchObjectException("Database: " + name + " not found");
+        }
+      } catch(MetaException | NoSuchObjectException e) {
+        throw new RuntimeException(e);
+      }
+      firePreEvent(new PreReadDatabaseEvent(db, this));
+    }
+  }
+
   @Override
   @Deprecated
   public Partition get_partition_with_auth(final String db_name,

Reply via email to