在使用hive的过程中,难免会遇到多用户使用的问题。在配置上主要分两个大的步骤来完成。
我配置的版本是cdh5.0,对应的hive版本是0.12
假设现在用户tom想通过hive对数据库order的order_item表进行查询操作
首先要在hive中配置用户tom对数据库和表的相关权限,在hive中提供了对数据库,表的授权管理,类似于操作系统权限可以授予给不同的主题,如用户(USER),组(GROUP),角色(ROLES)。那么要先使用grant语句针对用户tom可以访问的数据库和表进行授权
GRANT SELECT on TABLE(DATABASE) order_item to USER tom;
授权完成后,用户tom就可以查询order_item表了
这里有一个问题要说明下,默认情况下,任何用户都可以使用grant语句进行授权操作,所以必须要有一个超级管理员的角色来管理授权的操作,否则授权就没有任何意义了。建立超级管理员,需要添加hive.semantic.analyzer.hook配置,并实现自己的权限控制类
import org.apache.hadoop.hive.ql.parse.ASTNode; import org.apache.hadoop.hive.ql.parse.AbstractSemanticAnalyzerHook; import org.apache.hadoop.hive.ql.parse.HiveParser; import org.apache.hadoop.hive.ql.parse.HiveSemanticAnalyzerHookContext; import org.apache.hadoop.hive.ql.parse.SemanticException; import org.apache.hadoop.hive.ql.session.SessionState; /** * 设置Hive超级管理员 * */ public class AuthHook extends AbstractSemanticAnalyzerHook { private static String admin = "admin"; @Override public ASTNode preAnalyze(HiveSemanticAnalyzerHookContext context, ASTNode ast) throws SemanticException { switch (ast.getToken().getType()) { case HiveParser.TOK_CREATEDATABASE: case HiveParser.TOK_DROPDATABASE: case HiveParser.TOK_CREATEROLE: case HiveParser.TOK_DROPROLE: case HiveParser.TOK_GRANT: case HiveParser.TOK_REVOKE: case HiveParser.TOK_GRANT_ROLE: case HiveParser.TOK_REVOKE_ROLE: String userName = null; if (SessionState.get() != null && SessionState.get().getAuthenticator() != null) { userName = SessionState.get().getAuthenticator().getUserName(); } if (!admin.equalsIgnoreCase(userName)) { throw new SemanticException(userName + " can't use ADMIN options, except " + admin + "."); } break; default: break; } return ast; } }
添加了控制类之后还必须添加下面的配置:
<property>
<name>hive.semantic.analyzer.hook</name>
<value>com.xxx.AuthHook</value>
</property>
(若有使用hiveserver,hiveserver必须重启)
至此,只有admin用户可以进行Grant/Revoke操作。
hive授权管理完成之后,下一步就需要在hdfs的/user目录下建立用户的home目录,可以使用hadoop账户来建立。具体操作如下
hadoop fs -mkdir /user/tom hadoop fs -chown tom:tom /user/tom
建立此目录的目的是,当用户tom使用hive查询时,产生的mr job会在/user/tom/.staging目录下存储作业相关的临时文件。具体源码如下
首先调用JobSubmitter的submitJobInternal
JobStatus submitJobInternal(Job job, Cluster cluster) throws ClassNotFoundException, InterruptedException, IOException { //validate the jobs output specs checkSpecs(job); Configuration conf = job.getConfiguration(); addMRFrameworkToDistributedCache(conf); //获取临时存储目录 Path jobStagingArea = JobSubmissionFiles.getStagingDir(cluster, conf); .... } JobSubmissionFiles.getStagingDir(){ Path stagingArea = cluster.getStagingAreaDir(); } Cluster.getStagingAreaDir(){ if (stagingAreaDir == null) { stagingAreaDir = new Path(client.getStagingAreaDir()); } return stagingAreaDir; } YarnRunner.getStagingAreaDir(){ return resMgrDelegate.getStagingAreaDir(); } ResourceMgrDelegate.getStagingAreaDir(){ String user = UserGroupInformation.getCurrentUser().getShortUserName(); Path path = MRApps.getStagingAreaDir(conf, user); LOG.debug("getStagingAreaDir: dir=" + path); return path.toString(); } MRApps.getStagingAreaDir(){ //获取yarn.app.mapreduce.am.staging-dir的值,为/user return new Path(conf.get(MRJobConfig.MR_AM_STAGING_DIR, MRJobConfig.DEFAULT_MR_AM_STAGING_DIR) + Path.SEPARATOR + user + Path.SEPARATOR + STAGING_CONSTANT); }
经过层层调用,MRApps.getStagingAreaDir()组装最终的提交目录,为/user/$user/.staging,由此可见为什么需要配置/user目录下的tom目录
上述步骤完成后,就可以使用tom用户对order_item表进行查询相关的操作了
参考资料: