Интеграция FreeIPA с Active Directory

от автора

В 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. Это придется сделать по соображениям безопасности, поскольку последний раз модуль обновлялся два года назад. Существует риск, что он будет заброшен разработчиками.


А специальный промокод «Я С ХАБРА» откроет врата щедрости: назовите его консультанту на сайте при размещении заказа — и получите дополнительную скидку. Платить можно как всегда в рублях с НДС российской компании или в евро — компании в Нидерландах.


ссылка на оригинал статьи https://habr.com/ru/company/hostkey/blog/669978/