使用带有 Kerberos 身份验证的 JDBC 连接到 Hive 时出现问题

问题描述 投票:0回答:2

我正在尝试编写一个程序来使用具有 Kerberos 身份验证的 Jdbc 驱动程序连接到 Hive。我的程序如下:

public static void main(String a[])
{

    ...

    connectionString_ = "jdbc:hive2://cdh-542-kerberos.domain.com:10000/default;principal=hive/cdh-542-kerberos.domain.com@REALMDOMAIN";

    UserGroupInformation ugi = createUgi();

    connection = ugi.doAs(new PrivilegedExceptionAction<Connection>() {
        public Connection run() throws Exception {
            Connection connection = null;
            Class.forName(jdbcDriverClass_);
            connection =  DriverManager.getConnection(connectionString_);
            return connection;
        }
    });
    ... 
}



public static UserGroupInformation createUgi() 
{
    try{
        UserGroupInformation ugi = null;
        
        String principal = "hive/cdh-542-kerberos.domain.com@REALMDOMAIN"
        String keyTabLocation = "hive.keytab"
        
        logger.debug("principal:" + principal);
        logger.debug("keyTabLocation:" + keyTabLocation);
        ugi =  createkerbUser( principal, keyTabLocation);
        return ugi;
    }
    catch(Exception e)
    {
        throw new BDEToolSecurityException(BDEToolSecurityException.SECURITYEXCPETION, e);
    }
}

public static UserGroupInformation createkerbUser( String principal, String keyTabFilePath) 
{
    UserGroupInformation app_ugi = UserGroupInformation.loginUserFromKeytabAndReturnUGI(principal, keyTabFilePath);
    String user = getUserfromPrincipal(principal);
    
    if(user.trim().length() > 0){
        UserGroupInformation proxy_ugi = UserGroupInformation.createProxyUser(user, app_ugi);
        return proxy_ugi;
    }
    return app_ugi;
}

private static String getUserfromPrincipal(String principal)
{
    String user = Constants.emptyString;
    
    if(principal.contains(Constants.fSlash)){
        String[]  tokens = principal.split(Constants.fSlash);           
        if(tokens.length > 1){
            user = tokens[0];
        }            
    }       
    return user;
}

此代码在尝试

ugi.doAs() ...
时失败,但有以下异常

java.sql.SQLException: Could not open client transport with JDBC Uri: jdbc:hive2://cdh-542-kerberos.informatica.com:10000/default;principal=hive/cdh-542-kerberos.informatica.com@INFAQAKERB: GSS initiate failed
    at org.apache.hive.jdbc.HiveConnection.openTransport(HiveConnection.java:215)
    at org.apache.hive.jdbc.HiveConnection.<init>(HiveConnection.java:163)
    at org.apache.hive.jdbc.HiveDriver.connect(HiveDriver.java:105)
    at java.sql.DriverManager.getConnection(DriverManager.java:571)
    at java.sql.DriverManager.getConnection(DriverManager.java:233)
    at com.informatica.gcs.tools.bde.connectivity.tool.hive.HiveJdbcTest$1.run(HiveJdbcTest.java:148)
    at com.informatica.gcs.tools.bde.connectivity.tool.hive.HiveJdbcTest$1.run(HiveJdbcTest.java:144)
    at java.security.AccessController.doPrivileged(Native Method)
    at javax.security.auth.Subject.doAs(Subject.java:415)
    at org.apache.hadoop.security.UserGroupInformation.doAs(UserGroupInformation.java:1671)
    ... 6 more
Caused by: org.apache.thrift.transport.TTransportException: GSS initiate failed
    at org.apache.thrift.transport.TSaslTransport.sendAndThrowMessage(TSaslTransport.java:232)
    at org.apache.thrift.transport.TSaslTransport.open(TSaslTransport.java:316)
    at org.apache.thrift.transport.TSaslClientTransport.open(TSaslClientTransport.java:37)
    at org.apache.hadoop.hive.thrift.client.TUGIAssumingTransport$1.run(TUGIAssumingTransport.java:52)
    at org.apache.hadoop.hive.thrift.client.TUGIAssumingTransport$1.run(TUGIAssumingTransport.java:49)
    at java.security.AccessController.doPrivileged(Native Method)
    at javax.security.auth.Subject.doAs(Subject.java:415)
    at org.apache.hadoop.security.UserGroupInformation.doAs(UserGroupInformation.java:1671)
    at org.apache.hadoop.hive.thrift.client.TUGIAssumingTransport.open(TUGIAssumingTransport.java:49)
    at org.apache.hive.jdbc.HiveConnection.openTransport(HiveConnection.java:190)
    ... 15 more

密钥表和原理似乎都是正确的。我可以成功运行命令

kinit -k -t hive.keytab hive/cdh-542-kerberos.informatica.com@INFAQAKERB

任何人都可以帮助我进一步解决这个问题吗?我在这个问题上被困了将近一周。如果需要,我可以提供更多信息。

java hadoop jdbc hive cloudera-cdh
2个回答
0
投票

这不是票丢失/过期的问题。否则,错误堆栈将在“GSS 启动失败”之后读取“由 GSSException 引起:未提供有效凭据”。

可能出现的问题:

  1. 您尝试连接的服务器(Hive Server 2,端口 10000)和您的客户端计算机(进行 jdbc:hive 连接)似乎位于不同的域中。是这样吗

  2. 要确认您的服务器和客户端可以在该域中进行身份验证,并且其域配置正确(krb5.conf 等),请执行以下操作

    $ kinit -k -t hive.keytab hive/cdh-542-kerberos.informatica.com@INFAQAKERB (like you did)
    $ klist 
    
    • 在服务器和客户端执行此操作,然后将结果复制粘贴到此处。
  3. “org.apache.hive.jdbc.HiveConnection.openTransport(HiveConnection.java:215)”可以提供线索,表明这可能是从 HS2 服务器到域控制器服务器的防火墙/域配置问题。虽然您可以在客户端创建票证,但 HS2 服务器无法验证它。

  4. 在您的代码片段上 - 查看在 JDBC 中连接到 Kerberos Hive 的示例

    看来你的代码至少丢失了:

    UserGroupInformation.setConfiguration(conf);
    

    但不确定它是否与您的用例相关......

如果您能够解决此问题,请随时通知我们。


0
投票

对于 hive,您不应该使用 proxyuser 来执行 ugi.doAs。将代码修改为

public static UserGroupInformation createkerbUser( String principal, String keyTabFilePath) 
{
    return  UserGroupInformation.loginUserFromKeytabAndReturnUGI(principal, keyTabFilePath);
}

    public static UserGroupInformation createkerbUser( String principal, String keyTabFilePath) 
        {
            UserGroupInformation.loginUserFromKeytab(principal, keyTabFilePath);
            return UserGroupInformation.getLoginUser();
        }

如果您需要模仿,请附加

hive.server2.proxy.user=

<proxyUser>

(对于 apache 驱动程序)到 JDBC 连接字符串。

PS:在集群配置中,如果您计划使用“代理用户”属性,hive 用户应该具有模拟不同用户的权限。

© www.soinside.com 2019 - 2024. All rights reserved.