Как правильно сформировать keytab-файл с несколькими принципалами сервисов в среде Active Directory

Левинца Егор

Обсуждение статьи на форуме проекта Pro-LDAP.ru.

Предпосылки и исходные данные

Имеется настроенный домен Active Directory windom.net. Требуется настроить веб-сервер араche2 на сервере с Ubuntu так, чтобы он обслуживал два виртуальных хоста, — windom.net (он же www.windom.net) и sandbox.windom.net, — в которых пользователи проходили бы Kerberos-аутентификацию в Active Directory. Примерная DNS-зона:

windom.net      A      10.10.0.3  # Корень домена, A-запись указывает на ip-адрес веб-сервера
|
|\ gate         A      10.10.0.1  # Шлюз 
|\ ads          A      10.10.0.2  # Контроллер домена на MS Windows 2003 R2
|\ webserver    A      10.10.0.3  # Веб-сервер на Ubuntu 14.04, apache-2.4.7, mod_auth_kerb-5.4.1
|\ www          CNAME  webserver  # Ссылка на webserver для VitrualHost apache2, общий портал
 \ sandbox      CNAME  webserver  # Ссылка на webserver для VitrualHost apache2, ресурс для разработчиков

С одной стороны, подобная конфигурация уже много раз хорошо документирована в Интернет и нет смысла повторяться. С другой стороны, для работы mod_auth_kerb требуется keytab-файл с принципалами сервисов apache2. Сначала мне казалось, что там должны быть такие принципалы:

HTTP/windom.net@WINDOM.NET
HTTP/www.windom.net@WINDOM.NET
HTTP/sandbox.windom.net@WINDOM.NET
HTTP/webserver.windom.net@WINDOM.NET

Но на самом деле, как выяснилось опытным путём, оказалось достаточно двух (что, в общем-то, логично, учитывая работу протокола HTTP):

HTTP/windom.net@WINDOM.NET
HTTP/webserver.windom.net@WINDOM.NET

Кстати, это даёт некоторый бонус: виртуальные хосты, сколько бы их ни было, имена которых организуются CNAME-записями DNS, указывающими на основной веб-сервер, не нуждаются в дополнительных именах сервисных принципалов.

Итак, задача: сформировать в среде Active Directory рабочий keytab-файл с несколькими принципалами сервисов для его использования в apache2.

Совсем чуть-чуть теории

Что мы знаем о keytab-файлах? В Kerberos keytab (от "key table", "таблица ключей") — способ хранения долговременных ключей для одного или нескольких принципалов. Чаще всего таблицы ключей хранятся в виде файлов стандартизированного формата (те самые keytab-файлы). Таблица ключей может включать в себя одну или несколько записей, каждая из которых состоит из отметки времени (когда запись была добавлена в keytab), имени принципала, номера версии ключа (key version number или KVNO), типа шифрования и собственно зашифрованного ключа. Кроме всего прочего, этот ключ будет использоваться для аутентификации принципала в базе данных безопасности KDC. KVNO — целое положительное число, дополнительный критерий защиты: если в keytab несколько записей для одного и того же принципала с разным KVNO, валидной будет считаться та запись, KVNO которой совпадает с текущим KVNO этого принципала в базе данных безопасности KDC (обычно запись с наибольшим KVNO).

В среде Active Directory база данных безопасности KDC — это LDAP-каталог. Проверка валидности принципалов (пользователей и сервисов) происходит на основании паролей учётных записей пользователей или компьютеров, к которым "привязаны" эти принципалы. Имена принципалов пользователей хранятся в атрибуте userPrincipalName, принципалов сервисов — в атрибуте servicePrincipalName. У каждой учётной записи есть KVNO (хранится в атрибуте msDS-KeyVersionNumber). При смене пароля учётной записи KVNO увеличивается на единицу и все keytab-записи с принципалом, привязанным к этой учётной записи, и меньшим KVNO становятся невалидными, даже если пароли совпадают.

Следовательно, нам нужно создать учётную запись в LDAP-каталоге Active Directory, установить ей пароль (известный нам), привязать к этой учётной записи необходимые имена принципалов сервисов и сформировать keytab-файл с этими принципалами и ключами, основанными на известном нам пароле учётной записи.

Остальная теория — по мере выполнения.

Как сделать

Шаг 1. Создание учётной записи

Первая дилемма, с которой сталкиваются администраторы — какую учётную запись заводить: пользователя или компьютера. Обычно заводят учётную запись пользователя на том основании, что там легко задаётся пароль. Мне это кажется не совсем верным, поскольку сервисы работают на компьютерах и логичнее завести для этих целей учётку компьютера. Тем более учётки компьютеров не устаревают никогда. Но если вы всё же решили использовать учётку пользователя, принципиального значения это не имеет, просто скорректируйте команду создания учётной записи под себя.

