Kerberos после обновления с Java6 до Java7
У меня есть рабочее приложение, использующее расширение spring -security kerberos, работающее на jboss, запуск java 6.
Я в процессе обновления jvm от java 6 до java 7. Когда я это делаю, используя ту же базу кода и ту же самую keytab, которая работала на java 6, теперь я получаю сообщение об ошибке при использовании java 7.
Я последовательно получаю:
java.security.PrivilegedActionException: GSSException: ошибка не указана на уровне GSS-API
(Уровень механизма: неверный аргумент (400) -
Невозможно найти ключ соответствующего типа для расшифровки AP REP - RC4 с помощью HMAC)
Я попытался восстановить keytab с различными/криптографическими параметрами, которые были описаны на других форумах, но безрезультатно.
Я отлаживал код java 7, и действительно, классы, которые занимаются чтением keytab при запуске, изменились с 6 на 7. Может ли быть так, что мой keytab не читается в приложении правильно? Некоторые сообщения об отладке, которые я вижу при запуске с использованием Java6, больше не отображаются в 7, но я не могу сказать, работает ли это по дизайну или если это указывает на то, что что-то еще играет в игру? У кого-то еще были проблемы с обновлением с 6 до 7, и их интеграция с кеберосом нарушала их? Любые советы?
При запуске отладки spnego и kerberos для запуска мой журнал показывает:
2012-12-10 10:29:30,886 Debug is true storeKey true useTicketCache false useKeyTab true doNotPrompt true ticketCache is null isInitiator false KeyTab is jndi:/localhost/docfinity/WEB-INF/classes/config/common/security/http-docfinity.keytab refreshKrb5Config is false principal is HTTP/[email protected] tryFirstPass is false useFirstPass is false storePass is false clearPass is false
2012-12-10 10:30:26,322 principal is HTTP/[email protected]
2012-12-10 10:30:29,794 Will use keytab
2012-12-10 10:30:29,807 Ordering keys wrt default_tkt_enctypes list
2012-12-10 10:30:29,821 Config name: C:\Windows\krb5.ini
2012-12-10 10:30:29,827 Using builtin default etypes for default_tkt_enctypes
2012-12-10 10:30:29,832 default etypes for default_tkt_enctypes:
2012-12-10 10:30:29,837 17 aes128-cts-hmac-sha1-96
2012-12-10 10:30:29,839 16 des3-cbc-sha1-kd
2012-12-10 10:30:29,842 23 rc4-hmac
2012-12-10 10:30:29,846 1 des-cbc-crc
2012-12-10 10:30:29,849 3 des-cbc-md5
2012-12-10 10:30:29,851 .
2012-12-10 10:30:29,855 Commit Succeeded
Еще один вопрос - вы увидите, что он пытается прочитать C:\Windows\krb5.ini. У меня нет такого файла на моем сервере. Нужен ли он мне? У меня не было одного с java 6, и это сработало.
Aaron
Ответы
Ответ 1
Да! Мы закрепили SunJaasKerberosTicketValidator, чтобы выглядеть так:
String keyTabPath = this.keyTabLocation.getURL().toExternalForm();
String runtimeVersion = System.getProperty("java.version");
if (runtimeVersion.startsWith("1.7"))
{
LOG.info("Detected jdk 7. Modifying keytabpath");
if (keyTabPath != null)
{
if (keyTabPath.startsWith("file:"))
{
keyTabPath = keyTabPath.substring(5);
}
}
}
LOG.info("KeyTabPath: " + keyTabPath);
LoginConfig loginConfig = new LoginConfig(keyTabPath, this.servicePrincipal,
this.debug);
Ответ 2
Вот две потенциальные проблемы, которые могут повлиять на вас:
-
Java 7, похоже, переключает порядок шифрования по умолчанию. Подробности:
-
Вы не сказали, какую конкретную версию JDK 7 вы используете, но в ранних версиях JDK 7 была ошибка, которая предотвратила загрузку файлов keytab с помощью URL-адреса "file:":
Другой пользователь на SO работал вокруг последней проблемы, изменив Spring source:
Ответ 3
Измените объект keyTabLocation на строку.
So private String keyTabLocaiton.
@Override
public void afterPropertiesSet() throws Exception {
Assert.notNull(this.servicePrincipal, "servicePrincipal must be specified");
Assert.notNull(this.keyTabLocation, "keyTab must be specified");
// if (keyTabLocation instanceof ClassPathResource) {
// LOG.warn("Your keytab is in the classpath. This file needs special protection and shouldn't be in the classpath. JAAS may also not be able to load this file from classpath.");
// }
LoginConfig loginConfig = new LoginConfig(this.keyTabLocation, this.servicePrincipal,
this.debug);
Set<Principal> princ = new HashSet<Principal>(1);
princ.add(new KerberosPrincipal(this.servicePrincipal));
Subject sub = new Subject(false, princ, new HashSet<Object>(), new HashSet<Object>());
LoginContext lc = new LoginContext("", sub, null, loginConfig);
lc.login();
this.serviceSubject = lc.getSubject();
}
Также, где парень LoginConfig, установите флаг isInitiator в true.
public AppConfigurationEntry[] getAppConfigurationEntry(String name) {
HashMap<String, String> options = new HashMap<String, String>();
options.put("useKeyTab", "true");
options.put("keyTab", this.keyTabLocation);
options.put("principal", this.servicePrincipalName);
options.put("storeKey", "true");
options.put("doNotPrompt", "true");
if (this.debug) {
options.put("debug", "true");
}
options.put("isInitiator", "true");
//options.put("isInitiator", "false");
return new AppConfigurationEntry[] { new AppConfigurationEntry("com.sun.security.auth.module.Krb5LoginModule",
AppConfigurationEntry.LoginModuleControlFlag.REQUIRED, options), };
}
Надеюсь, это поможет вам исправить вашу проблему.