Getting a HiveServer2 Delegation Token
To acccess Hive metadata using HiveServer2, you need a special delegation token. (See Bring Your Own Delegation Token.) HiveServer2 does not provide an easy way to get this token, unlike the REST API that grants HDFS (data) delegation tokens.
The following utility code shows a way to get this token. You will need to modify this code for your own cluster; in particular, change the value of the connectURL
static.
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(); } } }
Following is an example call and its output:
$ 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