Programmatic Kerberos Configuration Issues for Solace

According to the Solace documentation, the only way to configure Kerberos authentication is via providing jaas.conf and a keytab:

In my application, I am trying to do programmatic Kerberos authentication. You may ask why? Well several reasons:

  1. I don’t want the keytabs and any file deps.
  2. I fetch the credentials from vault in the container during runtime. I have mechanisms in place to fetch creds rotations etc.
  3. Major one: I have Database authentication as well via JavaKerberos & Integrated security via creds from vault.

The Code:

For programmatic Kerberos authentication, generally the code goes like this:

public class MyCustomUsernamePasswordCallbackHandler implements CallbackHandler {
    private final String username;
    private final String password;

    public MyCustomUsernamePasswordCallbackHandler(String username, String password) {
        this.username = username;
        this.password = password;
    }

    public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException {
        for (Callback callback : callbacks) {
            if (callback instanceof NameCallback) {
                ((NameCallback) callback).setName(username);
            } else if (callback instanceof PasswordCallback) {
                ((PasswordCallback) callback).setPassword(password.toCharArray());
            } else {
                throw new UnsupportedCallbackException(callback);
            }
        }
    }
}

CallBackHandler callbackHandler = new MyCustomUsernamePasswordCallbackHandler("solace-user@YOUR.REALM", "yourPassword");

LoginContext loginContext = new LoginContext(
     "SolaceGSS", 
     null, 
     new UsernamePasswordCallbackHandler("solace-user@YOUR.REALM", "yourPassword"),
     new Configuration() {
        @Override
        public AppConfigurationEntry[] getAppConfigurationEntry(String name) {
            Map<String, String> options = new HashMap<>();
            options.put("useTicketCache", "false");
            options.put("storeKey", "false");
            options.put("doNotPrompt", "false");
            options.put("useFirstPass", "true");
            options.put("principal", "solace-user@YOUR.REALM");
            options.put("debug", "true");

            return new AppConfigurationEntry[] {
                new AppConfigurationEntry(
                    "com.sun.security.auth.module.Krb5LoginModule",
                    AppConfigurationEntry.LoginModuleControlFlag.REQUIRED,
                    options
            ) };
        }
});

loginContext.login();

Subject subject = loginContext.getSubject();

return Subject.doAs(subject, (PrivilegedAction<SolConnectionFactory>) () -> {
    SolConnectionFactory cf = SolJmsUtility.createConnectionFactory();
    Hashtable<String, Object> env = new Hashtable<>();
    env.put(SupportedProperty.SOLACE_JMS_HOST, "tcp://your-solace-host:port");
    env.put(SupportedProperty.SOLACE_JMS_AUTHENTICATION_SCHEME,   SupportedProperty.AUTHENTICATION_SCHEME_GSS_KRB);
    env.put(SupportedProperty.SOLACE_JMS_KRB_SERVICE_NAME, "solace");
    return SolJmsUtility.createConnectionFactory(env);
});


Now, the login actually gets successful. But the issue is, Solace doesn’t care about the LoginContext and session I created! Internally it tries to create it’s own login context. It tries to only read the global configuration and disregards the above Login subject I created with my custom jaas config and callback handler.That code resides in SimpleSmfClient → getKRBToken method.

So when I try to listen to anything with @JmsListener, it tries to authenticate on its own, with it’s own login context, and authentication fails becz it doesn’t find any jaas configs for Solace (Global one).

This is weird!

It gets messed up when there are other use cases like, say I want to pause Solace connections via JmsListenerEndpointRegistry when my DB connection is getting renewed. Then when I resume listeners, it tries to authenticate again… that too via it’s own new internal Login context.

What is the solution for this? What is the workaround? Is there a fix?

Hi there, I’m Solly AI, I generate responses to your questions using the power of the Solace Agent Mesh:

Please remember that AI technology can make mistakes so ensure that you read our Disclaimer.

AI Generated responses are a work in progress, your help in evaluating my response would be awesome! If my response makes sense, please mark it as a solution or give a :+1:. If my response doesn’t make sense for your topic, please react to it with a :shaking_face:.

Looking at the documentation, I can explain the reasoning for implementing programmatic Kerberos authentication with JMS without using jaas.conf and keytab files:

The PubSub+ Java API provides the AuthenticationStrategy.Kerberos class that allows programmatic configuration of Kerberos authentication without relying on external configuration files. This can be done through:

  1. Using the factory method Kerberos.of() to create a Kerberos authentication instance
  2. Configuring the authentication parameters programmatically through method chaining

However, the documentation indicates that Kerberos authentication requires:

  1. A valid JAAS configuration file specified through -Djava.security.auth.login.config=jaas.conf
  2. A Kerberos keytab file loaded on the event broker
  3. Kerberos authentication enabled on the Message VPN

Therefore, while the API provides methods for programmatic configuration, it is not possible to implement Kerberos authentication completely without jaas.conf and keytab files as these are fundamental requirements for Kerberos authentication with Solace.

Here are the relevant documentation links: