Когда инфраструктура только появляется, управление доступами кажется удивительно простой задачей. Пользователей немного, сервисов ещё меньше, а новый сотрудник получает доступы буквально за несколько минут. Администратор заводит учётную запись в GitLab, вручную добавляет пользователя в Jenkins, создаёт VPN-профиль, отправляет логин и пароль в корпоративный мессенджер и идёт пить кофе с ощущением хорошо выполненной работы.
Проблемы начинаются тогда, когда компания перестаёт быть маленькой. Пять сотрудников превращаются в пятьдесят. Затем в сто. Затем появляется несколько команд разработки, отдел аналитики, подрядчики, стажёры, внешние консультанты и дежурные инженеры. Одновременно с этим растёт количество систем: GitLab, Jenkins, Grafana, ArgoCD, Harbor, OpenSearch, VPN, внутренние порталы, Wiki, корпоративные приложения и ещё несколько загадочных виртуальных машин, назначение которых никто уже толком не помнит, но выключить их страшно, потому что "что-то перестанет работать".
В какой-то момент выясняется, что один и тот же пользователь существует одновременно в десятке различных систем. Где-то его логин записан как ivanov, где-то как i.ivanov, а где-то вообще как ivanov_test, потому что "так исторически сложилось". Добавление нового сотрудника превращается в длинный чек-лист из двадцати пунктов, а увольнение становится настоящим квестом с участием нескольких администраторов и надеждой на то, что никто ничего не забудет отключить.
Именно тогда появляются вопросы, которые очень любят задавать специалисты по информационной безопасности:
- Почему у уволенного сотрудника до сих пор работает доступ в Grafana?
- Кто выдал подрядчику права администратора в Jenkins?
- Почему разработчик имеет доступ в production VPN?
- Кто изменил членство пользователя в группе?
- Где вообще находится источник истины по пользователям?
После таких вопросов где-то в серверной начинает тихо грустить SysOps-инженер.
Проблема заключается не в количестве систем и даже не в количестве пользователей. Настоящая проблема - отсутствие единой модели управления идентификацией. Когда каждый сервис хранит пользователей самостоятельно, инфраструктура постепенно превращается в набор разрозненных островков, связанных между собой исключительно памятью администраторов и комментариями вида "не трогать, а то сломается".
Именно поэтому крупные организации давно пришли к концепции централизованного управления идентификацией и доступом - Identity and Access Management, или IAM. Суть подхода достаточно проста. Должен существовать единый источник истины, отвечающий за хранение пользователей и групп, а все остальные сервисы должны доверять этому источнику и использовать единый механизм аутентификации.
В экосистеме открытого программного обеспечения одной из наиболее мощных комбинаций для построения такой архитектуры считается связка FreeIPA и Keycloak.
FreeIPA берёт на себя роль корпоративного каталога пользователей. Он хранит учётные записи, группы, политики sudo, сведения о хостах, сертификаты и использует Kerberos для безопасной аутентификации. Для Linux-инфраструктуры FreeIPA фактически становится аналогом Active Directory из мира Windows.
Keycloak, в свою очередь, решает совершенно другую задачу. Он выступает в роли единой точки входа для современных приложений, предоставляя Single Sign-On, поддержку OAuth2, OpenID Connect, SAML, многофакторную аутентификацию, федерацию идентичностей и гибкое управление ролями. Большинство современных инфраструктурных сервисов умеют работать с Keycloak практически "из коробки".
Вместе эти два компонента позволяют построить систему, в которой жизненный цикл пользователя становится полностью управляемым и предсказуемым. Создание сотрудника в каталоге автоматически приводит к появлению доступа в корпоративных системах. Изменение членства в группах отражается на правах во всех приложениях. Увольнение сотрудника приводит к автоматическому отключению доступа ко всей инфраструктуре без необходимости обходить десятки административных панелей вручную.
Но даже здесь всё не так просто, как кажется на первый взгляд.
Keycloak действительно умеет напрямую подключаться к FreeIPA через LDAP Federation. И для небольших инфраструктур этого зачастую оказывается достаточно. Однако по мере роста компании появляются новые требования: автоматическое назначение ролей, аудит изменений, интеграция с SIEM, уведомления в Telegram, GitOps-подход к управлению доступами, собственная бизнес-логика и более гибкое управление жизненным циклом пользователей.
И тогда становится понятно, что классическое "подключили LDAP и забыли" далеко не всегда является идеальным решением.
В этой статье мы подробно разберём оба подхода. Мы поговорим о том, как правильно строить архитектуру FreeIPA и Keycloak в production-среде, научимся интегрировать их различными способами, напишем полноценный сервис синхронизации на Python, упакуем его в контейнер, запустим в Kubernetes, добавим автоматическое управление группами и ролями, реализуем блокировку уволенных сотрудников и обсудим те самые грабли, на которые обычно наступают только после первого серьёзного аудита безопасности.
Потому что управление идентификацией - это не про красивые схемы на архитектурных диаграммах. Это про возможность в любой момент ответить на простой вопрос:
"Кто именно и почему сейчас имеет доступ к вашей инфраструктуре?"
И если ответ на него не начинается со слов: "Ну, вообще-то это довольно сложная история...", значит вы всё сделали правильно.
Что такое FreeIPA и Keycloak и зачем их объединять
Если спросить у большинства администраторов, как выглядит управление пользователями в инфраструктуре, то ответы обычно будут очень похожими. Где-то есть GitLab со своими локальными учётными записями. Отдельно живёт Jenkins. У VPN собственная база пользователей. В Grafana свои администраторы. Внутренний Wiki-сервер аутентифицируется через какой-нибудь древний LDAP, который когда-то давно подняли "на время". А где-то в углу тихо работает старый сервер, пароль от которого записан в заметках бывшего сотрудника, ушедшего ещё до пандемии.
До определённого момента такой подход даже работает. Когда пользователей десять, а сервисов пять, ручное управление доступами кажется вполне разумным. Добавить нового разработчика можно за пятнадцать минут. Отключить доступ уволенному сотруднику - ещё быстрее. Но инфраструктура редко остаётся маленькой надолго. Вместе с ростом бизнеса растёт количество сервисов, команд и интеграций. И очень быстро выясняется, что учётные записи разбросаны по десяткам систем, права назначаются вручную, а никто уже не может с уверенностью сказать, кто и к чему имеет доступ.
Именно здесь на сцену выходит централизованное управление идентификацией.
Под идентификацией в данном случае понимается не только сам факт существования пользователя, но и весь его жизненный цикл:
-
создание учётной записи;
-
изменение персональных данных;
-
добавление в группы;
-
выдача ролей;
-
предоставление временных доступов;
-
отзыв прав;
-
отключение при увольнении;
-
аудит всех изменений.
В крупных организациях этот процесс называют Identity and Access Management - управлением идентификацией и доступом. Идея проста: должен существовать единый источник истины, которому доверяют все остальные системы.
FreeIPA - корпоративный каталог пользователей
FreeIPA можно представить как аналог Active Directory из мира Linux. Это не просто LDAP-сервер, как многие ошибочно считают. На самом деле FreeIPA представляет собой целый набор интегрированных компонентов, объединённых под единым интерфейсом и предназначенных для управления корпоративной инфраструктурой.
В состав FreeIPA входят:
-
LDAP-каталог на базе 389 Directory Server;
-
Kerberos для аутентификации;
-
DNS-интеграция;
-
управление хостами;
-
управление sudo-политиками;
-
сертификаты и центр сертификации;
-
политики доступа;
-
веб-интерфейс администрирования;
-
CLI-инструменты автоматизации.
По сути, FreeIPA отвечает на вопрос:
Кто этот пользователь?
Он хранит информацию о сотрудниках, их принадлежности к группам, параметрах учётных записей и связях между объектами инфраструктуры.
Например, пользователь может выглядеть следующим образом:
uid: ivanov
givenName: Иван
sn: Иванов
mail: ivanov@example.local
memberOf:
- devops
- vpn-users
- grafana-admins
А группа DevOps может содержать десятки сотрудников и использоваться одновременно для управления доступом к Linux-серверам, VPN и внутренним сервисам.
Самое главное преимущество FreeIPA заключается в том, что он становится тем самым "источником истины". Если пользователь существует в FreeIPA - значит, он сотрудник организации. Если пользователь заблокирован или удалён из FreeIPA - он перестаёт быть частью инфраструктуры.
Это значительно упрощает управление жизненным циклом учётных записей.
Почему одного FreeIPA недостаточно
Возникает вполне логичный вопрос: если FreeIPA умеет хранить пользователей и группы, зачем вообще нужен ещё и Keycloak?
Ответ кроется в том, что современная инфраструктура сильно изменилась.
Многие корпоративные приложения больше не умеют работать с Kerberos или классическим LDAP. Зато практически все они поддерживают современные протоколы аутентификации:
-
OAuth2;
-
OpenID Connect;
-
SAML 2.0.
Например:
-
Grafana прекрасно работает через OpenID Connect;
-
GitLab умеет использовать OAuth2 и SAML;
-
ArgoCD поддерживает OIDC;
-
Harbor интегрируется через OIDC;
-
Jenkins работает через SAML и OIDC;
-
OpenSearch Dashboards также умеет использовать современные протоколы.
Именно здесь появляется необходимость в промежуточном уровне, который будет выступать единым центром аутентификации для приложений.
Keycloak - единая точка входа
Keycloak представляет собой полноценную платформу управления доступом и единого входа.
Его основная задача заключается в том, чтобы отвечать на совершенно другой вопрос:
Что этому пользователю разрешено делать?
Keycloak предоставляет огромное количество возможностей:
-
Single Sign-On;
-
поддержку OAuth2;
-
поддержку OpenID Connect;
-
поддержку SAML;
-
многофакторную аутентификацию;
-
брокеринг внешних провайдеров идентификации;
-
управление ролями;
-
клиентские политики;
-
управление сессиями;
-
аудит входов;
-
саморегистрацию пользователей;
-
социальную аутентификацию;
-
федерацию пользователей.
Благодаря этому пользователь проходит аутентификацию один раз и получает доступ ко всем разрешённым системам.
Типичный сценарий выглядит следующим образом.
- Разработчик открывает ArgoCD.
- ArgoCD перенаправляет его в Keycloak.
- Keycloak предлагает выполнить вход.
- После успешной аутентификации пользователь получает токен доступа и автоматически попадает в систему.
- Затем он открывает Grafana.
И внезапно оказывается, что повторно вводить пароль уже не нужно.
С точки зрения пользователя это выглядит как магия. А с точки зрения администратора это означает снижение количества паролей, упрощение поддержки и централизованный контроль доступа.
Как FreeIPA и Keycloak дополняют друг друга
Очень важно понимать, что эти системы не конкурируют между собой. Наоборот, они прекрасно дополняют друг друга.
Их роли можно описать следующим образом:
| Компонент | Основная задача |
|---|---|
| FreeIPA | Хранение пользователей и групп |
| FreeIPA | Kerberos-аутентификация Linux-хостов |
| FreeIPA | Управление sudo и политиками |
| FreeIPA | Учёт жизненного цикла сотрудников |
| Keycloak | Единый вход в приложения |
| Keycloak | OAuth2, OIDC и SAML |
| Keycloak | MFA и управление сессиями |
| Keycloak | Назначение ролей приложениям |
Другими словами:
-
FreeIPA знает, кто вы.
-
Keycloak знает, куда вам можно.
-
Приложения доверяют Keycloak.
-
Linux-серверы доверяют FreeIPA.
Именно поэтому эта связка настолько популярна в корпоративных инфраструктурах.
Как это выглядит в реальной жизни
Представим обычный рабочий день. В компанию приходит новый DevOps-инженер. HR создаёт заявку. Администратор добавляет сотрудника в FreeIPA.
Пользователь автоматически попадает в группы:
devops
vpn-users
argocd-admins
grafana-admins
Через некоторое время сервис синхронизации передаёт информацию в Keycloak.
В результате новый сотрудник получает:
-
доступ к корпоративному VPN;
-
возможность входа в Grafana;
-
административный доступ в ArgoCD;
-
доступ к GitLab;
-
доступ к Harbor;
-
вход во внутренние сервисы через единый портал авторизации.
Через год сотрудник переводится в другую команду. Его просто удаляют из группы devops и добавляют в developers. Спустя несколько минут права автоматически меняются во всех системах.
А если сотрудник увольняется, его учётная запись блокируется в FreeIPA, после чего доступы исчезают сразу во всей инфраструктуре.
Без десятков чек-листов. Без панических звонков безопасников. Без фразы:
"Кажется, мы забыли отключить ему Jenkins..."
Почему это особенно важно для Kubernetes
В Kubernetes количество интеграций растёт особенно быстро.
Сегодня платформа может включать в себя:
-
сам Kubernetes;
-
ArgoCD;
-
Grafana;
-
Prometheus;
-
Harbor;
-
GitLab;
-
OpenSearch;
-
Vault;
-
внутренние панели самообслуживания;
-
VPN для администраторов.
Каждый из этих компонентов способен хранить пользователей самостоятельно. Но если пойти этим путём, через пару лет платформа превращается в музей локальных учётных записей и временных исключений. Поэтому зрелые платформенные команды стараются строить единый контур идентификации с самого начала. Даже если сегодня пользователей всего двадцать.
Потому что сто пользователей появляются незаметно. А вот разбирать последствия пяти лет ручного управления доступами приходится очень долго.
И обычно это происходит после первой серьёзной проверки информационной безопасности, когда внезапно выясняется, что учётная запись стажёра трёхлетней давности до сих пор обладает правами администратора в половине инфраструктуры.
Именно поэтому связка FreeIPA и Keycloak сегодня считается одним из наиболее мощных и гибких решений для построения корпоративного IAM на базе открытого программного обеспечения. Она позволяет сохранить Linux-ориентированный подход FreeIPA и одновременно получить все преимущества современных механизмов единого входа, которые ожидают от инфраструктуры пользователи и приложения.
А дальше возникает самый интересный вопрос.
Как именно заставить эти две системы работать вместе и какой способ интеграции выбрать, чтобы через год не захотелось всё переделать заново?
Варианты интеграции FreeIPA и Keycloak: выбираем между "просто работает" и "мы всё контролируем"
Когда инженеры впервые сталкиваются с задачей объединить FreeIPA и Keycloak, возникает вполне естественное желание открыть документацию, найти кнопку "Подключить LDAP" и на этом закончить проект.
И, что самое интересное, во многих случаях именно так и происходит.
Keycloak действительно умеет напрямую работать с LDAP-каталогами. FreeIPA, в свою очередь, предоставляет полноценный LDAP-интерфейс. На первый взгляд всё выглядит идеально: подключили одно к другому, нажали кнопку Synchronize и отправились заниматься более важными делами.
Именно поэтому огромное количество статей в интернете заканчивается примерно на этапе настройки LDAP Federation.
Однако в реальной эксплуатации всё оказывается несколько сложнее.
Потому что вопрос интеграции - это не только вопрос технической возможности подключения. Это ещё и вопрос того, насколько вы готовы жить с ограничениями выбранного подхода через год, два или пять лет.
На практике обычно используют два варианта интеграции.
-
LDAP Federation, встроенную в Keycloak.
-
Собственный сервис синхронизации пользователей и групп.
Оба подхода имеют право на жизнь. Более того, оба активно используются в production. Но между ними существует огромная разница.
Вариант первый. LDAP Federation - быстро и без боли
LDAP Federation представляет собой встроенный механизм Keycloak, позволяющий использовать внешний LDAP-каталог в качестве источника пользователей.
Схема работы выглядит очень просто.
FreeIPA
│
│ LDAP/LDAPS
│
Keycloak
│
Приложения
Когда пользователь пытается войти в систему, Keycloak обращается к FreeIPA, проверяет существование учётной записи и выполняет аутентификацию.
При необходимости Keycloak может импортировать данные пользователей в собственную базу либо обращаться к LDAP каждый раз при входе.
С точки зрения инфраструктурного инженера такой подход обладает несколькими серьёзными преимуществами.
Во-первых, он невероятно прост.
- Не нужно писать код.
- Не нужно поддерживать отдельный сервис.
- Не нужно думать об очередях, обработке ошибок и повторных попытках.
Достаточно заполнить несколько полей в интерфейсе Keycloak:
-
адрес LDAP-сервера;
-
учётные данные для подключения;
- базовый DN;
-
параметры поиска пользователей;
-
настройки групп.
Через несколько минут система уже работает.
Во-вторых, такой подход отлично подходит для небольших организаций.
Если у вас:
-
несколько десятков пользователей;
-
относительно простая структура групп;
-
нет сложной бизнес-логики;
-
отсутствуют требования к детальному аудиту;
-
нет выделенной платформенной команды,
то LDAP Federation может оказаться идеальным решением.
В-третьих, эксплуатационные затраты минимальны.
Фактически вам необходимо обслуживать только два компонента:
-
FreeIPA;
-
Keycloak.
Без дополнительных контейнеров и сервисов. Звучит прекрасно. Но именно здесь начинается самое интересное.
Почему LDAP Federation не всегда спасает
Настоящие проблемы появляются не в момент внедрения. Они появляются спустя несколько месяцев эксплуатации. Например, компания решила использовать группы FreeIPA для автоматического назначения ролей в приложениях. Внезапно оказывается, что логика преобразования LDAP-групп в роли Keycloak ограничена. Затем появляются вложенные группы.
И кто-нибудь задаёт невинный вопрос:
А можно автоматически выдавать роль администратора Grafana всем участникам группы DevOps, кроме подрядчиков?
Технически - да. Красиво - уже не всегда.
Потом приходит служба информационной безопасности и спрашивает:
А кто именно изменил роль пользователя?
Keycloak отвечает:
Ну... пользователь пришёл из LDAP.
FreeIPA отвечает:
Ну... пользователь состоит в группе.
А где произошло сопоставление ролей? Тишина.
Ещё через некоторое время возникает необходимость отправлять уведомления.
Например:
-
сообщать о блокировке сотрудников;
-
уведомлять о выдаче административных прав;
-
передавать события в SIEM;
-
создавать тикеты в Service Desk;
-
уведомлять руководителей.
И тут становится понятно, что встроенной федерации уже недостаточно. Наиболее частые проблемы LDAP Federation выглядят следующим образом.
Ограниченный контроль над логикой
Невозможно легко реализовать сложные правила.
Например:
если пользователь состоит в группе devops и работает в московском подразделении, назначить ему роль argocd-admin.
Такие вещи быстро превращаются в набор костылей.
Проблемы с вложенными группами
Nested groups выглядят замечательно на архитектурных схемах. До тех пор, пока не выясняется, что разные системы интерпретируют их по-разному. FreeIPA может видеть полную иерархию. Keycloak - только часть. Приложение - ещё что-нибудь своё. В результате доступы начинают вести себя весьма творчески.
Сложности с аудитом
Встроенные механизмы дают ограниченное понимание того:
-
кто получил права;
-
когда это произошло;
-
по какой причине;
-
какое правило сработало.
Аудит превращается в расследование.
Отсутствие GitOps
Современные платформенные команды всё чаще рассматривают доступы как код.
- Изменения проходят через Pull Request.
- Проверяются коллегами.
- Хранятся в Git.
- Откатываются при необходимости.
LDAP Federation плохо вписывается в подобную модель.
Ограниченная интеграция
Если хочется взаимодействовать с:
-
Telegram;
-
Slack;
-
Jira;
-
SIEM;
-
системами согласования;
-
CMDB,
приходится искать обходные пути.
Вариант второй. Собственный сервис синхронизации
Именно поэтому многие зрелые инфраструктурные команды переходят к модели отдельного sync-сервиса.
Выглядит это следующим образом.
FreeIPA
│
│ LDAP/LDAPS
Sync Service
│
│ REST API
Keycloak
│
Приложения
На первый взгляд архитектура кажется более сложной. Появляется дополнительный компонент.
Его необходимо:
-
разрабатывать;
-
тестировать;
-
разворачивать;
-
обновлять;
-
мониторить.
У многих инженеров возникает закономерный вопрос:
А не слишком ли это сложно?
На удивление, ответ чаще всего отрицательный. Потому что вместе с дополнительной сложностью появляется полный контроль над происходящим.
Какие возможности даёт собственный sync-сервис
Прежде всего появляется возможность реализовывать любую бизнес-логику.
Например:
Если пользователь состоит в группе devops
и имеет признак employee=true,
то выдать роль grafana-admin.
Или:
Если пользователь является подрядчиком,
не выдавать доступ к production.
Или даже:
Если сотрудник находится в отпуске более 30 дней,
временно отключить административные роли.
LDAP Federation на такое обычно смотрит с лёгким недоумением. А Python-сервис воспринимает подобные требования как обычный код. Кроме того, появляется полноценный аудит.
Каждое действие можно записывать:
2026-06-15 09:00:15
ivanov
добавлен в группу grafana-admins
2026-06-15 09:00:17
назначена роль grafana-admin
2026-06-15 09:00:18
отправлено уведомление в SIEM
Без археологических раскопок. Без попыток понять, кто именно нажал нужную кнопку.
GitOps для IAM
Одна из самых интересных возможностей собственного сервиса - превращение управления доступами в инфраструктурный код.
Например, можно хранить правила назначения ролей следующим образом:
role_mappings:
devops:
- grafana-admin
- argocd-admin
developers:
- grafana-viewer
contractors:
- vpn-users
Тогда изменение доступа превращается в обычный Pull Request. Инженер создаёт изменение. Коллеги его проверяют. После одобрения изменения автоматически применяются. Примерно так сегодня работают многие крупные платформенные команды.
Цена такой гибкости
Разумеется, чудес не бывает. За полный контроль приходится платить. Основные недостатки собственного сервиса выглядят следующим образом.
Дополнительный компонент
- Его нужно поддерживать.
- Следить за обновлениями зависимостей.
- Исправлять ошибки.
- Тестировать новые версии Keycloak.
Необходимость писать код
Кому-то придётся взять на себя ответственность за разработку.
А значит, появляются:
-
код-ревью;
-
тестирование;
-
документация;
-
CI/CD.
Более сложная архитектура
Теперь отказ sync-сервиса тоже нужно учитывать.
Нужно понимать:
-
что произойдёт при недоступности FreeIPA;
-
что делать при недоступности Keycloak;
-
как обрабатывать повторные попытки;
-
как избежать частичной синхронизации.
Это уже задачи уровня платформенной инженерии.
Что выбирают в реальной жизни
Если попытаться обобщить опыт эксплуатации, картина обычно выглядит следующим образом.
| Размер инфраструктуры | Рекомендуемый подход |
|---|---|
| До 50 пользователей | LDAP Federation |
| 50-300 пользователей | LDAP Federation или Sync Service |
| 300-1000 пользователей | Sync Service предпочтителен |
| Более 1000 пользователей | Практически всегда Sync Service |
| Высокие требования ИБ и аудита | Sync Service |
| GitOps и автоматизация | Sync Service |
И здесь нет универсально правильного ответа. LDAP Federation не является плохим решением. Наоборот, для многих компаний это самый разумный выбор.
Но если инфраструктура становится платформой, обслуживающей сотни пользователей и десятки сервисов, очень быстро выясняется, что возможность полностью контролировать жизненный цикл идентификации стоит дополнительных усилий.
Потому что IAM перестаёт быть просто "ещё одной настройкой Keycloak". Он становится одним из фундаментальных сервисов всей инфраструктуры. И ошибка в нём способна либо оставить без доступа половину компании, либо, что гораздо хуже, сохранить этот доступ тем, кому он уже давно не положен.
Поэтому прежде чем переходить к реализации, стоит сначала правильно спроектировать саму архитектуру взаимодействия FreeIPA и Keycloak. Именно от неё будет зависеть, станет ли ваша система управления доступами надёжным фундаментом или очередным техническим долгом, который все боятся трогать.
Разворачиваем FreeIPA
Если спросить у любого инженера, который хотя бы раз внедрял централизованную систему управления доступами, какой компонент вызывает наибольшее количество уважения и одновременно опасений, многие назовут именно FreeIPA. Не потому, что его сложно установить. Наоборот, в большинстве случаев установка проходит достаточно предсказуемо. Причина в другом. FreeIPA очень быстро превращается в один из важнейших сервисов всей инфраструктуры. Пока не работает Jenkins, разработчики ворчат. Пока недоступна Grafana, инженеры испытывают дискомфорт. Но если перестаёт работать корпоративный каталог пользователей, проблемы начинаются сразу у всех. Перестают выдаваться Kerberos-билеты, возникают сложности с SSH-доступом, ломаются LDAP-запросы, а в худшем случае новые сотрудники не могут получить доступ к необходимым системам, а старые продолжают пользоваться тем, что давно должны были потерять.
Именно поэтому развёртывание FreeIPA требует несколько иного подхода по сравнению с большинством современных сервисов. Здесь недостаточно просто выполнить команду docker run, убедиться, что контейнер поднялся, и считать задачу закрытой. Нужно заранее продумать схему именования, DNS-инфраструктуру, резервное копирование, отказоустойчивость и способ дальнейшей эксплуатации. Иначе через полгода можно обнаружить, что самая важная система в компании работает на виртуальной машине с названием test-auth-final-v2, которую никто не обновлял уже два года, потому что "вроде всё работает".
FreeIPA - не просто LDAP
Одной из наиболее распространённых ошибок является восприятие FreeIPA исключительно как LDAP-сервера. На самом деле FreeIPA представляет собой целый набор тесно интегрированных между собой компонентов. При установке поднимается не один процесс, а полноценная экосистема служб, обеспечивающих работу корпоративной идентификации.
В состав FreeIPA входят:
-
389 Directory Server - LDAP-каталог пользователей и групп;
-
Kerberos KDC - центр распределения Kerberos-билетов;
-
Dogtag Certificate System - инфраструктура открытых ключей и центр сертификации;
-
HTTP-сервер Apache;
-
службы управления политиками доступа;
-
механизмы управления хостами;
-
DNS-сервер (опционально);
-
средства репликации между узлами.
Именно поэтому FreeIPA требует более внимательного отношения, чем большинство привычных контейнеризированных приложений.
Где запускать FreeIPA
Технически FreeIPA можно запускать несколькими способами:
-
на физических серверах;
-
на виртуальных машинах;
-
в Docker;
-
в Kubernetes.
Однако далеко не все варианты одинаково подходят для production.
В реальных корпоративных инфраструктурах чаще всего используют виртуальные машины. Обычно разворачиваются минимум два экземпляра FreeIPA с репликацией между ними. Такой подход позволяет пережить обновления, сбои гипервизоров и плановое обслуживание без полной потери доступа к инфраструктуре.
Типичная схема выглядит следующим образом:
+--------------------+
| FreeIPA-01 |
| Primary Node |
+----------+---------+
|
Репликация
|
+----------+---------+
| FreeIPA-02 |
| Replica Node |
+--------------------+
Для лабораторий, демонстрационных стендов и тестирования контейнерный вариант подходит отлично. Именно его мы будем использовать далее, поскольку он позволяет быстро воспроизвести всю архитектуру без выделения дополнительных виртуальных машин.
Требования к инфраструктуре
FreeIPA не относится к ресурсоёмким системам, однако определённый запас мощности ему всё же необходим.
Для небольших инфраструктур до нескольких сотен пользователей обычно достаточно следующих ресурсов:
| Ресурс | Минимум | Рекомендуется |
|---|---|---|
| Процессор | 2 vCPU | 4 vCPU |
| Оперативная память | 4 ГБ | 8 ГБ |
| Дисковое пространство | 20 ГБ | 50 ГБ |
| Сетевое подключение | 1 Гбит/с | 1 Гбит/с |
Практика показывает интересную закономерность. Большую часть времени FreeIPA практически не нагружен. Но стоит наступить утру понедельника, когда вся компания одновременно подключается к VPN и начинает работать, как количество запросов резко возрастает. Поэтому закладывать минимальные ресурсы "впритык" обычно не лучшая идея.
DNS - фундамент всей установки
Если существует один компонент, который способен испортить жизнь любому инженеру, внедряющему FreeIPA, то это DNS.
Kerberos крайне чувствителен к корректности разрешения имён. Неправильно настроенные прямые или обратные записи способны привести к самым неожиданным последствиям:
-
невозможности получить Kerberos-билет;
-
ошибкам LDAP-аутентификации;
-
проблемам при присоединении клиентов;
-
сбоям репликации;
-
трудно диагностируемым ошибкам авторизации.
Перед установкой необходимо определить доменное имя и настроить соответствующие записи.
Например:
Домен: example.local
Kerberos Realm: EXAMPLE.LOCAL
ipa01.example.local → 10.10.10.11
ipa02.example.local → 10.10.10.12
10.10.10.11 → ipa01.example.local
10.10.10.12 → ipa02.example.local
Отсутствие PTR-записей входит в число самых популярных причин странного поведения FreeIPA. Именно поэтому опытные инженеры начинают диагностику не с просмотра логов, а с проверки DNS.
Быстрое развёртывание через Docker Compose
Для лабораторного стенда воспользуемся официальным контейнерным образом FreeIPA.
Создадим файл docker-compose.yml:
version: "3.9"
services:
freeipa:
image: freeipa/freeipa-server:rocky-9
container_name: freeipa
hostname: ipa.example.local
environment:
IPA_SERVER_HOSTNAME: ipa.example.local
IPA_SERVER_IP: 10.10.10.10
PASSWORD: SuperStrongPassword
TZ: Europe/Moscow
ports:
- "80:80"
- "443:443"
- "389:389"
- "636:636"
volumes:
- freeipa_data:/data
restart: unless-stopped
volumes:
freeipa_data:
На первый взгляд файл выглядит очень компактно. Но практически каждая директива здесь имеет значение.
Разбор конфигурации
Используем официальный образ проекта:
image: freeipa/freeipa-server:rocky-9
Использование сторонних сборок для столь критичного компонента выглядит сомнительной экономией времени.
Указываем полное имя узла:
hostname: ipa.example.local
Это имя будет использоваться внутри Kerberos и LDAP. Исправлять его после ввода системы в эксплуатацию крайне неприятно.
Передаём параметры установки:
environment:
IPA_SERVER_HOSTNAME: ipa.example.local
IPA_SERVER_IP: 10.10.10.10
PASSWORD: SuperStrongPassword
TZ: Europe/Moscow
Пароль администратора задаётся через переменную окружения исключительно для демонстрационных целей. В production подобные данные должны храниться в защищённых хранилищах секретов.
Сохраняем данные вне контейнера:
volumes:
- freeipa_data:/data
Без постоянного тома при пересоздании контейнера можно потерять весь каталог пользователей, что обычно крайне негативно влияет на настроение сотрудников.
Какие порты необходимо открыть
Часто в руководствах встречается формулировка:
"Откройте необходимые порты."
Но редко уточняется, какие именно.
В production-среде обычно используются следующие порты:
| Порт | Назначение |
|---|---|
| 80/tcp | HTTP |
| 443/tcp | Веб-интерфейс |
| 389/tcp | LDAP |
| 636/tcp | LDAPS |
| 88/tcp | Kerberos |
| 88/udp | Kerberos |
| 464/tcp | Смена Kerberos-паролей |
| 464/udp | Смена Kerberos-паролей |
| 53/tcp | DNS |
| 53/udp | DNS |
| 123/udp | NTP |
Для тестового стенда можно ограничиться только необходимыми службами, но в production стоит учитывать полный перечень зависимостей.
Запуск FreeIPA
Запускаем контейнер:
docker compose up -d
Проверяем его состояние:
docker ps
После первого запуска контейнер некоторое время выполняет инициализацию внутренних компонентов.
Посмотреть процесс установки можно следующим образом:
docker logs -f freeipa
В этот момент многие впервые сталкиваются с неожиданностью: FreeIPA запускается значительно дольше привычных микросервисов.
Это нормально.
Внутри контейнера происходит настройка LDAP, генерация сертификатов, конфигурация Kerberos и запуск остальных служб. Поэтому если контейнер не поднялся за несколько секунд, это ещё не повод начинать серию экстренных перезапусков.
Хотя именно так обычно и начинаются самые запоминающиеся инфраструктурные инциденты.
Проверяем работу FreeIPA
После завершения установки открываем веб-интерфейс:
https://ipa.example.local
Для входа используем учётную запись администратора:
Логин: admin
Пароль: SuperStrongPassword
Через интерфейс можно управлять:
-
пользователями;
-
группами;
-
хостами;
-
DNS;
-
сертификатами;
-
sudo-политиками;
-
репликацией.
Однако настоящий DevOps-инженер обычно первым делом открывает терминал.
Подключаемся внутрь контейнера:
docker exec -it freeipa bash
Получаем Kerberos-билет администратора:
kinit admin
Проверяем его наличие:
klist
Если всё настроено корректно, увидим примерно следующий результат:
Ticket cache: KCM:0
Default principal: admin@EXAMPLE.LOCAL
Valid starting Expires
06/15/2026 11:00 06/16/2026 11:00
Теперь можно использовать инструменты администрирования FreeIPA.
Например, вывести список пользователей:
ipa user-find
Или список групп:
ipa group-find
Создаём первых пользователей
Добавим тестового сотрудника:
ipa user-add ivanov \
--first=Иван \
--last=Иванов \
--email=ivanov@example.local
Установим пароль:
ipa passwd ivanov
Создадим группу DevOps:
ipa group-add devops
Добавим пользователя в неё:
ipa group-add-member devops \
--users=ivanov
Проверим результат:
ipa group-show devops
Получим примерно такой вывод:
Group name: devops
Member users: ivanov
Именно эти пользователи и группы в дальнейшем станут источником истины для всей нашей системы управления доступами.
Production best practices
За годы эксплуатации FreeIPA сформировался набор правил, нарушение которых обычно приводит к весьма поучительным историям.
-
Не храните пароли администратора в Git.
-
Всегда используйте резервное копирование.
-
Настройте репликацию минимум между двумя узлами.
-
Используйте LDAPS вместо обычного LDAP.
-
Следите за корректностью DNS и обратных записей.
-
Не запускайте production FreeIPA без понимания процедуры восстановления.
-
Документируйте все изменения конфигурации.
Особенно последний пункт.
Потому что память инфраструктурных инженеров удивительным образом работает избирательно. Через полгода никто уже не помнит, зачем была изменена конкретная настройка, зато все прекрасно помнят, кто именно случайно выключил FreeIPA в пятницу вечером.
Теперь, когда фундамент нашей системы идентификации готов, пользователи и группы созданы, а каталог начинает выполнять роль единого источника истины, можно переходить к следующему компоненту архитектуры - развёртыванию Keycloak, который превратит этот набор учётных записей в полноценную платформу единого входа для всей корпоративной инфраструктуры.
Разворачиваем Keycloak
Если FreeIPA в нашей архитектуре отвечает на вопрос: "Кто этот человек?", то Keycloak отвечает на другой, не менее важный вопрос:
"Что именно этому человеку разрешено делать?"
Именно Keycloak становится тем компонентом, с которым ежедневно взаимодействуют пользователи. Для большинства сотрудников он выглядит как обычная страница авторизации. Они открывают Grafana, ArgoCD или GitLab, вводят логин и пароль, иногда подтверждают вход через второй фактор и продолжают работать дальше.
Но для инфраструктурной команды Keycloak - это гораздо больше, чем просто форма входа.
Это центр единого входа (Single Sign-On), провайдер OpenID Connect, сервер OAuth2, шлюз SAML-аутентификации, механизм многофакторной защиты и, в конечном итоге, один из важнейших элементов всей платформы.
Если FreeIPA перестанет работать, сотрудники не смогут получить новые Kerberos-билеты и возникнут проблемы с инфраструктурными сервисами.
Если перестанет работать Keycloak, пользователи внезапно обнаружат, что:
-
не могут попасть в Grafana;
-
не открывается ArgoCD;
-
GitLab требует повторной авторизации;
-
Harbor недоступен;
-
OpenSearch не пускает аналитиков;
-
внутренние приложения выдают ошибку входа.
Именно поэтому относиться к развёртыванию Keycloak как к "ещё одному контейнеру" крайне опасно.
Что такое Keycloak
Keycloak представляет собой полноценную платформу управления идентификацией и доступом.
Он предоставляет следующие возможности:
-
Single Sign-On;
-
OpenID Connect;
-
OAuth 2.0;
-
SAML 2.0;
-
многофакторную аутентификацию;
-
федерацию пользователей;
-
Identity Brokering;
-
управление пользовательскими сессиями;
-
управление ролями;
-
аудит событий;
-
политики доступа;
-
саморегистрацию пользователей;
-
социальную аутентификацию.
Именно благодаря ему пользователь может один раз пройти аутентификацию и получить доступ сразу ко всем разрешённым приложениям.
Например, типичный сценарий выглядит следующим образом:
Пользователь
│
▼
Открывает Grafana
│
▼
Перенаправляется в Keycloak
│
▼
Вводит логин и пароль
│
▼
Получает токен OIDC
│
▼
Попадает в Grafana
│
▼
Открывает ArgoCD
│
▼
Повторный ввод пароля уже не требуется
Для пользователя это выглядит как магия.
Для инфраструктурной команды это означает снижение количества паролей, уменьшение нагрузки на поддержку и централизованный контроль доступа.
Где запускать Keycloak
Как и в случае с FreeIPA, вариантов несколько:
-
виртуальные машины;
-
Docker;
-
Kubernetes.
В отличие от FreeIPA, Keycloak гораздо лучше приспособлен к контейнерной эксплуатации.
Начиная с перехода на Quarkus архитектура Keycloak существенно изменилась. Он стал быстрее запускаться, потреблять меньше памяти и гораздо лучше масштабироваться.
Именно поэтому сегодня наиболее распространёнными вариантами являются:
-
Docker Compose для небольших инсталляций;
-
Kubernetes для production-платформ;
-
виртуальные машины для консервативных инфраструктур.
PostgreSQL обязателен
Одна из самых популярных ошибок начинающих инженеров выглядит следующим образом:
"Для начала запустим start-dev, а потом когда-нибудь перенесёмся на PostgreSQL."
А потом это "когда-нибудь" внезапно растягивается на несколько лет.
Встроенная база данных H2 предназначена исключительно для разработки.
В production использовать её нельзя.
Причины очевидны:
-
отсутствие отказоустойчивости;
-
ограничения по производительности;
-
отсутствие нормального резервного копирования;
-
риск потери данных.
Поэтому даже лабораторный стенд лучше сразу строить правильно.
Наша схема будет выглядеть следующим образом:
+----------------+
| PostgreSQL 16 |
+--------+-------+
|
|
+--------v-------+
| Keycloak |
| OIDC / SAML |
+--------+-------+
|
+-------------+--------------+
| | |
Grafana ArgoCD GitLab
Минимальные требования
Для небольшой инсталляции Keycloak обычно достаточно:
| Ресурс | Минимум | Рекомендуется |
|---|---|---|
| CPU | 2 vCPU | 4 vCPU |
| RAM | 2 ГБ | 4-8 ГБ |
| Диск | 10 ГБ | 20+ ГБ |
Основной потребитель ресурсов - это память.
Чем больше:
-
пользователей;
-
активных сессий;
-
клиентов;
-
токенов;
-
аутентификаций,
тем больше памяти потребуется.
Для нескольких сотен пользователей 4 ГБ памяти обычно хватает с большим запасом.
Разворачиваем PostgreSQL и Keycloak через Docker Compose
Создадим следующий файл docker-compose.yml:
version: "3.9"
services:
postgres:
image: postgres:16
container_name: keycloak-postgres
environment:
POSTGRES_DB: keycloak
POSTGRES_USER: keycloak
POSTGRES_PASSWORD: StrongPassword
volumes:
- postgres_data:/var/lib/postgresql/data
restart: unless-stopped
keycloak:
image: quay.io/keycloak/keycloak:26.2
container_name: keycloak
command:
- start-dev
environment:
KC_DB: postgres
KC_DB_URL_HOST: postgres
KC_DB_URL_DATABASE: keycloak
KC_DB_USERNAME: keycloak
KC_DB_PASSWORD: StrongPassword
KEYCLOAK_ADMIN: admin
KEYCLOAK_ADMIN_PASSWORD: SuperAdminPassword
ports:
- "8080:8080"
depends_on:
- postgres
restart: unless-stopped
volumes:
postgres_data:
Разбираем compose-файл
Используем PostgreSQL 16:
image: postgres:16
На сегодняшний день это одна из наиболее распространённых и хорошо поддерживаемых СУБД для Keycloak.
Создаём базу данных:
POSTGRES_DB: keycloak
Пользователя:
POSTGRES_USER: keycloak
И пароль:
POSTGRES_PASSWORD: StrongPassword
Разумеется, хранить такие значения в Git - плохая идея.
Но до секретов мы ещё доберёмся.
Настраиваем Keycloak
Указываем используемую СУБД:
KC_DB: postgres
Адрес PostgreSQL:
KC_DB_URL_HOST: postgres
Имя базы:
KC_DB_URL_DATABASE: keycloak
Учётные данные:
KC_DB_USERNAME: keycloak
KC_DB_PASSWORD: StrongPassword
Создаём администратора:
KEYCLOAK_ADMIN: admin
KEYCLOAK_ADMIN_PASSWORD: SuperAdminPassword
Эта учётная запись используется только для первоначального входа.
В production рекомендуется:
-
использовать отдельные административные аккаунты;
-
включить MFA;
-
отключить стандартного администратора после настройки.
Почему используется start-dev
Самый внимательный читатель наверняка заметил:
command:
- start-dev
И сразу возникнет вопрос:
"Но ведь это development-режим?"
Да.
Именно поэтому его использование допустимо только для лабораторных стендов.
Production-запуск выглядит иначе:
command:
- start
Либо:
kc.sh build
kc.sh start
Режим start-dev отключает часть защитных механизмов и предназначен исключительно для упрощения первоначального знакомства с системой.
К сожалению, в интернете можно встретить production-инсталляции, которые годами работают именно в этом режиме.
Обычно об этом узнают во время очередного аудита безопасности.
Запускаем Keycloak
Поднимаем сервисы:
docker compose up -d
Проверяем состояние контейнеров:
docker ps
Результат должен выглядеть примерно так:
CONTAINER ID IMAGE STATUS
a1b2c3d4 postgres:16 Up
b2c3d4e5 quay.io/keycloak/keycloak:26 Up
Следим за логами:
docker logs -f keycloak
После успешного запуска увидим примерно следующее:
Running the server in development mode.
Listening on: http://0.0.0.0:8080
Первый вход
Открываем браузер:
http://localhost:8080
Переходим в административную консоль.
Используем данные администратора:
Логин: admin
Пароль: SuperAdminPassword
После входа становится доступен интерфейс управления Keycloak.
Именно здесь создаются:
-
Realm;
-
клиенты;
-
роли;
-
политики доступа;
-
федерации пользователей;
-
механизмы MFA.
Создаём отдельный Realm
Одна из распространённых ошибок выглядит следующим образом:
"Давайте всё разместим в master."
Realm master предназначен исключительно для администрирования самого Keycloak.
Лучше создать отдельный Realm.
Например:
company
Именно внутри него будут располагаться:
-
пользователи;
-
группы;
-
приложения;
-
роли;
-
федерация FreeIPA.
Подобное разделение существенно упрощает дальнейшую эксплуатацию.
Production best practices
За годы эксплуатации Keycloak сформировался довольно предсказуемый список рекомендаций.
Никогда не используйте H2 в production.
Не запускайте production в режиме start-dev.
Используйте PostgreSQL с резервным копированием.
Включайте HTTPS.
Включайте MFA для администраторов.
Не используйте Realm master для пользовательских приложений.
Настраивайте мониторинг и аудит событий.
Регулярно обновляйте Keycloak.
Особенно последний пункт.
Потому что инфраструктурные инженеры удивительно любят обновлять Kubernetes, PostgreSQL и Linux, но почему-то забывают про системы управления идентификацией.
А потом внезапно выясняется, что весь корпоративный SSO работает на версии, которая вышла ещё тогда, когда разработчики спорили, стоит ли вообще переходить с Java EE на Quarkus.
Теперь у нас есть два важнейших компонента будущей платформы управления идентификацией. FreeIPA хранит пользователей и группы, а Keycloak готов выступить единым центром аутентификации для приложений. Самое время связать их между собой и настроить первый вариант интеграции - встроенную LDAP Federation, чтобы Keycloak начал видеть пользователей из FreeIPA без написания единой строчки собственного кода.
Настраиваем LDAP Federation в Keycloak
К этому моменту у нас уже есть два работающих компонента. FreeIPA хранит пользователей, группы и выступает источником истины для всей инфраструктуры. Keycloak готов выдавать токены, обеспечивать единый вход и выступать центральной точкой аутентификации для приложений. Осталось сделать так, чтобы они начали понимать друг друга.
Именно здесь большинство инженеров впервые знакомится с LDAP Federation и испытывает лёгкое чувство эйфории.
Потому что после всех разговоров про IAM, синхронизацию пользователей, архитектурные диаграммы и безопасность оказывается, что первый рабочий вариант интеграции настраивается буквально за десять-пятнадцать минут.
Но есть одна важная особенность.
LDAP Federation - это отличный старт. Особенно если у вас несколько десятков пользователей и относительно простая структура групп. Однако не стоит воспринимать её как универсальное решение всех проблем. Позже мы подробно поговорим о её ограничениях и о том, почему многие компании в итоге приходят к собственным сервисам синхронизации. Сейчас же наша задача - получить работающую интеграцию между FreeIPA и Keycloak без написания собственного кода.
Как работает LDAP Federation
Механизм работы достаточно прост.
Keycloak выступает в роли клиента LDAP-каталога.
Он подключается к FreeIPA, получает информацию о пользователях и при необходимости использует её для аутентификации.
Архитектурно это выглядит следующим образом:
+----------------------+
| FreeIPA |
| LDAP + Kerberos |
+----------+-----------+
|
LDAPS:636
|
v
+----------+-----------+
| Keycloak |
| LDAP Federation |
+----------+-----------+
|
+--------------+-------------+
| | |
v v v
Grafana ArgoCD GitLab
Когда пользователь пытается войти в приложение, происходит следующая последовательность действий:
-
Пользователь открывает Grafana.
-
Grafana перенаправляет его в Keycloak.
-
Keycloak получает логин и пароль.
-
Keycloak выполняет LDAP Bind к FreeIPA.
-
FreeIPA подтверждает подлинность пользователя.
-
Keycloak выдаёт OIDC-токен.
-
Пользователь попадает в приложение.
С точки зрения конечного пользователя всё выглядит как обычная форма входа.
Какие режимы работы поддерживает Keycloak
Перед настройкой важно понимать, что Keycloak умеет работать с LDAP несколькими способами.
Import Users
При включённом импорте пользователи копируются в локальную базу Keycloak.
Плюсы:
-
более быстрый поиск пользователей;
-
снижение нагрузки на LDAP;
-
возможность использовать дополнительные атрибуты Keycloak.
Минусы:
-
появляются две копии данных;
-
требуется периодическая синхронизация;
-
возможны расхождения между системами.
Read Only
Keycloak только читает данные из LDAP.
Все изменения производятся исключительно в FreeIPA.
Плюсы:
-
единый источник истины;
-
отсутствие конфликтов;
-
безопасная модель эксплуатации.
Минусы:
-
любые изменения выполняются через FreeIPA;
-
часть функций Keycloak становится недоступной.
Writable
Keycloak может изменять LDAP напрямую.
Звучит заманчиво.
На практике опытные инженеры стараются избегать этого режима.
Потому что очень быстро начинаются вопросы:
-
кто изменил пользователя;
-
почему группа исчезла;
-
кто удалил атрибут;
-
через какой интерфейс произошло изменение.
И дальше начинается инфраструктурная археология.
Почему мы выбираем READ_ONLY
Для нашей архитектуры мы будем использовать именно этот режим.
И причина достаточно проста.
FreeIPA является источником истины.
Только он должен отвечать за:
-
создание пользователей;
-
изменение атрибутов;
-
удаление сотрудников;
-
управление группами.
Keycloak не должен самостоятельно менять корпоративный каталог.
Иначе через некоторое время обязательно появится пользователь, которого создали "напрямую через Keycloak", а потом все будут пытаться понять, почему его нет в FreeIPA.
А подобные загадки обычно всплывают во время аудита информационной безопасности.
Добавляем LDAP Federation
Открываем административную консоль Keycloak.
Переходим в созданный ранее Realm.
Далее выбираем:
Realm Settings
↓
User Federation
↓
Add Provider
↓
ldap
После этого открывается форма настройки LDAP-подключения.
Основные параметры подключения
Заполняем следующие поля.
Vendor
Red Hat Directory Server
FreeIPA построен на базе 389 Directory Server, поэтому именно этот вариант обеспечивает наиболее корректную работу.
Connection URL
Если используется защищённое соединение:
ldaps://ipa.example.local:636
Если используется обычный LDAP:
ldap://ipa.example.local:389
Использовать LDAP в production крайне не рекомендуется.
Потому что логины и учётные данные начинают путешествовать по сети в открытом виде.
А специалисты ИБ очень не любят подобные сюрпризы.
Bind DN
Указываем пользователя, от имени которого Keycloak будет выполнять LDAP-запросы:
uid=admin,cn=users,cn=accounts,dc=example,dc=local
В реальной инфраструктуре лучше создать отдельную сервисную учётную запись только для чтения каталога.
Например:
uid=keycloak-sync,cn=users,cn=accounts,dc=example,dc=local
Использование администратора FreeIPA для повседневной интеграции считается плохой практикой.
Bind Credentials
Пароль сервисной учётной записи:
********
Users DN
Указываем контейнер пользователей:
cn=users,cn=accounts,dc=example,dc=local
Именно отсюда Keycloak будет получать список пользователей.
Настраиваем импорт пользователей
Для нашей лабораторной инсталляции установим следующие значения.
Import Users
ON
Это позволит хранить локальный кэш пользователей внутри Keycloak.
Edit Mode
READ_ONLY
Ещё раз.
Очень хочется выбрать Writable.
Не надо.
Sync Registrations
OFF
Регистрация пользователей через Keycloak нам не нужна.
Все сотрудники должны создаваться исключительно в FreeIPA.
Trust Email
ON
Поскольку источником истины является корпоративный каталог, адресам электронной почты можно доверять.
Проверяем соединение
После заполнения параметров нажимаем:
Test Connection
При успешном результате появится сообщение:
Success! Connection to LDAP established.
Затем выполняем:
Test Authentication
Если учётные данные корректны, увидим:
Success! Authentication succeeded.
Если на этом этапе появляются ошибки, не стоит сразу обвинять Keycloak.
В большинстве случаев проблема связана с:
-
DNS;
-
сертификатами LDAPS;
-
неверным Bind DN;
-
ошибками в пароле;
-
закрытыми сетевыми портами.
Настраиваем синхронизацию пользователей
После сохранения настроек становятся доступны дополнительные действия.
Особенно интересуют две кнопки.
Synchronize all users
Импортирует всех пользователей из LDAP.
Полезно использовать при первичной настройке.
Synchronize changed users
Импортирует только изменившиеся записи.
Используется при регулярной эксплуатации.
Нажимаем:
Synchronize all users
После завершения операции можно перейти в раздел:
Users
Если всё прошло успешно, там появятся пользователи из FreeIPA.
Например:
admin
ivanov
petrov
sidorov
Именно в этот момент многие впервые испытывают искреннюю радость от централизованной идентификации.
Потому что внезапно оказывается, что пользователи больше не живут отдельно в каждом приложении.
Проверяем аутентификацию
Попробуем войти под одним из импортированных пользователей.
Например:
Логин: ivanov
Пароль: ********
Если всё настроено правильно, Keycloak выполнит LDAP Bind через FreeIPA и авторизация завершится успешно.
При этом пароль пользователя никогда не хранится внутри Keycloak.
Он лишь проверяет его через LDAP.
Это ещё одна причина, по которой режим READ_ONLY считается наиболее безопасным.
Настройка групп
На этом этапе возникает соблазн сразу импортировать группы из FreeIPA и автоматически использовать их для назначения ролей.
Технически Keycloak умеет это делать.
Однако именно здесь начинают проявляться первые ограничения LDAP Federation.
Особенно если в инфраструктуре используются:
-
вложенные группы;
-
сложные правила сопоставления;
-
исключения;
-
разные политики доступа для подрядчиков и сотрудников;
-
автоматические уведомления.
В лабораторных стендах это обычно не вызывает проблем.
Но по мере роста инфраструктуры ситуация начинает меняться.
Именно поэтому следующая глава будет посвящена не столько успешным сценариям работы LDAP Federation, сколько диагностике возникающих проблем и методам их решения. Потому что интеграция, которая прекрасно работает в демонстрационном окружении на десяти пользователях, далеко не всегда ведёт себя столь же предсказуемо в production, где одновременно работают сотни инженеров и десятки приложений.
Проверяем работу LDAP и диагностируем проблемы
Есть одна интересная особенность практически всех интеграций на базе LDAP.
Когда всё работает, про него никто не вспоминает. Пользователи спокойно заходят в Grafana, GitLab и ArgoCD, разработчики получают свои токены, а инженеры считают, что архитектура была спроектирована идеально.
Но стоит появиться первой ошибке авторизации, как LDAP внезапно превращается в источник загадочных сообщений вида:
Invalid user credentials.
Failed to authenticate user.
LDAP connection error.
Cannot bind to LDAP server.
User not found.
И начинается то самое развлечение, которое знакомо любому инфраструктурному инженеру - диагностика проблем аутентификации.
Хуже всего то, что LDAP очень любит сообщать об ошибках максимально лаконично. Сообщение "Invalid credentials" может означать действительно неправильный пароль. А может означать неправильный Bind DN, проблемы с сертификатами LDAPS, неработающий DNS, просроченный Kerberos-билет или даже отсутствие обратной DNS-записи.
Поэтому опытные инженеры никогда не начинают расследование с Keycloak.
Они идут по слоям снизу вверх.
Схема диагностики LDAP
Практика показывает, что наиболее эффективным является следующий порядок проверки:
DNS
↓
Сетевая доступность
↓
LDAPS-соединение
↓
LDAP Bind
↓
LDAP Search
↓
Keycloak Federation
↓
Аутентификация пользователя
↓
Проверка групп
↓
Проверка приложений
Если пытаться диагностировать всё одновременно, очень легко потеряться.
А когда половина компании не может войти в корпоративные сервисы, паника обычно не помогает принимать правильные решения.
Проверяем DNS
Как уже говорилось ранее, DNS является одной из наиболее частых причин проблем.
Начинаем с проверки прямых записей:
dig ipa.example.local
или:
nslookup ipa.example.local
Ожидаемый результат:
ipa.example.local. 300 IN A 10.10.10.10
Затем проверяем обратное разрешение:
dig -x 10.10.10.10
или:
nslookup 10.10.10.10
Результат должен выглядеть примерно так:
10.10.10.10.in-addr.arpa PTR ipa.example.local.
Если обратная запись отсутствует, стоит исправить это сразу.
Kerberos умеет очень творчески реагировать на подобные ситуации.
Проверяем сетевую доступность
Убедимся, что Keycloak действительно может достучаться до FreeIPA.
Из контейнера Keycloak:
docker exec -it keycloak bash
Проверяем соединение:
nc -zv ipa.example.local 636
или:
telnet ipa.example.local 636
Ожидаемый результат:
Connection to ipa.example.local 636 port [tcp/ldaps] succeeded!
Если соединения нет, проверяем:
-
firewall;
-
security groups;
-
правила маршрутизации;
-
публикацию портов Docker;
-
политики Kubernetes NetworkPolicy.
Удивительно, насколько часто проблема оказывается именно здесь.
Проверяем сертификаты LDAPS
Следующий этап - проверка TLS.
Для этого используем OpenSSL:
openssl s_client \
-connect ipa.example.local:636 \
-showcerts
Если всё хорошо, увидим сертификат сервера:
Certificate chain
...
Verify return code: 0 (ok)
Наиболее частые ошибки:
self signed certificate
означает отсутствие доверия к сертификату.
certificate verify failed
означает проблемы с цепочкой сертификатов.
unable to get local issuer certificate
говорит о том, что контейнер Keycloak не доверяет CA FreeIPA.
Особенно часто это происходит при использовании собственных центров сертификации.
Проверяем LDAP Bind вручную
Теперь попробуем выполнить аутентификацию без участия Keycloak.
Для этого воспользуемся пакетом ldap-utils.
Если его нет:
apt update
apt install ldap-utils -y
Проверяем Bind:
ldapwhoami \
-x \
-H ldaps://ipa.example.local \
-D "uid=admin,cn=users,cn=accounts,dc=example,dc=local" \
-W
После ввода пароля ожидаем увидеть:
dn:uid=admin,cn=users,cn=accounts,dc=example,dc=local
Если появляется ошибка:
Invalid credentials (49)
проверяем:
-
пароль;
-
Bind DN;
-
статус учётной записи.
Если появляется:
Can't contact LDAP server (-1)
ищем проблемы в сети или TLS.
Проверяем поиск пользователей
Даже если Bind работает, это ещё не означает, что Keycloak сможет найти пользователей.
Выполняем LDAP Search:
ldapsearch \
-x \
-H ldaps://ipa.example.local \
-D "uid=admin,cn=users,cn=accounts,dc=example,dc=local" \
-W \
-b "cn=users,cn=accounts,dc=example,dc=local"
Ожидаемый результат:
dn: uid=ivanov,cn=users,cn=accounts,dc=example,dc=local
uid: ivanov
mail: ivanov@example.local
givenName: Иван
sn: Иванов
Если пользователей нет:
-
проверяем Base DN;
-
проверяем права сервисной учётной записи;
-
проверяем LDAP Filter.
Проверяем LDAP-фильтр
Очень частая проблема выглядит следующим образом:
Пользователи существуют.
LDAP работает.
Но Keycloak никого не импортирует.
Причина может скрываться в фильтре поиска.
Например:
(objectClass=person)
или:
(&(objectClass=person)(uid=*))
Неправильно настроенный фильтр способен вернуть пустой результат.
И тогда создаётся впечатление, что FreeIPA вообще не содержит пользователей.
Проверяем импорт пользователей в Keycloak
Переходим в:
User Federation
↓
LDAP Provider
Нажимаем:
Synchronize all users
Если импорт завершился успешно, увидим сообщение:
Successfully synchronized users
После этого проверяем раздел:
Users
Там должны появиться пользователи FreeIPA.
Если импорт не происходит, проверяем логи Keycloak.
Анализируем логи Keycloak
В Docker:
docker logs keycloak
В Kubernetes:
kubectl logs deployment/keycloak
Очень полезно включить более подробный уровень логирования:
--log-level=DEBUG
или:
KC_LOG_LEVEL=DEBUG
Типичные ошибки выглядят следующим образом.
Неверный пароль:
LDAP: error code 49
Неправильный DN:
LDAP: error code 32
Проблемы TLS:
SSLHandshakeException
Недоступный LDAP:
CommunicationException
Научившись различать эти сообщения, можно существенно сократить время расследований.
Проверяем аутентификацию пользователей
Предположим, пользователь импортирован.
Теперь проверяем вход.
Пытаемся авторизоваться:
ivanov
SuperPassword
Если вход не выполняется:
проверяем события Keycloak:
Events
↓
Login Events
Ищем причины отказа.
Например:
invalid_user_credentials
или:
user_not_found
Это позволяет понять, на каком этапе произошёл сбой.
Проверяем группы
Следующая категория проблем связана с группами.
Пользователь успешно входит в систему.
Но внезапно оказывается, что:
-
в Grafana он Viewer вместо Admin;
-
в ArgoCD нет административных прав;
-
в GitLab отсутствует доступ к проектам.
В этом случае необходимо проверить LDAP-атрибуты.
Например:
ldapsearch \
-x \
-H ldaps://ipa.example.local \
-D "uid=admin,cn=users,cn=accounts,dc=example,dc=local" \
-W \
"(uid=ivanov)" \
memberOf
Ожидаемый результат:
memberOf: cn=devops,...
memberOf: cn=grafana-admins,...
memberOf: cn=argocd-admins,...
Если нужных групп нет, проблема находится не в Keycloak.
Она находится в FreeIPA.
Проверяем приложения
Очень часто инженеры обвиняют LDAP в проблемах, которые вообще не связаны с LDAP.
Например:
Пользователь успешно входит в Keycloak.
Но Grafana всё равно не работает.
Тогда проверяем цепочку дальше:
Пользователь
↓
Keycloak
↓
OIDC Token
↓
Grafana
Нужно убедиться:
-
что клиент Keycloak настроен правильно;
-
что Redirect URI указан корректно;
-
что роли передаются в токене;
-
что приложение умеет их обрабатывать.
Именно поэтому диагностика должна идти последовательно.
Наиболее частые причины проблем
Если обобщить опыт эксплуатации, список лидеров выглядит следующим образом:
-
Неправильный DNS.
-
Отсутствие PTR-записей.
-
Проблемы с LDAPS-сертификатами.
-
Неверный Bind DN.
-
Ошибочный пароль сервисной учётной записи.
-
Неправильный Base DN.
-
Ошибки LDAP Filter.
-
Некорректная настройка групп.
-
Ошибки OIDC-клиентов.
-
Использование администратора FreeIPA вместо сервисной учётной записи.
Интересно, что сам LDAP как технология ломается довольно редко.
Гораздо чаще ломается всё вокруг него.
Как диагностируют проблемы опытные инженеры
У опытных DevOps-инженеров обычно есть простое правило:
Если что-то не работает, сначала проверь DNS.
Если DNS в порядке:
Проверь сеть.
Если сеть работает:
Проверь LDAP вручную.
Если LDAP отвечает:
Только после этого открывай Keycloak.
И только потом переходи к приложениям.
Потому что расследование инцидента методом случайного нажатия кнопок в административном интерфейсе редко приводит к успеху.
Зато последовательная диагностика позволяет локализовать проблему буквально за несколько минут.
И именно здесь многие команды впервые понимают одну неприятную вещь. Несмотря на всю простоту LDAP Federation, она начинает требовать всё больше внимания по мере роста инфраструктуры. Пользователей становится больше, групп становится больше, появляются исключения, требования ИБ, сложные правила сопоставления ролей и необходимость полноценного аудита.
И тогда возникает вполне закономерный вопрос:
А достаточно ли нам встроенной LDAP Federation, или пора задуматься о более гибком подходе?
Почему LDAP Federation не всегда достаточно
После первых успешных тестов LDAP Federation у большинства инженеров возникает вполне закономерное ощущение:
"А зачем вообще писать какой-то sync-сервис? Всё же работает."
И действительно, на этом этапе всё выглядит практически идеально.
У нас есть FreeIPA, который хранит пользователей и группы. Есть Keycloak, который умеет обращаться к LDAP. Пользователи импортируются буквально нажатием одной кнопки. Grafana начинает пускать сотрудников по OIDC, ArgoCD выдаёт доступы, GitLab принимает токены, а безопасники наконец перестают присылать письма с вопросом, почему у разработчиков пароли отличаются в каждой системе.
Если инфраструктура небольшая - скорее всего, на этом действительно можно остановиться.
Но проблема большинства инфраструктур заключается в том, что они имеют неприятную привычку расти.
Сегодня у вас двадцать сотрудников.
Через полгода их становится пятьдесят.
Через год - двести.
Появляются подрядчики, стажёры, внешние консультанты, дежурные смены, отдельные команды разработки, платформенная команда, аналитики и специалисты по информационной безопасности.
И вот именно тогда выясняется, что LDAP Federation - это отличный механизм федерации пользователей, но далеко не полноценная система управления жизненным циклом идентификаций.
Когда LDAP Federation действительно достаточно
Прежде чем ругать встроенную федерацию, стоит признать очевидный факт.
Для огромного количества компаний она является абсолютно правильным выбором.
LDAP Federation прекрасно подходит, если:
-
пользователей меньше 50-100 человек;
-
структура групп достаточно простая;
-
отсутствуют сложные правила назначения ролей;
-
нет требований по детальному аудиту;
-
отсутствуют интеграции с внешними системами;
-
доступы меняются относительно редко;
-
управление осуществляется небольшой командой администраторов.
В такой ситуации использование собственного сервиса синхронизации действительно может оказаться преждевременным усложнением архитектуры.
И это нормально.
Не каждая инфраструктура обязана выглядеть как платформа крупного банка.
Но по мере роста начинают проявляться ограничения.
Ограничение №1. Keycloak не является источником истины
Самая распространённая проблема выглядит удивительно просто.
Допустим, пользователь входит в систему.
Keycloak успешно получает информацию из FreeIPA.
Но затем возникает желание немного "подправить" данные прямо в Keycloak.
Например:
-
изменить отображаемое имя;
-
добавить атрибут;
-
скорректировать группу;
-
создать локального пользователя;
-
назначить исключение.
С этого момента начинается расхождение данных.
Например:
FreeIPA:
ivanov
├─ devops
└─ vpn-users
Keycloak:
ivanov
├─ devops
├─ vpn-users
└─ grafana-admin
Через некоторое время никто уже не понимает:
-
где находится актуальная информация;
-
кто изменил настройки;
-
почему права отличаются.
Именно поэтому зрелые инфраструктурные команды стараются придерживаться одного правила:
Источник истины должен быть только один.
Ограничение №2. Сложная бизнес-логика
Пока группы соответствуют ролям один к одному, LDAP Federation выглядит замечательно.
Например:
devops → argocd-admin
developers → grafana-viewer
vpn-users → vpn-access
Но потом приходят реальные требования бизнеса.
Например:
Всем сотрудникам группы DevOps выдавать административные права в Grafana, кроме подрядчиков.
Или:
Разработчики из московского офиса получают доступ к production только после прохождения обучения.
Или:
Сотрудники, находящиеся в отпуске более 30 дней, должны автоматически терять административные роли.
LDAP Federation на такие требования обычно смотрит с лёгким недоумением.
Потому что её задача - федерация пользователей.
Не реализация бизнес-процессов.
Ограничение №3. Вложенные группы
На архитектурных диаграммах nested groups выглядят невероятно красиво.
Например:
engineering
├─ developers
├─ devops
└─ sre
devops
├─ argocd-admins
├─ grafana-admins
└─ harbor-admins
Кажется, что достаточно один раз включить наследование.
На практике начинаются вопросы:
-
поддерживает ли вложенные группы FreeIPA;
-
корректно ли импортирует их Keycloak;
-
понимает ли их Grafana;
-
как ведёт себя GitLab;
-
как отображаются такие роли в токенах OIDC.
Разные системы трактуют подобные конструкции по-разному.
И через некоторое время получается инфраструктурная матрёшка, в которой никто уже не может точно объяснить происхождение конкретных прав.
Ограничение №4. Отсутствие полноценного аудита
Представим ситуацию.
Специалист ИБ задаёт вопрос:
Почему пользователь ivanov получил права администратора ArgoCD?
Логично было бы ответить:
Потому что вчера его перевели в платформенную команду.
Но в реальности начинается расследование.
FreeIPA говорит:
Пользователь состоит в группе devops.
Keycloak говорит:
Я импортировал пользователя.
ArgoCD говорит:
Мне пришла роль admin.
А вот кто именно назначил эту роль и почему это произошло - выяснить уже значительно сложнее.
Встроенная федерация даёт лишь ограниченные возможности аудита.
А когда количество пользователей переваливает за несколько сотен, подобные вопросы начинают возникать регулярно.
Ограничение №5. Нет интеграции с внешними системами
Современная инфраструктура редко существует в вакууме.
Очень часто требуется интеграция с:
-
Telegram;
-
Slack;
-
Microsoft Teams;
-
Jira;
-
SIEM;
-
Service Desk;
-
CMDB;
-
системами согласования.
Например:
При выдаче административной роли отправить уведомление безопасникам.
Или:
При блокировке пользователя создать тикет в Service Desk.
Или:
Перед назначением доступа запросить согласование руководителя.
LDAP Federation подобных механизмов не предоставляет.
Ограничение №6. Жизненный цикл пользователей
Самая болезненная тема любой инфраструктуры.
Увольнение сотрудников.
В идеальном мире процесс выглядит так:
Уволили сотрудника
↓
Учётная запись отключена
↓
Права автоматически отозваны
↓
Доступ исчез во всех системах
На практике же возникает множество нюансов.
Например:
-
нужно ли удалять пользователя или блокировать;
-
сколько хранить его данные;
-
кто должен получать уведомления;
-
какие действия необходимо зафиксировать в аудите;
-
требуется ли архивирование информации.
LDAP Federation умеет только часть подобных сценариев.
Полноценное управление жизненным циклом обычно требует дополнительной логики.
Ограничение №7. GitOps невозможен в полном объёме
За последние годы платформенные команды всё чаще используют принцип:
Всё должно быть описано в виде кода.
Мы привыкли хранить в Git:
-
Terraform;
-
Helm-чарты;
-
Kubernetes-манифесты;
-
Ansible;
-
Jenkins Pipeline.
Возникает закономерный вопрос.
Почему доступы должны жить иначе?
Например, гораздо удобнее описывать правила следующим образом:
role_mappings:
devops:
- grafana-admin
- argocd-admin
developers:
- grafana-viewer
contractors:
- vpn-users
Изменения проходят через Pull Request.
Коллеги проводят ревью.
После одобрения система автоматически применяет новые правила.
LDAP Federation практически не вписывается в подобную модель.
Ограничение №8. Масштабирование организации
Есть интересное наблюдение.
Проблемы LDAP Federation почти никогда не проявляются сразу.
Обычно всё происходит следующим образом.
Этап первый:
У нас 20 пользователей. Всё отлично.
Этап второй:
У нас 80 пользователей. Иногда неудобно.
Этап третий:
У нас 250 пользователей. Надо бы автоматизировать.
Этап четвёртый:
Кто-нибудь понимает, почему подрядчик получил доступ к production?
Именно поэтому многие организации начинают с LDAP Federation, а затем переходят к более сложной модели управления идентификацией.
Значит ли это, что LDAP Federation плохая?
Совершенно нет.
Наоборот.
LDAP Federation - это один из лучших способов быстро внедрить единый вход и избавиться от локальных пользователей в приложениях.
Она:
-
проста;
-
надёжна;
-
хорошо документирована;
-
встроена в Keycloak;
-
подходит большинству небольших инфраструктур.
Проблема не в самой технологии.
Проблема возникает тогда, когда на неё начинают возлагать задачи, для которых она изначально не проектировалась.
Пытаться построить полноценную платформу управления жизненным циклом идентификаций исключительно на LDAP Federation - примерно то же самое, что использовать Bash-скрипт вместо системы оркестрации.
До определённого момента это даже работает.
А потом внезапно оказывается, что этот Bash-скрипт состоит из трёх тысяч строк, запускается по cron каждые пять минут, боится пробелов в переменных и известен в компании под названием final_final_sync_v7.sh.
И никто не решается его трогать.
Именно в этот момент многие команды приходят к мысли, что между FreeIPA и Keycloak нужен ещё один компонент. Компонент, который будет не просто копировать пользователей, а управлять их жизненным циклом, реализовывать бизнес-логику, вести аудит, интегрироваться с внешними системами и превращать IAM из "набора настроек" в полноценный инфраструктурный сервис.
Поэтому следующим шагом мы спроектируем собственный сервис синхронизации, который позволит взять под контроль весь процесс управления идентификацией - от появления сотрудника в FreeIPA до автоматического назначения ролей, уведомлений и блокировки доступов во всей корпоративной инфраструктуре.
На этом этапе может показаться, что задача успешно решена. Пользователи из FreeIPA появляются в Keycloak, аутентификация работает, а большинство демонстрационных примеров из интернета уже полностью повторены. Однако именно здесь начинается самое интересное. Потому что production предъявляет совершенно другие требования. Бизнесу недостаточно просто видеть пользователей в интерфейсе Keycloak. Ему нужны автоматическая блокировка уволенных сотрудников, управление ролями, аудит, уведомления и возможность объяснить каждое изменение доступа.
Именно поэтому в следующей части мы спроектируем и реализуем собственный сервис синхронизации, который превратит FreeIPA и Keycloak из двух отдельно существующих продуктов в единую систему управления жизненным циклом цифровой личности сотрудника.