Второй вопрос при создании учётки компьютера — стоит ли использовать уже имеющуюся учётку, если Ваш сервер является членом домена? В моём случае на том же Ubuntu-сервере работает samba и учётная запись компьютера webserver создалась в Active Directory автоматически при вводе сервера в домен. Я считаю — не стоит, на том основании, что члены домена периодически (по умолчанию раз в 30 дней) меняют пароль своей учётной записи, поэтому keytab-файл (если он не связан с keytab-файлом samba) придётся переделывать. В общем, я решил завести новую учётную запись компьютера и назвать её www.

Наконец, как лучше создавать учётную запись компьютера: графическими средствами (ADUC) или из командной строки? Это дело вкуса. Единственный момент: при создании учётки из командной строки пароль ей не назначается и KVNO будет равен 1, а при создании из оснастки ADUC учётной записи сразу назначается некий "стандартный" пароль, и KVNO у неё будет 2. Это необходимо будет учитывать при выполнении последующих шагов.

Итак, создадим учётную запись компьютера www:

C:\Program Files\Support Tools>dsadd computer "CN=www,CN=Computers,DC=windom,DC=net"
dsadd успешно:CN=www,CN=Computers,DC=windom,DC=net

Проверим интересующие нас атрибуты учётной записи:

C:\Program Files\Support Tools>ldifde -d "CN=www,CN=Computers,DC=windom,DC=net" -l "userPrincipalName,servicePrincipalName,msDS-KeyVersionNumber"  -f c:\tmp\account.ldif
...
C:\Program Files\Support Tools>type c:\tmp\account.ldif

dn: CN=www,CN=Computers,DC=windom,DC=net
changetype: add
msDS-KeyVersionNumber: 1

Наша учётная запись создана без пароля (KVNO=1), имена принципалов пользователя и сервиса не назначены.

Шаг 2. Назначение учётной записи имён принципалов сервисов.

Если честно, этот шаг необязательный, поскольку применяемая на следующих двух шагах утилита ktpass так или иначе "привязывает" имя принципала сервиса к учётной записи. Но раз уж мы решили сделать всё правильно, то выполним привязку явно. Это делается с помощью утилиты setspn. Первые две команды назначают учётной записи компьютера требуемые нам имена принципалов сервиса, третья — выводит список назначенных учётной записи принципалов:

C:\Program Files\Support Tools>setspn -A HTTP/windom.net@WIMDOM.NET www
Registering ServicePrincipalNames for CN=www,CN=Computers,DC=windom,DC=net
        HTTP/windom.net@WIMDOM.NET
Updated object

C:\Program Files\Support Tools>setspn -A HTTP/webserver.windom.net@WIMDOM.NET www
Registering ServicePrincipalNames for CN=www,CN=Computers,DC=windom,DC=net
        HTTP/webserver.windom.net@WIMDOM.NET
Updated object

C:\Program Files\Support Tools>setspn -L www
Registered ServicePrincipalNames for CN=www,CN=Computers,DC=windom,DC=net:
    HTTP/webserver.windom.net@WIMDOM.NET
    HTTP/windom.net@WIMDOM.NET

Проверим интересующие нас атрибуты учётной записи:

C:\Program Files\Support Tools>ldifde -d "CN=www,CN=Computers,DC=windom,DC=net" -l "userPrincipalName,servicePrincipalName,msDS-KeyVersionNumber"  -f c:\tmp\account.ldif
...
C:\Program Files\Support Tools>type c:\tmp\account.ldif

dn: CN=www,CN=Computers,DC=windom,DC=net
changetype: add
servicePrincipalName: HTTP/webserver.windom.net@WIMDOM.NET
servicePrincipalName: HTTP/windom.net@WIMDOM.NET
msDS-KeyVersionNumber: 1

Пароля всё ещё нет (KVNO=1), имя принципала пользователя не назначено, но есть два имени принципалов сервиса.

Шаг 3. Задание пароля учётной записи, задание имени принципала пользователя и формирование keytab-файла для первого принципала сервиса.

Здесь в игру вступает супер-инструмент Microsoft: утилита ktpass. Она делает всё и сразу, поэтому пользоваться ей необходимо осторожно, иначе есть шанс всё испортить и придётся удалять учётку и начинать заново. Если Вы ещё не сталкивались с этой утилитой, лучше сразу посмотреть официальное руководство, чтобы представлять, о чём пойдёт речь далее.

