Avanpost FAM/MFA+ : Настройка LDAP с Microsoft Active Directory (MS AD) в качестве источника пользователей

Настройка LDAP с Microsoft Active Directory (MS AD) в качестве источника пользователей

Общие сведения

Avanpost FAM обладает встроенной функциональностью LDAP-синхронизации и LDAP-аутентификации. В статье описывается настройка интеграции с Microsoft Active Directory в качестве поставщика информации о пользователях, членстве пользователей в группах и в качестве средства проверки паролей. Интеграция осуществляется посредством протокола LDAP.

Механизм интеграции Avanpost FAM с MS AD посредством LDAP может применяться при решении следующих задач:

  1. Первичная загрузка данных о пользователях из домена MS AD.
  2. Поддержка актуальности данных о пользователях при их изменении в домене MS AD.
  3. Загрузка информации о членстве пользователей в группах в MS AD.
  4. Проверка пароля в MS AD при 2FA/MFA для корпоративных ресурсов.
  5. Проверка пароля в MS AD при 2FA для серверов и компьютеров под управлением Windows и Linux.

Avanpost FAM поддерживает одновременную интеграцию с несколькими доменами, в качестве которых могут выступать экземпляры MS AD и другие LDAP-каталоги (OpenLDAP, FreeIPA, Avanpost DS и т.д.).

Системные требования для интеграции Avanpost FAM:

  1. Сервер Microsoft Active Directory на базе Microsoft Windows Server 2012R2, Microsoft Windows Server 2016, Microsoft Windows Server 2019, Microsoft Windows Server 2022.
  2. Сервер Avanpost FAM 1.3+.

Настройка

Настройка на стороне Microsoft Active Directory

  1. Создать служебную УЗ c полномочиями Domain Users.
  2. Убедиться, что открыт LDAP-интерфейс.
  3. На стороне MS AD получить значения параметров, которые далее будут использованы для настройки на стороне Avanpost FAM.
    • значение IP-адреса или DNS-имя сервера MS AD;
    • значение порта LDAP-интерфейса сервера MS AD;
    • значение Base Distinguished Name (Base DN).
    • логин и пароль служебной УЗ в MS AD.



Настройка на стороне Avanpost FAM в случае первичной синхронизации

 1. В разделе «Настройки LDAP-провайдеров» создать новый провайдер.

Пример настроенной вкладки «Подключение» при подключении к Microsoft Active Directory:

2. На вкладке/шаге визарда создания нового LDAP-провайдера «Подключение» указать значения параметров:

ПараметрЧто указатьПримеры значений
Вкладка/шаг визарда «Подключение»
Тип LDAPТип LDAP-провайдера.Active Directory
HostIP-адрес или DNS имя контроллера домена.

Пример IP-адреса: 10.10.17.91,

Пример имени контроллера домена: dc-ad.avanpost.demo

PortПорт подключения к LDAP-каталогу.

Без TLS (LDAP): 389.

С TLS (LDAPS): 636.

SSLФункция включения поддержки подключения к LDAP-каталогу по протоколу LDAPS с TLS-шифрованием.

Включено или выключено; рекомендуется использовать TLS

BaseDNОбъект каталога, с которого производится поиск.DC=avanpost,DC=demo
Имя пользователяИмя служебной УЗ в виде DN, используемая для импорта УЗ и для проверки существования УЗ в LDAP-каталоге при попытке аутентифицироваться с использованием пароля от УЗ в домене.CN=famuser,OU=special,DC=avanpost,DC=demo
ПарольПароль от служебной УЗ.P@ssw0rd!

Расписание запуска синхронизации (Cron с секундами)

5-ти символьный формат cron  / 6-ти символьный формат quartz (секунды).0 30 12 * * *

Пример настроенной вкладки создания нового LDAP-провайдера «Подключение»:


3. На вкладке/шаге визарда «Интеграция» в секции «Настройка импорта пользователей» указать значения параметров:

