Ошибка подключения к кластеру с поддержкой Kerberos с использованием JDBC HiveDriver в Java. javax.security.sasl.Исключение SaslException: не удалось инициировать GSS

#java #jdbc #hive #kerberos #kudu

#java #jdbc #улей #kerberos #kudu

Вопрос:

Я пытаюсь подключиться к кластеру Apache Kudu с поддержкой аутентификации kerberos через механизм запросов impala, используя JDBC org.apache.hive.jdbc.HiveDriver из приложения Java. Приложение Java является приложением на основе Vert.x и запускается как fat jar. Эта настройка хорошо работает, когда аутентификация не включена (jdbc:hive2://:17660/defau<auth=noSasl) При включении аутентификации kerberos происходит сбой с ошибкой javax.security.sasl.Исключение SaslException: не удалось инициировать GSS [Вызвано исключением GSSException: не предоставлены действительные учетные данные (уровень механизма: попытка получить новые учетные данные ИНИЦИАЛИЗАЦИИ не удалась! (null))]

Ниже приведена настройка кода для подключения через JDBC.

 url= jdbc:hive2://<server>:17660/defau<principal=hive/pg3.map@KERB;
 

(также пробовал)

 jdbc:hive2://<server>:17660/defau<principal=hive/pg3.map@KERB;auth=kerberos;kerberosAuthType=fromSubject;ssl=false;
 

Я устанавливаю следующие свойства в коде, прежде чем пытаться установить соединение.

 System.setProperty("sun.security.krb5.debug", "true");
System.setProperty("sun.security.krb5.conf", "/etc/krb5.conf");
System.setProperty("java.security.auth.login.config", "kerberos_login_config.ini");
System.setProperty("javax.security.auth.useSubjectCredsOnly", "false");
 

содержимое файла kerberos_login_config.ini выглядит следующим образом (я пробовал с кэшем билетов и без него, конечный результат тот же)

 com.sun.security.jgss.initiate {
com.sun.security.auth.module.Krb5LoginModule required
useKeyTab=true
keyTab="javausr.keytab"
principal="javausr/pg3.map@KERB"
useTicketCache=true
doNotPrompt=true
storeKey=true
tryFirstPass=true
useFirstPass =true
renewTGT=false
client=true
ticketCache="/tmp/krb5cc_1007"
debug=true;
};
 

файл krb5.conf

 includedir /etc/krb5.conf.d/

[logging]
default = FILE:/var/log/krb5libs.log
kdc = FILE:/var/log/krb5kdc.log
admin_server = FILE:/var/log/kadmind.log

[libdefaults]
dns_lookup_realm = false
ticket_lifetime = 24h
renew_lifetime = 7d
forwardable = true
rdns = true
pkinit_anchors = /etc/pki/tls/certs/ca-bundle.crt
default_realm = KERB
default_ccache_name = KEYRING:persistent:%{uid}
default_tkt_enctypes = des3-hmac-sha1 des-cbc-crc
default_tgs_enctypes = des3-hmac-sha1 des-cbc-crc

[realms]
KERB = {
kdc = pg3.map
admin_server = pg3.map
}

[domain_realm]
.pg3.map = KERB
pg3.map = KERB
 

Также я пробовал запускать команду kinit и без нее на сервере.

 kinit -kt javausr.keytab javausr/pg3.map@KERB
 

My pom file has below dependencies added (apart from other Vertx requirements)

 <dependency>
            <groupId>org.spark-project.hive</groupId>
            <artifactId>hive-jdbc</artifactId>
            <version>1.2.1.spark2</version>
            <classifier>standalone</classifier>
</dependency>
<dependency>
            <groupId>org.apache.hadoop</groupId>
            <artifactId>hadoop-common</artifactId>
            <version>2.7.3</version>
</dependency>
<dependency>
            <groupId>org.apache.hadoop</groupId>
            <artifactId>hadoop-auth</artifactId>
            <version>2.7.3</version>
</dependency>
<dependency>
            <groupId>org.apache.hadoop</groupId>
            <artifactId>hadoop-core</artifactId>
            <version>1.2.1</version>
</dependency>
<dependency>
            <groupId>commons-configuration</groupId>
            <artifactId>commons-configuration</artifactId>
            <version>1.6</version>
</dependency>
 

При запуске я получаю приведенную ниже ошибку и stacktrace в консоли.

 Java config name: /etc/krb5.conf
Loaded from Java config
21/01/05 16:22:41 WARN util.NativeCodeLoader: Unable to load native-hadoop library for your platform... using builtin-java classes where applicable
21/01/05 16:22:42 INFO jdbc.HiveConnection: Will try to open client transport with JDBC Uri: jdbc:hive2://<server>:17660/defau<principal=hive/pg3.map@KERB;
Acquire TGT from Cache
Principal is javausr/pg3.map@KERB
null credentials from Ticket Cache
>>> KeyTabInputStream, readName(): KERB
>>> KeyTabInputStream, readName(): javausr
>>> KeyTabInputStream, readName(): pg3.map
>>> KeyTab: load() entry length: 67; type: 16
Looking for keys for: javausr/pg3.map@KER
Found unsupported keytype (2) for javausr/pg3.map@KERB
Found unsupported keytype (2) for javausr/pg3.map@KERB
Found unsupported keytype (2) for javausr/pg3.map@KERB
Found unsupported keytype (3) for javausr/pg3.map@KERB
Found unsupported keytype (3) for javausr/pg3.map@KERB
Found unsupported keytype (8) for javausr/pg3.map@KERB
Found unsupported keytype (3) for javausr/pg3.map@KERB
Found unsupported keytype (8) for javausr/pg3.map@KERB
Found unsupported keytype (8) for javausr/pg3.map@KERB
Added key: 16version: 1
Added key: 23version: 1
default etypes for default_tkt_enctypes: 16.
Added key: 16version: 1
default etypes for default_tkt_enctypes: 16.
default etypes for default_tkt_enctypes: 16.
>>> KrbAsReq creating message
>>> KrbAsReq creating message
>>> KrbAsReq creating message
>>> KrbKdcReq send: kdc=pg3.map UDP:88, timeout=30000, number of retries =3, #bytes=166
>>> KrbKdcReq send: kdc=pg3.map UDP:88, timeout=30000, number of retries =3, #bytes=166
>>> KrbKdcReq send: kdc=pg3.map UDP:88, timeout=30000, number of retries =3, #bytes=166
>>> EType: sun.security.krb5.internal.crypto.Des3CbcHmacSha1KdEType
>>> EType: sun.security.krb5.internal.crypto.Des3CbcHmacSha1KdEType
>>> EType: sun.security.krb5.internal.crypto.Des3CbcHmacSha1KdEType
        [Krb5LoginModule] tryFirstPass failed with:Message stream modified (41)
Acquire TGT from Cache
        [Krb5LoginModule] tryFirstPass failed with:Message stream modified (41)
Acquire TGT from Cache
        [Krb5LoginModule] tryFirstPass failed with:Message stream modified (41)
Principal is null
null credentials from Ticket Cache
Principal is null
null credentials from Ticket Cache
        [Krb5LoginModule] authentication failed 
Unable to obtain Principal Name for authentication 
Acquire TGT from Cache
        [Krb5LoginModule] authentication failed 
Unable to obtain Principal Name for authentication 
Principal is null
null credentials from Ticket Cache
        [Krb5LoginModule] authentication failed 
Unable to obtain Principal Name for authentication 
21/01/05 16:22:42 ERROR transport.TSaslTransport: SASL negotiation failure
javax.security.sasl.SaslException: GSS initiate failed [Caused by GSSException: No valid credentials provided (Mechanism level: Attempt to obtain new INITIATE credentials failed! (null))]
    at com.sun.security.sasl.gsskerb.GssKrb5Client.evaluateChallenge(GssKrb5Client.java:211)
    at org.apache.thrift.transport.TSaslClientTransport.handleSaslStartMessage(TSaslClientTransport.java:94)
    at org.apache.thrift.transport.TSaslTransport.open(TSaslTransport.java:271)
    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:422)
    at org.apache.hadoop.security.UserGroupInformation.doAs(UserGroupInformation.java:1698)
    at org.apache.hadoop.hive.thrift.client.TUGIAssumingTransport.open(TUGIAssumingTransport.java:49)
    at org.apache.hive.jdbc.HiveConnection.openTransport(HiveConnection.java:204)
    at org.apache.hive.jdbc.HiveConnection.<init>(HiveConnection.java:176)
    at org.apache.hive.jdbc.HiveDriver.connect(HiveDriver.java:105)
    at com.mchange.v2.c3p0.DriverManagerDataSource.getConnection(DriverManagerDataSource.java:161)
    at com.mchange.v2.c3p0.WrapperConnectionPoolDataSource.getPooledConnection(WrapperConnectionPoolDataSource.java:161)
    at com.mchange.v2.c3p0.WrapperConnectionPoolDataSource.getPooledConnection(WrapperConnectionPoolDataSource.java:147)
    at com.mchange.v2.c3p0.impl.C3P0PooledConnectionPool$1PooledConnectionResourcePoolManager.acquireResource(C3P0PooledConnectionPool.java:202)
    at com.mchange.v2.resourcepool.BasicResourcePool.doAcquire(BasicResourcePool.java:1176)
    at com.mchange.v2.resourcepool.BasicResourcePool.doAcquireAndDecrementPendingAcquiresWithinLockOnSuccess(BasicResourcePool.java:1163)
    at com.mchange.v2.resourcepool.BasicResourcePool.access$700(BasicResourcePool.java:44)
    at com.mchange.v2.resourcepool.BasicResourcePool$ScatteredAcquireTask.run(BasicResourcePool.java:1908)
    at com.mchange.v2.async.ThreadPoolAsynchronousRunner$PoolThread.run(ThreadPoolAsynchronousRunner.java:696)
