Сквозная аутентификация в Linux: настройка Kerberos, интеграция с браузером и автоматизация через Keytab

от автора

Введение

Масштабный переход на отечественные ИТ-решения ставит перед системными инженерами и разработчиками задачу глубокого освоения базовых механизмов корпоративной безопасности. В основе современных российских экосистем управления инфраструктурой (таких как ALD Pro на базе Astra Linux) лежит программный комплекс FreeIPA. Главным фундаментом доверия, централизованной авторизации и безопасности в этой экосистеме выступает протокол Kerberos. Его корректное понимание и настройка определяют стабильность работы всех смежных сервисов — от сетевых папок до сложных корпоративных веб-приложений.

В этой статье детально разберем «анатомию» Kerberos в среде Linux и покажем, как заставить этот протокол эффективно работать на стыке системного администрирования и веб-разработки. Пройдем полный практический путь, разделенный на несколько логических этапов:

  • Разберем структуру и параметры подсистемы /etc/krb5.conf, а также научимся управлять Kerberos-флагами и жизненным циклом билетов.

  • Освоим диагностику доменной среды с помощью инструментов kinit, klist и утилит манипуляции таблицами ключей (Keytab).

  • Реализуем логику автономного извлечения мандатов (credentials) и получения билетов на языке JavaScript без использования внешних системных утилит.

  • В качестве практической базы задействуем готовый контроллер домена, оставшийся от прошлых экспериментов с политиками ALD Pro. На его примере разберем типичные проблемы интеграции, включая рассинхронизацию номеров версий ключей (KVNO) и ошибки DNS-резолвинга.

Финальным этапом станет развертывание отечественного решения КриптоАРМ ID в связке с ALD Pro. Настроим сквозную аутентификацию (Single Sign-On) через механизм SPNEGO/Negotiate, что позволит полностью автоматизировать работу в доменной среде, а также развернем встроенный модуль OAuth/OIDC для бесшовного «проваливания» сотрудников во внешние корпоративные приложения.

Содержание

Теоретический минимум: как работает Kerberos

Kerberos — это сетевой протокол аутентификации, предназначенный для обеспечения надежной защиты в открытых сетях. Если говорить просто, это система, которая позволяет подтвердить личность пользователя, не передавая его пароль в открытом (или даже зашифрованном) виде по сети.

В основе Kerberos лежит концепция доверенной третьей стороны. Чтобы клиент (пользователь) и сервер (служба) могли доверять друг другу, им нужен посредник, который поручится за каждого. Эту роль выполняет Центр распределения ключей (KDC — Key Distribution Center).

Процесс инициализации доступа можно разделить на три ключевых шага:

1.     Запрос на «пропуск»: когда вы входите в систему, клиент отправляет запрос в KDC. На этом этапе сервер еще не знает, действительно ли вы тот, за кого себя выдаете, поэтому он готовит для вас «пакет доверия» — TGT (Ticket Granting Ticket) или Билет на получение билетов.

2.     Защита паролем: KDC не требует от вас прислать пароль. Вместо этого он берет ваш пароль (точнее, его хэш) из своей базы данных и использует его как замок (ключ шифрования) для этого пакета. Только тот, кто знает правильный пароль, сможет «открыть» ответ от сервера.

3.     Локальная проверка: получив зашифрованный TGT, клиентская машина пытается расшифровать его с помощью пароля, который вы ввели при логине. Если пароль верный — пакет открывается, и клиент получает валидный билет TGT. Если пароль неверный — расшифровка превращается в «мусор», и аутентификация проваливается.

Ваш пароль никогда не покидает ваш компьютер. Он используется только локально для вскрытия замка, который повесил сервер. Успешно расшифрованный TGT становится вашим цифровым паспортом: теперь вы можете предъявлять его системе, чтобы получать доступ к почте, файловым серверам или базам данных, не вводя пароль повторно.

Формализовано процесс аутентификации по протоколу Kerberos V5 представляется в следующем виде (рис. 1):

1. Обмен с сервером аутентификации (AS Exchange)

Все начинается с того, что пользователь вводит логин и пароль. Клиентское ПО преобразует пароль в секретный ключ (хэш).

  • Запрос: Клиент отправляет запрос на аутентификацию (Message 0) к AS.

  • Проверка: AS ищет пользователя в базе данных. Если он найден, сервер генерирует ответ из двух частей:

    • Message 1: Зашифровано секретным ключом пользователя. Содержит сессионный ключ «Клиент-TGS».

    • Message 2 (TGT): Зашифровано ключом сервера выдачи билетов (TGS). Клиент не может его прочитать.

  • Результат: Клиент расшифровывает Message 1 своим ключом и получает сессионный ключ для общения с TGS.

2. Обмен с сервером выдачи билетов (TGS Exchange)

Теперь клиенту нужно получить разрешение на доступ к конкретному сервису.

  • Запрос: Клиент формирует Message 3 (включает в себя зашифрованный TGT из предыдущего шага) и Message 4 (аутентификатор, зашифрованный ключом «Клиент-TGS»).

  • Проверка: TGS расшифровывает TGT своим ключом, достает оттуда сессионный ключ и с его помощью вскрывает аутентификатор. Если данные о клиенте в обоих сообщениях совпадают, проверка пройдена.

  • Результат: TGS отправляет:

    • Message 5: Билет на сервис, зашифрованный ключом самого целевого сервиса (SS).

    • Message 6: Данные для клиента, зашифрованные ключом «Клиент-TGS».

  • Клиент расшифровывает Message 6 и получает сессионный ключ «Клиент-Сервер».

3. Обмен с сервером приложения (Service Server Exchange)

Финальный этап — непосредственное подтверждение личности перед целевым сервисом.

  • Запрос: Клиент отправляет серверу Message 5 (билет) и Message 7 (новый аутентификатор).

  • Проверка: Сервер (SS) расшифровывает билет своим секретным ключом, достает сессионный ключ и с его помощью проверяет аутентификатор клиента.

  • Взаимная проверка (опционально): Сервер может отправить Message 8, чтобы подтвердить свою личность клиенту. Клиент проверяет временную метку в сообщении.

  • Результат: Установлено полное доверие. Клиент начинает взаимодействие с сервисом.

Рис.1. Иллюстрация процесса аутентификации по протоколу Kerberos

Рис.1. Иллюстрация процесса аутентификации по протоколу Kerberos

Если рассматривать реализацию Kerberos в ALD Pro (FreeIPA), то компоненты Kerberos KDC/Kadmin реализованы с использованием программного обеспечения MIT Kerberos. Оно обеспечивает службы аутентификации для всего домена FreeIPA, его пользовательских служб и других компонентов. Сервер Kerberos является одним из основных элементов сервера FreeIPA.

От теории к практике: из чего состоит «цифровой пропуск»?

Чтобы описанный выше механизм работал в реальной сети, системе нужно понимать, кому именно выдается билет и в рамках какой юрисдикции он действует. Для этого вводятся строгие определения сущностей, которые в мире Kerberos называются принципалами.

В популярных решениях для управления идентификацией, таких как FreeIPA, реализация Kerberos строится на четкой структуре этих имен.

Принципал Kerberos — это уникальный идентификатор, которому Kerberos может присваивать билеты. Принципалы могут иметь произвольное количество компонентов. Каждый компонент разделяется разделителем компонентов, обычно /. Последний компонент — это область (realm), отделенная от остальной части принципала разделителем областей, обычно @. Обычно субъект делится на три части: основной субъект, экземпляр и область. Формат типичного субъекта Kerberos выглядит следующим образом primary/instance@REALM:

  • Primary — это первая часть основного имени. В случае пользователя это то же самое, что и ваше имя пользователя. Для хоста primary — это слово host.

  • Instance представляет собой необязательную строку, указывающую на основной субъект. Экземпляр отделяется от основного субъекта косой чертой (/). В случае пользователя экземпляр обычно равен null, но у пользователя может быть и дополнительный субъект с экземпляром admin, который он/она использует для администрирования базы данных. Субъект admin@ALD.COMPANY.LAN полностью отделен от основного субъекта admin/admin@ALD.COMPANY.LAN, имеет отдельный пароль и отдельные права доступа. В случае хоста экземпляром является полное имя хоста, например, dc-1.ald.company.lan.

  • REALM — это ваша область Kerberos. В большинстве случаев область действия Kerberos — это ваше доменное имя, написанное заглавными буквами. Например, машина dc-1.ald.company.lan будет находиться в области действия ALD.COMPANY.LAN.

