Конфигурация OmniAuth
Deckhouse Code поддерживает вход через внешних провайдеров аутентификации (OmniAuth), в том числе через OpenID Connect (OIDC) и SAML. Ниже описаны общие параметры OmniAuth, параметры провайдеров и дополнительные возможности Deckhouse Code.
Поддерживаемые провайдеры
В параметре name записи провайдера указывается одно из следующих значений:
openid_connect— OpenID Connect (описан ниже);saml— SAML (описан ниже);oauth2_generic— произвольный провайдер OAuth 2.0;jwt— аутентификация по JWT;github— GitHub;gitlab— GitLab.com;google_oauth2— Google;azure_activedirectory_v2— Microsoft Entra ID (Azure AD);atlassian_oauth2— Atlassian;crowd— Atlassian Crowd;auth0— Auth0;alicloud— AliCloud;salesforce— Salesforce;shibboleth— Shibboleth.
Вход через LDAP настраивается отдельно, в секции spec.appConfig.ldap. (подробнее — в разделе «Синхронизация с LDAP»).
Общие параметры OmniAuth
Параметры задаются в секции spec.appConfig.omniauth.:
enabled— разрешает вход через внешних провайдеров. По умолчанию —true.providers— список провайдеров, через которых разрешён вход. По умолчанию —[].allow_single_sign_on— список провайдеров, для которых при первом входе автоматически создаётся учётная запись (например,['openid_connect']). Также принимает значенияtrue(все провайдеры) иfalse. Если автоматическое создание отключено, пользователь должен сначала получить учётную запись в Deckhouse Code, а затем связать её с провайдером. По умолчанию —false.block_auto_created_users— еслиtrue, автоматически созданные учётные записи блокируются до одобрения администратором. По умолчанию —true.auto_link_ldap_user— связывает учётную запись с учётной записью LDAP при первом входе (подробнее — в разделе «Связывание учётных записей OIDC с LDAP»). По умолчанию —false.auto_link_user— связывает вход через провайдера с существующей учётной записью Deckhouse Code по адресу электронной почты. Принимает список провайдеров или значенияtrueиfalse. По умолчанию —false.auto_sign_in_with_provider— имя провайдера, на страницу входа которого пользователь перенаправляется автоматически, минуя страницу входа Deckhouse Code. По умолчанию —false.external_providers— список провайдеров, учётные записи которых создаются как внешние. По умолчанию —[].allow_bypass_two_factor— список провайдеров, вход через которых не требует двухфакторной аутентификации. Также принимает значенияtrueиfalse. По умолчанию —false.sync_profile_from_provider— список провайдеров, из данных которых обновляется профиль пользователя при каждом входе. Также принимает значенияtrueиfalse. По умолчанию —false.sync_profile_attributes— список атрибутов профиля, которые обновляются при синхронизации:name,email,location. Синхронизируемые атрибуты становятся доступными только для чтения. По умолчанию —['email'].
OpenID Connect (OIDC)
Провайдеры перечисляются в параметре providers секции spec.appConfig.omniauth.. Для провайдера OIDC доступны следующие параметры:
name— тип провайдера. Для OIDC — всегда'openid_connect'.label— подпись кнопки входа. По умолчанию —'Openid Connect'.icon— адрес изображения, которое будет показано на кнопке входа.args— параметры подключения к провайдеру:name— имя стратегии OmniAuth, совпадает со значением параметраnameпровайдера;scope— список запрашиваемых областей доступа, например['openid', 'profile', 'email'];response_type— тип ответа OAuth 2.0. Для потока Authorization Code —'code';issuer— адрес OIDC-провайдера;discovery— еслиtrue, настройки провайдера запрашиваются автоматически по адресу<issuer>/.well-known/openid-configuration;client_auth_method— способ аутентификации клиента на token endpoint:'basic'или'query';uid_field— поле из данных пользователя, которое используется какuidучётной записи (например,preferred_username). Если параметр не задан или поле отсутствует, используется полеsub;send_scope_to_token_endpoint— передавать ли параметрscopeв запросах к token endpoint. Задайтеfalse, если провайдер не принимает этот параметр. По умолчанию —true;pkce— включает Proof Key for Code Exchange (PKCE);client_options:identifier— идентификатор клиента, зарегистрированного у провайдера;secret— секрет клиента;redirect_uri— адрес установки Deckhouse Code с путём/users/auth/openid_connect/callback. Тот же адрес должен быть указан в настройках клиента на стороне провайдера.
Дополнительно Deckhouse Code поддерживает следующие параметры. Они указываются на верхнем уровне записи провайдера, рядом с параметром name:
-
allowed_groups— список групп, пользователям которых разрешён вход. Пользователи вне этих групп будут заблокированы. По умолчанию —null(разрешены все группы). -
admin_groups— список групп, пользователи которых получают административные права. По умолчанию —null(права администратора не выдаются ни одной группе). -
auditor_groups— список групп, пользователи которых получают роль аудитора: доступ только на чтение ко всем группам и проектам, без доступа к административному разделу. По умолчанию —null(роль аудитора не выдаётся ни одной группе). -
groups_attribute— имя атрибута, из которого извлекаются группы пользователя. По умолчанию —'groups'.
Параметры admin_groups и auditor_groups учитываются, только если задан параметр allowed_groups. Если пользователь входит и в admin_groups, и в auditor_groups, ему назначаются права администратора.
Пример конфигурации OIDC
Настройка выполняется в секции spec.appConfig.omniauth.:
providers:
- name: 'openid_connect' # Не изменяйте это значение.
label: 'Keycloak' # Подпись кнопки входа.
allowed_groups:
- 'gitlab'
admin_groups:
- 'admin'
auditor_groups:
- 'audit'
groups_attribute: 'gitlab_group'
args:
name: 'openid_connect'
scope:
- 'openid'
- 'profile'
- 'email'
response_type: 'code'
issuer: 'https://keycloak.example.com/realms/example'
discovery: true
client_auth_method: 'query'
uid_field: 'preferred_username'
send_scope_to_token_endpoint: false
pkce: true
client_options:
identifier: '<client_id>'
secret: '<client_secret>'
redirect_uri: 'https://code.example.com/users/auth/openid_connect/callback'
SAML
Для провайдеров SAML доступны аналогичные параметры:
-
allowed_groups— список групп с разрешённым входом.
По умолчанию —null(разрешены все группы). -
admin_groups— группы с административными правами.
По умолчанию —null(права администратора не выдаются ни одной группе). -
auditor_groups— группы, пользователи которых получают роль аудитора: доступ только на чтение ко всем группам и проектам.
По умолчанию —null(роль аудитора не выдаётся ни одной группе). -
groups_attribute— имя атрибута, содержащего группы. По умолчанию —'Groups'.
Пример конфигурации SAML
Настройка выполняется в секции spec.appConfig.omniauth.:
providers:
- name: 'saml'
allowed_groups:
- 'gitlab'
admin_groups:
- 'admin'
groups_attribute: 'gitlab_group'
Если пользователь входит в admin_groups, но не указан в allowed_groups, доступ будет запрещён. В этом случае административные права также не будут назначены.
Синхронизация с LDAP
Deckhouse Code поддерживает синхронизацию пользователей, групп и прав доступа с LDAP-сервером. Синхронизация выполняется автоматически раз в час, либо с заданной периодичностью.
Вы можете настроить периодичность синхронизации через параметр cronJobs в секции spec.appConfig.:
cron_jobs:
ldap_sync_worker:
cron: "0 * * * *"
Ограничения на стороне LDAP-сервера
Во время синхронизации выполняются LDAP-запросы ко всем пользователям и группам, указанным в конфигурации. При необходимости используется постраничная загрузка (pagination). Если на стороне LDAP установлены ограничения на число возвращаемых объектов, это может привести к ошибкам синхронизации или удалению прав доступа у пользователей.
Пример конфигурации LDAP-провайдера
Конфигурация размещается в spec.appConfig.ldap.:
main:
label: ldap
host: 127.0.0.1
port: 3389
bind_dn: 'uid=viewer,ou=People,dc=example,dc=com'
base: 'ou=People,dc=example,dc=com'
uid: 'cn'
password: 'viewer123'
sync_name: true
group_sync: {
create_groups: true,
base: 'ou=Groups,dc=example,dc=org',
filter: '(objectClass=groupOfNames)',
prefix: {
attribute: 'businessCategory',
default: 'default-program',
},
top_level_group: "LdapGroups",
name_mask: "(?<=-)[A-z0-9А-я]*$",
owner: "root",
role_mapping: [
{ by_name: '.*-project_manager-.*', gitlab_role: 'maintainer' },
{ by_name: '.*-developer-.*', gitlab_role: 'developer' },
{ by_name: '.*-participant-.*', gitlab_role: 'reporter' }
]
}
Группы и права доступа
LDAP-группы сопоставляются с группами GitLab. При этом можно назначать роли пользователям на основе имени группы.
Обязательные параметры:
group_sync.base— DN, с которого начинается поиск LDAP-групп.
Опциональные параметры:
group_sync.create_groups— еслиtrue, группы будут создаваться в Deckhouse Code.group_sync.filter— LDAP-фильтр для поиска групп.group_sync.scope— область поиска групп (0 — Base, 1 — SingleLevel, 2 — WholeSubtree).group_sync.prefix— определяет, из какого атрибута брать имя родительской группы. Если атрибут отсутствует — используется значение по умолчанию.group_sync.top_level_group— имя группы верхнего уровня, в которую будут добавлены все синхронизированные группы.group_sync.name_mask— регулярное выражение для извлечения имени группы из атрибута CN (Common Name).group_sync.owner— имя пользователя, который будет добавлен как владелец группы (по умолчанию —root).
Секция role_mapping
Назначает права пользователям на основе имени группы (cn):
role_mapping.by_name— регулярное выражение; если имя группы совпадает, пользователю назначается соответствующая роль.role_mapping.gitlab_role— название роли в Deckhouse Code (например:guest,reporter,developer,maintainer,owner).
Определение членов группы
LDAP Sync не поддерживает транзитивность для вложенных групп. Подробная информация в разделе «Вложенные группы и транзитивность».
Deckhouse Code поддерживает следующие атрибуты для определения членов группы (все значения — массив DN):
member;uniquemember;memberof;memberuid;submember.
Синхронизация пользователей
Во время синхронизации обновляются имена и email-адреса пользователей, а также статус блокировки.
Опциональные параметры:
sync_name — если true, имя пользователя будет обновлено по данным LDAP.
Блокировка пользователей по данным LDAP
Если пользователь удалён из LDAP, очередная плановая синхронизация заблокирует его учётную запись. Если пользователя вернули в LDAP, следующая синхронизация разблокирует учётную запись автоматически.
Блокировка выполняется всегда и не требует дополнительных настроек: источником истины для статуса учётной записи остаётся LDAP. Вход заблокированного пользователя через OIDC-провайдера завершится отказом, даже если в самом провайдере пользователь активен.
Если в вашем каталоге пользователей не удаляют, а блокируют через атрибут, исключите заблокированных пользователей из выдачи LDAP с помощью параметра user_filter. Укажите один фильтр, соответствующий вашему каталогу:
user_filter: '(!(pwdAccountLockedTime=*))' # OpenLDAP ppolicy
user_filter: '(!(nsAccountLock=TRUE))' # 389-DS
user_filter: '(!(userAccountControl:1.2.840.113556.1.4.803:=2))' # Active Directory
user_filter: '(!(employeeType=blocked))' # собственный атрибут
Связывание учётных записей OIDC с LDAP
Если пользователи входят через OIDC-провайдера (например, Keycloak), а права выдаются по LDAP-группам, включите автоматическое связывание OIDC-учётной записи с учётной записью LDAP. Настройка выполняется в секции spec.appConfig.omniauth.:
auto_link_ldap_user: true
Поиск учётной запись LDAP
При первом входе через OIDC Deckhouse Code ищет пользователя в LDAP. Для поиска используются два значения из данных OIDC-провайдера:
uid— значение поля, указанного в параметреuid_fieldпровайдера (например,preferred_username);- email — адрес электронной почты пользователя.
Настроенные LDAP-серверы опрашиваются по очереди. На каждом сервере выполняется до четырёх попыток поиска, до первого совпадения:
| Искомое значение | Атрибут для поиска |
|---|---|
uid |
Атрибут, указанный в параметре uid LDAP-сервера (например, cn) |
uid |
Почтовые атрибуты: mail, email, userPrincipalName |
| Те же почтовые атрибуты | |
uid |
DN — если значение uid само является DN |
Если пользователь найден, к его учётной записи добавляется LDAP-идентификатор с найденным DN. Если ни одна попытка не дала результата, учётная запись создаётся без привязки к LDAP.
Таким образом, связывание сработает, только если uid или email из OIDC-провайдера совпадает со значением соответствующего атрибута в LDAP.
Первый и последующие входы
Первый успешный вход связывает учётную запись с LDAP. При последующих входах:
- LDAP не опрашивается — используется ранее установленная связь;
- доступ и административные права переоцениваются по группам из данных OIDC-провайдера (параметры
allowed_groupsиadmin_groups). Если пользователя убрали из разрешённой группы, учётная запись будет заблокирована; - членства в группах и проектах, а также роли в них при входе через OIDC не меняются — их обновляет фоновая синхронизация с LDAP по расписанию.
Поэтому сразу после первого входа пользователь может войти, но членств в группах и проектах у него ещё нет: они появятся после ближайшей синхронизации. Чтобы не ждать её, запустите синхронизацию вручную (подробнее — в разделе «Ручной запуск синхронизации»).
Синхронизация групп и членств пользователя при входе выполняется только при входе через LDAP-провайдера (имя провайдера начинается с ldap). Вход через OIDC-провайдера её не запускает, даже если учётная запись уже связана с LDAP.
Вход пользователей, найденных в LDAP
Чтобы пользователи, найденные в LDAP, могли входить сразу, а остальные отправлялись на одобрение администратору, задайте следующие параметры в секции spec.appConfig.:
omniauth:
auto_link_ldap_user: true
# Пользователь не найден в LDAP — учётная запись создаётся заблокированной,
# до одобрения администратором.
block_auto_created_users: true
ldap:
main:
# Пользователь найден в LDAP — вход разрешён сразу.
block_auto_created_users: false
Особенности связывания
- Если пользователя блокируют переименованием
cnв каталоге, при первом входе он всё равно может быть найден по email и связан с учётной записью LDAP. Для блокировки используйте удаление пользователя из каталога или параметрuser_filter(подробнее — в разделе «Блокировка пользователей по данным LDAP»). - Если пользователь не был связан с LDAP и его заблокировала задача
Ldap::BlockNonLdapUsersWorker, автоматическая разблокировка не сработает. Такого пользователя нужно разблокировать вручную и связать с учётной записью LDAP.
Устранение проблем с синхронизацией
Если предыдущее задание синхронизации завершилось некорректно, Redis может сохранить блокировку на его выполнение (по умолчанию параметр concurrency = 1). Это помешает запуску нового задания.
Чтобы снять блокировку:
- Подключитесь к Redis, используя базы, указанные в
config/redis.shared_state.ymlиconfig/redis.queues.yml. -
Удалите ключ
sidekiq:concurrency_limit:throttled_jobs:{ldap/sync_worker}следующими командами:keys *ldap* del "sidekiq:concurrency_limit:throttled_jobs:{ldap/sync_worker}"
Ручной запуск синхронизации
Чтобы синхронизировать группы сразу после их изменения на стороне LDAP, выполните следующие шаги:
- Зайдите на страницу worker’а синхронизации LDAP
/admin/sidekiq/cron/namespaces/default/jobs/ldap_sync_worker. - В верхнем правом углу нажмите кнопку «Запустить» и подтвердите в диалоговом окне.

