Как получить возобновляемые билеты Kerberos, используя Java GSS+JAAS
Я использую jTDS для подключения к SQLServer. Внутренне jTDS использует GSS, чтобы получить билет службы Kerberos и установить безопасный контекст. Поскольку мое приложение является долгоживущим, а мои соединения поддерживаются все время, мне нужно, чтобы этот билет службы Kerberos был возобновляемым, чтобы позволить SQL-серверу обновлять их самостоятельно (политики kdc настроены на истечение срока действия всех билетов через 12 часов).
JTDS делает для получения токена Kerberos (более или менее) следующее:
GSSManager manager = GSSManager.getInstance();
// Oids for Kerberos5
Oid mech = new Oid("1.2.840.113554.1.2.2");
Oid nameType = new Oid("1.2.840.113554.1.2.2.1");
// Canonicalize hostname to create SPN like MIT Kerberos does
GSSName serverName = manager.createName("MSSQLSvc/" + host + ":" + port, nameType);
GSSContext gssContext = manager.createContext(serverName, mech, null, GSSContext.DEFAULT_LIFETIME);
gssContext.requestMutualAuth(false);
gssContext.requestCredDeleg(true);
byte[] ticket = gssContext.initSecContext(new byte[0], 0, 0);
Я подозреваю, что полученный мной билет не подлежит продлению. Я проверяю это, делая что-то вроде следующего:
ExtendedGSSContext extendedContext = (ExtendedGSSContext) gssContext;
boolean[] flags = (boolean[]) extendedContext.inquireSecContext(InquireType.KRB5_GET_TKT_FLAGS);
System.out.println("Renewable = " + flags[8]);
В нашей конкретной конфигурации GSS получает kerberos TGT из модуля входа в систему JAAS. У нас есть следующая переменная, установленная в false -Djavax.security.auth.useSubjectCredsOnly=false
и в файле login.cfg у нас настроен следующий модуль входа в систему:
com.sun.security.jgss.krb5.initiate {
com.sun.security.auth.module.Krb5LoginModule required
useKeytTab=true
keyTab="/home/batman/.batman.ktab"
principal="batman@GOTHAMCITY.INT"
storeKey=true
doNotPrompt=true
debug=false
};
Еще я замечаю, что getLifetime()
метод GSSContext
не похоже на работу. Он всегда возвращает 2147483647 (max int) независимо от того, каков реальный срок действия билета.
Я чувствую себя комфортно с разветвленным драйвером jTDS, поэтому я могу изменить способ, которым он устанавливает контекст GSS, если это необходимо.
Что я пробовал:
Используйте нативную реализацию GSS API:
Для меня это работает нормально с точки зрения получения возобновляемых билетов, но это налагает другой набор проблем (с точки зрения обеспечения того, что кэш билетов установлен правильно и билеты там обновляются должным образом). Если бы я мог обойти эту опцию, было бы хорошо. Однажды я заметил, что getLifetime()
Метод на самом деле возвращает реальное время жизни в секундах от билета.
Переопределение KerberosLoginModule:
Основываясь на ответе на этот вопрос, Jaas - запрос возобновляемых билетов Kerberos, я переопределил LoginModule, чтобы установить RENEW. KDCOption
в KrbAsReqBuilder
перед запросом TGT. Это прекрасно работает в том смысле, что я получаю возобновляемую TGT, но билет, полученный от этой TGT GSS, все еще не возобновляем. Если я установлю точку останова в конструкторе объекта KDCOption и установлю флаг RENEW вручную для каждого запроса (даже KrbTgsReq
сделано GSS), это работает, но для того, чтобы это изменение было продуктивным, требуется серьезное переписывание GSS, с которым я не чувствую себя комфортно.
1 ответ
Для администраторов тот факт, что билеты Kerberos имеют срок службы, является важной функцией безопасности. Пользователь знает пароль, поэтому он может получить новый билет в любой момент. Но для злоумышленника это проблема - после истечения срока действия билета его нельзя использовать для взлома системы. Администраторы хотят, чтобы это время жизни было как можно короче, но не слишком коротким (например, 1 час), потому что пользователи будут генерировать в 10 раз больше запросов на вход, чем сейчас, и ActiveDirectory будет трудно обрабатывать.
Когда нам нужно пройти аутентификацию в Kerberos, мы должны использовать пул соединений (и DataSource). Чтобы использовать эту функцию в jTDS, вам нужно добавить ConnectionPoolImplementation (рекомендуется: DBCP или c3p0, см.: http://jtds.sourceforge.net/features.html).
Если вы хотите написать свое приложение, используя более старый способ подключения к базе данных (без источника данных, то есть создать соединение и поддерживать его живым, потому что создавать его дорого...), тогда следующим препятствием будет "продление срока службы". В ActiveDirectory билеты Kerberos по умолчанию могут быть обновлены в течение 7 дней. В AD есть глобальная настройка, которая позволяет установить 0 (неограниченное время продления), но вам нужно убедить Администратора домена снизить безопасность всего домена только потому, что без этого не будет работать ни одна служба.