Проблема решена.
Вот небольшое расследование.
Есть два сервера.
test-0001/apache,php/Centos 7.2 (нормально аутентифицирует по kerberos) и
test-0002/apache,php/OracleLinux 7.2 (сбой аутентификации kerberos).
Анализ протокола обмена HTTP показал, что «почему-то» web-клиент (IE, FF, Chrome) как один отличают компьютер
test-0002 от
test-0001. Отличие состоит в том, что ключ аутентификации, которые web-клиент отправляет в качестве авторизации пользователя ооочень сильно отличается «размером»:
Запрос к
test-0002 (сбой аутентификации по Kerberos):
Запрос к
test-0001 (аутентификация Kerberos выполняется нормально):
Давайте всё-таки выясним, почему ключ от
test-0002 короче
test-0001 ??? Начну с того, что формат ключа -
ASN.1 (если интересно, то гляньте
https://ru.wikipedia.org/wiki/ASN.1 ). В инете есть просмотрщик этого формата:
https://lapo.it/asn1js
Анализ ключа в запросе от
test-0002:
1. NEGOEX – насколько я понял именно этот формат обеспечивает «объединение» нескольких аутентификаторов одного и того же пользователя в разных протоколах. В данном ключе вложен только протокол NTLM
2. Данные для протокола NTLM (который не поддерживается компонентом apache mod_auth_gssapi).
Анализ ключа в запросе к
test-0001:
Как видим во втором ключе уже присутствует протокол Kerberos!!! Занятно! Т.е. проблема для
test-0002 не на стороне сервера, раз клиент сразу не отдаёт ему ключ правильного формата!
Хм. А давайте-ка посмотрим в журнал windows?
0x7 KDC_ERR_S_PRINCIPAL_UNKNOWN
0x19 KDC_ERR_PREAUTH_REQUIRED
Опаньки! Это что такое??? Какая-то проблема с принципалом? И почему только с
test-0002? (Записей, указывающих на другой компьютер, например,
test-0001 не найдено). Получается, что браузер до ответа на запрос серверу уже что-то «подозревает», раз не отдаёт ему нужный ключ (ОЧЕНЬ БОЛЬШАЯ ПРОСЬБА: ЕСЛИ КТО-ТО ПОНИМАЕТ ПРОЦЕСС, КАК БРАУЗЕР ПРИНИМАЕТ РЕШЕНИЕ КАК СОЗДАТЬ КЛЮЧ ДЛЯ АУТЕНТИФИКАЦИИ - РАССКАЖИТЕ МНЕ НЕМНОГО ОБ ЭТОМ!!!).
Если порыться в интернете, то вопросов по этой ошибке много (
https://www.google.ru/search?q=KDC_ERR_S_PRINCIPAL...), но в основном они без ответа. Тупик? Ничего подобного! Давайте глянем в документацию Microsoft по поводу SPN:
https://msdn.microsoft.com/en-us/library/ms677949%...
Т.е. spn моего сервиса должен быть зарегистрирован только в одном аккаунте. ЗАПОМНИМ ЭТО!!! И вот ещё один интересный момент:
https://msdn.microsoft.com/en-us/library/ms677601%...
Тут написано, что SPN должен быть уникальным. Если он не уникален, то аутентификация даст сбой.
А вот давайте проверим, а действительно ли SPN для сервера
test-0002 уникален? На просторах интернета нашёлся простой скрипт
powershell, который после небольшой модификации показывает интересующие нас SPN-ы:
social.technet.microsoft.com/wiki/contents/article...#Set Search
cls
$search = New-Object DirectoryServices.DirectorySearcher([ADSI]“”)
$search.filter = “(servicePrincipalName=HTTP/test-*)”
$results = $search.Findall()
#list results
foreach($result in $results)
{
$userEntry = $result.GetDirectoryEntry()
Write-host "Object Name = " $userEntry.name -backgroundcolor "yellow" -foregroundcolor "black"
Write-host "DN = " $userEntry.distinguishedName
Write-host "Object Cat. = " $userEntry.objectCategory
Write-host "servicePrincipalNames"
$i=1
foreach($SPN in $userEntry.servicePrincipalName)
{
Write-host "SPN(" $i ") = " $SPN $i+=1
}
Write-host ""
}
Результат:
WTF???
ПОЧЕМУ В ДВУХ РАЗНЫХ АККАУНТАХ ОДИН И ТОТ ЖЕ SPN??? (Помните, чуть выше я просил запомнить правило, что spn должен быть уникален и присвоен только одному аккаунту?) Или может быть я что-то неправильно понял? Пойдём дальше и давайте посмотрим атрибуты для учёток
test-0002 и
test-0001, но не через оснастку AD, а через оснастку ADSI:
test-0002 – OK.
А вот для
test-0001 нас ждёт СЮРПРИЗ (удивительно, что сюрприз связан с аккаунтом сервера на котором ВСЁ РАБОТАЕТ!!!):
Так, так!!! Оказывается, что spn для сервера
test-0002 имеется в AD в двух экземплярах – в учётке
test-0002_httpd и в учётке
test-0001_httpd ! Чего по документации быть
не должно! Вот это и был корень проблемы! Дубликат SPN.
После удаления дубликата всё заработало!!!
Всем спасибо за внимание.)))
P.S.
Рекомендация для заведения SPN. Нужно использовать команду
setspn -S, а не
servspn -A, т.к.
setspn -S проверяет наличие дубликатов. Очень рекомендую к прочтению статью
https://social.technet.microsoft.com/wiki/contents....