Caused by: GSSException: No valid credentials provided (Mechanism level: Attempt to obtain new INITIATE credentials failed! (null))
    at sun.security.jgss.krb5.Krb5InitCredential.getTgt(Krb5InitCredential.java:385)
    at sun.security.jgss.krb5.Krb5InitCredential.getInstance(Krb5InitCredential.java:160)
    at sun.security.jgss.krb5.Krb5MechFactory.getCredentialElement(Krb5MechFactory.java:122)
    at sun.security.jgss.krb5.Krb5MechFactory.getMechanismContext(Krb5MechFactory.java:189)
    at sun.security.jgss.GSSManagerImpl.getMechanismContext(GSSManagerImpl.java:224)
    at sun.security.jgss.GSSContextImpl.initSecContext(GSSContextImpl.java:212)
    at sun.security.jgss.GSSContextImpl.initSecContext(GSSContextImpl.java:179)
    at com.sun.security.sasl.gsskerb.GssKrb5Client.evaluateChallenge(GssKrb5Client.java:192)
    ... 21 more
Caused by: javax.security.auth.login.LoginException: Unable to obtain Principal Name for authentication 
    at com.sun.security.auth.module.Krb5LoginModule.promptForName(Krb5LoginModule.java:845)
    at com.sun.security.auth.module.Krb5LoginModule.attemptAuthentication(Krb5LoginModule.java:708)
    at com.sun.security.auth.module.Krb5LoginModule.login(Krb5LoginModule.java:618)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at javax.security.auth.login.LoginContext.invoke(LoginContext.java:755)
    at javax.security.auth.login.LoginContext.access$000(LoginContext.java:195)
    at javax.security.auth.login.LoginContext$4.run(LoginContext.java:682)
    at javax.security.auth.login.LoginContext$4.run(LoginContext.java:680)
    at java.security.AccessController.doPrivileged(Native Method)
    at javax.security.auth.login.LoginContext.invokePriv(LoginContext.java:680)
    at javax.security.auth.login.LoginContext.login(LoginContext.java:587)
    at sun.security.jgss.GSSUtil.login(GSSUtil.java:258)
    at sun.security.jgss.krb5.Krb5Util.getInitialTicket(Krb5Util.java:175)
    at sun.security.jgss.krb5.Krb5InitCredential$1.run(Krb5InitCredential.java:377)
    at sun.security.jgss.krb5.Krb5InitCredential$1.run(Krb5InitCredential.java:373)
    at java.security.AccessController.doPrivileged(Native Method)
    at sun.security.jgss.krb5.Krb5InitCredential.getTgt(Krb5InitCredential.java:372)
    ... 28 more
 

Это происходит при попытке подключения через java-приложение с использованием jdbc. Можно подключиться к python с того же сервера после выполнения kinit, используя приведенный ниже код.

 conn = dbapi.connect(host=<server>, port=17660, use_ssl = False, auth_mechanism='GSSAPI',
    kerberos_service_name='impala')
 

Любая помощь в решении этой проблемы очень ценится.

Ответ №1:

В итоге выяснилось, что Java не поддерживает тип кэша «KEYRING» и должен использовать тип кэша «FILE». Это можно либо сделать, установив «default_ccache_name = FILE:/tmp/krb5cc_%{uid}» в файле krb5.conf, либо установив переменную среды KRB5CCNAME в кэш типа ФАЙЛА.