ПараметрЧто указатьПримеры значений
Вкладка/шаг визарда «Интеграция», раздел «Настройки импорта пользователей»
Фильтр поиска пользователейLDAP-фильтр для импорта пользователей.(&(objectClass=user)(objectCategory=person)(memberof=CN=VPN,OU=FAM,DC=avanpost,DC=demo))
Фильтр поиска аутентифицируемого пользователя

LDAP-фильтр для поиска пользователей, проверка пароля которых будет выполняться в MS AD.

Чтобы для пользователей из этого домена MS AD проверка пароля выполнялась в LDAP-каталоге, то необходимо указать значение LDAP-фильтра. Иначе оставить пустое значение параметра.

(&(objectClass=user)(samAccountName=%s))
LDAP атрибут, содержащий логин пользователяПараметр, на основании которого будет сформирован логин в Avanpost FAM. Для MS AD обычно используется sAMAccountName.sAMAccountName
Внешний ключ УЗУникальный ключ (атрибут пользователя) в MS AD

objectSid


Не рекомендуется использовать атрибут DN в качестве внешнего ключа УЗ. Если уже указан атрибут DN и была выполнена синхронизация с AD, то необходимо использовать для настройки инструкцию по настройке при повторной синхронизации.

Атрибут для связывания УЗ из LDAP c УЗ IDPПараметр для проверки уникальности учетной записи в MS AD.userPrincipalName
Атрибут пользователя (или DN), перечисляемый в поле member группы LDAPНаименование атрибута пользователя, по которому будет производиться поиск пользователей по группам.DN
Импорт дополнительных атрибутов УЗМаппинг импорта дополнительных атрибутов из AD в FAMПриложение В

Пример настроенной вкладки визарда «Интеграция» в секции «Настройка импорта пользователей». При установленном флаге «Обновлять данные пользователя в процессе аутентификации» данные пользователя (такие какие как имя, фамилия и пр.) обновляются при аутентификации пользователя в системах, доступ к которым идёт через FAM, не дожидаясь синхронизации с доменом по расписанию. При установленном флаге «Обновлять пароль в процессе аутентификации» по тому же принципу будет обновляться и пароль:

4. На вкладке/шаге визарда «Интеграция» в секции «Настройка импорта групп» указать значения параметров:

ПараметрЧто указатьПримеры значений
Вкладка/шаг визарда «Интеграция», раздел «Настройки импорта групп»
Фильтр поиска группLDAP-фильтр для импорта групп. Если в  данной настройке будут найдены пользователи из «Фильтр поиска пользователей», то их учетные записи автоматически попадут в эту группу в FAM.(&(objectClass=group)(CN=VPN))
Атрибут наименования группыАтрибут AD с наименованием группы.CN
Атрибут описания группыАтрибут AD с описанием группы.description
Атрибут со списком участников группыАтрибут AD со списком пользователей группы.member

Пример настроенной вкладки визарда «Интеграция» в секции «Настройка импорта групп»:


5. Убедиться, что провайдер находится в статусе «Active».

Настройка на стороне Avanpost FAM в случае осуществленной ранее синхронизации с AD

В случае, если уже была успешная синхронизация с AD, следует:

  1. Сделать копию (бэкап) базы данных и сервера перед выполнением данной инструкции.
  2. Добавить дополнительный атрибут учётной записи в настройках FAM.

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

5. После необходимо перейти к настройкам интеграции и остановить синхронизацию.


6. Далее подключиться к базе данных под пользователем, указанным в секции настроек базы данных конфигурационного файла config.toml.

7. Выполнить следующий SQL-запрос:

UPDATE public.user_external_ids
SET  id_value=subq.value,
                 id_key='objectSid'
FROM (
                SELECT value, user_Id
                FROM public.user_custom_attributes
                WHERE attr_id=(SELECT id FROM public.user_custom_attributes_schema WHERE name='objectSid')) AS subq
WHERE subq.user_Id = public.user_external_ids.user_id
;

 8. В настройках FAM необходимо изменить внешний ключ учётной записи на значение objectSid.

9. После сохранения настроек необходимо выполнить команду:

sudo journalctl -xefu idp

Проверка настройки 

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

Если используются скрипты PowerShell, то запуск проверки следует производить от имени пользователя, от имени которого будут производится синхронизация LDAP.

