GSSException: No valid credentials provided (Mechanism level: Failed to find any Kerberos tgt)
Asked Answered
M

3

16

I am very much new to the MOngoDB + Java Configuration. I am trying to achive the connection from remote mongodb server from Java application. I want to use GSSAPI mechanism for connection with mongotemplate. Below code has been executing successfully. Below code is from my configuration file.

List<ServerAddress> serverAddresses = new ArrayList<ServerAddress>();
    ServerAddress address = new ServerAddress(host, port);
    serverAddresses.add(address);
    List<MongoCredential> credentials = new ArrayList<MongoCredential>();

    MongoCredential credential = MongoCredential.createGSSAPICredential(userName);

    credential.withMechanismProperty("SERVICE_NAME", gssapiServiceName);
    credential.withMechanismProperty("CANONICALIZE_HOST_NAME", true);
    credentials.add(credential);

    return new MongoClient(serverAddresses, credentials);

But when I am trying execute below code I am getting exception

DB db = mongoTemplate.getDb();
Set<String> dbCollections1 = db.getCollectionNames();

Exception:

GSSException: No valid credentials provided (Mechanism level: Failed to find any Kerberos tgt) at sun.security.jgss.krb5.Krb5InitCredential.getInstance(Krb5InitCredential.java:147) at sun.security.jgss.krb5.Krb5MechFactory.getCredentialElement(Krb5MechFactory.java:122) at sun.security.jgss.GSSManagerImpl.getCredentialElement(GSSManagerImpl.java:193) at sun.security.jgss.GSSCredentialImpl.add(GSSCredentialImpl.java:427) at sun.security.jgss.GSSCredentialImpl.(GSSCredentialImpl.java:62) at sun.security.jgss.GSSManagerImpl.createCredential(GSSManagerImpl.java:154) at com.mongodb.DBPort$GSSAPIAuthenticator.getGSSCredential(DBPort.java:622) at com.mongodb.DBPort$GSSAPIAuthenticator.createSaslClient(DBPort.java:593) at com.mongodb.DBPort$SaslAuthenticator.authenticate(DBPort.java:895) at com.mongodb.DBPort.authenticate(DBPort.java:432) at com.mongodb.DBPort.checkAuth(DBPort.java:443) at com.mongodb.DBTCPConnector.innerCall(DBTCPConnector.java:289) at com.mongodb.DBTCPConnector.call(DBTCPConnector.java:269) at com.mongodb.DBCollectionImpl.find(DBCollectionImpl.java:84) at com.mongodb.DB.command(DB.java:320) at com.mongodb.DB.command(DB.java:299) at com.mongodb.DB.command(DB.java:388) at com.mongodb.DBApiLayer.getCollectionNames(DBApiLayer.java:152)

Moldavia answered 20/11, 2015 at 14:22 Comment(4)
I don't know anything about MongoDB, but that error message means that GSSAPI thinks you want to use Kerberos protocol -- is that true? if yes, did you provide the config to tell GSSAPI how to contact the Kerberos server? and (a) where the existing Kerberos ticket is cached, or (b) how to find the password and create the ticket on the fly? By the way, if you use a Sun/Oracle JVM, did you download the "unlimited strength crypto" policy JARs to enable AES256 encryption?Cambrai
Yes, I want to use Kerberos protocol. I have set two System Environment Variables 1. KRB5_CONFIG=krb5.conf 2.KRB5_KTNAME=username.keytab This is what I did for configuration perspective. I am accessing this mongodb server from Java web application. Hope I am able to provide answer to your queries.Moldavia
Have a look at #21375872 for the dirty details of setting the Kerberos conf (well, some of the details)Cambrai
Plus a useful trace flag to untangle config issues: -Djava.security.debug=gssloginconfig,configfile,configparser,logincontextCambrai
M
19

Million thanks to all who have responded and take a look to my question.

After adding some System Properties and a new conf file, Finally I am able to get connected with MongoDB server. Herewith the updated code -

try {
        System.setProperty("java.security.krb5.conf","C:/mongodb/UnixKeytab/krb5.conf");
        System.setProperty("java.security.krb5.realm","EXAMPLE.COM");
        System.setProperty("java.security.krb5.kdc","example.com");
        System.setProperty("javax.security.auth.useSubjectCredsOnly","false");
        System.setProperty("java.security.auth.login.config","C:/mongodb/UnixKeytab/gss-jaas.conf");


        List<ServerAddress> serverAddresses = new ArrayList<ServerAddress>();
        ServerAddress address = new ServerAddress(host, port);
        serverAddresses.add(address);
        List<MongoCredential> credentials = new ArrayList<MongoCredential>();
        MongoCredential credential = MongoCredential.createGSSAPICredential(username);
        credentials.add(credential);
        MongoClient mongoClient1 = new MongoClient(serverAddresses, credentials);
        DB db = mongoClient1.getDB(database);

    } catch (UnknownHostException e) {
        e.printStackTrace();
    }

My krb5.conf file look like below -

[libdefaults]
     default_realm = EXAMPLE.COM
     default_tkt_enctypes = des-cbc-md5 rc4-hmac
     default_tgs_enctypes = des-cbc-md5 rc4-hmac
     default_keytab_name = <keytab file path>
[realms]
EXAMPLE.COM = {
    kdc = example.com
    master_kdc = example.com
    default_domain = EXAMPLE.COM
}
INTRANET = {
    kdc = example.com
    master_kdc = example.com
    default_domain = example.com
}

My gss-jaas.conf look like below -

com.sun.security.jgss.initiate {
com.sun.security.auth.module.Krb5LoginModule required
useKeyTab=true
useTicketCache=false
principal="my-account@MY_REALM"
doNotPrompt=true
keyTab="path-to-my-keytab-file"
debug=true;};

Code I have posted is working for me. Hope this will work for others.

Moldavia answered 23/11, 2015 at 12:37 Comment(0)
O
6

Adding some information to this post as its extremely useful already.

If the Sasl/createSaslClient is not run within the Subject:doAs method that is retrieved from the LoginContext, the credentials will not be picked up from the krb5.conf file. I.e the GSS code looks at the current thread's security manager for the Subject which is registered via the Subject:doAs method, and then uses the credentials from this subject. This Subject should've been obtained via jaas which in turn would read the correct jaas and krb5.conf credentials, but if you do not run the sasl and saslclient methods inside the Subject:doAs method all this doesn't matter.

You can get around it by setting javax.security.auth.useSubjectCredsOnly=false which means if no credentials can be found, some default names in the jaas file will be searched for see LoginConfigImpl.java#92, one is com.sun.security.jgss.initiate.

e.g

com.sun.security.jgss.initiate{
   com.sun.security.auth.module.Krb5LoginModule required
   doNotPrompt=true
   useTicketCache=true
   useKeyTab=true
   keyTab="mykeytab"
   principal="service/host@REALM";
 };
Owing answered 13/12, 2016 at 23:26 Comment(0)
J
1

I faced the same error "Mechanism level: Failed to find any Kerberos tgt". My problem looks different from yours, but it could be useful to other ones with the same error.

In my case it was caused by an error in writing the principal name in one of my configuration files.

I suggest to check the Jaas LoginManager configuration file (provided with java.security.auth.login.config) and policy files for principals. Typical error is the domain name in lowercase: [email protected] instead of [email protected]

In the case you set/refer to the principal programmatically, you can also check the principal name correctness in your code. Regards

Johniejohnna answered 16/8, 2017 at 9:31 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.