#java #kerberos #gssapi
#ява #керберос #gssapi с #java #kerberos #gssapi
Вопрос:
У меня был сервис, который пытается использовать кеш тикетов kerberos, но я всегда получаю ошибку типа Caused by: java.lang.RuntimeException: GSSException: No valid credentials provided (Mechanism level: Failed to find any Kerberos credentails)
.
Если я не использую кэширование билетов, кажется, что все просто работает. Ниже приведены параметры, которые я использую для указания кэширования билетов.
loginContext = new LoginContext("", null, null, new Configuration()
{
@Override
public AppConfigurationEntry[] getAppConfigurationEntry(String name)
{
Map<String, String> options = new HashMap<>();
options.put("refreshKrb5Config", "true");
options.put("doNotPrompt", "true");
if (LOG.isDebugEnabled()) {
options.put("debug", "true");
}
if (config.getKeytab() != null) {
options.put("keyTab", config.getKeytab().getAbsolutePath());
}
options.put("isInitiator", "false");
options.put("useKeyTab", "true");
options.put("principal", servicePrincipal);
//options.put("storeKey", "true");
//manually specify /tmp/krb5cc_ServiceUid for ticketCache
options.put("ticketCache", config.getCredentialCache().getAbsolutePath());
options.put("useTicketCache", "true");
options.put("renewTGT", "true");
return new AppConfigurationEntry[] {new AppConfigurationEntry(Krb5LoginModule.class.getName(), REQUIRED, options)};
}
});
loginContext.login();
Затем я использую приведенные ниже фрагменты кода, чтобы получить учетные данные:
String name = loginContext.getSubject().getPrincipals().iterator().next().getName();
serverCredential = doAs(loginContext.getSubject(), () -> gssManager.createCredential(
//gssManager.createName(config.getServiceName() "@" hostname, GSSName.NT_HOSTBASED_SERVICE),
gssManager.createName(name, GSSName.NT_HOSTBASED_SERVICE),
//INDEFINITE_LIFETIME,
DEFAULT_LIFETIME,
/*new Oid[] {
new Oid("1.2.840.113554.1.2.2"), // kerberos 5
new Oid("1.3.6.1.5.5.2") // spnego
},*/
new Oid("1.2.840.113554.1.2.2"),
ACCEPT_ONLY));
Есть ли что-то не так с приведенными выше фрагментами кода? Я также подтвердил, что /tmp/krb5cc_ServiceUid
это действительно существует.
Спасибо
Комментарии:
1. AFAIK Java имеет только частичную реализацию Kerberos. Он может считывать TGT из кеша билетов (если конфигурация JAAS позволяет это), но не может записывать в кеш — без обновления, без создания, без повторного создания. И он никогда не использует кеш для служебных билетов.
2. Для справки, я никогда не писал код для серверной части, и я всегда передавал параметры JAAS через файл conf (синтаксис своеобразный, но как только вы понимаете, что у вас может быть несколько именованных разделов с каждым из нескольких типов аутентификации, это становится довольно легко читать …)
3. Для справки, стек Hadoop имеет свою собственную реализацию Kerberos, которая основана на Java impl, но переопределяет ряд вещей — например, он позволяет обновлять существующий TGT в кэше, выполнив
kinit -R
команду :-04. Поскольку вы не упоминаете активацию трассировок отладки, обратите внимание, что
-Dsun.security.krb5.debug=true
и-Djava.security.debug=gssloginconfig,configfile,configparser,logincontext
создадут ОГРОМНЫЕ дампы в SdtErr / StdOut, но эти дампы могут помочь вам понять, какие параметры применяются, а какие молчаливо игнорируются (дух!)