Основной функционал ktpass:

Как видите, функционал богатый и чёткого описания как всё это должно работать, нет. Поэтому ещё раз предупреждаю: будьте внимательны и осторожны, перед выполнением команды Вы должны чётко понимать, что собираетесь сделать.

Стоит обратить внимание на то, как именно задаются аргументы при вызове ktpass. Некоторые из них могут задаваться с указанием знаков "-" или "/", например -out и /out — это одно и то же. Другие же аргументы задаются с указанием знаков "-" или "+", и это уже далеко не одно и то же. Например, -answer и +answer задают режим интерактивности работы утилиты: в первом случае при возникновении вопроса она будет ждать ответа от пользователя, во втором — самостоятельно положительно отвечать на возникающие вопросы. Чтобы не путаться, в примерах ниже "простые" аргументы я всегда указываю со знаком "/", а "альтернативные" — с требуемым по ситуации знаком.

Итак, нам нужно задать пароль учётной записи компьютера и сформировать keytab-файл для первого принципала сервиса. При этом (по умолчанию) имя принципала сервиса будет привязано к учётной записи, а также задано в качестве имени принципала пользователя этой учётной записи. Выполним команду:

C:\Program Files\Support Tools>ktpass /mapuser WINDOM\www$ /princ HTTP/windom.net@WIMDOM.NET /ptype KRB5_NT_SRV_HST /pass XXXXXXXXX /out c:\tmp\a1.keytab +answer
Targeting domain controller: ADS.windom.net
Using legacy password setting method
Successfully mapped HTTP/windom.net to WWW$.
WARNING: Account WWW$ is not a user account (uacflags=0x1021).
WARNING: Resetting WWW$'s password may cause authentication problems if WWW$ is being used as a server.

Reset WWW$'s password [y/n]?  auto: YES
Key created.
Output keytab to c:\tmp\a1.keytab:
Keytab version: 0x502
keysize 61 HTTP/windom.net@WIMDOM.NET ptype 3 (KRB5_NT_SRV_HST) vno 2 etype 0x17 (RC4-HMAC) keylength 16 (0xaa00bb11cc22dd33aa44bb55cc66dd77)

Подробнее остановимся на переданных аргументах. В аргументе /mapuser WINDOM\www$ указывается имя учётной записи, к которой будет привязываться принципал сервиса. В аргументе /princ HTTP/windom.net@WIMDOM.NET указывается имя принципала сервиса, который мы собираемся привязывать, и для которого будет сформирована keytab-запись. В аргументе /ptype KRB5_NT_SRV_HST указывается тип принципала. Я посчитал, что из возможных вариантов для учётки компьютера тип KRB5_NT_SRV_HST наиболее уместен, к тому же ktpass не ругается на несоответствие типов принципала, как было в случае указания универсального и рекомендуемого типа KRB5_NT_PRINCIPAL. В аргументе /pass задаётся пароль сразу и для учётной записи компьютера, и для формирования ключа в keytab-записи с использованием нужного алгоритма шифрования. Кстати об алгоритмах шифрования: в MS Windows Server 2003 R2 их немного, поэтому я не стал задавать аргумент /crypto, и ktpass выбрал единственно приемлемый вариант RC4-HMAC (по умолчанию). В MS Windows Server 2008 R2 алгоритмов побольше, есть из чего выбрать, или вообще передать значение /crypto ALL (в 2003-м сервере не поддерживается). Вернёмся к нашим паролям. Поскольку у нас два принципала сервиса в одной учётке, пароль для них нужно указывать один и тот же, поэтому использовать аргумент +rndpass (генерация случайного пароля) нельзя. В аргументе /out c:\tmp\a1.keytab указан keytab-файл (промежуточный), куда мы будем выводить информацию по keytab-записи первого принципала сервиса. Наконец, аргумент +answer говорит о том, что на все возникающие вопросы нужно отвечать утвердительно.

Коротко о выводе команды. Сначала ktpass сообщил нам об успешной привязке принципала сервиса к учётной записи. Затем предупредил о том, что смена пароля учётной записи компьютера может привести к выбрасыванию компьютера из домена и попросил подтвердить это действие. Благодаря аргументу +answer автоматически получил утвердительный ответ и (ВНИМАНИЕ!) поменял пароль учётной записи (в нашем случае — задал его). Затем он сформировал ключ принципала сервиса и вывел keytab-запись в указанный keytab-файл. Последняя строка вывода даёт нам представление о содержимом keytab-записи, оно соответствует переданным аргументам. Обратите внимание на подстроку vno 2, она говорит о том, что в keytab-записи используется KVNO=2 (номер повысился при смене пароля учётной записи). Да, хотя явно об этом не говорится, было задано имя принципала пользователя учётной записи (совпадает с переданным именем принципала сервиса).

