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 371cb0f..2e0fc4c 100644 --- a/common/src/java/org/apache/hadoop/hive/conf/HiveConf.java +++ b/common/src/java/org/apache/hadoop/hive/conf/HiveConf.java @@ -134,7 +134,8 @@ HiveConf.ConfVars.HMSHANDLERINTERVAL, HiveConf.ConfVars.HMSHANDLERFORCERELOADCONF, HiveConf.ConfVars.METASTORE_PARTITION_NAME_WHITELIST_PATTERN, - HiveConf.ConfVars.METASTORE_DISALLOW_INCOMPATIBLE_COL_TYPE_CHANGES + HiveConf.ConfVars.METASTORE_DISALLOW_INCOMPATIBLE_COL_TYPE_CHANGES, + HiveConf.ConfVars.USERS_IN_ROOT_ROLE }; /** @@ -905,7 +906,8 @@ // none is the default(past) behavior. Implies only alphaNumeric and underscore are valid characters in identifiers. // column: implies column names can contain any character. HIVE_QUOTEDID_SUPPORT("hive.support.quoted.identifiers", "column", - new PatternValidator("none", "column")) + new PatternValidator("none", "column")), + USERS_IN_ROOT_ROLE("hive.users.in.root.role","") ; public final String varname; diff --git a/itests/hive-unit/src/test/java/org/apache/hadoop/hive/metastore/TestEmbeddedHiveMetaStore.java b/itests/hive-unit/src/test/java/org/apache/hadoop/hive/metastore/TestEmbeddedHiveMetaStore.java index b6b0e6e..d8396b0 100644 --- a/itests/hive-unit/src/test/java/org/apache/hadoop/hive/metastore/TestEmbeddedHiveMetaStore.java +++ b/itests/hive-unit/src/test/java/org/apache/hadoop/hive/metastore/TestEmbeddedHiveMetaStore.java @@ -18,7 +18,14 @@ package org.apache.hadoop.hive.metastore; +import java.io.IOException; + import org.apache.hadoop.hive.conf.HiveConf; +import org.apache.hadoop.hive.conf.HiveConf.ConfVars; +import org.apache.hadoop.hive.metastore.HiveMetaStore.HMSHandler; +import org.apache.hadoop.hive.metastore.api.PrincipalType; +import org.apache.hadoop.hive.metastore.api.Role; +import org.apache.hadoop.hive.metastore.model.MRole; import org.apache.hadoop.util.StringUtils; public class TestEmbeddedHiveMetaStore extends TestHiveMetaStore { @@ -49,4 +56,15 @@ protected void tearDown() throws Exception { throw new Exception(e); } } + + public void testCreateRootNAddUser() throws IOException, Throwable { + HiveConf conf = new HiveConf(); + conf.setVar(ConfVars.USERS_IN_ROOT_ROLE, "root_user"); + conf.setVar(ConfVars.HIVE_AUTHORIZATION_MANAGER, + "org.apache.hadoop.hive.ql.security.authorization.plugin.HiveAuthorizerFactory"); + RawStore rawStore = new HMSHandler("testcreateroot", conf).getMS(); + Role rootRole = rawStore.getRole(HiveMetaStore.root); + assertTrue(rootRole.getOwnerName().equals(HiveMetaStore.root)); + assertEquals(rawStore.listPrincipalGlobalGrants(HiveMetaStore.root, PrincipalType.ROLE).get(0).getPrivilege(),"All"); + } } diff --git a/metastore/src/java/org/apache/hadoop/hive/metastore/HiveMetaStore.java b/metastore/src/java/org/apache/hadoop/hive/metastore/HiveMetaStore.java index 58f9957..bdea297 100644 --- a/metastore/src/java/org/apache/hadoop/hive/metastore/HiveMetaStore.java +++ b/metastore/src/java/org/apache/hadoop/hive/metastore/HiveMetaStore.java @@ -35,7 +35,6 @@ import java.util.HashSet; import java.util.Iterator; import java.util.LinkedHashMap; -import java.util.LinkedHashSet; import java.util.LinkedList; import java.util.List; import java.util.Map; @@ -43,6 +42,7 @@ import java.util.Properties; import java.util.Set; import java.util.Timer; +import java.util.concurrent.atomic.AtomicBoolean; import java.util.regex.Pattern; import org.apache.commons.cli.OptionBuilder; @@ -164,6 +164,7 @@ * default port on which to start the Hive server */ private static final int DEFAULT_HIVE_METASTORE_PORT = 9083; + public static final String root = "root"; private static HadoopThriftAuthBridge.Server saslServer; private static boolean useSasl; @@ -189,6 +190,7 @@ public TTransport getTransport(TTransport trans) { IHMSHandler { public static final Log LOG = HiveMetaStore.LOG; private static boolean createDefaultDB = false; + private static AtomicBoolean rootCreated = new AtomicBoolean(false); private String rawStoreClassName; private final HiveConf hiveConf; // stores datastore (jpox) properties, // right now they come from jpox.properties @@ -342,6 +344,7 @@ private boolean init() throws MetaException { wh = new Warehouse(hiveConf); createDefaultDB(); + createRootRoleNAddUsers(); if (hiveConf.getBoolean("hive.metastore.metrics.enabled", false)) { try { @@ -466,6 +469,82 @@ private void createDefaultDB() throws MetaException { } } + private void createRootRoleNAddUsers() throws MetaException { + + if(rootCreated.get()) { + return; + } + Class authCls; + Class authIface; + try { + authCls = hiveConf.getClassByName(hiveConf.getVar(ConfVars.HIVE_AUTHORIZATION_MANAGER)); + authIface = Class.forName("org.apache.hadoop.hive.ql.security.authorization.plugin.HiveAuthorizerFactory"); + } catch (ClassNotFoundException e) { + LOG.debug("Not on new auth interface", e); + return; + } + if (authCls.isInstance(authIface)) { + LOG.info("Invalid value for auth manager in config."); + return; + } + RawStore ms = getMS(); + try { + ms.addRole(root, root); + } catch (InvalidObjectException e) { + LOG.debug("root role already exists",e); + } catch (NoSuchObjectException e) { + // This should never be thrown. + LOG.debug(e); + } + + // now grant all privs to root + PrivilegeBag privs = new PrivilegeBag(); + privs.addToPrivileges(new HiveObjectPrivilege( + new HiveObjectRef(HiveObjectType.GLOBAL, null, null, + null, null), root, PrincipalType.ROLE, new PrivilegeGrantInfo( + "All", 0, root, PrincipalType.ROLE, true))); + try { + ms.grantPrivileges(privs); + } catch (InvalidObjectException e) { + // Surprisingly these privs are already granted. + LOG.debug("Failed while granting global privs to root", e); + } catch (NoSuchObjectException e) { + // Unlikely to be thrown. + LOG.debug("Failed while granting global privs to root", e); + } + + // now add pre-configured users to root role + String userStr = hiveConf.getVar(ConfVars.USERS_IN_ROOT_ROLE); + if (userStr == null || userStr.isEmpty()) { + LOG.info("No user is added in root role, since config is empty"); + return; + } + // Since user names need to be valid unix user names, per IEEE Std 1003.1-2001 they cannot + // contain comma, so we can safely split above string on comma. + String users[] = userStr.split(","); + if (null == users || users.length == 0) { + LOG.info("No user is added in root role, since config value is in incorrect format."); + return; + } + Role rootRole; + try { + rootRole = ms.getRole(root); + } catch (NoSuchObjectException e) { + LOG.debug("Failed to retrieve just added root role",e); + return; + } + for (String userName : users) { + try { + ms.grantRole(rootRole, userName, PrincipalType.USER, root, PrincipalType.ROLE, true); + } catch (NoSuchObjectException e) { + LOG.debug("Failed to add "+ rootRole + " in root role",e); + } catch (InvalidObjectException e) { + LOG.debug(userName + " already in root role", e); + } + } + rootCreated.set(true); + } + private void logInfo(String m) { LOG.info(threadLocalId.get().toString() + ": " + m); logAuditEvent(m);