Интеграция с LDAP

Tengri может аутентифицировать пользователей во внешнем LDAP — контроллере домена Active Directory или другом LDAP-сервере — по зашифрованному соединению. На этой странице описано, как подключить LDAP, сопоставить его учетные записи пользователям Tengri и проверить результат.

Обзор

LDAP регистрируется как поставщик идентификационной информации, наряду с SAML. Tengri позволяет связать пользователя внутри системы и пользователя в LDAP.

Связывание учетных записей возможно и для служебных, и для обычных УЗ:

Служебные учетные записи

Перед запуском внутренней подсистемы Tengri проверяет, что сопоставленная ей учетная запись в LDAP все еще включена.

Обычные пользователи

Имя входа и пароль проверяются подключением к LDAP, а результат сопоставляется пользователю Tengri, с которым связана эта учетная запись.

Вход через LDAP работает только по явной связи. Администратор заранее создает пользователя в Tengri и связывает его с учетной записью LDAP. Вход с идентификатором, который еще не связан, отклоняется: Tengri никогда не создает пользователя автоматически при входе и не выводит роли из групп LDAP.

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

Tengri принимает одну привязку к LDAP. Создание второй отклоняется, а вход всегда разрешается через единственную включенную привязку — выбрать LDAP во время входа нельзя. Несколько контроллеров домена поддерживаются как несколько узлов внутри этой одной привязки.

Перед началом

Вам потребуются:

  • Работающий сервер Tengri с настроенным мастер-ключом.

  • Контроллер домена, доступный по LDAPS, обычно на порту 636, либо по LDAP со StartTLS.

  • Учетная запись только для чтения в LDAP. Tengri подключается под ней для поиска пользователей.

  • Сертификат CA, которым подписан сертификат контроллера домена, в формате PEM.

Обычный LDAP на порту 389 отклоняется. Простое подключение передало бы пароль в открытом виде, поэтому любая привязка, транспорт которой не LDAPS и не StartTLS, отклоняется при создании — а не позже, при входе.

Без мастер-ключа подсистема LDAP недоступна без явных сообщений: расшифровать привязку нечем, поэтому вход через LDAP завершается обычной ошибкой учетных данных. Если ничего в интеграции не работает, проверьте мастер-ключ в первую очередь.

Создание привязки

Привязки создаются на SQL или на странице LDAP в интерфейсе администрирования. Выполните от имени администратора:

CREATE IDP 'corp-ad' PROTOCOL ldaps DISPLAY NAME 'Corp Active Directory'
  WITH (
    host          = 'dc1.corp.example.com,dc2.corp.example.com',
    port          = 636,
    tls           = 'ldaps',
    ca_cert       = '-----BEGIN CERTIFICATE-----
...
-----END CERTIFICATE-----',
    bind_dn       = 'CN=svc-tngri,OU=Service,DC=corp,DC=example,DC=com',
    bind_password = '<секрет>',
    base_dn       = 'DC=corp,DC=example,DC=com',
    user_filter   = '(sAMAccountName={username})',
    login_attr    = 'sAMAccountName',
    group_attr    = 'memberOf'
  );

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

Проверка привязки

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

Успешная проверка показывает согласованный транспорт и контекст именования LDAP:

ok
host=dc1.corp.example.com port=636 tls=ldaps
tls_version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384
naming_context=dc=corp,dc=example,dc=com

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

Изменение привязки дополняет сохраненную конфигурацию, а не заменяет ее целиком, поэтому оставленный пустым пароль подключения сохраняет уже записанный секрет. При выводе конфигурации пароль всегда маскируется.

Связывание служебных учетных записей

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

Примером такой системы является процесс оптимизации хранимых файлов (compaction).

Учетная запись в LDAP может называться иначе, чем пользователь Tengri:

prostore user edit --username compaction \
  --ldap-idp corp-ad \
  --ldap-principal svc-tngri-compaction

Вы указываете имя принципала в LDAP. Tengri находит эту запись и сохраняет собственный неизменяемый идентификатор LDAP — именно он позволяет связи пережить переименование.

Отключение этой учетной записи в LDAP теперь не даст подсистеме запуститься при следующем перезапуске, и отказ будет записан в журнал аудита.

Веб-приложение и websocket используют одну служебную учетную запись, поэтому ее блокировка останавливает оба. Заблокированная учетная запись останавливает только свою подсистему, остальная часть системы продолжает работать.

