这是本节的多页打印视图。
点击此处打印.
返回本页常规视图.
代理用户和委托令牌
向单个 Vertica 用户授予 HDFS 访问权限的另一种方法是直接或通过代理用户使用委托令牌。在此配置中,Vertica 代表其他一些 (Hadoop) 用户访问 HDFS。Hadoop 用户根本不需要是 Vertica 用户。
在 Vertica 中,您可以指定 Hadoop 用户的名称以代表 (doAs) 执行操作,也可以直接使用从 HDFS 获得的 Kerberos 委托令牌(自带您的委托令牌)。在 doAs 案例中,Vertica 为该用户获取委托令牌,因此这两种方法最终都使用委托令牌来访问 HDFS 中的文件。
使用 HadoopImpersonationConfig 会话参数以指定用于 HDFS 访问的用户或委托令牌。每个会话可以使用不同的用户,并且可以使用 doAs 或委托令牌。HadoopImpersonationConfig 的值是一组 JSON 对象。
要使用任一类型的委托令牌(更具体地说,当设置 HadoopImpersonationConfig 时),您必须通过 WebHDFS 访问 HDFS。
1 - 用户模拟 (doAs)
您可以使用用户模拟从 Vertica 访问 HDFS 群集中的数据。这种方法称为 "doAs"(表示 "do As"),因为 Vertica 使用单个代理用户代表另一个 (Hadoop) 用户。模拟的 Hadoop 用户不需要是 Vertica 用户。
在下图中,Alice 是 Hadoop 用户,但不是 Vertica 用户。她以代理用户 vertica-etl 的身份连接到 Vertica。在她的会话中,Vertica 代表 doAs 用户 (Alice) 获得一个委托令牌 (DT),并使用该委托令牌访问 HDFS。
您可以使用带有或不带 Kerberos 的 doAs,只要 HDFS 和 Vertica 匹配即可。如果 HDFS 使用 Kerberos,那么 Vertica 也必须使用 Kerberos。
用户配置
Hadoop 管理员必须创建一个代理用户并允许其代表其他用户访问 HDFS。在 core-site.xml 中设置值,如下例所示:
<name>hadoop.proxyuser.vertica-etl.users</name>
<value>*</value>
<name>hadoop.proxyuser.vertica-etl.hosts</name>
<value>*</value>
在 Vertica 中,创建相应的用户。
会话配置
要代表 Hadoop 用户发出请求,首先设置 HadoopImpersonationConfig 会话参数以指定用户和 HDFS 群集。Vertica 将以该用户身份访问 HDFS,直到会话结束或您更改参数为止。
此会话参数的值是 JSON 对象的集合。每个对象指定一个 HDFS 群集和一个 Hadoop 用户。对于群集,您可以指定名称服务或单个名称节点。如果您使用的是 HA 名称节点,则必须使用名称服务或指定所有名称节点。 HadoopImpersonationConfig 格式 描述了完整的 JSON 语法。
以下示例显示了代表两个不同用户的访问权限。用户 "stephanie" 和 "bob" 是 Hadoop 用户,而不是 Vertica 用户。"vertica-etl" 是 Vertica 用户。
$ vsql -U vertica-etl
=> ALTER SESSION SET
HadoopImpersonationConfig = '[{"nameservice":"hadoopNS", "doAs":"stephanie"}]';
=> COPY nation FROM 'webhdfs:///user/stephanie/nation.dat';
=> ALTER SESSION SET
HadoopImpersonationConfig = '[{"nameservice":"hadoopNS", "doAs":"bob"}, {"authority":"hadoop2:50070", "doAs":"rob"}]';
=> COPY nation FROM 'webhdfs:///user/bob/nation.dat';
Vertica 使用从名称节点获取的 Hadoop 委托令牌来模拟 Hadoop 用户。在长时间运行的会话中,令牌可能会过期。Vertica 会尝试自动更新令牌;请参阅令牌过期。
测试配置
您可以使用 HADOOP_IMPERSONATION_CONFIG_CHECK 函数测试 HDFS 委托令牌,使用 HCATALOGCONNECTOR_CONFIG_CHECK 测试 HCatalog 连接器委托令牌。
2 - 自带您的委托令牌
您可以为 Vertica 提供一个 Hadoop 委托令牌以供使用,而不是创建代理用户并授予其访问 HDFS 以与 doAs 一起使用的权限。您必须从 Hadoop 名称节点获取此委托令牌。在此模型中,安全性完全在 Hadoop 端处理,Vertica 只传递一个令牌。Vertica 可能会或可能不会进行 Kerberize。
典型的工作流是:
使用委托令牌时,客户端可以作为任何 Vertica 用户进行连接。不需要代理用户。
在下图中,Bob 有一个 Hadoop 颁发的委托令牌。他连接到 Vertica,Vertica 使用该委托令牌访问 HDFS 中的文件。
会话配置
设置 HadoopImpersonationConfig 会话参数以指定委托令牌和 HDFS 群集。Vertica 将使用该委托令牌访问 HDFS,直到会话结束、令牌过期或您更改参数为止。
此会话参数的值是 JSON 对象的集合。每个对象指定一个 WebHDFS 格式的委托令牌(“令牌”)和一个 HDFS 名称服务或名称节点。 HadoopImpersonationConfig 格式 描述了完整的 JSON 语法。
以下示例显示了代表两个不同用户的访问权限。用户 "stephanie" 和 "bob" 是 Hadoop 用户,而不是 Vertica 用户。"dbuser1" 是没有特殊权限的 Vertica 用户。
$ vsql -U dbuser1
=> ALTER SESSION SET
HadoopImpersonationConfig ='[{"authority":"hadoop1:50070","token":"JAAGZGJldGwxBmRiZXRsMQCKAWDXJgB9igFg-zKEfY4gao4BmhSJYtXiWqrhBHbbUn4VScNg58HWQxJXRUJIREZTIGRlbGVnYXRpb24RMTAuMjAuMTAwLjU0OjgwMjA"}]';
=> COPY nation FROM 'webhdfs:///user/stephanie/nation.dat';
=> ALTER SESSION SET
HadoopImpersonationConfig ='[{"authority":"hadoop1:50070","token":"HgADdG9tA3RvbQCKAWDXJgAoigFg-zKEKI4gaI4BmhRoOUpq_jPxrVhZ1NSMnodAQnhUthJXRUJIREZTIGRlbGVnYXRpb24RMTAuMjAuMTAwLjU0OjgwMjA"}]';
=> COPY nation FROM 'webhdfs:///user/bob/nation.dat';
您可以使用 WebHDFS REST API 获取委托令牌:
$ curl -s --noproxy "*" --negotiate -u: -X GET "http://hadoop1:50070/webhdfs/v1/?op=GETDELEGATIONTOKEN"
Vertica 不会也不能在授权令牌到期时更新它们。您必须保持会话短于令牌生命周期,或实施更新方案。
委托令牌和 HCatalog 连接器
HiveServer2 对委派令牌使用不同的格式。因此,要使用 HCatalog 连接器,您必须设置两个委托令牌,一个用于往常用途(授权),一个用于 HiveServer2(架构)。HCatalog 连接器使用架构令牌访问元数据,使用授权令牌访问数据。架构名称与您在 CREATE HCATALOG SCHEMA 中指定的 Hive 架构相同。以下示例显示了如何使用这两个委托令牌。
$ vsql -U dbuser1
-- set delegation token for user and HiveServer2
=> ALTER SESSION SET
HadoopImpersonationConfig='[
{"nameservice":"hadoopNS","token":"JQAHcmVsZWFzZQdyZWxlYXNlAIoBYVJKrYSKAWF2VzGEjgmzj_IUCIrI9b8Dqu6awFTHk5nC-fHB8xsSV0VCSERGUyBkZWxlZ2F0aW9uETEwLjIwLjQyLjEwOTo4MDIw"},
{"schema":"access","token":"UwAHcmVsZWFzZQdyZWxlYXNlL2hpdmUvZW5nLWc5LTEwMC52ZXJ0aWNhY29ycC5jb21AVkVSVElDQUNPUlAuQ09NigFhUkmyTooBYXZWNk4BjgETFKN2xPURn19Yq9tf-0nekoD51TZvFUhJVkVfREVMRUdBVElPTl9UT0tFThZoaXZlc2VydmVyMkNsaWVudFRva2Vu"}]';
-- uses HiveServer2 token to get metadata
=> CREATE HCATALOG SCHEMA access WITH hcatalog_schema 'access';
-- uses both tokens
=> SELECT * FROM access.t1;
--uses only HiveServer2 token
=> SELECT * FROM hcatalog_tables;
HiveServer2 不像 WebHDFS 那样为委派令牌提供 REST API。请参阅获取 HiveServer2 委托令牌了解一些提示。
测试配置
您可以使用 HADOOP_IMPERSONATION_CONFIG_CHECK 函数测试 HDFS 委托令牌,使用 HCATALOGCONNECTOR_CONFIG_CHECK 测试 HCatalog 连接器委托令牌。
3 - 获取 HiveServer2 委托令牌
要使用 HiveServer2 访问 Hive 元数据,您需要一个特殊的委托令牌。(请参阅自带您的委托令牌。)与授予 HDFS(数据)委托令牌的 REST API 不同,HiveServer2 不提供获取此令牌的简单方法。
以下实用程序代码显示了获取此令牌的方法。您需要为自己的群集修改此代码;特别是,更改 connectURL
静态的值。
import java.io.FileWriter;
import java.io.PrintStream;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.io.Writer;
import java.security.PrivilegedExceptionAction;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.hive.shims.Utils;
import org.apache.hadoop.security.UserGroupInformation;
import org.apache.hive.jdbc.HiveConnection;
import org.json.simple.JSONArray;
import org.json.simple.JSONObject;
public class JDBCTest {
public static final String driverName = "org.apache.hive.jdbc.HiveDriver";
public static String connectURL = "jdbc:hive2://node2.cluster0.example.com:2181,node1.cluster0.example.com:2181,node3.cluster0.example.com:2181/;serviceDiscoveryMode=zooKeeper;zooKeeperNamespace=hiveserver2";
public static String schemaName = "hcat";
public static String verticaUser = "condor";
public static String proxyUser = "condor-2";
public static String krb5conf = "/home/server/kerberos/krb5.conf";
public static String realm = "EXAMPLE.COM";
public static String keytab = "/home/server/kerberos/kt.keytab";
public static void main(String[] args) {
if (args.length < 7) {
System.out.println(
"Usage: JDBCTest <jdbc_url> <hive_schema> <kerberized_user> <proxy_user> <krb5_conf> <krb_realm> <krb_keytab>");
System.exit(1);
}
connectURL = args[0];
schemaName = args[1];
verticaUser = args[2];
proxyUser = args[3];
krb5conf = args[4];
realm = args[5];
keytab = args[6];
System.out.println("connectURL: " + connectURL);
System.out.println("schemaName: " + schemaName);
System.out.println("verticaUser: " + verticaUser);
System.out.println("proxyUser: " + proxyUser);
System.out.println("krb5conf: " + krb5conf);
System.out.println("realm: " + realm);
System.out.println("keytab: " + keytab);
try {
Class.forName("org.apache.hive.jdbc.HiveDriver");
System.out.println("Found HiveServer2 JDBC driver");
} catch (ClassNotFoundException e) {
System.out.println("Couldn't find HiveServer2 JDBC driver");
}
try {
Configuration conf = new Configuration();
System.setProperty("java.security.krb5.conf", krb5conf);
conf.set("hadoop.security.authentication", "kerberos");
UserGroupInformation.setConfiguration(conf);
dtTest();
} catch (Throwable e) {
Writer stackString = new StringWriter();
e.printStackTrace(new PrintWriter(stackString));
System.out.println(e);
System.out.printf("Error occurred when connecting to HiveServer2 with [%s]: %s\n%s\n",
new Object[] { connectURL, e.getMessage(), stackString.toString() });
}
}
private static void dtTest() throws Exception {
UserGroupInformation user = UserGroupInformation.loginUserFromKeytabAndReturnUGI(verticaUser + "@" + realm, keytab);
user.doAs(new PrivilegedExceptionAction() {
public Void run() throws Exception {
System.out.println("In doas: " + UserGroupInformation.getLoginUser());
Connection con = DriverManager.getConnection(JDBCTest.connectURL);
System.out.println("Connected to HiveServer2");
JDBCTest.showUser(con);
System.out.println("Getting delegation token for user");
String token = ((HiveConnection) con).getDelegationToken(JDBCTest.proxyUser, "hive/_HOST@" + JDBCTest.realm);
System.out.println("Got token: " + token);
System.out.println("Closing original connection");
con.close();
System.out.println("Setting delegation token in UGI");
Utils.setTokenStr(Utils.getUGI(), token, "hiveserver2ClientToken");
con = DriverManager.getConnection(JDBCTest.connectURL + ";auth=delegationToken");
System.out.println("Connected to HiveServer2 with delegation token");
JDBCTest.showUser(con);
con.close();
JDBCTest.writeDTJSON(token);
return null;
}
});
}
private static void showUser(Connection con) throws Exception {
String sql = "select current_user()";
Statement stmt = con.createStatement();
ResultSet res = stmt.executeQuery(sql);
StringBuilder result = new StringBuilder();
while (res.next()) {
result.append(res.getString(1));
}
System.out.println("\tcurrent_user: " + result.toString());
}
private static void writeDTJSON(String token) {
JSONArray arr = new JSONArray();
JSONObject obj = new JSONObject();
obj.put("schema", schemaName);
obj.put("token", token);
arr.add(obj);
try {
FileWriter fileWriter = new FileWriter("hcat_delegation.json");
fileWriter.write(arr.toJSONString());
fileWriter.flush();
} catch (Exception e) {
e.printStackTrace();
}
}
}
以下是一个调用及其输出的示例:
$ java -cp hs2token.jar JDBCTest 'jdbc:hive2://test.example.com:10000/default;principal=hive/_HOST@EXAMPLE.COM' "default" "testuser" "test" "/etc/krb5.conf" "EXAMPLE.COM" "/test/testuser.keytab"
connectURL: jdbc:hive2://test.example.com:10000/default;principal=hive/_HOST@EXAMPLE.COM
schemaName: default
verticaUser: testuser
proxyUser: test
krb5conf: /etc/krb5.conf
realm: EXAMPLE.COM
keytab: /test/testuser.keytab
Found HiveServer2 JDBC driver
log4j:WARN No appenders could be found for logger (org.apache.hadoop.metrics2.lib.MutableMetricsFactory).
log4j:WARN Please initialize the log4j system properly.
log4j:WARN See http://logging.apache.org/log4j/1.2/faq.html#noconfig for more info.
In doas: testuser@EXAMPLE.COM (auth:KERBEROS)
Connected to HiveServer2
current_user: testuser
Getting delegation token for user
Got token: JQAEdGVzdARoaXZlB3JlbGVhc2WKAWgvBOwzigFoUxFwMwKOAgMUHfqJ5ma7_27LiePN8C7MxJ682bsVSElWRV9ERUxFR0FUSU9OX1RPS0VOFmhpdmVzZXJ2ZXIyQ2xpZW50VG9rZW4
Closing original connection
Setting delegation token in UGI
Connected to HiveServer2 with delegation token
current_user: testuser
4 - HadoopImpersonationConfig 格式
HadoopImpersonationConfig 会话参数的值是由一个或多个 JSON 对象组成的集合。每个对象为一个 Hadoop 目标描述一个 doAs 用户或委托令牌。您必须使用 WebHDFS 而不是 LibHDFS++,才能使用模拟。
语法
[ { ("doAs" | "token"): value,
("nameservice" | "authority" | "schema"): value} [,...]
]
属性
示例
在以下 doAs 示例中,Bob 是 Hadoop 用户,vertica-etl 是已进行 Kerberize 的代理用户。
$ kinit vertica-etl -kt /home/dbadmin/vertica-etl.keytab
$ vsql -U vertica-etl
=> ALTER SESSION SET
HadoopImpersonationConfig = '[{"nameservice":"hadoopNS", "doAs":"Bob"}]';
=> COPY nation FROM 'webhdfs:///user/bob/nation.dat';
在以下示例中,当前 Vertica 用户(无论是谁)使用 Hadoop 委托令牌。此令牌属于 Alice,但您从未在此处指定用户名。相反,您使用它从 Hadoop 获取委托令牌。
$ vsql -U dbuser1
=> ALTER SESSION SET
HadoopImpersonationConfig ='[{"nameservice":"hadoopNS","token":"JAAGZGJldGwxBmRiZXRsMQCKAWDXJgB9igFg-zKEfY4gao4BmhSJYtXiWqrhBHbbUn4VScNg58HWQxJXRUJIREZTIGRlbGVnYXRpb24RMTAuMjAuMTAwLjU0OjgwMjA"}]';
=> COPY nation FROM 'webhdfs:///user/alice/nation.dat';
在以下示例中,"authority" 指定不使用高可用性的 Hadoop 群集上的(单个)名称节点。
$ vsql -U dbuser1
=> ALTER SESSION SET
HadoopImpersonationConfig ='[{"authority":"hadoop1:50070", "doAs":"Stephanie"}]';
=> COPY nation FROM 'webhdfs://hadoop1:50070/user/stephanie/nation.dat';
要访问 Hive 中的数据,您需要指定两个委托令牌。第一个用于名称服务或授权,像往常一样进行数据访问。第二个用于架构的 HiveServer2 元数据。HiveServer2 需要 WebHDFS 格式的委托令牌。架构名称是您使用 CREATE HCATALOG SCHEMA 指定的 Hive 架构。
$ vsql -U dbuser1
-- set delegation token for user and HiveServer2
=> ALTER SESSION SET
HadoopImpersonationConfig='[
{"nameservice":"hadoopNS","token":"JQAHcmVsZWFzZQdyZWxlYXNlAIoBYVJKrYSKAWF2VzGEjgmzj_IUCIrI9b8Dqu6awFTHk5nC-fHB8xsSV0VCSERGUyBkZWxlZ2F0aW9uETEwLjIwLjQyLjEwOTo4MDIw"},
{"schema":"access","token":"UwAHcmVsZWFzZQdyZWxlYXNlL2hpdmUvZW5nLWc5LTEwMC52ZXJ0aWNhY29ycC5jb21AVkVSVElDQUNPUlAuQ09NigFhUkmyTooBYXZWNk4BjgETFKN2xPURn19Yq9tf-0nekoD51TZvFUhJVkVfREVMRUdBVElPTl9UT0tFThZoaXZlc2VydmVyMkNsaWVudFRva2Vu"}]';
-- uses HiveServer2 token to get metadata
=> CREATE HCATALOG SCHEMA access WITH hcatalog_schema 'access';
-- uses both tokens
=> SELECT * FROM access.t1;
--uses only HiveServer2 token
=> SELECT * FROM hcatalog_tables;
HadoopImpersonationConfig 集合中的每个对象都指定与一个 Hadoop 群集的连接。您可以添加任意数量的连接,包括添加与多个 Hadoop 群集的连接。以下示例显示了两个不同 Hadoop 群集的委托令牌。Vertica 在连接时为每个群集使用正确的令牌。
$ vsql -U dbuser1
=> ALTER SESSION SET
HadoopImpersonationConfig ='[
{"nameservice":"productionNS","token":"JAAGZGJldGwxBmRiZXRsMQCKAWDXJgB9igFg-zKEfY4gao4BmhSJYtXiWqrhBHbbUn4VScNg58HWQxJXRUJIREZTIGRlbGVnYXRpb24RMTAuMjAuMTAwLjU0OjgwMjA"},
{"nameservice":"testNS", "token":"HQAHcmVsZWFzZQdyZWxlYXNlAIoBYVJKrYSKAWF2VzGEjgmzj_IUCIrI9b8Dqu6awFTHk5nC-fHB8xsSV0VCSERGUyBkZWxlZ2F0aW9uETEwLjIwLjQyLjEwOTo4MDIw"}]';
=> COPY clicks FROM 'webhdfs://productionNS/data/clickstream.dat';
=> COPY testclicks FROM 'webhdfs://testNS/data/clickstream.dat';