ALD Pro — российская служба каталогов на основе FreeIPA: данные пользователей и групп хранятся в 389 Directory Server, аутентификация выполняется через MIT Kerberos. Stronghold подключается к ALD Pro как к обычному LDAP-серверу, а при необходимости — как к центру распределения ключей Kerberos.

Цель

После настройки:

  • Пользователи домена ALD Pro входят в Stronghold под своими доменными учётными записями через метод ldap.
  • Права в Stronghold назначаются по членству в группах ALD Pro.
  • Пользователи с действующим билетом Kerberos входят без ввода пароля (метод kerberos, необязательно; только Stronghold EE).
  • Пароли служебных учётных записей домена ротирует Stronghold через механизм секретов LDAP.

Схема входа через LDAP в ALD Pro

Предварительные требования

Перед началом подготовьте:

  • Развёрнутый домен ALD Pro, например ald.example.com с контроллерами dc01.ald.example.com и dc02.ald.example.com.
  • Сетевой доступ от узлов Stronghold к контроллерам домена по порту 636 (LDAPS), а для Kerberos — по порту 88.
  • Сертификат корневого УЦ домена. На любом узле, введённом в домен, он находится в файле /etc/ipa/ca.crt.
  • Токен Stronghold с правами на настройку методов аутентификации, механизмов секретов, политик и Identity.
  • Утилиты ldapsearch и jq на рабочей станции администратора.

В примерах используется базовый DN dc=ald,dc=example,dc=com. Замените его на DN своего домена.

Шаг 1. Подготовьте служебную учётную запись для поиска

Stronghold ищет пользователей и группы от имени отдельной учётной записи с правами только на чтение. Не используйте для этого учётные записи администраторов домена.

  1. Создайте системную учётную запись (sysaccount) в ALD Pro. В FreeIPA это делается LDIF-файлом от имени cn=Directory Manager:

    dn: uid=stronghold-bind,cn=sysaccounts,cn=etc,dc=ald,dc=example,dc=com
    changetype: add
    objectclass: account
    objectclass: simplesecurityobject
    uid: stronghold-bind
    userPassword: <BIND_PASSWORD>
    passwordExpirationTime: 20380119031407Z
    nsIdleTimeout: 0
    ldapmodify -x -H ldaps://dc01.ald.example.com -D "cn=Directory Manager" -W -f stronghold-bind.ldif

    <BIND_PASSWORD> — пароль учётной записи stronghold-bind.

    Если системные учётные записи в вашей инсталляции не используются, создайте обычного пользователя домена с бессрочным паролем и укажите его DN uid=stronghold-bind,cn=users,cn=accounts,dc=ald,dc=example,dc=com.

  2. Скопируйте сертификат УЦ домена на рабочую станцию, с которой настраиваете Stronghold:

    scp admin@dc01.ald.example.com:/etc/ipa/ca.crt ./ald-ca.crt
  3. Проверьте, что учётная запись видит пользователей и группы по LDAPS:

    LDAPTLS_CACERT=./ald-ca.crt ldapsearch -x -H ldaps://dc01.ald.example.com -D "uid=stronghold-bind,cn=sysaccounts,cn=etc,dc=ald,dc=example,dc=com" -W -b "cn=users,cn=accounts,dc=ald,dc=example,dc=com" "(uid=ivanov)" uid memberOf

    В выводе должны быть атрибут uid пользователя и список групп в memberOf.

Шаг 2. Настройте метод LDAP