Чтобы посмотреть, как завершилась запущенная синхронизация, откройте страницу метрик задачи синхронизации LDAP:
/admin/sidekiq/metrics?substr=SyncWorker&period=8h. На графике отображается статистика вызовов, в таблице ниже — количество успешно и аварийно завершённых вызовов синхронизации LDAP.

Чтобы посмотреть полные логи процесса синхронизации:
-
На странице worker’а
/admin/sidekiq/cron/namespaces/default/jobs/ldap_sync_workerнайдите таблицу событий запусков «История». Первая строка соответствует последнему запуску. Скопируйте значение в колонке JID (Job ID) — оно понадобится для поиска по логам.
-
Подключитесь к кластеру и определите имя пода Sidekiq командой:
d8 k -n d8-code -l app.kubernetes.io/component=sidekiq get pod -o NAME -
Выполните сбор логов, подставив скопированный JID и имя пода (POD_NAME):
d8 k -n d8-code logs POD_NAME | jq 'select(.jid=="JID")'
Со временем старые логи удаляются ротацией, и получить их будет нельзя. При необходимости запустите синхронизацию повторно и соберите актуальные логи.
Особенности работы LDAP Sync
Алгоритм синхронизации
LDAP Sync использует плоский алгоритм синхронизации:
- Получение групп. Выполняется LDAP-запрос, который получает все группы по параметрам
base,filterиscope. - Извлечение участников. Для каждой найденной группы читаются атрибуты членства:
member,uniquemember,memberof,memberuid,submember. - Сопоставление пользователей. Каждый DN из атрибутов членства сопоставляется со значением
Identity.extern_uidв базе данных. - Игнорирование неизвестных DN. Если DN не соответствует известному пользователю, он пропускается. Например, это может быть DN вложенной группы.
Циклические зависимости между группами
Циклические зависимости в иерархии LDAP-групп не приводят к ошибкам синхронизации. LDAP Sync обрабатывает группы плоско, по заданному фильтру, и не пытается воспроизводить древовидную структуру LDAP.
Рекурсивный обход вложенности не выполняется, поэтому циклы не влияют на результат синхронизации.
Вложенные группы и транзитивность
LDAP Sync не поддерживает транзитивность для вложенных групп.
Во время синхронизации LDAP Sync обрабатывает только прямые значения атрибутов членства группы и не выполняет рекурсивный обход вложенных групп.
Если одна LDAP-группа содержит другую как участника, пользователи вложенной группы не будут автоматически добавлены в родительскую группу.
Для корректной синхронизации все необходимые DN пользователей должны присутствовать непосредственно в атрибутах членства группы.
Если требуется учитывать вложенные группы, это нужно реализовать на стороне LDAP-сервера. Например, можно заполнять атрибут submember полным списком транзитивных участников.
Такой подход упрощает процесс синхронизации и исключает проблемы, связанные с рекурсивной обработкой групп.
Создание локальной учётной записи при включённой синхронизации с LDAP
Локальные учётные записи можно создавать и использовать даже при включённой синхронизации с LDAP.
Чтобы такие пользователи могли входить через веб-интерфейс, в административном разделе на странице «Настройки» → «Общие» → «Ограничения входа» должна быть включена настройка «Разрешить аутентификацию по паролю и passkey для веб-интерфейса» (password_authentication_enabled_for_web).
Пример настройки: вход через OIDC и права из LDAP
Ниже приведена последовательность настройки, при которой пользователи входят через OIDC-провайдера (например, Keycloak), а группы, членства в них и роли приходят из LDAP.
Что потребуется
- OIDC-провайдер.
- LDAP-каталог с теми же пользователями и с группами, имена которых позволяют определить роль.
- Сервисная учётная запись LDAP с правами на чтение каталога (параметры
bind_dnиpassword).
Значение uid или email в OIDC-провайдере должно совпадать со значением соответствующего атрибута в LDAP, иначе связывание не сработает (подробнее — в разделе «Как ищется учётная запись LDAP»).
Шаг 1. Настройте LDAP-провайдера
Конфигурация размещается в spec.appConfig.ldap.:
main:
label: ldap
host: ldap.example.com
port: 3389
bind_dn: 'uid=viewer,ou=People,dc=example,dc=com'
password: 'viewer123'
base: 'ou=People,dc=example,dc=com'
uid: 'cn'
sync_name: true
# Не учитывать пользователей, заблокированных в каталоге (опционально).
user_filter: '(!(nsAccountLock=TRUE))'
# Пользователь найден в LDAP — вход разрешён сразу.
block_auto_created_users: false
group_sync: {
create_groups: true,
base: 'ou=Groups,dc=example,dc=com',
filter: '(objectClass=groupOfNames)',
top_level_group: "LdapGroups",
name_mask: "(?<=-)[A-z0-9]*$",
owner: "root",
role_mapping: [
{ by_name: '.*-maintainer-.*', gitlab_role: 'maintainer' },
{ by_name: '.*-developer-.*', gitlab_role: 'developer' },
{ by_name: '.*-participant-.*', gitlab_role: 'reporter' }
]
}
Шаг 2. Настройте OIDC-провайдера и включите связывание с LDAP
Конфигурация размещается в секции spec.appConfig.omniauth.:
auto_link_ldap_user: true
providers:
- name: 'openid_connect' # Не изменяйте это значение.
label: 'Keycloak' # Подпись кнопки входа.
groups_attribute: 'gitlab_group'
args:
name: 'openid_connect'
scope:
- 'openid'
- 'profile'
- 'email'
response_type: 'code'
issuer: 'https://keycloak.example.com/realms/example'
discovery: true
client_auth_method: 'query'
uid_field: 'preferred_username'
send_scope_to_token_endpoint: false
pkce: true
client_options:
identifier: '<client_id>'
secret: '<client_secret>'
redirect_uri: 'https://code.example.com/users/auth/openid_connect/callback'
Значение uid_field используется при поиске пользователя в LDAP. Оно должно совпадать со значением атрибута, указанного в параметре uid LDAP-сервера, или с адресом электронной почты — подробнее в разделе «Как ищется учётная запись LDAP».
Остальные параметры провайдера описаны в разделе «OpenID Connect (OIDC)».
Шаг 3. Проверьте связывание при первом входе
- Войдите тестовым пользователем через OIDC-провайдера.
- Откройте страницу пользователя в административном разделе (
/admin/users/<username>/identities). У связанной учётной записи должно быть два идентификатора:openid_connectиldapmain(имя LDAP-идентификатора складывается из префиксаldapи имени LDAP-сервера, в примере —main).
Если LDAP-идентификатора нет, проверьте следующее:
- значения
uidили email в OIDC-провайдере и в LDAP совпадают; - пользователь попадает в область поиска
baseи не отсекается фильтромuser_filter; - параметр
auto_link_ldap_userвключён.
Шаг 4. Дождитесь синхронизации прав
Дождитесь ближайшей синхронизации или запустите её вручную (подробнее — в разделе «Ручной запуск синхронизации»), после чего проверьте, что:
- группы созданы внутри группы, указанной в
group_sync.top_level_group; - пользователь добавлен в них с ролью, соответствующей
role_mapping.