FreeIPA объединяет Kerberos с LDAP, используя принципалы для обеспечения сквозной аутентификации (SSO). При вводе нового сервера или пользователя в инфраструктуру FreeIPA, система автоматически создает соответствующие записи в базе Kerberos и генерирует необходимые ключи (keytabs), позволяя узлам сети доверять друг другу «из коробки», следуя классическому алгоритму обмена сообщениями Msg 0–8.

В операционных системах семейства Linux (включая ALD Pro и системы на базе FreeIPA) основным инструментом для просмотра вашего «цифрового пропуска» (билетов Kerberos) является терминал. Вот некоторые из команд, которые необходимы при настройке системы:

1. Просмотр активных билетов (команда klist)

Это самый простой и наглядный способ. Откройте терминал и введите:

klist

Что вы увидите в выводе:

  • Default principal: ваше полное имя в системе Kerberos (например, admin@ALD.COMPANY.LAN). Это и есть ваш «паспортный ID».

  • Valid starting / Expires: срок действия билета. «Цифровой паспорт» не вечен, обычно он выдается на 10–24 часа.

  • Service principal: список сервисов, на которые вы уже получили билеты. Самый первый в списке обычно — krbtgt/ALD.COMPANY.LAN@ALD.COMPANY.LAN. Это и есть тот самый TGT, о котором мы говорили.

В Linux билеты по умолчанию не хранятся в файле паролей. Они находятся в кеше учетных данных (Credential Cache). Найти путь к нему можно в той же команде klist, в строке:

Ticket cache: FILE:/tmp/krb5cc_1000

Обычно это:

  • Файл в /tmp/: например, /tmp/krb5cc_UID, где UID — это идентификатор вашего пользователя.

  • В памяти (Keyring): в современных дистрибутивах кеш может храниться в оперативной памяти (KCM или KEYRING), чтобы его было сложнее украсть с диска.

Если нужно увидеть детальную техническую информацию (флаги билета, адреса), используйте расширенную команду:

klist -e

Флаг -e покажет типы шифрования (например, aes256-cts-hmac-sha1-96), которые использовались для создания вашего «пропуска».

В выводе команды klist напротив каждого билета можно увидеть набор букв (например, F, R, I). Это и есть атрибуты вашего «цифрового пропуска». Вот что они означают в контексте Kerberos:

Флаг

Название

Что означает

F

Forwardable

Пересылаемый. Вы можете передать этот билет другому серверу, и он сможет использовать его, чтобы получить билеты для других сервисов от вашего имени. Важно для многоуровневых приложений.

f

Forwarded

Пересланный. Этот билет был получен с использованием другого билета с флагом F.

R

Renewable

Обновляемый. Билет можно продлить (с помощью kinit -R) без повторного ввода пароля, пока не истечет «срок жизни обновления» (Renew until).

P

Proxyable

Допускающий прокси. Позволяет сервису получить билет только для определенного узкого набора ресурсов от вашего имени.

p

Proxy

Прокси-билет. Указывает, что данный билет является результатом частичного делегирования прав.

I

Initial

Первичный. Этот флаг стоит только у TGT. Он означает, что билет был выдан сервером аутентификации (AS) напрямую на основе вашего пароля, а не на основе другого билета.

A

Pre-authenticated

Предварительно аутентифицированный. Означает, что перед выдачей билета клиент доказал, что знает пароль (через механизм пре-аутентификации, чтобы защититься от офлайн-перебора).

H

Hardware Auth

Аппаратная аутентификация. Указывает, что для получения билета использовался аппаратный токен или смарт-карта.

При анализе вывода klist -f обратите внимание на флаги. Например, наличие флага I (Initial) подтверждает, что вы прошли полный цикл обмена с сервером (AS Exchange), а флаг R (Renewable) позволит вам не вводить пароль снова в конце рабочего дня, просто обновив сессию командой kinit -R.

Для управления файлами keytab (таблицами ключей), которые позволяют сервисам и хостам проходить аутентификацию без участия человека и ввода пароля, используется интерактивная утилита ktutil. Она незаменима в тех случаях, когда администратору нужно объединить несколько файлов keytab в один или вручную добавить запись для конкретного принципала с известным паролем.

Конфигурация /etc/krb5.conf: манифест доверия

Файл /etc/krb5.conf — это главный конфигурационный файл, который сообщает системе, где искать контроллеры домена и какие правила шифрования использовать. В среде ALD Pro он создается автоматически при вводе машины в домен, но для понимания (или тонкой отладки) важно знать значение его ключевых секций.

Разберем типовой конфиг:

includedir /etc/krb5.conf.d/includedir /var/lib/sss/pubconf/krb5.include.d/[logging] default = FILE:/var/log/krb5libs.log kdc = FILE:/var/log/krb5kdc.log admin_server = FILE:/var/log/kadmind.log[libdefaults] default_realm = ALD.COMPANY.LAN dns_lookup_realm = false dns_lookup_kdc = true rdns = false ticket_lifetime = 24h forwardable = true udp_preference_limit = 0 default_ccache_name = KEYRING:persistent:%{uid}
  • default_realm: указывает область (Realm) по умолчанию. Если вы введете kinit admin, система сама допишет @ALD.COMPANY.LAN.

  • ticket_lifetime: срок годности «цифрового паспорта». Обычно это 24 часа. После этого билет TGT станет недействительным.

  • forwardable: тот самый флаг F. Разрешает передавать ваши полномочия сервисам (необходимо для многоуровневых систем).

  • udp_preference_limit = 0: важная настройка для стабильности. При значении 0 Kerberos всегда будет использовать TCP вместо UDP. Это избавляет от проблем с фрагментацией больших пакетов (билетов), которые часто не проходят через сетевое оборудование.

  • default_ccache_name: место хранения билетов. Значение KEYRING говорит о том, что билеты хранятся в защищенной области памяти ядра, а не в файле в /tmp.

[realms] ALD.COMPANY.LAN = {  kdc = dc-1.ald.company.lan:88  master_kdc = dc-1.ald.company.lan:88  admin_server = dc-1.ald.company.lan:749  default_domain = ald.company.lan  pkinit_anchors = FILE:/var/lib/ipa-client/pki/kdc-ca-bundle.pem  pkinit_pool = FILE:/var/lib/ipa-client/pki/ca-bundle.pem}
  • kdc: Адрес сервера, который выдает билеты. Порт 88 — стандарт для Kerberos.

  • admin_server: Сервер для смены паролей (порт 749).

  • pkinit_anchors: Путь к сертификатам удостоверяющего центра. Это критично для FreeIPA, так как позволяет использовать смарт-карты и сертификаты для входа в домен.

[domain_realm] .ald.company.lan = ALD.COMPANY.LAN ald.company.lan = ALD.COMPANY.LAN dc-1.ald.company.lan = ALD.COMPANY.LAN[dbmodules]  ALD.COMPANY.LAN = {    db_library = ipadb.so  }[plugins] certauth = {  module = ipakdb:kdb/ipadb.so  enable_only = ipakdb }

Эта секция — «переводчик». Она объясняет системе, что, если имя сервера заканчивается на .ald.company.lan, то за билетом для него нужно идти в область ALD.COMPANY.LAN.

Если этот файл настроен неверно, ни kinit, ни другие сервисы не смогут найти «точку входа» в домен. Например, если вы используете нестандартные DNS, вам придется вручную прописывать все адреса KDC в секции [realms].

