0

I am trying to connect to Impala DB using kerberos KeyTab authentication and JAAS configuration.

I am already able to connect to Impala DB by setting System property - "java.security.auth.login.config" to JAAS config file. And it works perfectly. Here is the working code:

System.setProperty("sun.security.krb5.debug", "false");
System.setProperty("javax.security.auth.useSubjectCredsOnly", "true");
System.setProperty("java.security.krb5.conf", krb5ConfPath);
System.setProperty("java.security.auth.login.config", jaasPath);

org.apache.hadoop.conf.Configuration conf = new org.apache.hadoop.conf.Configuration();
conf.set("hadoop.security.authentication", "kerberos");

UserGroupInformation.setConfiguration(conf);
UserGroupInformation.loginUserFromKeytab(principal, keyTabPath);

DataSourceBuilder dataSourceBuilder = DataSourceBuilder.create(DatabaseConfig.class.getClassLoader());
return dataSourceBuilder.build();

Problem is that JAAS config requires absolute path to keytab file. In my case this path will vary environment to environment and I do not want to maintain different jaas.config for each environment.

So I took programmatic approach of generating JAAS config. I am able to create "javax.security.auth.login.Configuration" object and setting it using
javax.security.auth.login.Configuration.setConfiguration(jaasConfig);

But when I run the code with this change it fails to pick the JAAS configuration and fails with below exception:

Failed to obtain JDBC Connection; nested exception is java.sql.SQLException: [Simba]ImpalaJDBCDriver Error creating login context using ticket cache: Unable to obtain Principal Name for authentication.

Can anybody please explain why code is running fine when configuration is set via System property but not working when it is being set programmatically.

System.setProperty("sun.security.krb5.debug", "false");
System.setProperty("javax.security.auth.useSubjectCredsOnly", "true");
System.setProperty("java.security.krb5.conf", krb5ConfPath);

javax.security.auth.login.Configuration jaasConfig = createJaasConfig(keyTabPath);
             javax.security.auth.login.Configuration.setConfiguration(jaasConfig);

org.apache.hadoop.conf.Configuration conf = new org.apache.hadoop.conf.Configuration();
conf.set("hadoop.security.authentication", "kerberos");

UserGroupInformation.setConfiguration(conf);
UserGroupInformation.loginUserFromKeytab(principal, keyTabPath);

DataSourceBuilder dataSourceBuilder = DataSourceBuilder.create(DatabaseConfig.class.getClassLoader());
return dataSourceBuilder.build();

This is how I am creating JAAS Config:

private static javax.security.auth.login.Configuration createJaasConfig(final String keyTabPath) throws Exception {

        // Create entry options.
        Map<String, Object> options = new HashMap<>();
        options.put("useTicketCache", "false");
        options.put("doNotPrompt", "true");
        options.put("useKeyTab", "true");
        options.put("debug", "false");
        // options.put("storeKey", "true");
        options.put("principal", "user@DOMAIN.COM");
        options.put("keyTab", keyTabPath);

        // Create entries
        AppConfigurationEntry[] entries = {
            new AppConfigurationEntry(
                Krb5LoginModule.class.getCanonicalName(),
                AppConfigurationEntry.LoginModuleControlFlag.REQUIRED,
                options
            )
        };

        // Create configuration
        return new javax.security.auth.login.Configuration() {
            @Override
            public AppConfigurationEntry[] getAppConfigurationEntry(String name) {
                return entries;
            }
        };
    }
  • If the raw JAAS config is used to create a process-private Kerberos ticket, why do you create another process-private ticket with static `UserGroupInformation` object _(which is a Hadoop-specific wrapper around JAAS)_? – Samson Scharfrichter Jun 21 '19 at 13:35
  • To enable debug traces about the way JAAS interprets its config (incl. silent errors), cf. the bottom of https://stackoverflow.com/a/42506620/5162372 – Samson Scharfrichter Jun 21 '19 at 13:38
  • Hi @SamsonScharfrichter, i am sorry but i did not understand that UserGroupInformation part. What I have understood till now is that UserGroupInformation will eventually perform Subject.doAs for connection. For the log part I enabled those properties already. I can attach logs here if you want. – Anupam Gangrade Jun 21 '19 at 14:15
  • UGI is part of the Hadoop stack. It's used by Hadoop client libs. But the JDBC drivers don't use the Hadoop clients libs, they use standard JAAS instead - especially the Cloudera drivers that have _no_ dependency against Hadoop JARs _(developed with commercial SIMBA SDK)_; for the Apache driver it's not 100% true because it reuses some Kerberos utility methods, which is a pain on Windows BTW – Samson Scharfrichter Jun 21 '19 at 15:47

0 Answers0