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 <[email protected]>
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,