Критически важный момент для работы SSO (Single Sign-On) заключается в том, что даже если Kerberos в системе и /etc/krb5.conf настроены идеально, браузер (Яндекс.Браузер, Chromium, Google Chrome) из соображений безопасности «не доверяет» всем сайтам подряд ваш «цифровой пропуск». Для того чтобы браузер автоматически передавал Kerberos-билет на сервер, его нужно внести в «белый список».

Как все работает на примере интерфейса панели администрирования ALD Pro

Рассмотрим, как всё работает на практике, при использовании доменной структуры. В нашем распоряжении — контроллер домена ALD Pro на базе Astra Linux, где управление идентификацией осуществляется через FreeIPA. FreeIPA использует Kerberos для реализации технологии единого входа (SSO). Это позволяет пользователю ввести пароль лишь один раз при входе в систему, после чего он получает доступ ко всем доменным ресурсам (включая веб-интерфейс ALD Pro и КриптоАРМ ID) без повторных запросов.

Шаг 1. Подготовка пользователя

В консоли управления ALD Pro в разделе «Активные пользователи» создаем новую учетную запись (рис. 2). В момент создания пользователя во FreeIPA для него автоматически создается принципал (рис. 3).

Рис. 2. Активные пользователи

Рис. 2. Активные пользователи
Рис. 3. Создание нового пользователя

Рис. 3. Создание нового пользователя

Получать билет Kerberos нужно только в том случае, если первоначальный билет Kerberos был уничтожен или срок его действия истек.

Пользователь FreeIPA (рис. 4), пройдя процедуру аутентификацию на локальном компьютере, также автоматически входит в FreeIPA. После входа в систему ему не требуется использовать утилиту kinit для доступа к ресурсам FreeIPA.

Рис. 4. Пользователь активен

Рис. 4. Пользователь активен

Шаг 2. Получение «цифрового паспорта»

Важно понимать: если пользователь вошел в систему под своей доменной учетной записью, билет Kerberos (TGT) выдается ему автоматически. Утилита kinit в этом случае не требуется — вход в интерфейс ALD Pro произойдет бесшовно.

Однако, если срок действия билета истек или вам нужно получить билет для другого пользователя (например, для администратора), используются следующие команды:

Для текущего пользователя (рис. 5):

Рис.5. Получение тикета для текущего пользователя

Рис.5. Получение тикета для текущего пользователя

Система запросит пароль и, при успехе, молча завершит работу, обновив ваш кеш.

Для другого активного пользователя домена (рис. 6):

Рис.6. Получение тикета для другого пользователя

Рис.6. Получение тикета для другого пользователя

Это полезно для проверки доступа под разными ролями, не выходя из сеанса операционной системы.

Шаг 3. Проверка и очистка кеша

Чтобы убедиться, что «пропуск» получен и содержит верные данные, используем уже знакомую нам утилиту klist. В выводе увидим принципал (например, admin@ALD.COMPANY.LAN), что подтверждает готовность к работе с сервисами (рис. 7).

Рис.7. Проверка получения «пропуска»

Рис.7. Проверка получения «пропуска»

Для тестирования сценариев аутентификации (например, при отладке интеграции с различными системами SSO) критически важно уметь «сжигать» старые билеты. Для этого используется команда:

kdestroy

Она полностью очищает кеш учетных данных. После этого любая попытка входа в защищенный сервис потребует нового прохождения цикла AS Exchange (команды kinit или повторного ввода пароля).

Что случилось в Яндекс.Браузере?

Как упоминалось чуть раньше, браузер (Яндекс.Браузер, Chromium, Google Chrome) из соображений безопасности «не доверяет» всем сайтам подряд ваш цифровой паспорт. На практике это выглядит следующим образом: устанавливаем в систему Яндекс.Браузер sudo apt install yandex-browser-stable. После установки пробуем войти в систему администрирования ALDPro под текущим пользователем и получаем сообщение (рис. 8):

Рис.8. Неудачная попытка аутентификации Kerberos

Рис.8. Неудачная попытка аутентификации Kerberos

Каким образом можно решить эту проблему? Начинаем разбираться с этой проблемой, если учесть, что в FireFox все работает. В Linux настройка браузера делается либо через запуск с флагами, либо через политики. Самый надежный способ для интеграции — настройка через конфигурационные файлы с определением политик. Рассмотрим оба способа:

1. Список разрешенных доменов

Браузеру нужно указать, для каких доменов он может использовать аутентификацию Negotiate (Kerberos). Поэтому можно прописать ваш домен (из krb5.conf) и запустить браузер с флагом через терминал (для быстрой проверки):

yandex-browser —auth-server-whitelist=»*.ald.company.lan»

2. Постоянная настройка (через политики)

Чтобы пользователю не нужно было ничего вводить вручную, в Linux создается json-файл политики:

/etc/opt/yandex/browser/policies/managed/kerberos.json (путь может немного отличаться в зависимости от дистрибутива).

Содержимое файла json:

{  "AuthServerAllowlist": "*.ald.company.lan",  "AuthNegotiateDelegateAllowlist": "*.ald.company.lan"}
  • AuthServerAllowlist — разрешает аутентификацию.

  • AuthNegotiateDelegateAllowlist — разрешает делегирование (флаг Forwardable), если серверу нужно передать ваш билет дальше.

Сначала пробуем запустить браузер с флагом включения домена в белый список. В итоге получаем ошибку CertVerifyProcBuiltin for dc-1.ald.company.lan failed: ERROR: No matching issuer found и net_error -202 (ERR_CERT_AUTHORITY_INVALID), которая говорит о том, что Яндекс Браузер не доверяет вашему корпоративному Центру Сертификации (CA). Значит нужно указать корневой сертификат домена. На контроллере домена он находится здесь: /etc/ipa/ca.crt и его можно загрузить через настройки браузера.

Набираем в адресной строке браузера команду browser://settings/certificates, выбираем «Сертификаты», «Центры сертификации» (Authorities) и нажимаем «Импорт». Не забываем установить галочку «Доверять при идентификации сайтов». Корневой сертификат загружен (рис. 9).

Рис.9. Установка корневого сертификата домена

Рис.9. Установка корневого сертификата домена

Пробуем снова и опять неудачно, хотя на консоли никаких ошибок нет. Значит нужно посмотреть политики. Делается это с помощью команды browser://policy (запуск через адресную строку) (рис. 10).

Рис.10. Отсутствие политик Яндекс браузера

Рис.10. Отсутствие политик Яндекс браузера

На рисунке 10 в разделе «Yandex Browser Policies» четко написано: «Политики не заданы». Это означает, что запуск с флагом —auth-server-whitelist не сработал. Яндекс Браузер просто проигнорировал этот параметр, поэтому он и не пытается использовать Kerberos, в отличие от Firefox (у которого свои независимые настройки в about:config).

Не будем полагаться на командную строку и пропишем политику жестко в системный файл, чтобы она всегда была активна:

sudo mkdir -p /etc/opt/yandex/browser/policies/managed/

sudo nano /etc/opt/yandex/browser/policies/managed/kerberos.json

и добавляем туда текст json, который был предложен в начале п.2.

Полностью перезапускаем браузер и проверяем результат. Видим, что политики подтянулись из файла конфигурации (рис. 11).

Рис.11. Обновленные политики Яндекс браузера

Рис.11. Обновленные политики Яндекс браузера

И вот аутентификация по Kerberos прошла успешно (рис. 12).

Рис.12. Успешная аутентификация по Kerberos

Рис.12. Успешная аутентификация по Kerberos

На основе этого опыта можно сформулировать 4 ключевых рекомендации по настройке Kerberos (доступ через браузер) в корпоративной среде:

1. Используйте JSON-политики вместо флагов запуска. Это главная рекомендация. Флаги в терминале —auth-server-whitelist часто игнорируются, если браузер запущен в фоновом режиме или открыт через ярлык на панели задач. Для Яндекс Браузера: /etc/opt/yandex/browser/policies/managed/ Для Chromium/Chrome: /etc/opt/chrome/policies/managed/ Настройки применяются для всех пользователей системы и не «слетают» при обновлении.

