我正在尝试使用 kerberos KeyTab 身份验证和 JAAS 配置连接到 Impala DB。
我已经能够通过将系统属性 - “java.security.auth.login.config”设置为 JAAS 配置文件来连接到 Impala DB。而且效果很好。这是工作代码:
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();
问题是 JAAS 配置需要 keytab 文件的绝对路径。在我的情况下,这条路径会因环境而异,我不想为每个环境维护不同的 jaas.config。
所以我采用了生成 JAAS 配置的程序化方法。我能够创建“javax.security.auth.login.Configuration”对象并使用
javax.security.auth.login.Configuration.setConfiguration(jaasConfig) 设置它;
但是,当我使用此更改运行代码时,它无法选择 JAAS 配置并且失败并出现以下异常:
获取JDBC连接失败;嵌套异常是 java.sql.SQLException:[Simba]ImpalaJDBCDriver 使用票证缓存创建登录上下文时出错:无法获取用于身份验证的主体名称。
任何人都可以解释为什么当通过系统属性设置配置时代码运行良好,但在以编程方式设置时不工作。
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();
这就是我创建 JAAS 配置的方式:
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;
}
};
}