Включите метод ldap, подключите его к контроллерам домена и проверьте вход.

  1. Включите метод аутентификации:

    d8 stronghold auth enable ldap
  2. Настройте подключение к ALD Pro. Группы ищутся по атрибуту member объектов групп:

    d8 stronghold write auth/ldap/config url="ldaps://dc01.ald.example.com:636,ldaps://dc02.ald.example.com:636" certificate=@ald-ca.crt insecure_tls=false starttls=false binddn="uid=stronghold-bind,cn=sysaccounts,cn=etc,dc=ald,dc=example,dc=com" bindpass='<BIND_PASSWORD>'
    d8 stronghold write auth/ldap/config userdn="cn=users,cn=accounts,dc=ald,dc=example,dc=com" userattr="uid" groupdn="cn=groups,cn=accounts,dc=ald,dc=example,dc=com" groupfilter="(&(objectClass=groupOfNames)(member={{.UserDN}}))" groupattr="cn" username_as_alias=true

    <BIND_PASSWORD> — пароль учётной записи stronghold-bind из шага 1. Первая команда настраивает подключение, вторая — поиск пользователей и групп.

    Основные параметры:

    ПараметрЗначение для ALD Pro
    urlСписок контроллеров домена через запятую. Stronghold перебирает их по порядку при ошибке подключения.
    certificateСертификат УЦ домена из /etc/ipa/ca.crt.
    insecure_tlsfalse — проверка сертификата сервера обязательна.
    starttlsfalse для ldaps://. Если используется ldap:// на порту 389, укажите true.
    userdn, userattrКонтейнер пользователей FreeIPA и атрибут входа uid.
    groupdn, groupfilter, groupattrКонтейнер групп и фильтр, который находит группы, где пользователь указан в member. Имя группы берётся из cn.
    username_as_aliasИмя псевдонима сущности совпадает с именем пользователя в домене.

    Альтернативный вариант — читать группы из атрибута memberOf объекта пользователя:

    d8 stronghold write auth/ldap/config groupdn="cn=users,cn=accounts,dc=ald,dc=example,dc=com" groupfilter="(&(objectClass=person)(uid={{.Username}}))" groupattr="memberOf"

    В этом случае в список групп попадут и роли, привилегии, правила HBAC и другие объекты, в которых состоит пользователь. Вариант с member возвращает только группы из cn=groups,cn=accounts.

    Запись в auth/ldap/config меняет только параметры, переданные в команде. Остальные параметры сохраняют текущие значения.

  3. Проверьте вход под доменной учётной записью:

    d8 stronghold login -method=ldap username=ivanov

    Имя пользователя указывается без домена. Если группам ещё не назначены политики, токен получит только политику default.

Шаг 3. Сопоставьте группы ALD Pro с политиками

Используйте один из двух способов. Не назначайте политики одной и той же группе обоими способами — это усложняет аудит прав.

Через группы метода LDAP

Имя группы в Stronghold должно совпадать со значением cn группы в ALD Pro:

d8 stronghold write auth/ldap/groups/stronghold-admins policies=admin
d8 stronghold write auth/ldap/groups/developers policies=dev-read

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

Через внешние группы Identity

Внешние группы позволяют назначить политики один раз и использовать их для нескольких методов входа (например, ldap и kerberos), а также применять к группе правила MFA.

  1. Создайте внешнюю группу и сохраните её идентификатор:

    GROUP_ID=$(d8 stronghold write -field=id identity/group name="ald-stronghold-admins" type="external" policies="admin")
  2. Получите accessor метода ldap/:

    LDAP_ACCESSOR=$(d8 stronghold auth list -format=json | jq -r '."ldap/".accessor')
  3. Создайте псевдоним группы. Значение name должно совпадать с именем группы в ALD Pro:

    d8 stronghold write identity/group-alias name="stronghold-admins" mount_accessor="$LDAP_ACCESSOR" canonical_id="$GROUP_ID"

Stronghold обновляет членство сущности во внешних группах при каждом входе и продлении токена. Изменения групп в ALD Pro применяются к выданным токенам при их продлении.

Шаг 4. Настройте единый вход по Kerberos (необязательно)

Метод kerberos принимает заголовок SPNEGO от клиента с действующим билетом Kerberos, а группы пользователя получает из LDAP. Параметры метода описаны в справочнике API методов аутентификации.