Проверка пользователей
$LDAPSEARCH = New-Object System.DirectoryServices.DirectorySearcher
$LDAPSEARCH.SearchRoot = "LDAP://DC=avanpost,DC=test"
$LDAPSEARCH.Filter = "(&(objectClass=user)(objectCategory=person)(memberof= CN=Employees,OU=AvanGroups,DC=avanpost,DC=test))"
$LDAPSEARCH.FindAll()
Проверка групп
$LDAPSEARCH = New-Object System.DirectoryServices.DirectorySearcher
$LDAPSEARCH.SearchRoot = "LDAP://DC=avanpost,DC=test" 
$LDAPSEARCH.Filter = "(&(objectClass=group)(CN=Employees))"
$LDAPSEARCH.FindAll()

Сценарии использования

Первичная загрузка/импорт пользователей из домена на базе Microsoft Active Directory в Avanpost FAM

Система Avanpost FAM может выполнить первичную загрузку и создание пользователей, импортировав данные из домена Microsoft Active Directory. Загрузка всех пользователей будет выполнена в результате первой синхронизации в соответствии с заданным расписанием.

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

Важно

Если в группе (которая присутствует в фильтре на синхронизации) состоит более 1500 пользователей, то группа создается, но пользователи в нее не включаются. Они попадают только в группу по умолчанию, который указаны в настройке LDAP-провайдера. Эта проблема возникает, поскольку Active Directory по умолчанию возвращает только первые 1000 объектов и 1500 атрибутов для каждого объекта в результатах запроса LDAP. При выполнении запроса LDAP из Avanpost FAM, группы считаются объектами, а члены группы (пользователи) — атрибутами. Если вы запросите группу, насчитывающую более 1500 участников, для этой группы не будет получено никаких результатов.

Варианты решения:
  1. В настройках LDAP провайдера в параметре "Атрибут со списком участников группы" укажите значение диапазона пользователей, чтобы запросить подмножество членов группы. Синтаксис настройки атрибута для импорта первой тысячи участников группы: member;range=0-999.
    Пример настроенной конфигурации:


  2. Необходимо отредактировать пороговые значение параметра "MaxValRange" в зависимости от количества пользователей в вашей группе в политиках LDAP в Active Directory. Для этого необходимо воспользоваться консольной утилитой Ntdsutil.exe.
    С подробной инструкцией по изменению параметров политики LDAP в Active Directory следует ознакомиться на сайте Microsoft по ссылке: View and set LDAP policy in Active Directory by using Ntdsutil.exe

Важно

Значение в параметре "MaxValRange" не должно превышать количества пользователей в импортируемой группе.

Автоматическое создание пользователя в Avanpost FAM при его добавлении в домене Microsoft Active Directory

При добавлении пользователей в Microsoft Active Directory, подключенном к Avanpost FAM, система будет автоматически создавать пользователей, которые попадают под правила заданного LDAP-фильтра поиска пользователей.

Обновление атрибутов пользователя при их изменении в домене Microsoft Active Directory

При изменении атрибутов пользователя в домене Microsoft Active Directory, подключенном к Avanpost FAM, система будет автоматически обновлять значения атрибутов, которые настроены в правилах маппинга.

Аутентификация с проверкой пароля через LDAP BIND в домене Microsoft Active Directory

Если пользователь найден в домене Microsoft Active Directory, подключенном к Avanpost FAM, в соответствии с заданным фильтром поиска аутентифицируемого пользователя, то пароль проверяется в LDAP-каталоге. Иначе проверка пароля пользователя выполняется внутренними средствами Avanpost FAM.

Быстрое удаление пользователей из групп Microsoft Active Directory

Для быстрого удаления пользователей из групп следует изменить настройки LDAP.

  1. Создать в домене новую группу пользователей. В FAM зайти в настройки LDAP (Сервис > Настройки LDAP провайдеров > Выбираем необходимую интеграцию > Интеграция).

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

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

Исключения

Если пользователь был добавлен в FAM через LDAP и пользователь ни разу не заходил в ЛК, то аутентификация через MSCHAPv2 не сработает. 

