Невозможно пройти проверку подлинности с помощью Apache http client 4.5 с использованием кэша билетов Kerberos
Я выполняю запрос https для службы REST, прошедшей проверку подлинности Kerberos. Все хорошо, если я использую keytab. Тем не менее, у меня есть требование, чтобы я использовал файл кэша билетов Kerberos, который создается при входе на рабочую станцию с использованием его пароля.
Я заменю домен на MY_DOMAINE.COM
Итак, klist показывает:
Ticket cache: FILE:/tmp/krb5cc_210007
Default principal: dragomira@MY_DOMAINE.COM
Valid starting Expires Service principal
05/15/18 07:21:51 05/15/18 17:21:51 krbtgt/MY_DOMAINE.COM@MY_DOMAINE.COM
renew until 05/22/18 06:18:22
Использование curl работает нормально:
curl -k --negotiate -u : 'my_url' -v
Теперь вернемся к коду. Мой login.conf выглядит так:
com.sun.security.jgss.login {
com.sun.security.auth.module.Krb5LoginModule required
client=TRUE
doNotPrompt=true
useTicketCache=true;
};
com.sun.security.jgss.initiate {
com.sun.security.auth.module.Krb5LoginModule required
client=TRUE
doNotPrompt=true
useTicketCache=true;
};
com.sun.security.jgss.accept {
com.sun.security.auth.module.Krb5LoginModule required
client=TRUE
doNotPrompt=true
useTicketCache=true;
};
Соответствующий Java-код для моего http-клиента, который подходит для Kerberos:
try {
SSLContext sslContext = new SSLContextBuilder().loadTrustMaterial(null, (chain, authType) -> true).build();
HostnameVerifier hostnameVerifier = new NoopHostnameVerifier();
Registry<AuthSchemeProvider> authSchemeRegistry = RegistryBuilder.<AuthSchemeProvider>create()
.register(AuthSchemes.SPNEGO, new SPNegoSchemeFactory())
.build();
Credentials dummyCredentials = new NullCredentials();
CredentialsProvider credProv = new BasicCredentialsProvider();
credProv.setCredentials(new AuthScope(null, -1, null), dummyCredentials);
this.httpClient = HttpClientBuilder.create()
.setDefaultAuthSchemeRegistry(authSchemeRegistry)
.setDefaultCredentialsProvider(credProv)
.setSSLContext(sslContext)
.setSSLHostnameVerifier(hostnameVerifier)
.build();
} catch (NoSuchAlgorithmException | KeyStoreException | KeyManagementException e) {
throw new RuntimeException(e.getMessage(), e);
}
Перед этим я устанавливаю эти свойства java:
java.security.auth.login.config=/home/dragomira/kerberos/login.conf
java.security.krb5.conf=/etc/krb5.conf
sun.security.krb5.debug=true
javax.security.auth.useSubjectCredsOnly=false
Выходные данные журнала Kerberos:
Загружен из конфигурации Java
>>>KinitOptions cache name is /tmp/krb5cc_210007
>>>DEBUG <CCacheInputStream> client principal is dragomira@MY_DOMANIN.COM
>>>DEBUG <CCacheInputStream> server principal is krbtgt/MY_DOMANIN.COM@MY_DOMANIN.COM
>>>DEBUG <CCacheInputStream> key type: 18
>>>DEBUG <CCacheInputStream> auth time: Tue May 15 06:18:22 EDT 2018
>>>DEBUG <CCacheInputStream> start time: Tue May 15 07:21:51 EDT 2018
>>>DEBUG <CCacheInputStream> end time: Tue May 15 17:21:51 EDT 2018
>>>DEBUG <CCacheInputStream> renew_till time: Tue May 22 06:18:22 EDT 2018
>>> CCacheInputStream: readFlags() FORWARDABLE; RENEWABLE; INITIAL; PRE_AUTH;
>>>DEBUG <CCacheInputStream> client principal is dragomira@MY_DOMANIN.COM
>>>DEBUG <CCacheInputStream> server principal is HTTP/configuration.prd.int.MY_DOMANIN.COM@MY_DOMANIN.COM
>>>DEBUG <CCacheInputStream> key type: 23
>>>DEBUG <CCacheInputStream> auth time: Tue May 15 06:18:22 EDT 2018
>>>DEBUG <CCacheInputStream> start time: Tue May 15 07:57:49 EDT 2018
>>>DEBUG <CCacheInputStream> end time: Tue May 15 17:21:51 EDT 2018
>>>DEBUG <CCacheInputStream> renew_till time: Tue May 22 06:18:22 EDT 2018
>>> CCacheInputStream: readFlags() FORWARDABLE; RENEWABLE; PRE_AUTH;
>>> unsupported key type found the default TGT: 18
Так что мне кажется, что билет читается, но никакие учетные данные не извлекаются из него, так как я получаю в конце 401.
Должен ли я сделать что-то особенное для apache http client 4.5, чтобы использовать тикет?
С уважением
3 ответа
На основании ошибки: unsupported key type found the default TGT: 18
Тип 18 = aes-256-cts-hmac-sha1-96 (см. Параметры IANA Kerberos)
Я думаю, что вы используете JRE с ограниченной политикой JCE и должны установить неограниченную политику JCE.
На сайте загрузок Oracle для Oracle JRE. Проверьте в разделе "Дополнительные ресурсы" файлы политики неограниченной юрисдикции расширения криптографии Java (JCE) для JDK/JRE 8.
Смотри также: Oracle Java SE 8 technotes jgss
ПРИМЕЧАНИЕ. Инфраструктура JCE в JDK включает в себя возможность применения ограничений в отношении криптографических алгоритмов и максимальной криптографической силы, доступной для приложений. Такие ограничения указаны в "файлах политики юрисдикции". Файлы политики юрисдикции, связанные с Java SE, ограничивают максимальную длину ключа. Следовательно, чтобы использовать тип шифрования AES256, вам необходимо установить крипто-политику JCE с неограниченной версией, чтобы разрешить AES с 256-битным ключом.
Тестирование вашей политики ( источник):
jrunscript -e 'print (javax.crypto.Cipher.getMaxAllowedKeyLength("AES") >= 256);'
Начиная с 2018 года, Oracle JDK во всех поддерживаемых версиях начинает поставляться с политикой JCE неограниченной силы по умолчанию:
https://bugs.openjdk.java.net/browse/JDK-8189377
Также посмотрите эти интересные обходные пути с помощью отражения и возможную настройку переопределения для JRE9: /questions/38908746/kak-izbezhat-ustanovki-fajlov-politiki-jce-unlimited-strength-pri-razvertyivanii-prilozheniya/38908763#38908763
Ммм...
Принципал по умолчанию: dragomira@MY_DOMAINE.COM
Основным клиентом DEBUG является dragomira@MY_DOMANIN.COM
Domanín?
Я делаю то же самое в весенней загрузке приложения. Я могу сделать остальной вызов, используя билет кеша (users/conf/krb5_xyz) и аутентифицирован должным образом.
мой рабочий клиент:
public class Test {
public static void main(String[] args) {
Map<String, Object> loginOption = new HashMap<>();
loginOption.put("refreshKrb5Config","true");
loginOption.put("useTicketCache", "true");
loginOption.put("ticketCache","h:/config/krb5cc_xyz");
loginOption.put("doNotPrompt","true");
loginOption.put("debug","true");
/*
option 1 : using keytab
KerberosRestTemplate restTemplate = new KerberosRestTemplate("C:\\Users\\xyz\\kerberos\\kerberos\\src\\main\\resources\\xyz.keytab", "wdd@sd.sd.sd");*/
/* option 2: using cache */
KerberosRestTemplate restTemplate = new KerberosRestTemplate(null , "-",loginOption);
String response = restTemplate.getForObject("http://host:13080/xyz",String.class);
System.out.println("Result"+response);
}