Если LDAP недоступен, результат проверки считается неопределенным: запуск продолжается на локальных учетных данных, с предупреждением в журнале. Подсистему останавливает только однозначный ответ «учетная запись отключена». Недоступность контроллера не должна останавливать платформу.

Определение отключенной учетной записи опирается на атрибут, который для этого использует Active Directory. Серверы LDAP, не публикующие такой атрибут, дают сведения о состоянии только самим фактом существования записи, а нечитаемое значение трактуется как «включена».

Сопоставление учетных записей LDAP пользователям

На этом шаге учетная запись LDAP связывается с пользователем Tengri. Связь задается явно: Tengri не считает, что учетная запись LDAP alice.smith — это локальный пользователь alice.

Способов два, и они различаются тем, включается ли вместе со связью вход через LDAP. Это различие — самая частая неожиданность в этой возможности.

Средствами SQL

-- создать пользователя, который аутентифицируется только через LDAP
CREATE USER alice IDENTIFIED BY LDAP IDP 'corp-ad' PRINCIPAL 'alice.smith'
  DEFAULT WORKER POOL default;

-- либо связать существующего пользователя с учетной записью LDAP
ALTER USER alice IDENTIFIED BY LDAP IDP 'corp-ad' PRINCIPAL 'alice.smith';

Оба варианта во время выполнения обращаются к LDAP, сохраняют полученный идентификатор и сразу включают вход через LDAP — что одновременно отключает локальный пароль. Используйте этот способ, если пользователь должен стать пользователем LDAP с этого момента.

Снять связь:

ALTER USER alice RESET IDENTIFIED BY LDAP;

Средствами командной строки

prostore user edit --username alice \
  --ldap-idp corp-ad \
  --ldap-principal alice.smith

Связь записывается и идентификатор определяется, но вход через LDAP остается выключенным: пользователь продолжает входить как раньше. Это подходящий способ для поэтапного перехода, и именно на нем основана проверка служебных учетных записей выше.

Вход через LDAP включается отдельным осознанным шагом:

prostore user edit --username alice --enable-ldap

Обратные действия — --disable-ldap, либо --unlink-ldap, чтобы полностью снять связь.

Что дает каждое состояние

Один пользователь, проведенный через весь жизненный цикл, и результат после каждого шага:

После шага Локальный пароль сохранен Вход через LDAP Локальный пароль принимается Пароль LDAP принимается

пользователь создан с локальным паролем

да

выкл

да

нет

учетная запись связана

да

выкл

да

нет

вход через LDAP включен

да

вкл

нет

да

связь снята

да

выкл

да

нет

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

У пользователя, созданного через CREATE USER …​ IDENTIFIED BY LDAP, локального пароля никогда не было. Снятие связи оставит его вообще без пригодного способа входа, и вход завершится ошибкой auth unavailable. Задайте такому пользователю пароль до снятия связи.

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

Вход в систему

Веб-интерфейс

Точка входа сначала проверяет локальный пароль и при неудаче обращается к LDAP. Настраивать ничего не нужно, отдельной формы входа через LDAP нет.

Протокол PostgreSQL

Пользователи из LDAP аутентифицируются методом передачи пароля внутри обязательного туннеля TLS — то же ограничение действует и в собственной аутентификации PostgreSQL через LDAP.

TLS именно требуется, а не рекомендуется: без него соединение прерывается до передачи пароля.

psql "host=tengri.example.com port=5432 user=alice sslmode=require"

Подключение к LDAP выполняется с сохраненным именем входа, а не с тем, что введено в приглашении, и отклоняется, если возвращенный из LDAP идентификатор больше не совпадает с сохраненным.

Задания по расписанию

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

Меры защиты

Обеспечиваются продуктом и не настраиваются.

Мера Поведение

Транспорт

Только LDAPS или StartTLS; обычное подключение отклоняется при создании привязки

Проверка сертификата

Включена по умолчанию

Пустой пароль

Отклоняется до обращения к LDAP — пустой пароль означает анонимное подключение, которое иначе выглядело бы как успех

Подстановка в фильтр

Имя входа экранируется перед подстановкой в фильтр поиска

Перенаправления

Переход по перенаправлениям отключен, соответствующие ответы отбрасываются

Соединение

Только для чтения, с тайм-аутами подключения и приема

Подбор паролей

Вход через LDAP проходит через ту же блокировку и ограничение по адресу, что и локальный, со случайной задержкой при неудаче