2. Настраивайте сразу два параметра. Для полноценной работы (особенно если сервис использует перенаправления или требует делегирования прав) всегда прописывайте обе политики: AuthServerAllowlist — разрешает саму аутентификацию. AuthNegotiateDelegateAllowlist — разрешает делегирование (передачу) тикета Kerberos серверу.

3. Всегда проверяйте через browser://policy. Это главный инструмент диагностики. Если в таблице пусто — браузер не видит настройки (проверяйте пути к JSON-файлам и права доступа на них). Если в колонке «Status» стоит ошибка — вы ошиблись в синтаксисе JSON (например, забыли кавычки или запятую).

4. Доверяйте корневому сертификату (CA). Как было показано, Kerberos-аутентификация часто происходит поверх HTTPS. Если браузер не доверяет сертификату контроллера домена или веб-сервера (ошибка net_error -202), он может прервать соединение еще до того, как попробует отправить Kerberos-тикет. Всегда устанавливайте корневой сертификат домена в системное хранилище или напрямую в настройки браузера.

Программная модель: получение Kerberos-тикетов на JavaScript

Посмотрим можно ли быстро собрать реализацию аутентификации (подобие серверного скрипта), например, с использованием библиотеки Node.js. Для Node.js наиболее стабильным решением является использование библиотеки Kerberos (официальный пакет от MongoDB, поддерживающий GSSAPI) или работа через оболочку над системными вызовами.

1. Подготовка окружения. Перед написанием кода необходимо убедиться, что в системе установлены заголовочные файлы Kerberos, так как библиотека компилирует нативные модули:

sudo apt-get install libkrb5-dev

sudo apt install nodejs npm

npm install kerberos

Причем следует учесть, что библиотека Kerberos будет работать со старыми версиями Node.js (нужно обновить Node.js как минимум до v18 или v20 (LTS)). Если вы застряли на Node.js v10, попробуйте установить версию kerberos, которая её поддерживала (например, из ветки 1.x).

На некоторых системах могут возникнуть проблемы с установкой новой версии Node.js, я делал это по следующему сценарию

curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.0/install.sh | bash

export NVM_DIR=»$HOME/.nvm»
[ -s «$NVM_DIR/nvm.sh» ] && \. «$NVM_DIR/nvm.sh»
[ -s «$NVM_DIR/bash_completion» ] && \. «$NVM_DIR/bash_completion»

nvm install —lts

В результате библиотека kerberos установилась без проблем (рис. 13).

Рис.13. Приемлемая конфигурация Node.js

Рис.13. Приемлемая конфигурация Node.js

2. Сценарий: Аутентификация по паролю и получение сервисного тикета. Основная задача кода — инициализировать контекст безопасности и получить токен, который можно передать в заголовке HTTP (SPNEGO) или использовать для внутренней проверки. Этот код предназначен для реализации технологии Single Sign-On (SSO) в корпоративной сети. Он позволяет вашему приложению автоматически «представляться» серверу от имени текущего пользователя, используя его доменную учетную запись (Kerberos/Active Directory/ALD Pro).

Пример реализации (пришлось поломать голову над проблемой канонизации):

