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;
}
};
}