Это происходит из-за особенности протоколов LDAP и MSCHAPv2, так как при аутентификации пользователя через LDAP в ответе будет содержаться только разрешение на вход, а MSCHAPv2 передает аутентификационные данные в "шифрованном виде". То есть по "зашифрованным" данным из MSCHAPv2 FAM не может сформировать запрос в AD для подтверждения легитимности пользователя.

Важно, что бы в интеграции с AD был включен параметр "Обновлять пароль в процессе аутентификации", так как иначе FAM не сможет получить пароль для дальнейшей проверок.

Важно, что бы пароли в FAM хранились в открытом или зашифрованном виде, так как FAM не сможет проверить пароль из MSCHAPv2 по хешу.

Пользователю необходимо один раз авторизоваться в FAM, что бы FAM первоначально проверил правильность введенных данных в AD, а потом только сохранил данную информацию в шифрованном виде у себя в БД для дальнейшей проверки через MSCHAPv2. 

Приложение А. Примеры LDAP-фильтров для выборки пользователей, синхронизируемых из MS AD в Avanpost FAM

Пример LDAP-фильтра для выгрузки пользователей из нескольких групп:

(&(objectClass=user)(objectCategory=person)(|(memberof=CN=VPN,OU=FAM,DC=avanpost,DC=demo)(memberof=CN=Servicedesk,OU=FAM,DC=avanpost,DC=demo)(memberof=CN=1C,OU=FAM,DC=avanpost,DC=demo)))

Приложение Б. Примеры LDAP-фильтров для выборки групп, синхронизируемых из MS AD в Avanpost FAM

Пример LDAP-фильтра для выгрузки нескольких определённых групп:

(&(objectClass=group)(|(CN=1C)(CN=VPN)(CN=Servicedesk)))

Приложение В. Примеры импортируемых атрибутов пользователей при синхронизации из MS AD в Avanpost FAM

Таблица с указанием наиболее часто импортируемых атрибутов пользователя в MS AD:

Атрибут

Значение

Пример значения

name

ФИО

Петров Иван Сергеевич

givenName

Имя

Иван

sn

Фамилия

Петров

displayName

ФИО

Петров Иван Сергеевич

mail

E-mail (атрибут E-mail-Addresses); загружается в основной атрибут номера телефона

petrovis@avanpost.ru

sAMAccountName

Имя входа пользователя

petrovIS

userPrincipalName

Имя входа пользователя

petrovis@avanpost.ru

CN

Общее имя (Common Name) 

Петров Иван Сергеевич

OU

Подразделение (Organizational Unit)

ИТ отдел

DN

Уникальное имя (Distinguished Name)

CN=Петров Иван Сергеевич,OU=ИТ отдел,DC=avanpost,DC=ru

mobile

Мобильный номер телефона (атрибут Mobile в Microsoft Outlook); загружается в основной атрибут номера телефона

Значение номера телефона в сохранённом формате

telephoneNumber

Рабочий номер телефона (атрибут Business в Microsoft Outlook)

Значение номера телефона в сохранённом формате

Исчерпывающий перечень доступных для загрузки атрибутов содержится в документации на Microsoft Active Directory.

Приложение C. Скрипт автоматизации загрузки пользователей из MS AD в Avanpost FAM

Для упрощения импорта пользователей нужно воспользоваться готовым PowerShell-скриптом (расширение .ps1).

  1. Сохраните файл из примера ниже, введите путь и имя файла скрипта и используйте параметры для отправки данных и задания параметров. Прежде чем запускать скрипт в Windows, необходимо изменить политику выполнения PowerShell по умолчанию, инструкцию об этом следует посмотреть в Помощи своей операционной системы.
  2. Первым вопросом будет определение домена, для которого создается LDAP-фильтр. Следует ввести "y" для положительного ответа, и "n", если нужно выбрать другой домен.
  3. Далее следует определить, сопоставлен ли сам фильтр и ввести IP-адрес контроллера домена. Сразу после этого нужно ввести логин пользователя и пароль для авторизации. Имя пользователя вводится без указания домена.

