В IT-инфраструктуре HOSTKEY для хранения учетных данных и контроля доступа традиционно использовался FreeIPA. Когда появилась необходимость управлять офисными компьютерами с Windows и оборудованием Cisco Systems, пришлось задуматься об интеграции с Active Directory. Рассказываем, как она была реализована в нашей локальной сети.
Для решения задачи можно интегрировать клиентов Linux непосредственно в домен Active Directory и управлять ими с контроллера домена. Второй вариант — интеграция, основанная на синхронизации данных или доверии домена (AD trust). В этом случае учетные записи пользователей с ранее определенными атрибутами реплицируются в другой службе каталогов и становятся доступными для клиентов на Linux.
Недостатки AD trust
Хотя на AD trust тратятся значительные ресурсы разработчиков, это решение имеет существенные минусы и подходит компаниям, инфраструктура которых изначально основана на Active Directory. Мы же работали с FreeIPA, поэтому внедрение требовало значительных трудозатрат: фактически всю систему управления учетными записями пользователей пришлось бы создавать заново.
Второй минус — необходимость постоянной поддержки серверов с AD и FreeIPA,так как при падении связи между ними сервер с FreeIPA становится бесполезен и нарушается работа всей компании. Авторизация — чувствительный участок, который должен быть максимально отказоустойчивым. AD trust в подобной ситуации — дополнительная точка отказа.
Плюсы и минусы Windows sync
Вариант с механизмом Windows sync из FreeIPA предполагает полную синхронизацию всех учетных данных по протоколу LDAP. При этом FreeIPA и Active Directory остаются автономными решениями, и в случае повреждения любого сервера откажут только подключенные к нему сервисы, а не вся инфраструктура. Пользователь работает через одно окно с FreeIPA: например, в нем можно изменить пароль учетной записи одновременно для основанной на Windows и на Linux инфраструктуре.
Мы остановились на этом варианте, но решили его доработать, поскольку Windows sync не предназначен для управления группами.
К сожалению, механизм синхронизации Windows sync во FreeIPA не считается приоритетным и не развивается, особенно в вопросах управления группами. Нам же группы были необходимы, чтобы организовать структуру персонала по отделам или в ином произвольном порядке. Такой подход позволяет прописывать правила и политики на группу, а не на каждого пользователя в отдельности, что значительно упрощает управление учетными записями и доступом к данным, а также доставку ПО. Другое преимущество групп — они могут быть вложенными.
Например, структура отдела DEVOPS у нас состоит из следующих подгрупп, для каждой из которых определены наборы прав и политик, а также необходимых для работы сервисов:
Созданную учетную запись сотрудника мы добавляем в определенную подгруппу, например в младших инженеров. В итоге новый пользователь оказывается в целом наборе групп: пользователи Rocket.Chat, Jira и т. д. Он автоматически получает доступ ко всем прописанным для подгруппы сервисам. Такую схему нетрудно построить и путем создания полностью аналогичных групп во FreeIPA и AD, но администрировать их придется вручную. Минусы очевидны: будет тратиться время на выполнение рутинных задач, а также (и это главное) возникнут потенциальные угрозы безопасности инфраструктуры. Например, простая смена прав доступа может привести к сбоям в производственном процессе из-за ошибок ручной настройки.
Решение
Нам была необходима автоматическая синхронизация, которую пришлось реализовать самостоятельно на основе module manage-freeipa. В итоге был написан скрипт, который получает информацию о группах во FreeIPA, включая вложенные подгруппы, и переносит ее в AD. Приводим пошаговое описание алгоритма:
1. Импорт модуля module manage-freeipa.
2. После импорта модуля мы подключаемся к серверу с помощью заранее добавленных учетных данных:
$IPAURL = "freeipa_URL"
$IPAUSER = "USER"
$IPAPASS = "PASSWORD"
$ADOUUSERS = "*OU=users,OU=ipa,DC=win,DC=EXAMPLE,DC=COM"
$ADOUGROUPS = "*OU=groups,OU=ipa,DC=win,DC=EXAMPLE,DC=COM"
3. Затем в AD запрашиваем список групп из OU:
$OU = Get-ADOrganizationalUnit -SearchBase "OU=groups,OU=ipa,DC=win,DC=EXAMPLE,DC=COM" -Filter *
4. Фильтруем группу trust admins, которая не участвует в синхронизации данных между FreeIPA и AD:
$groupsAD = $OU | ForEach-Object {Get-ADGroup -SearchBase $_.DistinguishedName -Filter *} | Where {$_.name -notlike "trust admins"}
5. Получаем список всех групп в FreeIPA, за исключением trust admins и групп, которые используются исключительно в управляемой FreeIPA инфраструктуре. Выбор осуществляется только по полю cn:
$groupsIPA = Find-IPAGroup | Where {$_.dn -notlike "cn=invapi*" -and $_.dn -notlike "cn=jira*" -and $_.dn -notlike "cn=trust admins*"} | Select-Object -Property cn
6.Существует ряд групп, которые есть только в AD, мы ищем их и убираем из общего списка:
$groupsOnlyAD = $groupsAD.name | ?{$groupsIPA.cn -notcontains $_}
$listGroupsAD = $groupsAD.Name | ?{$groupsOnlyAD -notcontains $_}
7. Берем список из FreeIPA и отсекаем все группы, которые есть в AD. В итоге остается только список новых групп, которые есть в FreeIPA, но отсутствуют в AD:
$listAddGroups = $groupsIPA.cn | ?{$groupsAD.Name -notcontains $_}
8. Далее идет команда на добавление этих групп в AD:
$listAddGroups | ForEach-Object {New-ADGroup $_ -path 'OU=groups,OU=ipa,DC=win,DC=EXAMPLE,DC=COM' -GroupScope Global -PassThru -Verbose}
9. Затем идет цикл операций для каждой группы AD, которая есть в списке $ListGroupsAD.
9.1. Получаем список пользователей — участников группы в AD:
$listGroupsAD |
ForEach { $Groupname = $_
$listGroupMembersUsersAD = Get-ADGroupMember $Groupname | Where {$_.distinguishedName -like $ADOUUSERS} | select SamAccountName
9.2. Получаем список подгрупп участников группы в AD:
$listGroupMembersGroupsAD = Get-ADGroupMember $Groupname | Where {$_.distinguishedName -like $ADOUGROUPS} | select SamAccountName
9.3. Получаем список пользователей этой группы во FreeIPA:
$listGroupMemberUserIPA = Invoke-FreeIPAAPIgroup_show -group_name $Groupname | Select-Object -Property member_user
9.4. Получаем список подгрупп этой группы во FreeIPA:
$listGroupMemberGroupIPA = Invoke-FreeIPAAPIgroup_show -group_name $Groupname | Select-Object -Property member_group
9.5. Списки подгрупп и пользователей в FreeIPA и AD сравниваются (список пользователей FreeIPA вычитается из списка пользователей из AD и наоборот). Формируются списки пользователей и подгрупп на добавление и удаление:
$delListMembers = $listGroupMembersUsersAD.SamAccountName | ?{$listGroupMemberUserIPA.member_user -notcontains $_}
$delListGroups = $listGroupMembersGroupsAD.SamAccountName | ?{$listGroupMemberGroupIPA.member_group -notcontains $_}
$addListMembers = $listGroupMemberUserIPA.member_user| ?{$listGroupMembersUsersAD.SamAccountName -notcontains $_}
$addListGroups = $listGroupMemberGroupIPA.member_group | ?{$listGroupMembersGroupsAD.SamAccountName -notcontains $_}
9.6. Далее идет проверка, есть ли кто-то в списке на удаление пользователей и подгрупп: если никого нет, следующий шаг пропускается:
if (! ([string]::isnullorempty($delListMembers)))
{
$delListMembers | ForEach-Object {Remove-ADGroupMember $Groupname $_ -Confirm:$false}
}
if (! ([string]::isnullorempty($delListGroups)))
{
$delListGroups | ForEach-Object {Remove-ADGroupMember $Groupname $_ -Confirm:$false}
}
9.7. Такая же проверка выполняется на добавление пользователей и подгрупп:
if (! ([string]::isnullorempty($addListGroups))){
$addListGroups | ForEach-Object { Add-AdGroupMember -Identity $Groupname -members $_ }
}
if (! ([string]::isnullorempty($addListMembers)))
9.8. Перед добавлением пользователя в группу в AD необходимо проверить, есть ли он в AD. Весь цикл операций пункта 9 выполняется для каждой группы списка $listGroupsAD, полученного в пункте 6. После завершения происходит отключение сессии от сервера FreeIPA:
$addListMembers |
ForEach-Object { try
{
Get-ADUser -Identity $_
Add-AdGroupMember -Identity $Groupname -members $_
}
catch {}
}
}
}
Disconnect-IPA
Скрипт запускается планировщиком заданий каждые 15 минут.
Выводы
Скрипт значительно упростил управление учетными записями пользователей и введение новых сотрудников в рабочий процесс, а также повысил общую безопасность внутренней IT-инфраструктуры компании HOSTKEY. Дальше мы планируем настроить интеграцию FreeIPA с Active Directory напрямую через API без прокладки в виде module manage-freeipa. Это придется сделать по соображениям безопасности, поскольку последний раз модуль обновлялся два года назад. Существует риск, что он будет заброшен разработчиками.
А специальный промокод «Я С ХАБРА» откроет врата щедрости: назовите его консультанту на сайте при размещении заказа — и получите дополнительную скидку. Платить можно как всегда в рублях с НДС российской компании или в евро — компании в Нидерландах.
edo1h
не можете пояснить? не пробовал, но как мне представляется, доверие работает в обе стороны, и сразу после его настройки пользователи и группы из freeipa автомагически станут доступными на windows, останется только раздать им права
nikweter
Когда я занимался этой штукой, там доверие работало только в одну сторону. FreeIPA видела пользователей в АД и можно было с ними работать. А вот виндовс пользователей ИПА не видела. Ну или я не смог правильно настроить (хотя я пытался именно двухстороннее доверие).
Позже, в списках рассылки вроде мелькало упоминание одним из разработчиков именно таких ограничений, но я уже отошел от этой темы и больше не интересовался.
volkanin
Наверное, это потому, что в freeipa не реализован глобальный каталог ?
nikweter
Ну это был 2017 год, с трудом припоминаю что там и как. Со стороны линукса все было удобно, одной командой вводишь компы в домен, роли, сертификаты - круть. А в потрохах - не очень удобные схемы лдап, шаманство с доверием, с SSO.
За давностью лет меня пытать бессмысленно, слишком устаревшая инфа.
mityann
Сейчас действительно уже реализованы двусторонние трасты (не тестировал). Но под нашу задачу нужны односторонние. Работают достаточно стабильно, но подводных камней много. Для подключения к AD используется sssd и на самом деле он кеширует весь каталог (судя по логам). Можно указать отдельный dn, который будет использоваться, чтобы не синхронить весь данные. Т.е. в случае разрыва связи с AD, все продолжает работать (со стороны клиентов IPA).
edo1h
интересно