Метод аутентификации kerberos доступен только в Stronghold EE. Проверьте сценарий на тестовом стенде перед внедрением.

  1. Создайте в ALD Pro сервисный принципал для HTTP-адреса Stronghold и получите keytab:

    kinit admin
    ipa service-add HTTP/stronghold.ald.example.com
    ipa-getkeytab -s dc01.ald.example.com -p HTTP/stronghold.ald.example.com -k stronghold.keytab
  2. Включите метод. Метод читает токен SPNEGO из заголовка запроса Authorization и возвращает заголовок WWW-Authenticate, поэтому разрешите оба заголовка для подключения:

    d8 stronghold auth enable -passthrough-request-headers=Authorization -allowed-response-headers=www-authenticate kerberos

    Если метод уже включён, задайте те же заголовки для существующего подключения:

    d8 stronghold auth tune -passthrough-request-headers=Authorization -allowed-response-headers=www-authenticate kerberos/
  3. Передайте keytab в кодировке Base64:

    base64 -w0 stronghold.keytab > stronghold.keytab.b64
    d8 stronghold write auth/kerberos/config keytab=@stronghold.keytab.b64 service_account="HTTP/stronghold.ald.example.com" add_group_aliases=true

    С add_group_aliases=true метод передаёт группы пользователя из LDAP в Identity как псевдонимы групп, и внешние группы Identity работают для метода kerberos. Каждая запись в auth/kerberos/config заменяет конфигурацию целиком: передавайте keytab, service_account и add_group_aliases в одной команде.

    Значение service_account — имя принципала в keytab в том же виде, что и в ipa-getkeytab -p (HTTP/<FQDN>). Не указывайте для этого принципала remove_instance_name=true: параметр убирает instance (часть после /) из имён принципалов в keytab и из имени пользователя при входе, и запись HTTP/stronghold.ald.example.com перестанет совпадать.

  4. Настройте поиск групп в LDAP. Параметры auth/kerberos/config/ldap совпадают с параметрами auth/ldap/config:

    d8 stronghold write auth/kerberos/config/ldap url="ldaps://dc01.ald.example.com:636,ldaps://dc02.ald.example.com:636" certificate=@ald-ca.crt insecure_tls=false binddn="uid=stronghold-bind,cn=sysaccounts,cn=etc,dc=ald,dc=example,dc=com" bindpass='<BIND_PASSWORD>'
    d8 stronghold write auth/kerberos/config/ldap userdn="cn=users,cn=accounts,dc=ald,dc=example,dc=com" userattr="uid" groupdn="cn=groups,cn=accounts,dc=ald,dc=example,dc=com" groupfilter="(&(objectClass=groupOfNames)(member={{.UserDN}}))" groupattr="cn"

    <BIND_PASSWORD> — пароль учётной записи stronghold-bind из шага 1. Первая команда настраивает подключение, вторая — поиск пользователей и групп.

  5. Назначьте политики группам:

    d8 stronghold write auth/kerberos/groups/stronghold-admins policies=admin

    Если вы используете внешние группы Identity, создайте для каждой группы второй псевдоним с accessor метода kerberos/ вместо этого шага. Метод создаёт псевдонимы групп, только если в auth/kerberos/config задан add_group_aliases=true.

  6. Проверьте вход с машины, введённой в домен:

    kinit ivanov
    curl --negotiate -u : -X POST https://stronghold.ald.example.com/v1/auth/kerberos/login

    Запрос должен быть POST: GET по этому пути всегда возвращает 401 Negotiate. В ответе в поле auth.client_token вернётся токен Stronghold.

    Вход через d8 stronghold login -method=kerberos и в веб-интерфейсе не поддерживается: в CLI для kerberos не зарегистрирован обработчик входа, а веб-интерфейс позволяет только включить метод и не имеет формы входа для него. Используйте API, например curl.

Шаг 5. Ротируйте пароли служебных учётных записей

Механизм секретов LDAP меняет пароли существующих учётных записей домена и выдаёт их приложениям. Для ALD Pro используйте схему openldap: пароль хранится в атрибуте userPassword.

В FreeIPA пароль, заданный другой учётной записью, по умолчанию помечается как истёкший, и пользователь должен сменить его при следующем входе. Учётная запись, от имени которой Stronghold меняет пароли, должна входить в список passSyncManagersDNs записи cn=ipa_pwd_extop,cn=plugins,cn=config, иначе ротированные пароли будут сразу истекать.

  1. Создайте в ALD Pro учётную запись stronghold-rotator с правом менять пароли целевых служебных учётных записей.

  2. Включите механизм секретов и настройте подключение:

    d8 stronghold secrets enable ldap
    d8 stronghold write ldap/config url="ldaps://dc01.ald.example.com:636" certificate=@ald-ca.crt insecure_tls=false binddn="uid=stronghold-rotator,cn=users,cn=accounts,dc=ald,dc=example,dc=com" bindpass='<ROTATOR_PASSWORD>' userdn="cn=users,cn=accounts,dc=ald,dc=example,dc=com" userattr="uid" schema=openldap

    <ROTATOR_PASSWORD> — текущий пароль учётной записи stronghold-rotator.

  3. Смените пароль учётной записи stronghold-rotator, чтобы его знал только Stronghold:

    d8 stronghold write -f ldap/rotate-root

    Получить новый пароль после ротации нельзя. Если Stronghold потеряет доступ к ALD Pro, пароль придётся сбросить средствами домена.