В случае успешной авторизации, будет выдан список (перечень) всех доменных групп. В начале строки будет указан номер группы. Следует выбрать те их них, которые необходимо импортировать. Для этого следует перечислить их номера через пробел, затем нажать Enter.

Далее при желании следует скопировать фильтры поиска, а также имя служебного пользователя в буфер обмена. Обратите внимание на то, что после копирования следует убрать переносы строк. Для выхода нажать Enter.


if (!(Get-Command 'Get-ADUser' -errorAction SilentlyContinue))
{
Write-Host @'
Необходимый модуль PS для выполнения скрипта не доступен, следует установить:
-С помощью команд в PowerShell с повышенными правами:
dism /online /get-capabilities | ForEach {if ($_ -match "DS-LDS.Tools" ) {$mass = $_ -split " : "}}
& 'dism' @('/online', '/add-capability', $('/CapabilityName:'+$mass[1]))
-Через графический интерфейс. Настройки - Приложения - Дополнительные компоненты:
Добавить компонент "Средства удаленного администрирования сервера: средства 
доменных служб Active Directory и служб облегченного доступа к каталогам"
'@
Read-Host 'Press Enter to exit...'
Exit
}
$domain = Get-WmiObject -Class Win32_ComputerSystem
$groupforfilter = @()
$serviceuser = ""
if ($domain.PartOfDomain) {
    if (('y','н') -contains (Read-Host "Для этого домена ""$($domain.Domain)"" составляем LDAP-фильтр?[y\n]")) {
        $groups = @()
        Get-ADGroup -Filter * -Properties * | Where-Object {!($_.IsCriticalSystemObject) -or $_.name -like "Пользователи удаленного рабочего стола" -or $_.name -like "Remote Desktop Users"} | Sort CN | ForEach-Object {$groups+=@{Name=$_.CN;DN=$_.DistinguishedName}}
        for ($i = 0; $i -lt $groups.count; $i++) {
            Write-Host $i'-'$($groups[$i].Name+' ['+$groups[$i].DN+']')}
        do {$groupforfilter = $($(Read-Host "`nИз каких групп выше нужно импортировать пользователей?").Trim(","," ") -split  {$_ -eq " " -or $_ -eq ","})}
        until ($groupforfilter)
        $serviceuser = Read-Host "Введите логин служебного пользователя"
        try {$serviceuser = $(Get-ADUser -Identity $serviceuser -Properties DistinguishedName).DistinguishedName}
        catch [Microsoft.ActiveDirectory.Management.ADIdentityNotFoundException] {
            $serviceuser = "Такой пользователь "+$serviceuser+" не найден"
        }
    }else{
    $DCip = Read-Host "Введите ip-адрес контроллера домена (запрос будет на порт 9389)"
    $Cred = Get-Credential -Message 'Введите имя служебного пользоватля без домена и пароль'
    $groups = @()    
    try {Get-ADGroup -Filter * -Server $DCip -Credential $Cred -Properties * | Where-Object {!($_.IsCriticalSystemObject) -or $_.name -like "Пользователи удаленного рабочего стола" -or $_.name -like "Remote Desktop Users"} | Sort CN | ForEach-Object {$groups+=@{Name=$_.CN;DN=$_.DistinguishedName}}}
    catch [Microsoft.ActiveDirectory.Management.ADServerDownException]{
        Read-Host $("Не удалось подключиться к "+$DCip+":9389`nPress Enter to exit...")
        Exit}
    catch [System.Security.Authentication.AuthenticationException] {
        Read-Host "Не удалось авторизоваться с введёнными учетными данными`nPress Enter to exit..."
        Exit}
    for ($i = 0; $i -lt $groups.count; $i++) {
            Write-Host $i'-'$($groups[$i].Name+' ['+$groups[$i].DN+']')}
    do {$groupforfilter = $($(Read-Host "`nИз каких групп выше нужно импортировать пользователей?").Trim(","," ") -split {$_ -eq " " -or $_ -eq ","})}
        until ($groupforfilter)
    #$serviceuser=$($Cred.UserName -split '\\')[1]
    $serviceuser=$Cred.UserName
    $serviceuser = $(Get-ADUser -Identity $serviceuser -Properties DistinguishedName).DistinguishedName
    }
}else{
    $DCip = Read-Host "Введите ip-адрес контроллера домена (запрос будет на порт 9389)"
    $Cred = Get-Credential -Message 'Введите имя служебного пользоватля - domain\user и пароль'
    $groups = @()    
    try {Get-ADGroup -Filter * -Server $DCip -Credential $Cred -Properties * | Where-Object {!($_.IsCriticalSystemObject) -or $_.name -like "Пользователи удаленного рабочего стола" -or $_.name -like "Remote Desktop Users"} | Sort CN | ForEach-Object {$groups+=@{Name=$_.CN;DN=$_.DistinguishedName}}}
    catch [Microsoft.ActiveDirectory.Management.ADServerDownException]{
        Read-Host $("Не удалось подключиться к "+$DCip+":9389`nPress Enter to exit...")
        Exit}
    catch [System.Security.Authentication.AuthenticationException] {
        Read-Host "Не удалось авторизоваться с введёнными учетными данными`nPress Enter to exit..."
        Exit}
    for ($i = 0; $i -lt $groups.count; $i++) {
            Write-Host $i'-'$($groups[$i].Name+' ['+$groups[$i].DN+']')}
    do {$groupforfilter = $($(Read-Host "`nИз каких групп выше нужно импортировать пользователей?").Trim(","," ") -split {$_ -eq " " -or $_ -eq ","})}
        until ($groupforfilter)
    #$serviceuser=$($Cred.UserName -split '\\')[1]
    $serviceuser=$Cred.UserName
    $serviceuser = $(Get-ADUser -Identity $serviceuser -Properties DistinguishedName).DistinguishedName
    }