const kerberos = require('kerberos');async function getKerberosToken(servicePrincipal) {    try {        // Превращаем "HTTP/myservice.domain.ru" в "HTTP@myservice.domain.ru"        // Это обходит проблему некорректной канонизации в Astra Linux        const formattedPrincipal = servicePrincipal.replace('/', '@');        // Инициализация с флагом no_canonicalize        const client = await kerberos.initializeClient(formattedPrincipal, {             no_canonicalize: true         });        // Генерация тикета        const ticket = await client.step("");                return ticket;    } catch (err) {        throw new Error(`Ошибка Kerberos (${servicePrincipal}): ${err.message}`);    }}// ПРИМЕР ИСПОЛЬЗОВАНИЯ:(async () => {    const spn = "HTTP/dc-1.ald.company.lan"; // Пишем в стандартном формате    try {        const token = await getKerberosToken(spn);        console.log("Токен сформирован:", token.substring(0, 30) + "...");    } catch (e) {        console.error(e.message);    }})();

Проверяем работоспособность кода (рис. 14).

Рис.14. Получение токена

Рис.14. Получение токена

Для чего нужен этот код? Во-первых, реализация беспарольной аутентификации, приложение получает временный секретный «билет» (токен) из системы, чтобы доказать веб-серверу или базе данных, кто вы такой, не запрашивая пароль повторно. Во-вторых, пароль пользователя никогда не передается по сети и не хранится в коде. В-третьих, автоматизация — скрипт полезен для системных администраторов и разработчиков, которым нужно программно обращаться к защищенным ресурсам внутри домена (например, к API другого сервера).

На что нужно обратить внимание (важные моменты):

  • Наличие билета (kinit): Код не будет работать, если пользователь не вошел в домен. В Linux это проверяется командой klist. Если билета нет, нужно сначала выполнить kinit.

  • Синтаксис SPN: Строка HTTP/dc-1… — это идентификатор сервиса. Если ошибиться в одной букве или указать IP-адрес вместо FQDN (полного имени), Kerberos выдаст ошибку «Server not found».

  • Зависимость от ОС: Модуль kerberos — это «обертка» над системными библиотеками. Если на сервере не установлены пакеты libkrb5-dev и krb5-user, код не скомпилируется и не запустится.

  • Формат с @: В Astra Linux мы заменили / на @ (например, HTTP@hostname), чтобы избежать проблем с DNS-канонизацией, когда система пытается сама «додумать» имя сервера и делает это неправильно.

  • Срок жизни токена: Полученный Base64-токен одноразовый и имеет очень короткий срок жизни (обычно несколько минут). Его нельзя сохранить «на завтра», его нужно генерировать прямо перед запросом.

3. Сценарий: Работа через Keytab (автоматизация). Если JS-скрипт работает как фоновый сервис (daemon), он должен уметь сам обновлять тикеты без участия пользователя.  Для автоматизации работы через Keytab (без ввода пароля вручную), вам нужно объединить функцию обновления билета и вашу функцию получения токена. В фоновых сервисах это стандартная практика: сначала проверяем/обновляем системный билет, затем генерируем токен.

Следует учесть, что использование учетной записи admin для автоматизации — это критическая уязвимость. Если файл с ключом (keytab) попадет в чужие руки, злоумышленник получит полный контроль над всем доменом ALD Pro. Кроме того, личные учетные записи подчиняются политикам смены пароля: как только вы измените пароль в консоли, ваш фоновый скрипт мгновенно «сломается», так как данные в файле keytab перестанут совпадать с базой домена.

Для надежной и безопасной работы следует создать техническую учетную запись (например, svc_node). Такому пользователю нужно ограничить права доступа только теми действиями, которые необходимы для работы скрипта (принцип минимальных привилегий). В ALD Pro рекомендуется отключить для этой учетки политику истечения срока действия пароля, чтобы сервис не останавливался каждые 30–90 дней.

Использование Service Principal (созданного через ipa service-add) — еще более профессиональный подход. Сервисные записи изначально предназначены для работы через keytab, они не имеют пароля для ручного входа через UI, что исключает риск случайного «сброса» ключей при смене пароля администратором. Это гарантирует, что ваш Node.js скрипт будет работать автономно годами, не требуя вмешательства.

В моем случае, я использую техническую учетную запись sch, которую создал ранее, но работать буду под учеткой админа. Попробую создать каталог /home/admin/tmp, сформирую в него файл sch.keytab  и назначу права (иногда утилита капризничает из-за прав на папку в домашнем каталоге):

sudo /usr/sbin/ipa-getkeytab -s dc-1.ald.company.lan -p sch@ALD.COMPANY.LAN -k /home/admin/tmp/sch.keytab

sudo chown admin:admins /home/admin/tmp/sch.keytab

sudo chmod 600 /home/admin/tmp/sch.keytab

Никуда не перелогиниваюсь и сразу делаю проверку перед отладкой скрипта (рис. 15):

Рис.15. Проверка выдачи билета

Рис.15. Проверка выдачи билета

Как видно из рисунка все прошло успешно, билет для sch существует. Создаем скрипт для получения билета на основе keytab. Пример реализации:

const { execSync } = require('child_process');const kerberos = require('kerberos');const path = require('path');const fs = require('fs');/** * НАСТРОЙКИ КЭША ДЛЯ FREEIPA * Принудительно используем файловый кэш вместо системного KEYRING. */const CCACHE_PATH = path.join(__dirname, 'krb5cc_node_service');const KRB5CCNAME_VAL = `FILE:${CCACHE_PATH}`;// Принудительно выставляем для текущего процесса Node.jsprocess.env.KRB5CCNAME = KRB5CCNAME_VAL;// 1. Функция обновления системного билета через Keytabfunction refreshTicketWithKeytab(principal, keytabPath) {    try {        // Проверяем физическое существование файла перед запуском kinit        if (!fs.existsSync(keytabPath)) {            throw new Error(`Файл keytab не найден по пути: ${keytabPath}`);        }        // Явно передаем переменную окружения KRB5CCNAME внутрь execSync        const execOptions = { env: { ...process.env, KRB5CCNAME: KRB5CCNAME_VAL }, stdio: 'pipe' };        // Очищаем старый кэш (игнорируем ошибку, если файла еще нет)        try { execSync(`kdestroy -c ${KRB5CCNAME_VAL}`, execOptions); } catch (e) {}        // Выполняем kinit        execSync(`kinit -kt ${keytabPath} ${principal}`, execOptions);        console.log(`[OK] Билет для ${principal} успешно получен в ${KRB5CCNAME_VAL}`);        return true;    } catch (error) {        // Выводим реальную ошибку из консоли kinit, а не просто stderr Node.js        const stderr = error.stderr ? error.stderr.toString().trim() : '';        console.error("[Error] Ошибка kinit (FreeIPA):", error.message, stderr);        return false;    }}// 2. Функция получения SPN токенаasync function getKerberosToken(servicePrincipal) {    try {        // Передаем строку "HTTP@dc-1.ald.company.lan" и разрешаем канонизацию        const client = await kerberos.initializeClient(servicePrincipal, {            no_canonicalize: false        });        const ticket = await client.step("");        return ticket;    } catch (err) {        throw new Error(`Ошибка формирования токена (${servicePrincipal}): ${err.message}`);    }}// 3. Главный сценарий использованияasync function runAutomatedTask() {    // ВАЖНО: используем пользователя sch, для которого успешно создали keytab!    const MY_PRINCIPAL = "sch@ALD.COMPANY.LAN";    const KEYTAB_PATH = "/home/admin/tmp/sch.keytab";    const SERVICE_SPN = "HTTP@dc-1.ald.company.lan";  // Имя веб-сервиса (цель аутентификации)    console.log("Запуск автоматического получения билета...");    // Шаг А: Авторизация в фоне через Keytab    if (refreshTicketWithKeytab(MY_PRINCIPAL, KEYTAB_PATH)) {        try {            // Шаг Б: Генерация токена для сервиса            const token = await getKerberosToken(SERVICE_SPN);            console.log("-----------------------------------------");            console.log("Керберос-токен успешно сформирован (GSSAPI):");            console.log(token.substring(0, 50) + "...");            console.log("-----------------------------------------");            console.log("[УСПЕХ] Скрипт отработал корректно.");        } catch (e) {            console.error("[Error на Шаге Б]", e.message);        }    } else {        console.error("[FAIL] Не удалось обновить билет Kerberos.");    }}runAutomatedTask();

Этот скрипт — инструмент для автоматической Kerberos-аутентификации в инфраструктуре ALD Pro (или FreeIPA). Он позволяет приложению на Node.js доказать свою личность серверу, не требуя ручного ввода пароля. Скрипт получает временный «билет» (Kerberos Ticket) из системы и на его основе генерирует Base64-токен (Service Ticket). Этот токен вставляется в HTTP-заголовок Authorization: Negotiate <токен>, позволяя обращаться к защищенным API, базам данных или веб-сервисам внутри домена.

Благодаря использованию Keytab, скрипт может работать как служба (daemon). Он сам обновляет свои права доступа, даже если сервер перезагрузился или сессия пользователя закрылась (рис. 16).

Пароль не хранится в открытом виде в коде. Вместо него используется файл ключей (Keytab), доступ к которому ограничен на уровне ОС (рис. 17).

Рис.16. Успешное получение билета для пользователя sch

Рис.16. Успешное получение билета для пользователя sch
Рис.17. Вход через Kerberos под учетной запись пользователя sch

Рис.17. Вход через Kerberos под учетной запись пользователя sch

4. Серверная часть: Проверка билета и аутентификация в Node.js. Для того, чтобы выполнить аутентификацию пользователя и смоделировать работу некоторой системы SSO нужно, чтобы в файле keytab был прописан принципал HTTP/dc-1.ald.company.lan@ALD.COMPANY.LAN.  Как видно из ранее приведенных примеров такой сервис-принципал отсутствует в текущем файле keytab. Его конечно можно добавить командой

sudo ipa-getkeytab -p HTTP/dc-1.ald.company.lan -k home/admin/tmp/sch.keytab 

но это может привести к негативным последствиям ввиду того, что мы экспериментируем непосредственно на контроллере домена, где панель администрирования под управлением Apache2 также имеет свой keytab. Изменение версии в одном keytab не приводит к автоматическому обновлению всех других файлов ключей и приводит к рассинхронизации по версии KVNO. А как следствие – вы не сможете войти под старыми учетными записями в другие системы. Чтобы не столкнуться с этими проблемами и ускорить получение результата, я использую существующий файл http.keytab, его можно найти по пути /var/lib/ipa/gssproxy/http.keytab.

Выполним несколько команд:

sudo chown admin:admins /home/admin/tmp/http.keytab

sudo chmod 400 /home/admin/tmp/http.keytab

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

klist -kt /home/admin/tmp/http.keytab

Рис.18. Просмотр содержимого файла http.keytab

Рис.18. Просмотр содержимого файла http.keytab

В выводе видим строки, содержащие HTTP/dc-1.ald.company.lan@ALD.COMPANY.LAN. Имя хоста должно совпадать с тем, что будет написано в нашем скрипте (SERVICE_SPN).

Для реализации аутентификации на стороне сервера (например, в API на базе Express) библиотека kerberos предоставляет метод initializeServer. Основная задача сервера — принять заголовок Negotiate от клиента и подтвердить его подлинность с помощью системного keytab-файла сервиса. Созданный скрипт успешно моделирует классический трехсторонний процесс Kerberos-аутентификации (клиент — KDC — сервер) в рамках одного процесса. Он избавляет от необходимости разворачивать реальный веб-сервер (например, Apache/Nginx) на этапе первичного тестирования. Пример реализации проверки:

const { execSync } = require('child_process');const kerberos = require('kerberos');const path = require('path');const fs = require('fs');// Настройки кэша и keytab (Адаптировано под FreeIPA/Astra)const CCACHE_PATH = path.join(__dirname, 'krb5cc_node_service');process.env.KRB5CCNAME = `FILE:${CCACHE_PATH}`;// ПОДГОТОВКА ПЕРЕМЕННЫХ (Проверьте, что пути и имена верны!)const CLIENT_PRINCIPAL = "sch@ALD.COMPANY.LAN";const CLIENT_KEYTAB = "/home/admin/tmp/sch.keytab";const SERVICE_SPN = "HTTP@dc-1.ald.company.lan";// --- ШАГ 1: ПОЛУЧЕНИЕ БИЛЕТА КЛИЕНТОМ ---function clientRefreshTicket() {    try {        try { execSync(`kdestroy -c ${process.env.KRB5CCNAME}`); } catch(e){}        execSync(`kinit -kt ${CLIENT_KEYTAB} ${CLIENT_PRINCIPAL}`);        console.log(`[КЛИЕНТ] Билет Kerberos успешно получен.`);        return true;    } catch (error) {        console.error("[КЛИЕНТ ОШИБКА] Не удалось выполнить kinit:", error.message);        return false;    }}// --- ШАГ 2: ГЕНЕРАЦИЯ ТОКЕНА КЛИЕНТОМ ---async function clientGenerateToken() {    // Для Linux используем формат с '@' для корректной работы GSSAPI    const client = await kerberos.initializeClient(SERVICE_SPN, { no_canonicalize: false });    const ticket = await client.step("");    return ticket;}// --- ШАГ 3: ПРОВЕРКА ТОКЕНА НА СЕРВЕРЕ ---async function serverVerifyToken(ticket) {    try {        const server = await kerberos.initializeServer(SERVICE_SPN);        await server.step(ticket);        if (!server.contextComplete) {            throw new Error("Контекст GSSAPI не завершен.");        }        return { success: true, username: server.username };    } catch (err) {        return { success: false, error: err.message };    }}// --- ГЛАВНЫЙ СЦЕНАРИЙ ---async function run() {    console.log("=== СТАPT СКВОЗНОГО ТЕСТА KERBEROS ===");    // 1. Клиент авторизуется в KDC    if (!clientRefreshTicket()) return;    try {        // 2. Клиент генерирует токен (Имитация отправки в браузер / КриптоАРМ)        const token = await clientGenerateToken();        console.log(`[КЛИЕНТ] Сгенерирован токен (длина: ${token.length} симв.)`);        console.log(`[КЛИЕНТ] Передаем токен на сервер...`);        // 3. Сервер принимает токен и проверяет его валидность        const authResult = await serverVerifyToken(token);        console.log("------------------------------------------------");        if (authResult.success) {            console.log(`[СЕРВЕР СТАТУС] 🟢 УСПЕХ!`);            console.log(`[СЕРВЕР] Пользователь опознан как: ${authResult.username}`);        } else {            console.error(`[СЕРВЕР СТАТУС] 🔴 ОТКАЗ АУТЕНТИФИКАЦИИ!`);            console.error(`[СЕРВЕР ОШИБКА] Детали: ${authResult.error}`);        }        console.log("------------------------------------------------");    } catch (e) {        console.error("[КРИТИЧЕСКАЯ ОШИБКА ТЕСТА]", e.message);    }}run();

Результат запуска скрипта (рис. 19):

Рис.19. Пользователь sch успешно прошел аутентификацию

Рис.19. Пользователь sch успешно прошел аутентификацию

Представленный скрипт является эффективным инструментом автоматизированного контроля (Smoke-тестом) для проверки инфраструктуры Kerberos/FreeIPA перед деплоем реальных приложений.

Главная ценность скрипта заключается в локализации ошибок. Если данный скрипт отрабатывает успешно (🟢 УСПЕХ), это гарантирует, что:

  • Файлы keytab не повреждены и содержат актуальные версии ключей (KVNO).

  • DNS-имена (SPN) и доменные зоны настроены правильно.

  • Системные библиотеки GSSAPI/Kerberos в ОС Astra Linux совместимы с Node.js.

Если в дальнейшем реальное веб-приложение (например, под управлением Apache или Express.js) выдаст ошибку 401 Unauthorized, разработчик будет точно знать, что проблема кроется в настройках самого веб-сервера или браузера, а не в инфраструктуре Kerberos. Скрипт рекомендуется использовать как эталонный тест при проведении регламентных работ или обновлении ключей на контроллере домена.

Установка и предварительная настройка КриптоАРМ ID

Давайте рассмотрим, насколько сложно настроить реальную систему SSO и обеспечить пользователям доступ по протоколу Kerberos. Для этого возьмем программный продукт КриптоАРМ ID и развернем его на той же машине.

КриптоАРМ ID —приложение для управления аутентификацией пользователей в инфраструктуре открытых ключей (PKI), интегрированное с доменными учетными данными Kerberos. Начиная с версии 1.1.5, в КриптоАРМ ID реализована поддержка входа через Kerberos для сред, где в качестве контроллера домена и службы каталогов используются Active Directory или решения на базе LDAP (например, ALD Pro/FreeIPA). Рассмотрим, как использовать этот функционал для настройки сквозной аутентификации (SSO).

Сначала установим КриптоАРМ ID, продукт доступен для установки и тестирования из репозитория. Инструкция по развертыванию в Docker имеется там же, я остановлюсь только на особенностях, которые потребуется учесть в нашем случае.

Я буду запускать КриптоАРМ ID на том же стенде, где развернут контроллер домена ALD Pro. Поскольку порт :443 уже занят веб-сервером Apache2, самым быстрым решением для тестов будет его запуск на каком-то нестандартном порту, например, 5443. Благо в состав КриптоАРМ ID входит реверс-прокси Traefik, который можно сконфигурировать так как нам нужно.

Следует учесть еще один момент — реверс-прокси Traefik по умолчанию использует самоподписанный сертификат. Для корректной работы SSO и HTTPS нам необходимо подставить в Traefik валидный сертификат домена.

Пример файла docker-compose.yaml КриптоАРМ ID, сконфигурированного под наши нужды:

volumes:  images:services:  traefik:    image: traefik:v2.11    container_name: traefik    command:      - --providers.docker=true      - --providers.docker.exposedbydefault=false      - --ping=true      - --api=true      - --api.insecure=true      - --api.dashboard=true      - --entryPoints.http.address=:80      - --entryPoints.https.address=:5443      - --entryPoints.http.http.redirections.entryPoint.to=https      - --entryPoints.http.http.redirections.entryPoint.scheme=https      - --log=true      - --providers.file.filename=/etc/traefik/dynamic_conf.yml      - --log.level=DEBUG    labels:      - traefik.enable=true      - traefik.http.routers.traefik-forward-auth.middlewares=traefik-forward-auth      - traefik.http.middlewares.traefik-forward-auth.forwardauth.authResponseHeaders=set-cookie    ports:      - 8081:80      - 5443:5443    volumes:      - /var/run/docker.sock:/var/run/docker.sock      - ./acme.json:/acme.json      - ./dynamic_conf.yml:/etc/traefik/dynamic_conf.yml:ro      - /etc/traefik/certs/server.crt:/etc/traefik/certs/server.crt:ro      - /etc/traefik/certs/server.key:/etc/traefik/certs/server.key:ro    networks:      default:        aliases:          - dc-1.ald.company.lan  id-front:    image: registry.digtlab.ru/cryptoarm/id/front:v1.1.5    container_name: id-front    restart: always    volumes:      - ./nginx.conf:/etc/nginx/conf.d/nginx.conf    depends_on:      - id-back    labels:      - traefik.enable=true      - traefik.http.routers.front.rule=Host(`dc-1.ald.company.lan`)      - traefik.http.routers.front.entrypoints=https      - traefik.http.routers.front.tls=true      - traefik.http.services.id-front.loadbalancer.server.port=80      - traefik.http.routers.front.tls.domains[0].main=dc-1.ald.company.lan    env_file:      - .env  id-back:    image: registry.digtlab.ru/cryptoarm/id/back:v1.1.5    container_name: id-back    restart: always    environment:      - KRB5_CONFIG=/etc/krb5.conf      - KRB5_KTNAME=/app/id.keytab    volumes:      - images:/app/public/images      - ./kbs/krb5.conf:/etc/krb5.conf:ro         # Новый "плоский" конфиг      - ./kbs/id.keytab:/app/id.keytab:ro    depends_on:      - id-db    command: >      sh -c "npx prisma migrate deploy && npm run start:prod"    env_file:      - .env  id-oidc:    image: registry.digtlab.ru/cryptoarm/id/oidc:v1.1.5    container_name: id-oidc    volumes:      - ./data/jwks:/app/jwks    env_file:        - .env  id-auth:    image: registry.digtlab.ru/cryptoarm/id/auth:v1.1.5    container_name: id-auth    env_file:        - .env  id-redis:    container_name: id-redis    image: "redis"    restart: always    volumes:      - ./data/redis:/data    env_file:      - .env  id-db:    container_name: id-db    image: postgres:14.4    restart: always    volumes:      - ./data/postgres:/var/lib/postgresql/data    env_file:      - .env

Изменения в файле .env

ID_HOST=dc-1.ald.company.lanDOMAIN=https://dc-1.ald.company.lan:5443POSTGRES_USER=name_userPOSTGRES_PASSWORD=passwordPOSTGRES_DB=name_dbADMIN_MAIL=qwerty@example.comREDIS_PORT=6379REDIS_HOST=id-redisDATABASE_URL=postgresql://name_user:password@id-db:5432/name_db# Only for testing with self-signed certificatesNODE_TLS_REJECT_UNAUTHORIZED=0CLIENT_ID=6f30e2db-cc75-4c98-aa95-fe381c4d1ff4CLIENT_SECRET=22665b55-58e0-48da-b8bf-f357bc0da68c

На контроллере домена ALD Pro уже имеются необходимые сертификаты и ключи, выпущенные локальным удостоверяющим центром. Нам остается лишь извлечь их, при этом следует помнить, что закрытый ключ часто зашифрован и его нужно подготовить для использования в Traefik. Создадим каталог /etc/traefik/certs и выполним ряд команд:

sudo cp /var/lib/ipa/certs/kdc.crt /etc/traefik/certs/server.crt

sudo cp /var/lib/ipa/certs/kdc.key /etc/traefik/certs/server.key

# Устанавливаем права, чтобы Traefik (внутри Docker) мог их прочитать

sudo chmod 644 /etc/traefik/certs/server.crt /etc/traefik/certs/server.key

sudo chown admin:$(id -gn) /etc/traefik/certs/server.crt /etc/traefik/certs/server.key

Уведитесь, что используемый ключ server.key не зашифрован, зашифрованный ключ не подойдет для использования. Формируем файл dynamic_conf.yml с содержимым:

http:  routers:    dummy:      rule: "Host(`dummy.lan`)"      service: noop@internal      tls: {}tls:  certificates:    - certFile: /etc/traefik/certs/server.crt      keyFile: /etc/traefik/certs/server.key  stores:    default:      defaultCertificate:        certFile: /etc/traefik/certs/server.crt        keyFile: /etc/traefik/certs/server.key

Создаем упрощенный конфиг в папке проекта,
файл /home/admin/cryptoarm-id/kbs/krb5.conf и добавляем в него текст:

[libdefaults]    default_realm = ALD.COMPANY.LAN    dns_lookup_realm = false    dns_lookup_kdc = true    rdns = false    ticket_lifetime = 24h    forwardable = true    udp_preference_limit = 0[realms]    ALD.COMPANY.LAN = {        kdc = dc-1.ald.company.lan        admin_server = dc-1.ald.company.lan    }[domain_realm]    .ald.company.lan = ALD.COMPANY.LAN    ald.company.lan = ALD.COMPANY.LAN

Также нам надо повторить процедуру использования системного keytab (ранее мы его уже копировали при настройке скриптов):

# 1. Копируем системный keytab в рабочую директорию

sudo cp /var/lib/ipa/gssproxy/http.keytab /home/admin/cryptoarm-id/kbs/id.keytab

# 2. Меняем владельца на вашего пользователя и его группу

sudo chown admin:admins /home/admin/cryptoarm-id/kbs/id.keytab

# 3. Выставляем права 644

sudo chmod 644 /home/admin/cryptoarm-id/kbs/id.keytab

Запустим сервис и залогинимся как admin/admin (рис. 20):

Рис.20. Успешный запуск сервиса КриптоАРМ ID на валидном сертификате

Рис.20. Успешный запуск сервиса КриптоАРМ ID на валидном сертификате

Видим, что сервис запущен, сертификат успешно принимается браузером, а значит, можно приступать к дальнейшим действиям уже внутри системы SSO.

Подключение провайдера ALD Pro в КриптоАРМ ID

Так как на машине у нас развернут контроллер домена ALD Pro, значит можно использовать этот провайдер, чтобы импортировать учетные данные пользователей. В панели администрирования КриптоАРМ ID сформируем новый провайдер и перейдем к его настройкам (рис. 21).

Рис.21. Добавление нового провайдера ALD Pro

Рис.21. Добавление нового провайдера ALD Pro

На рисунке 22 показано окно настройки интеграции с отечественной службой каталогов ALD Pro. В этой форме задаются ключевые параметры, которые позволяют внешней информационной системе обращаться к базе данных ALD Pro для проверки подлинности сотрудников при входе.

Первым делом указывается адрес сервера ALDPRO (aldpro_url), который определяет сетевой путь к контроллеру домена. В данном примере используется протокол LDAP и IP-адрес ldap://10.0.1.11, однако встроенная подсказка рекомендует применять более безопасный шифрованный протокол LDAPS с указанием доменного имени. Этот параметр отвечает за то, куда именно система будет отправлять запросы на аутентификацию.

Вторым важным параметром является база поиска (aldpro_base), написанная в стандартном формате LDAP-пути. Она жестко задает начальную точку (ветку) в иерархии каталога, начиная с которой система будет искать учетные записи. Судя по значению cn=users,cn=accounts,dc=ald,dc=company,dc=lan, поиск ограничен конкретным контейнером пользователей внутри корпоративной структуры, что ускоряет обработку запросов и исключает лишние объекты.

В самом конце формы вводится домен ALDPRO (aldpro_domain), представляющий собой классическое имя домена организации — в данном случае ald.company.lan. Этот параметр окончательно связывает настройки с конкретным пространством имен вашей локальной сети, завершая конфигурацию провайдера для корректной авторизации пользователей.

Рис.22. Параметры провайдера ALD Pro (часть 1)

Рис.22. Параметры провайдера ALD Pro (часть 1)

На втором рисунке 23 показано продолжение формы настройки, где задаются правила фильтрации, маппинга данных и параметры сервисного доступа к службе каталогов ALD Pro.

Первое поле Фильтр поиска (aldpro_filter) отвечает за критерии отбора учетных записей при авторизации. Значение (objectClass=*) является максимально широким и означает поиск по абсолютно всем объектам в указанной ранее базе. На практике сюда чаще подставляют более строгие фильтры (например, ограничивающие поиск только активными пользователями или членами конкретных групп), чтобы система не пыталась авторизовать технические учетные записи или компьютеры.

Второе поле Сопоставление атрибутов ALDPRO (ldap_mapping) связывает внутренние поля профиля вашей системы с соответствующими атрибутами в базе LDAP. Настроенная строка given_name:givenName, family_name:sn, email:mail автоматически переносит личные данные сотрудника при первом входе. Это избавляет от ручного заполнения карточек: имя (givenName), фамилия (sn) и электронная почта (mail) подтягиваются в профиль пользователя напрямую из ALD Pro.

Третье обязательное поле Логин администратора (aldpro_admin_dn) — это сервисная учетная запись (Bind DN), от имени которой система будет подключаться к каталогу. Введенный путь uid=admin,cn=users,cn=accounts,dc=ald,dc=company,dc=lan указывает на аккаунт администратора. Без этих учетных данных внешняя система не сможет авторизоваться в ALD Pro, а значит, не сможет выполнить поиск пользователей и проверить их пароли.

Рис.23. Параметры провайдера ALD Pro (часть 2)

Рис.23. Параметры провайдера ALD Pro (часть 2)

На третьем рисунке 24 показана финальная часть формы, где настраиваются параметры безопасности, кастомизация ошибок и интеграция со сквозной аутентификацией.

Первое обязательное поле Пароль администратора (aldpro_admin_pwd) служит для аутентификации сервисного аккаунта, указанного на предыдущем шаге. Введенный секретный ключ скрыт за маской (точками). Он необходим для того, чтобы система могла успешно авторизоваться (выполнить операцию LDAP Bind) на сервере ALD Pro и получить легитимные права на чтение каталога пользователей.

Поле Текст ошибки при смене пароля (password_error) отвечает за понятное информирование пользователей. Введенное значение «Пароль слишком простой» будет отображаться сотруднику, если служба ALD Pro вернет специфический код ошибки 0000052D при попытке обновить учетные данные. Это русифицирует стандартные системные ответы каталога, делая интерфейс более дружелюбным.

Ниже расположены два важных переключателя. Опция Запретить сброс пароля в данном случае выключена. Если её активировать, пользователи не смогут сбросить или восстановить свой пароль штатными средствами подключаемой системы. Опция Использовать Kerberos включена, что активирует бесшовный вход в систему (silent SSO) через браузер. При этом интеграция работает автоматически через механизм Negotiate, а обычная LDAP-форма используется как резервный вариант (Fallback), если Kerberos-авторизация не сработает.

Рис.24. Параметры провайдера ALD Pro (часть 3)

Рис.24. Параметры провайдера ALD Pro (часть 3)

На четвертом рисунке 25 представлена дополнительная часть формы, которая становится доступной при включении тумблера «Использовать Kerberos». Здесь настраиваются опциональные параметры для работы технологии сквозной аутентификации (Single Sign-On).

Первое поле Kerberos service principal (optional) позволяет вручную задать уникальный идентификатор службы (SPN). Полный вариант выглядит как HTTP@id.example.local и используется для корректного приема браузерного билета аутентификации (Negotiate-ticket). Если администратор заполняет это поле, оно получает наивысший приоритет, переопределяя автоматические алгоритмы системы.

Второе поле Kerberos hostname (optional) предназначено для указания конкретного сетевого имени узла. Оно используется бэкендом для автоматического конструирования имени сервис-принципала, если первое поле осталось пустым. Если это текстовое поле не заполнять, система автоматически подставит текущее доменное имя (hostname) самого веб-сервиса, на котором развернуто приложение.

Третье поле Kerberos service name (optional) определяет класс или имя самой службы в контексте Kerberos. Подсказка под формой указывает, что для веб-приложений это значение обычно оставляют пустым или вручную вписывают туда стандартный протокол HTTP. Поля этой секции часто остаются незаполненными, если конфигурация сети позволяет серверу определить параметры авторизации автоматически.

Рис.25. Настройки Kerberos

Рис.25. Настройки Kerberos

Сквозная аутентификация по Kerberos

После того как интеграция с провайдером ALD Pro полностью сконфигурирована внутри панели администрирования, можно переходить к проверке сквозного входа (Single Sign-On) на стороне реального пользователя.

Для чистоты эксперимента создадим в административной панели ALD Pro нового пользователя с доменным аккаунтом vtb. Чтобы КриптоАРМ ID смог первично зафиксировать эту учетную запись в своей базе и сопоставить атрибуты, пользователю необходимо выполнить первый ознакомительный вход. Сделать это можно стандартным способом — введя логин и пароль в веб-форме (рис. 26).

Рис.26. Пользователь vtb успешно прошел аутентификацию

Рис.26. Пользователь vtb успешно прошел аутентификацию

Убедившись, что первый вход прошел успешно, перейдем в панель управления учетными записями КриптоАРМ ID под правами администратора. В разделе «Пользователи» мы увидим, что профиль сотрудника создался автоматически. Все ключевые данные (Имя, Фамилия) и доменный статус подтянулись из каталога ALD Pro без ручного вмешательства администратора (рис. 27).

Рис.27. Учетные данные доменного пользователя vtb успешно подтянулись в систему

Рис.27. Учетные данные доменного пользователя vtb успешно подтянулись в систему

Теперь проверим работу механизма Silent SSO (входа без ввода пароля). Для этого нам понадобится активный Kerberos-билет (TGT) в кеше операционной системы. Не выходя из текущего сеанса Linux, откроем консоль и принудительно запросим билет для нашего тестового пользователя с помощью стандартной утилиты kinit:

kinit vtb@ALD.COMPANY.LAN

Проверим выдачу билета (рис. 28):

Рис.28. Учетные данные доменного пользователя vtb успешно подтянулись в систему

Рис.28. Учетные данные доменного пользователя vtb успешно подтянулись в систему

Успешный вход пользователя vtb без ввода пароля наглядно доказывает, что базовый сценарий сквозной аутентификации Kerberos (SPNEGO/Negotiate) работает без нареканий. Браузер корректно извлек «цифровой паспорт» из кэша операционной системы Linux и передал его бэкенду КриптоАРМ ID, который, в свою очередь, успешно верифицировал тикет через локальный Keytab-файл (рис. 29).

Рис.29. Успешный вход в систему пользователя vtb по протоколу Kerberos

Рис.29. Успешный вход в систему пользователя vtb по протоколу Kerberos

Однако на этом возможности интеграции не ограничиваются. После того как КриптоАРМ ID успешно опознал доменного пользователя по Kerberos, платформа начинает выступать в роли доверенного провайдера идентичности (IdP — Identity Provider).

Это открывает возможность для сквозной авторизации в любых сторонних корпоративных приложениях (CRM, трекеры задач, внутренние порталы), поддерживающих современный протокол OAuth 2.0 / OpenID Connect (OIDC). За этот функционал в архитектуре КриптоАРМ ID отвечает отдельный микросервис id-oidc, который разворачивается в общем Docker-контуре.

На практике это работает следующим образом:

  1. Администратор один раз регистрирует внешнее веб-приложение в панели КриптоАРМ ID, генерируя пару Client ID и Client Secret.

  2. Когда пользователь пытается зайти, например, в корпоративную базу знаний, сайт перенаправляет его на страницу авторизации КриптоАРМ ID.

  3. Поскольку сессия пользователя уже открыта благодаря Kerberos, КриптоАРМ ID мгновенно и незаметно для человека выписывает OAuth-токен.

  4. Пользователь автоматически «проваливается» в целевое приложение, вообще не видя окон ввода логина или пароля.

Такой гибридный подход позволяет связать классическую «строгую» безопасность домена ALD Pro (FreeIPA) с гибкостью современных веб-сервисов, создавая полностью бесшовную рабочую среду для сотрудников.

Заключение

В ходе работы мы подробно разобрали, как устроена сквозная аутентификация в Linux-среде на базе отечественного каталога ALD Pro (FreeIPA). Мы прошли весь путь: от низкоуровневой настройки конфигурационных файлов и разбора Kerberos-флагов до написания сервисных скриптов на Node.js, работающих автономно через Keytab-файлы.

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

  • Простая интеграция с ALD Pro: данные доменных пользователей и маппинг атрибутов настраиваются через понятный веб-интерфейс.

  • Стабильный Silent SSO: после добавления JSON-политик в браузеры сквозная Kerberos-аутентификация работает без сбоев и повторных запросов пароля.

  • Удобная контейнеризация: поставка в Docker-compose со встроенным Traefik позволяет быстро развернуть систему на нестандартных портах и легко подключить доменные SSL-сертификаты.

  • Функция полноценного IdP (Identity Provider): поскольку пользователь уже успешно аутентифицирован внутри домена через Kerberos, КриптоАРМ ID позволяет подключать внешние корпоративные приложения по протоколу OAuth (через встроенный модуль OIDC). Это дает сотрудникам возможность бесшовно «проваливаться» в сторонние веб-ресурсы и сервисы без повторного ввода учетных данных.

  • Надежная защита учетных данных: связка Kerberos и PKI исключает передачу паролей в открытом виде по сети.

Проведенное исследование доказывает, что переход на связку ALD Pro и КриптоАРМ ID позволяет сохранить привычный для пользователей уровень комфорта за счет технологии единого входа (SSO). При этом администраторы получают гибкую, безопасную и полностью контролируемую систему управления цифровыми профилями внутри локальной сети.

ссылка на оригинал статьи https://habr.com/ru/articles/1036670/