Статическая роль

Статическая роль привязывает одну учётную запись домена к имени в Stronghold и меняет её пароль по расписанию:

d8 stronghold write ldap/static-role/svc-gitlab dn="uid=svc-gitlab,cn=users,cn=accounts,dc=ald,dc=example,dc=com" username="svc-gitlab" rotation_period="24h"

Приложение читает текущий пароль:

d8 stronghold read ldap/static-cred/svc-gitlab

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

d8 stronghold write -f ldap/rotate-role/svc-gitlab

Библиотека учётных записей (check-out)

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

d8 stronghold write ldap/library/ops-shared service_account_names="svc-ops1,svc-ops2" ttl=1h max_ttl=4h

Значения service_account_names сравниваются с атрибутом из userattr (здесь uid), поэтому указывайте значение uid, а не полный DN.

Выдача, проверка статуса и возврат:

d8 stronghold write -f ldap/library/ops-shared/check-out
d8 stronghold read ldap/library/ops-shared/status
d8 stronghold write ldap/library/ops-shared/check-in service_account_names="svc-ops1"

Пример политики для приложения и дежурных инженеров:

path "ldap/static-cred/svc-gitlab" {
  capabilities = ["read"]
}

path "ldap/library/ops-shared/check-out" {
  capabilities = ["update"]
}

path "ldap/library/ops-shared/check-in" {
  capabilities = ["update"]
}

path "ldap/library/ops-shared/status" {
  capabilities = ["read"]
}

Проверка

Проверьте результат:

  1. Войдите под пользователем из группы stronghold-admins и проверьте политики токена:

    d8 stronghold login -method=ldap username=ivanov
    d8 stronghold token lookup

    В policies (или identity_policies при использовании внешних групп) должна быть политика admin.

  2. Убедитесь, что пользователь не из группы получает только default.

  3. Прочитайте пароль статической роли и выполните с ним ldapsearch -D "uid=svc-gitlab,..." — вход должен пройти успешно.

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

Типовые ошибки и способы их устранения:

СимптомВероятная причинаЧто сделать
ldap operation failed: failed to bind as user или Invalid Credentials при входеНеверный пароль пользователя, неверный userdn/userattr или неверный пароль binddnПроверьте поиск и bind командой ldapsearch из шага 1. Проверьте, что пользователь находится в cn=users,cn=accounts.
x509: certificate signed by unknown authorityВ certificate не указан УЦ домена или указан не тот сертификатПередайте /etc/ipa/ca.crt в certificate. Не включайте insecure_tls.
x509: certificate is valid for ..., not ...Адрес в url не совпадает с именем в сертификате контроллераУказывайте FQDN контроллеров, а не IP-адреса.
Вход проходит, но токен получает только defaultgroupfilter не находит группы или имена групп не совпадают с auth/ldap/groups/<GROUP_NAME> и псевдонимамиВыполните ldapsearch с фильтром из groupfilter, подставив DN пользователя. Сравните cn групп с именами в Stronghold.
Пользователь не может войти после нескольких неудачных попыток, пароль верныйСработала блокировка Stronghold (lockout_threshold, по умолчанию 5 попыток на 15 минут) или учётная запись заблокирована в ALD ProДождитесь окончания lockout_duration или проверьте статус учётной записи в ALD Pro. Настройки блокировки описаны в разделе «Метод LDAP».
Приложение не может войти с паролем из static-credПароль помечен в ALD Pro как истёкшийДобавьте учётную запись Stronghold в passSyncManagersDNs и выполните rotate-role.

Очистка

Отключите методы аутентификации и механизм секретов:

d8 stronghold auth disable kerberos
d8 stronghold auth disable ldap
d8 stronghold secrets disable ldap

При отключении механизма секретов пароли учётных записей не меняются. Смените их средствами ALD Pro, а затем удалите учётные записи stronghold-bind и stronghold-rotator.

Дополнительные ресурсы