if ($groupforfilter.Count -gt 1) {
    $filtergroup = '(|'
    $groupforfilter.ForEach({$filtergroup+='(memberof='+$groups[$_].DN+')'})
    $filtergroup += ')'
    $filtergropgroup = '(|'
    $groupforfilter.ForEach({$filtergropgroup+='(cn='+$groups[$_].Name+')'})
    $filtergropgroup += ')'
} else {
    $filtergroup = ''
    $filtergropgroup = ''
    $groupforfilter.ForEach({$filtergroup+='(memberof='+$groups[$_].DN+')'})
    $groupforfilter.ForEach({$filtergropgroup+='(cn='+$groups[$_].Name+')'})
}
$ldapusers="(&(objectClass=user)(objectCategory=person)"+$filtergroup+")"
$ldapuser="(&(objectClass=user)(sAMAccountName=%s)"+$filtergroup+")"
$ldapgroups="(&(objectClass=group)"+$filtergropgroup+")"
Write-Host ("`nФильтр поиска пользователЕЙ:`n"+$ldapusers+"`n")
Write-Host ("Внешний ключ учётной записи: objectSid`n")
Write-Host ("Фильтр поиска групп:`n"+$ldapgroups+"`n")
Write-Host ("Фильтр поиска пользователЯ:`n"+$ldapuser+"`n")
Write-Host ("Имя служебного пользователя: "+$serviceuser)
Write-host ("`nВНИМАНИЕ. После копирования мышью из консоли нужно убрать переносы строк`n")
if (('y','н') -contains $(Read-Host 'cкопировать "Фильтр поиска пользователЕЙ" в буфер обмена?[y\n]')) {Set-Clipboard -Value $ldapusers}
if (('y','н') -contains $(Read-Host 'cкопировать "Фильтр поиска групп" в буфер обмена?[y\n]')) {Set-Clipboard -Value $ldapgroups}
if (('y','н') -contains $(Read-Host 'cкопировать "Фильтр поиска пользователЯ" в буфер обмена?[y\n]')) {Set-Clipboard -Value $ldapuser}
if (('y','н') -contains $(Read-Host 'cкопировать "Имя служебного пользователя" в буфер обмена?[y\n]')) {Set-Clipboard -Value $serviceuser}
Read-Host 'Press Enter to exit...'


Обсуждение