Представим себе ситуацию, что есть некий сервер на базе Debian GNU/Linux, который уже введён в домен Active Directory с помощью SSSD и realmd и на нём уже имеется keytab-файл, который используется для механизмов аутентификации Kerberos и Single sign-on (SSO) при подключении к серверу по протоколу SSH. И вот возникает необходимость на данном Linux-сервере дополнительно настроить роль веб-сервера для служебных администраторских задач и организовать Kerberos SSO при подключении к веб-узлам этого веб-сервера. По ранее описанным примерам (здесь, здесь и здесь), предполагается, что для целей Kerberos-аутентификации веб-сервера Apache в домене Active Directory (AD) создаётся отдельная сервисная учётная запись типа User, для которой генерируется keytab-файл и в последствии привязывается к настройкам Apache на стороне Linux-сервера. С точки зрения аспектов безопасности такой поход (отдельный Linux-сервис = отдельная учётная запись в AD со своим keytab-файлом) можно считать вполне правильным. Но что, если Linux-сервис, использующий Kerberos-аутентификацию, используется не широким кругом пользователей, а исключительно для административных целей парой-тройкой системных администраторов? В таком случае создание отдельной учётной записи типа User в домене со своим keytab-файлом может показаться избыточным. В этой заметке мы рассмотрим пример того, как добавить дополнительную нужную нам запись servicePrincipalName (SPN) (на примере SPN-записи типа HTTP/) в уже имеющийся на Linux-сервере keytab-файл, ориентированный на сам хост (содержащий SPN-записи типа HOST/). В результате мы получим Kerberos аутентификацию на веб-узлах нашего Linux-сервера и при этом не будем плодить в домене лишние сервисные учётные записи типа User.
Изменение учётной записи компьютера в AD
Для начала нам необходимо обеспечить наличие всех нужных SPN-записей в свойствах учётной записи Linux-сервера (объект типа Computer) в домене AD. В нашем примере используется учётная запись компьютера kom-srv01.holding.com, который уже был ранее заведён в домен.
Посмотрим текущее состояние SPN-записей в каталоге AD для этого хоста на любом Windows-компьютере, входящем в домен (для просмотра SPN достаточно прав рядового пользователя домена) с помощью утилиты setspn:
setspn -L holding.com\kom-srv01
Зарегистрирован ServicePrincipalNames для CN=KOM-SRV01,OU=Servers,DC=holding,DC=com:
RestrictedKrbHost/KOM-SRV01.holding.com
RestrictedKrbHost/KOM-SRV01
HOST/KOM-SRV01.holding.com
HOST/KOM-SRV01
Как видим, в каталоге AD у учётной записи нашего Linux-сервера присутствуют только базовые SPN-записи типа HOST/ и RestrictedKrbHost/.
Зарегистрируем для этой учётной записи компьютера новую SPN-запись, которая будут содержать имя нужных нам дополнительной службы, например HTTP/kom-srv01.holding.com, следующим образом (для изменения SPN требуются права администратора домена):
setspn -A HTTP/kom-srv01.holding.com holding.com\kom-srv01
Проверка домена DC=holding,DC=com
Регистрация ServicePrincipalNames для CN=KOM-SRV01,OU=Servers,DC=holding,DC=com
HTTP/kom-srv01.holding.com
Обновленный объект
Снова проверим полный список зарегистрированных SPN-записей:
setspn -L holding.com\kom-srv01
Зарегистрирован ServicePrincipalNames для CN=KOM-SRV01,OU=Servers,DC=holding,DC=com:
HTTP/kom-srv01.holding.com
RestrictedKrbHost/KOM-SRV01.holding.com
RestrictedKrbHost/KOM-SRV01
HOST/KOM-SRV01.holding.com
HOST/KOM-SRV01
Порядок. Теперь можно переходить к правке keytab-файла на стороне Linux-сервера.
Правка keytab-файла на Linux-сервере
Войдём в режим работы с утилитой ktutil:
# ktutil
Выполним команду list, которая покажет, какими данными оперирует утилита (пока там пусто):
ktutil: list
slot KVNO Principal
---- ---- ---------------------------------------------------------------------
Выполним команду чтения содержимого из нашего keytab-файла (read_kt), который мы хотим использовать, как исходный. Следом выполним команду list с опциями -k (отображать ключи шифрования) и -e (отображать тип шифрования) (вывод утилиты усечён):
ktutil: read_kt /etc/apache2/krb5.keytab
ktutil: list -k -e
slot KVNO Principal
---- ---- ---------------------------------------------------------------------
1 3 KOM-SRV01$@HOLDING.COM (aes256-cts-hmac-sha1-96) (0xeaa481895ed765dc171329)
2 3 KOM-SRV01$@HOLDING.COM (aes128-cts-hmac-sha1-96) (0xb419907dea0e6d6610a)
3 3 KOM-SRV01$@HOLDING.COM (des3-cbc-sha1) (0xbf1bec79328e67310262aa9d0)
4 3 KOM-SRV01$@HOLDING.COM (arcfour-hmac) (0x205802fe6a42a245f9)
5 3 KOM-SRV01$@HOLDING.COM (des-cbc-md5) (0x22aadb38391fb)
6 3 KOM-SRV01$@HOLDING.COM (des-cbc-crc) (0x22aadb38391fb)
...
12 3 host/kom-srv01.holding.com@HOLDING.COM (des-cbc-crc) (0x22aadb38391fb)
...
18 3 HOST/KOM-SRV01@HOLDING.COM (des-cbc-crc) (0x22aadb38391fb)
...
24 3 HOST/KOM-SRV01.holding.com@HOLDING.COM (des-cbc-crc) (0x22aadb38391fb)
...
30 3 RestrictedKrbHost/KOM-SRV01@HOLDING.COM (des-cbc-crc) (0x22aadb38391fb)
...
36 3 RestrictedKrbHost/KOM-SRV01.holding.com@HOLDING.COM (des-cbc-crc) (0x22aadb38391fb)
Следующей командой add_entry добавим в массив данных, с которыми оперирует утилита, нужную нам дополнительную запись принципала Kerberos. При этом будем использовать ключи:
- key – используем ключ шифрования вместо пароля. Пароль учётной записи Linux-компьютера в AD нам неизвестен, а вот все нужные нам ключи шифрования для разных типов шифрования мы видим в результате вывода предыдущей команды;
- p – имя принципала Kerberos (SPN-запись в формате SERVICE/server.fqdn@DOMAIN.FQDN, которую мы хотим добавить в keytab-файл) по аналогии с тем, как оно отображается в результате вывода предыдущей команды;
- k - текущий номер KVNO (отображается в результате вывода предыдущей команды);
- e - тип шифрования по аналогии с тем, как он отображается в результате вывода предыдущей команды;
После ввода команды будет запрошен ключ шифрования в hex-формате. Используем значение, которое мы видим в результате вывода ранее выполненной команды (list -k -e) для соответствующего типа шифрования (последнее значение в скобках с отброшенной в начале значения частью 0x)
ktutil: add_entry -key -p HTTP/kom-srv01.holding.com@HOLDING.COM -k 3 -e aes256-cts-hmac-sha1-96
Key for HTTP/kom-srv01.holding.com@HOLDING.COM (hex): eaa481895ed765dc171329
Таким образом мы можем добавить аналогичные записи для всех необходимых типов шифрования по аналогии с записями типа HOST/:
ktutil: add_entry -key -p HTTP/kom-srv01.holding.com@HOLDING.COM -k 3 -e aes128-cts-hmac-sha1-96
Key for HTTP/kom-srv01.holding.com@HOLDING.COM (hex): b419907dea0e6d6610a
ktutil: add_entry -key -p HTTP/kom-srv01.holding.com@HOLDING.COM -k 3 -e des3-cbc-sha1
Key for HTTP/kom-srv01.holding.com@HOLDING.COM (hex): bf1bec79328e67310262aa9d0
ktutil: add_entry -key -p HTTP/kom-srv01.holding.com@HOLDING.COM -k 3 -e arcfour-hmac
Key for HTTP/kom-srv01.holding.com@HOLDING.COM (hex): 205802fe6a42a245f9
ktutil: add_entry -key -p HTTP/kom-srv01.holding.com@HOLDING.COM -k 3 -e des-cbc-md5
Key for HTTP/kom-srv01.holding.com@HOLDING.COM (hex): 22aadb38391fb
ktutil: add_entry -key -p HTTP/kom-srv01.holding.com@HOLDING.COM -k 3 -e des-cbc-crc
Key for HTTP/kom-srv01.holding.com@HOLDING.COM (hex): 22aadb38391fb
Проверим, что у нас получилось в конечном итоге (вывод утилиты усечён):
ktutil: list -k -e
slot KVNO Principal
---- ---- ---------------------------------------------------------------------
...
37 3 HTTP/kom-srv01.holding.com@HOLDING.COM (aes256-cts-hmac-sha1-96) (0xeaa481895ed765dc171329)
38 3 HTTP/kom-srv01.holding.com@HOLDING.COM (aes128-cts-hmac-sha1-96) (0xb419907dea0e6d6610a)
39 3 HTTP/kom-srv01.holding.com@HOLDING.COM (des3-cbc-sha1) (0xbf1bec79328e67310262aa9d0)
40 3 HTTP/kom-srv01.holding.com@HOLDING.COM (arcfour-hmac) (0x205802fe6a42a245f9)
41 3 HTTP/kom-srv01.holding.com@HOLDING.COM (des-cbc-md5) (0x22aadb38391fb)
42 3 HTTP/kom-srv01.holding.com@HOLDING.COM (des-cbc-crc) (0x22aadb38391fb)
По завершению добавления записей командой write_kt сохраняем получившийся массив данных в новый keytab-файл и выходим из интерактивного режима работы утилиты:
ktutil: write_kt /etc/apache2/krb5_refreshed.keytab
ktutil: exit
Таким образом мы получили keytab-файл, записи которого соответствуют SPN, зарегистрированным для учётной записи Linux-сервера в каталоге AD.
Осталось подключить обновлённый keytab-файл к конфигурации Apache и проверить результат. Пример настройки с использованием keytab-файла в конфигурации Apache мы уже рассматривали ранее в заметке Настройка Kerberos аутентификации с SSO на веб-сервере Apache с помощью SSSD, поэтому сразу перейдём к проверке результата.
Проверка Kerberos аутентификации с SSO на стороне клиента
Перейдём на клиентскую Windows-машину и с правами пользователя, имеющего доступ к только что настроенному веб-сайту Apache, обратимся к этому сайту через веб браузер. Но перед тем как открыть сайт, закроем клиентский браузер и очистим кэш билетов Kerberos командой:
klist purge
После этого откроем веб-сайт Apache с настроенной Kerberos аутентификацией и проверим то, как изменилось состояние кэша билетов на клиентской машине:
klist
...
#1> Клиент: petya @ HOLDING.COM
Сервер: HTTP/kom-srv01.holding.com @ HOLDING.COM
Тип шифрования KerbTicket: AES-256-CTS-HMAC-SHA1-96
флаги билета 0x40a10000 -> forwardable renewable pre_authent name_canonicalize
Время начала: 10/12/2017 20:34:24 (локально)
Время окончания: 10/13/2017 6:34:22 (локально)
Время продления: 10/19/2017 20:34:22 (локально)
Тип ключа сеанса: AES-256-CTS-HMAC-SHA1-96
Флаги кэша: 0
Вызванный центр распространения ключей: DC01.holding.com
...
Как видим, Kerberos-билет, связанный с веб-сервером на Linux, успешно получен.
Прекрасно!
Пара комментариев. Во-первых, на самом деле добавлять SPN типа HTTP для учётной записи сервера в AD при помощи setspn не обязательно. По умолчанию в AD SPN-записи типа HOST заменяют некоторые другие, включая HTTP. Т.е. когда клиент запрашивает у доменного контроллера билет для SPN вида "HTTP/server.domain", тот сначала ищет подходящий компьютер с именно такой SPN, но если не находит, то ищет компьютер с SPN "HOST/server.domain" и, в случае успеха, возвращает билет, зашифрованный ключом этой учётки (но билет будет выдан для "HTTP/server.domain", как клиент и запрашивал). При этом добавлять записи в keytab для SPN типа HTTP всё равно надо.
Во-вторых, по большому счёту, ничего не мешает засунуть в уже имеющийся keytab-файл записи для нового SPN, даже если в AD этот SPN принадлежит другой учётной записи - конечно, при этом сами ключи будут отличаться (ключи можно вытащить, например, при помощи ktpass). Но я не знаю, как в таком случае SSSD будет себя вести при обновлении пароля учётной записи компьютера.
С благодарностью воспользовался инструкцией, но в гораздо более простом виде. Как оказалось, достаточно воспользоваться SPN-конструкцией host/, которая доступна в keytab-файле после ввода сервера AD-домен. Этой SPN-записи хватило, чтобы успешно выдать тикет клиенту для доменной авторизации в СУБД Линтер.
При этом была важная заминка, не хватало прав на чтение keytab-файла у учетки, от которой был запущен сервис. После выдачи прав sudo chmod go+r /etc/krb5.keytab все заработало.