0

I had a service which tries to use kerberos ticket cache but I always get error like Caused by: java.lang.RuntimeException: GSSException: No valid credentials provided (Mechanism level: Failed to find any Kerberos credentails).

If I do not use ticket caching, everything seems just works. Below is the parameters I use to specify ticket caching.

            loginContext = new LoginContext("", null, null, new Configuration()
            {
                @Override
                public AppConfigurationEntry[] getAppConfigurationEntry(String name)
                {
                    Map<String, String> options = new HashMap<>();
                    options.put("refreshKrb5Config", "true");
                    options.put("doNotPrompt", "true");
                    if (LOG.isDebugEnabled()) {
                        options.put("debug", "true");
                    }
                    if (config.getKeytab() != null) {
                        options.put("keyTab", config.getKeytab().getAbsolutePath());
                    }
                    options.put("isInitiator", "false");
                    options.put("useKeyTab", "true");
                    options.put("principal", servicePrincipal);
                    //options.put("storeKey", "true");
                    
                    //manually specify /tmp/krb5cc_ServiceUid for ticketCache
                    options.put("ticketCache", config.getCredentialCache().getAbsolutePath());
                    options.put("useTicketCache", "true");
                    options.put("renewTGT", "true");

                    return new AppConfigurationEntry[] {new AppConfigurationEntry(Krb5LoginModule.class.getName(), REQUIRED, options)};
                }
            });
            loginContext.login();

Then I use below code snippets to get the credential:

            String name = loginContext.getSubject().getPrincipals().iterator().next().getName();
            serverCredential = doAs(loginContext.getSubject(), () -> gssManager.createCredential(
                    //gssManager.createName(config.getServiceName() + "@" + hostname, GSSName.NT_HOSTBASED_SERVICE),
                    gssManager.createName(name, GSSName.NT_HOSTBASED_SERVICE),
                    //INDEFINITE_LIFETIME,
                    DEFAULT_LIFETIME,
                    /*new Oid[] {
                            new Oid("1.2.840.113554.1.2.2"), // kerberos 5
                            new Oid("1.3.6.1.5.5.2") // spnego
                    },*/
                    new Oid("1.2.840.113554.1.2.2"),
                    ACCEPT_ONLY));

Is there anything wrong with above code snippets? I also confirmed that /tmp/krb5cc_ServiceUid indeed exists.

Thank you

Bostonian
  • 615
  • 7
  • 16
  • AFAIK Java only has a _partial_ implementation of Kerberos. It can read a TGT from the ticket cache (if the JAAS config allows it), but **cannot write** to the cache -- no renewal, no creation, no re-creation. And it never uses the cache for service tickets. – Samson Scharfrichter Sep 11 '20 at 10:59
  • For the record, I never wrote code for the server side, and I always passed JAAS options via a conf file _(the syntax is peculiar but once you understand that you can have multiple named sections with each multiple auth kinds, it becomes quite easy to read...)_ – Samson Scharfrichter Sep 11 '20 at 11:04
  • For the record, the Hadoop stack has its own Kerberos implementation that builds on the Java impl but overrides a number of things - for instance, it allows renewal of an existing TGT in the cache, by running a `kinit -R` command **:-0** – Samson Scharfrichter Sep 11 '20 at 11:06
  • Since you don't mention activating the debug traces, note that `-Dsun.security.krb5.debug=true` and `-Djava.security.debug=gssloginconfig,configfile,configparser,logincontext` will produce HUGE dumps to SdtErr / StdOut but these dumps might help you understand which options are applied, and which ones are silently ignored (duh!) – Samson Scharfrichter Sep 11 '20 at 11:16

0 Answers0