Проверим интересующие нас атрибуты учётной записи:

C:\Program Files\Support Tools>ldifde -d "CN=www,CN=Computers,DC=windom,DC=net" -l "userPrincipalName,servicePrincipalName,msDS-KeyVersionNumber"  -f c:\tmp\account.ldif
...
C:\Program Files\Support Tools>type c:\tmp\account.ldif

dn: CN=www,CN=Computers,DC=windom,DC=net
changetype: add
userPrincipalName: HTTP/windom.net@WIMDOM.NET
servicePrincipalName: HTTP/windom.net
servicePrincipalName: HTTP/webserver.windom.net@WIMDOM.NET
servicePrincipalName: HTTP/windom.net@WIMDOM.NET
msDS-KeyVersionNumber: 2

Пароль установлен (KVNO=2), имя принципала пользователя назначено, добавлено ещё одно имя принципала сервиса.

Шаг 4. Формирование keytab-файла для двух принципалов сервиса.

На этом этапе нам нужно создать keytab-запись для второго принципала сервиса с ключом на основе того же пароля, импортировать keytab-запись первого принципала сервиса из промежуточного keytab-файла, созданного на предыдущем шаге, и записать обе keytab-записи в итоговый keytab-файл. При этом нам нельзя менять пароль самой учётной записи компьютера, поскольку KVNO этой учётки повысится и keytab-запись, созданная на предыдущем этапе, перестанет быть валидной. Выполним команду:

C:\Program Files\Support Tools>ktpass /mapuser WINDOM\www$ /princ HTTP/webserver.windom.net@WIMDOM.NET /ptype KRB5_NT_SRV_HST /pass XXXXXXXXX -setpass /kvno 2 /in c:\tmp\a1.keytab /out c:\tmp\apache2.keytab -setupn
Existing keytab:

Keytab version: 0x502
keysize 61 HTTP/windom.net@WIMDOM.NET ptype 3 (KRB5_NT_SRV_HST) vno 2 etype 0x17 (RC4-HMAC) keylength 16 (0xaa00bb11cc22dd33aa44bb55cc66dd77)
Targeting domain controller: ADS.windom.net
Using legacy password setting method
Successfully mapped HTTP/webserver.windom.net to WWW$.
Key created.
Output keytab to c:\tmp\apache2.keytab:
Keytab version: 0x502
keysize 61 HTTP/windom.net@WIMDOM.NET ptype 3 (KRB5_NT_SRV_HST) vno 2 etype 0x17 (RC4-HMAC) keylength 16 (0xaa00bb11cc22dd33aa44bb55cc66dd77)
keysize 71 HTTP/webserver.windom.net@WIMDOM.NET ptype 3 (KRB5_NT_SRV_HST) vno 2 etype 0x17 (RC4-HMAC) keylength 16 (0xaa00bb11cc22dd33aa44bb55cc66dd77)

Аргументы /mapuser, /princ и /ptype имеют тот же смысл, что и на предыдущем шаге. Пароль в аргументе /pass, очевидно, должен совпадать с паролем учётной записи компьютера, поэтому мы задаём его таким же, как и на предыдущем шаге. Важнейший момент: чтобы не повышать KVNO, нам нельзя переназначать пароль самой учётной записи компьютера, за это отвечает аргумент -setpass. Таким образом, пароль из аргумента /pass будет использован только для создания keytab-записи. Из-за того, что пароль учётки не менялся, ktpass (по крайней мере в MS Windows Server 2003 R2) теряется — какой KVNO нужно назначить keytab-записи? Аргументом /kvno 2 мы явно указываем ему номер KVNO. В аргументе /in c:\tmp\a1.keytab мы указываем файл, из которого необходимо импортировать уже имеющиеся keytab-записи (промежуточный keytab-файл, созданный на предыдущем шаге). В аргументе /out c:\tmp\apache2.keytab указывается имя итогового keytab-файла, куда будут записаны импортированная и вновь сформированная keytab-записи. Наконец, аргументом -setupn мы указываем, что переназначать имя принципала пользователя учётной записи компьютера не требуется.

Теперь рассмотрим вывод команды. Первым делом ktpass показал нам содержимое импортированной из промежуточного файла keytab-записи. Затем сообщил об успешной привязке принципала сервиса к учётной записи. Затем он сформировал ключ принципала сервиса и вывел две keytab-записи в указанный keytab-файл. Обратите внимание, что KVNO двух keytab-записей совпадает (vno 2).

