1. 背景
hive metastore 在使用 remote 模式时,需要在 hive-site.xml 中配置远程数据库的连接信息
<property>
<name>javax.jdo.option.ConnectionUserName</name>
<value>test</value>
</property>
<property>
<name>javax.jdo.option.ConnectionPassword</name>
<value>test</value>
</property>
在生产环境中肯定不能随意暴露明文密码,经过查找,还没发现可以支持配置加密密码,在使用时解密的处理方案。但是可以通过 Hadoop Credential Providers 功能把密码保存到密钥库中,然后移除配置文件中的密码项
2. 实现原理
从 0.14 版本开始[HIVE-7634],在 hive 实现中对 javax.jdo.option.ConnectionPassword 默认使用了 hadoop credential provider 功能
在org.apache.hadoop.hive.metastore.ObjectStore#getDataSourceProps
中看一下是如何获取到数据库密码的
try {
String passwd =ShimLoader.getHadoopShims().getPassword(conf, HiveConf.ConfVars.METASTOREPWD.varname);
if (passwd != null && !passwd.isEmpty()) {
prop.setProperty(HiveConf.ConfVars.METASTOREPWD.varname, passwd);
}
HadoopShims#getPassword
其实是代理了org.apache.hadoop.conf.Configuration#getPassword
方法,先从 credential 密钥文件中读取密码,如果不存在再从配置文件中获取
public char[] getPassword(String name) throws IOException {
char[] pass = null;
pass = getPasswordFromCredentialProviders(name);
if (pass == null) {
pass = getPasswordFromConfig(name);
}
return pass;
}
3. 实现步骤
3.1 生成密钥文件
[root ~] hadoop credential create javax.jdo.option.ConnectionPassword -provider jceks://file/hive/conf/hive.jceks
Enter password:
Enter password again:
javax.jdo.option.ConnectionPassword has been successfully created.
org.apache.hadoop.security.alias.JavaKeyStoreProvider has been updated.
这里输入的密码是 metastore 数据库的密码,即 javax.jdo.option.ConnectionPassword 值。文件在生成后可以使用以下命令查看 jceks 文件中包含的配置项
hadoop credential list -provider jceks\://file/hive/conf/hive.jceks
3.2 修改 hive-site.xml 文件
把 javax.jdo.option.ConnectionPassword 从配置文件中删除,并添加以下配置
<property>
<name>hadoop.security.credential.provider.path</name>
<value>jceks://file/hive/conf/hive.jceks</value>
</property>
3.3 重启 hiveserver2 和 metastore 服务