Параметры привязки

Хранятся в зашифрованном виде вместе с привязкой. Задаются в CREATE IDP или ALTER IDP, либо на странице администрирования LDAP.

Параметр Тип По умолчанию Описание

host

строка или список

обязательный

Один или несколько узлов контроллеров. Несколько узлов перебираются циклически при отказе.

port

int

636

Порт LDAP.

tls

ldaps | starttls

ldaps

Защита транспорта. Другие значения отклоняются.

ca_cert

PEM

пусто

Набор сертификатов CA, по которому проверяется сертификат контроллера. Пустое значение означает системное хранилище доверия.

require_cert

bool

true

Проверять сертификат контроллера. Значение false снимает эту защиту.

timeout

int, секунды

10

Тайм-аут подключения и приема. Должен быть положительным.

bind_dn

строка

обязательный

Различающееся имя учетной записи для поиска.

bind_password

строка

обязательный

Ее пароль. Маскируется при выводе; при изменении можно не указывать, чтобы сохранить записанный.

base_dn

строка

обязательный

База поиска пользователей.

user_filter

строка

(sAMAccountName={username})

Фильтр поиска. Должен содержать {username}, который экранируется перед подстановкой.

login_attr

строка

sAMAccountName

Атрибут с именем входа.

uid_attr

строка

objectGUID

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

display_name_attr

строка

displayName

Атрибут отображаемого имени.

email_attr

строка

mail

Атрибут адреса электронной почты.

group_attr

строка

memberOf

Атрибут членства в группах. Считывается, но не используется для авторизации.

Для Active Directory значения по умолчанию верны. Для OpenLDAP задайте фильтр (uid={username}), атрибут имени входа uid, атрибут идентификатора entryUUID и атрибут отображаемого имени cn.

Сохраняемый идентификатор приводится к единому виду: 16-байтовый идентификатор Active Directory становится обычной строкой UUID, остальные значения кодируются. Замена атрибута идентификатора после связывания пользователей делает недействительными все сохраненные связи.

Жизненный цикл привязки

Операция Влияние на связанных пользователей

Переименование привязки

Ссылка обновляется у всех связанных пользователей.

Отключение привязки

Вход через LDAP перестает разрешаться, связи сохраняются.

Удаление привязки

Отклоняется, пока есть связанные пользователи.

Удаление привязки с CASCADE

Снимает связь с LDAP у всех связанных пользователей.

Коды ошибок

Проверка возвращает устойчивый код, который показывается при проверке соединения и в журнале сервера.

Код Значение

config_invalid

Параметры отклонены до обращения к сети — чаще всего это обычный LDAP или фильтр без подстановки имени входа.

connect_failed

LDAP недоступен: неверный узел или порт, межсетевой экран либо неудачное установление TLS.

bind_failed

Не удалось подключиться учетной записи для поиска — неверное имя или пароль.

invalid_credentials

LDAP отклонил пароль пользователя.

empty_password

Передан пустой пароль; отклонен до обращения к LDAP.

user_not_found

Ни одна запись не совпала с фильтром поиска.

link_target_missing

Вход через LDAP включен для пользователя без связи.

master_key_missing

Мастер-ключ не задан, расшифровать привязку невозможно.

Устранение неполадок

Обычный LDAP отклонен

Транспорт привязки не указан или отличается от LDAPS и StartTLS.

Ошибка сертификата в журнале

Сертификат контроллера не выстраивается в цепочку к указанному набору CA. Исправьте набор. Отключение проверки подтвердит диагноз, но оставит соединение открытым для перехвата — это не рабочее состояние.

--ldap-idp and --ldap-principal must be given together

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

cannot enable LDAP auth

Вход через LDAP включается для пользователя без связи. Сначала создайте связь.

Конфликт при связывании

Пользователь уже связан с другой учетной записью LDAP. Если переназначение намеренное, сначала снимите текущую связь.

auth unavailable

У пользователя не осталось включенных способов входа — обычно это созданный через LDAP пользователь, у которого сняли связь. Задайте ему локальный пароль.

An IdP with protocol 'ldaps' already exists

Поддерживается только одна привязка к LDAP. Измените существующую вместо создания второй.

has N user(s) assigned; use CASCADE to also revoke

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

Подсистема не запустилась

Учетная запись LDAP, сопоставленная ее служебному пользователю, отключена или удалена. Включите ее в LDAP или снимите связь.