Проверим интересующие нас атрибуты учётной записи:

C:\Program Files\Support Tools>ldifde -d "CN=www,CN=Computers,DC=windom,DC=net" -l "userPrincipalName,servicePrincipalName,msDS-KeyVersionNumber"  -f c:\tmp\account.ldif
...
C:\Program Files\Support Tools>type c:\tmp\account.ldif

dn: CN=www,CN=Computers,DC=windom,DC=net
changetype: add
userPrincipalName: HTTP/windom.net@WIMDOM.NET
servicePrincipalName: HTTP/webserver.windom.net
servicePrincipalName: HTTP/windom.net
servicePrincipalName: HTTP/webserver.windom.net@WIMDOM.NET
servicePrincipalName: HTTP/windom.net@WIMDOM.NET
msDS-KeyVersionNumber: 2

Пароль учётной записи не изменился (KVNO=2), имя принципала пользователя не изменилось, добавлено ещё одно имя принципала сервиса.

Собственно всё, задача решена: правильный keytab-файл для двух принципалов сервиса сформирован. Осталось передать его в нужное место, ограничить права доступа и тестировать работу аутентификации apache2.

И ещё один небольшой бонус напоследок, пока мы не покинули Windows-сервер: утилита ktpass — это единственный известный мне инструмент, с помощью которого можно легально (не прибегая к ухищрениям c LDAP-каталогом) сменить пароль учётной записи компьютера. Для этого нужно просто "попытаться" привязать к ней неверно сформированное имя принципала сервиса. ktpass выдаст ошибку, но пароль всё равно сменит. Пример:

C:\Program Files\Support Tools>ktpass /mapuser WINDOM\somepc$ /princ imposible@WIMDOM.NET /pass XXXXXXXXX -setupn +answer
Targeting domain controller: ADS.windom.net
Using legacy password setting method
Failed to set property "servicePrincipalName" to "imposible" on Dn "CN=somepc,CN=Computers,DC=windom,DC=net": 0x13.
WARNING: Unable to set SPN mapping data.
  If SOMEPC$ already has SPN mapping installed for  imposible, this is no cause for concern.
WARNING: Account SOMEPC$ is not a user account (uacflags=0x1021).
WARNING: Resetting SOMEPC$'s password may cause authentication problems if SOMEPC$ is being used as a server.

Reset SOMEPC$'s password [y/n]?  auto: YES
WARNING: pType and account type do not match. This might cause  problems.
Key created.

Ссылки

Материалы, которые помогли мне разобраться в теме:

Последнее изменение страницы — 20 апреля 2016 года.

Обсуждение статьи на форуме проекта Pro-LDAP.ru.

Эта страница

Содержание

Предпосылки и исходные данныеСовсем чуть-чуть теорииКак сделатьСсылки
Как правильно сформировать keytab-файл с несколькими принципалами сервисов в среде Active Directory
OpenLDAP 2.4 Руководство

Содержание

Введение в службы каталогов OpenLDAPБыстрое развёртывание и начало работыОбщая картина - варианты конфигурацииСборка и установка OpenLDAPНастройка slapd

 

Конфигурационный файл slapdЗапуск slapdКонтроль доступаОграниченияИнструментыМеханизмы манипуляции даннымиНаложенияСпецификация схемы

 

БезопасностьSASLTLSРаспределённая служба каталоговРепликацияОбслуживаниеМониторингПроизводительностьУстранение неполадок
Перевод официального руководства OpenLDAP 2.4 Admin Guide
Полное содержание здесь
LDAP для учёных-ракетчиков

Содержание

О книгеКонцепции LDAPОбъекты LDAPУстановка LDAPПримерыНастройкаРепликация и отсылкиLDIF и DSMLПротоколLDAP API

 

HOWTOНеполадкиПроизводительностьИнструменты LDAPБезопасностьЗаметкиРесурсы LDAPRFC и X.500ГлоссарийОбъекты
Перевод "LDAP for Rocket Scientists"
Полное содержание здесь
Ресурсы

Книги

Руководство OpenLDAP 2.4LDAP для учёных-ракетчиков

Другие

СтатьиТермины LDAPman-страницы OpenLDAP 2.4Список RFCКлиенты LDAPФайлы наборов схемы
Полезные ресурсы
Форум

 

Разделы форумаНепрочитанные сообщенияПоследние сообщения
Форум проекта
Главная

Pro-LDAP.ru

О проектеНовости проектаУчастникиСтаньте участником!Сообщите об ошибке!Об авторских правахСоглашения проекта
Присоединяйсь!