Интеграция с IdP-провайдером
Система BAF позволяет настроить интеграцию с провайдером IdP по протоколу OIDC для организации аутентификации и авторизации через внешний источник пользователей.
При этом сама система не хранит данные таких внешних пользователей — вся информация о пользователе передается в ходе выполнения потока OIDC, и в результате формируется cookie с коротким сроком действия для взаимодействия с панелью управления BAF. На текущий момент поддерживается только режим работы Authorization Code.
Кроме того, система полагается на IdP-провайдера в части сопоставления ролей, пользователей и рабочих пространств. Сами роли и их привилегии создаются внутри BAF, но связь «роль — пользователь — рабочее пространство» должна быть задана на стороне IdP.
Таким образом, задача интегратора состоит в корректном переносе и поддержании в согласованном состоянии рабочих пространств и ролей между IdP и BAF. Предполагается, что создание новых учетных записей и ролей происходит редко, поэтому синхронизация выполняется нечасто.
Если вам не требуется интеграция с IdP, пропустите его настройку и оставьте стандартные значения поставки.
Подготовка IdP
Перед настройкой BAF необходимо подготовить IdP. Рассмотрим процесс на примере Keycloak.
Создание realm
Для управления пользователями BAF рекомендуем создать отдельный realm, чтобы интеграция с BAF не пересекались с другими интеграциями.
Создание клиента
После создания отдельного realm необходимо создать client, который будет использоваться BAF для взаимодействия с Keycloak.
Тип клиента должен быть OpenID Connect, также необходимо выбрать client-id. В примере возьмем baf-client.


Далее необходимо настроить проверку URL-адресов перенаправления. Для примера предположим, что BAF развернут по адресу https://127.0.0.1:8090. Рекомендуемая настройка URL показана ниже:

Ваш домен системы может отличаться, однако путь перенаправления всегда соответствует /signin-idp/*, поскольку этот путь зашит внутри BAF.
В результате этих операций появится новый клиент, через который BAF будет взаимодействовать с Keycloak.
Сопоставление ролей
Задача привязки ролей и учетных записей к пользователям лежит на стороне IdP-провайдера. Необходимо выстроить удобную для вас систему, позволяющую добавлять пользователям IdP информацию о ролях и рабочих пространствах для последующей трансформации в claims токена и разбора внутри BAF.
Система BAF должна однозначно понимать, какого типа роль, к какой учетной записи она привязана, и какому пользователю принадлежит.
Для этого система разбирает утверждения, полученные при аутентификации пользователя в IdP, формирует из них набор ролей и сохраняет всю информацию в cookie с коротким сроком действия, которая затем используется BAF для аутентификации и авторизации пользователя.
Мы рассматриваем систему ролей на основе атрибутов пользователя Keycloak, однако вы можете использовать любой другой способ формирования утверждений, который вам покажется удобным.
В данной системе у каждого пользователя внутри realm появляется набор атрибутов. Каждый атрибут означает наличие или отсутствие роли: для глобальных ролей — просто факт наличия, а для локальных — в каком рабочем пространстве эта роль действует.
Роли имеют уникальное имя и споставление происходит по нему.
Атрибуты пользователей
Для начала создадим атрибут для стандартной глобальной роли SuperAdmin. Любая другая созданная вами роль, которая должна работать в глобальном контексте, настраивается аналогично.
Перейдите на страницу Realm Settings, вкладку User Profile и нажмите кнопку Create Attribute.

Откроется страница создания атрибута. В основном вы можете настроить атрибут по своему усмотрению. Имя атрибута здесь играет только визуальную роль и на сопоставление не влияет. Самое важное — корректно настроить Validators и Annotations.
- В Validators выберите тип
optionsс двумя значениями:trueиfalse. - В Annotations выберите аннотацию
select-radiobuttons.

В результате у каждого пользователя realm появится атрибут, означающий наличие или отсутствие глобальной роли SuperAdmin.
Чтобы настроить локальные роли, необходимо получить список существующих рабочих пространств. Удобнее всего это сделать через страницу рабочих пространств, которая доступна пользователям с ролью SuperAdmin. Рекомендуется сначала настроить сопоставления для роли SuperAdmin и назначить ее соответствующему пользователю, а затем вернуться к данному разделу и настроить локальные роли.
Далее настроим атрибут для локальной роли, например, ApplicantReader. Снова нажмите Create Attribute.
На странице настройки атрибута также важно настроить Validators и Annotations, остальное — на ваше усмотрение.
- В Validators выберите два типа:
multivalued(для возможности выбора нескольких значений) иoptionsсо значениями идентификаторов рабочих пространств (их можно скопировать на странице рабочих пространств, открыв ее пользователем с рольюSuperAdmin). - В Annotations выберите аннотацию
multivalue.

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

Сопоставление claims
Создав атрибуты, вы обеспечили возможность настраивать роли у пользователей, но BAF все еще не будет их видеть. Для отображения пользовательских атрибутов необходимо настроить их сопоставление с claims.
Для этого перейдите во вкладку Client Scopes в ранее созданном клиенте и выберите область с описанием «Dedicated scope and mappers for this client».


Добавьте сопоставители для новых атрибутов. Начнем с глобальной роли SuperAdmin.
Нажмите Add Mapper → By Configuration и в открывшемся списке выберите User Attribute.

Настройте атрибут:
- User Attribute — выберите из списка ранее созданный атрибут
SuperAdmin. - Token Claim Name — задайте формат ключа для claim. Важно запомнить этот формат, так как он будет участвовать в логике разбора данных роли на стороне BAF. Для примера используем
grole-<имя роли внутри <ShortProductName/>>, т.е.grole-SuperAdmin. - Claim JSON Type — выберите
string. - Add to ID token, Add to access token, Add to userinfo, Add to token introspection — оставьте включенными.

В результате будет сформировано утверждение с ключом grole-SuperAdmin и значением true или false.
Теперь настроим сопоставитель для локальной роли ApplicantReader. Конфигурация аналогична, за исключением включенного поля Multivalued и другого шаблона ключа утверждения (поле Token Claim Name): role-<имя роли внутри <ShortProductName/>>, т.е. role-ApplicantReader.

В результате будет сформировано утверждение с ключом role-ApplicantReader и значением UUID рабочего пространства. Если рабочих пространств несколько, будет создано несколько claims с одинаковыми ключами и соответствующими значениями UUID.
Важно понимать, в каком формате утверждения передаются в систему BAF, чтобы корректно настроить правила разбора.
Настройка интеграции с IdP в системе BAF
Настройка значений в чарте
Для настройки интеграции необходимо заполнить секцию idp в файле ./values.baf.yaml.
Описание полей секции:
enable— включена ли интеграция с IdP. Необходимо установить значениеtrue.url— URL созданногоrealmвнутри IdP. На основе примера (Keycloak развернут по адресу127.0.0.1:8080) URL будет следующим:http://127.0.0.1:8080/realms/baf/. Если используется безопасный транспорт, укажитеhttpsвместоhttp.claimParseRules— правила разбора ключей и значений утверждений.Idp__Debug— режим отладки механизма аутентификации через IdP. Установка значенияtrueвключает специальный режим логирования, позволяющий отследить, какие утверждения приходят от IdP, и как они разбираются системой.Idp__UserIdPrincipalName— имя утверждения, используемое как источник идентификатора пользователя. Рекомендуется оставить значение по умолчанию и менять его только при наличии проблем.Idp__UsernamePrincipalName— имя утверждения, используемое как источник имени пользователя. Рекомендуется оставить значение по умолчанию и менять его только при наличии проблем.Idp__ClientId— идентификатор клиента, созданного в IdP, который будет использоваться BAF.Idp__ClientSecret— конфигурация Kubernetes-секрета, содержащего аутентификационный секрет клиента.Idp__RequireHttps— флаг, показывающий, требуется ли HTTPS-соединение для работы с IdP. Для тестов можно установить вfalse, для рабочей среды обязательно значениеtrue.
Пример конфигурации на основе примера подготовки IdP:
idp:
enable: "true"
url: "http://127.0.0.1:8080/realms/baf/"
claimParseRules:
- KeyRule: 'role-<roleName>'
ValueRule: '<workspaceId>'
- KeyRule: 'grole-<roleName>'
ValueRule: '<enabled>'
envOverride:
Idp__Debug:
value: "true"
Idp__ClientId:
value: "baf-client"
Idp__RequireHttps:
value: "false"
Составление правил разбора
Система BAF использует собственный синтаксис для разбора claims. Напомним, что claim состоит из двух частей: ключ и значение. Обе части могут содержать полезные данные, поэтому правило разбора состоит из двух частей: правило для ключа (KeyRule) и правило для значения (ValueRule).
Синтаксис следующий: все, что находится вне символов < и >, является структурными данными и должно полностью совпадать с текстом в правиле, чтобы правило применилось. Все, что заключено в угловые скобки, будет сохранено в одноименные переменные.
Переменные:
roleName— имя роли.workspaceId— идентификатор рабочего пространства, в котором действует роль.enabled— флаг, указывающий, действительно ли данное утверждение с ролью активно. Значение должно быть логического типа (строкаtrueилиfalse). Этот флаг позволяет игнорировать claim, если IdP всегда отправляет его, даже когда значение пустое.
В системе может быть несколько правил. Это удобно, если форматы claims для глобальных и локальных ролей отличаются. Все claims, пришедшие от IdP, проверяются по порядку на соответствие каждому правилу из списка. Как только ключ и значение claim совпадают с каким-либо правилом, проверка для данного claim прекращается, и система переходит к следующему claim.
Логика обработки разобранных данных:
- Если заполнены переменные
roleNameиworkspaceId, то пользователю добавляется локальная роль для указанного рабочего пространства. - Если заполнена только переменная
roleName, то пользователю добавляется глобальная роль. - Если переменная
enabledустановлена вfalse, claim игнорируется, даже если разбор был успешным.
Примеры
Рассмотрим пример правила для локальной роли:
KeyRule: 'role-<roleName>'
ValueRule: '<workspaceId>'
Такое правило разберет claim role-SuperAdmin: cb58a1f2-2985-4d9f-94b6-dc6ce03e2ca7 на переменные:
roleName=SuperAdminworkspaceId=cb58a1f2-2985-4d9f-94b6-dc6ce03e2ca7
Сlaim rrole-SuperAdmin: cb58a1f2-2985-4d9f-94b6-dc6ce03e2ca7 будет проигнорирован, так как ключ не совпадает с шаблоном.
Обратите внимание, что правило, состоящее полностью из переменных (например, ValueRule: '<workspaceId>'), будет принимать любые строки. Однако это может привести к ошибкам: например, claim role-SuperAdmin: workspaceId-cb58a1f2... при разборе значения workspaceId получит строку workspaceId-cb58a1f2..., которая не является корректным UUID, и это вызовет ошибку.
Теперь рассмотрим пример правила для глобальной роли:
KeyRule: 'grole-<roleName>'
ValueRule: '<enabled>'
Такое правило разберет claim grole-SuperAdmin: false на переменные:
roleName=SuperAdminenabled=false
Если переменная enabled отсутствует, она автоматически считается равной true.
Режим отладки
При включении режима отладки для интеграции с IdP любая попытка аутентификации через IdP будет генерировать дополнительные логи внутри поды baf-dashboard-dep.
В логах сначала выводится информация о пользователе из служебных claim, ключи которых задаются параметрами Idp__UserIdPrincipalName и Idp__UsernamePrincipalName:
Start parsing claims
User Id: 73254712-90c5-41ff-96e4-8c5e7e79185e
User name: bafk
Далее выводится список полученных от IdP claims в формате ключ: значение и список правил (в формате KeyRule ValueRule, заданный в claimParseRules), которые проверялись для каждого claim.
Пример claims, которые не были распознаны ни одним правилом:
- Claim: http://schemas.microsoft.com/claims/authnclassreference: 1
Check rule: role-<roleName> <workspaceId>
Check rule: grole-<roleName> <enabled>
- Claim: email_verified: false
Check rule: role-<roleName> <workspaceId>
Check rule: grole-<roleName> <enabled>
Если какое-либо правило подходит, то выводятся переменные, извлеченные из ключа и значения.
Обратите внимание, что и ключ, и значение должны быть успешно разобраны, иначе claim пропускается.
Пример claim, распознанного как глобальная роль:
- Claim: grole-superAdmin: true
Check rule: role-<roleName> <workspaceId>
Check rule: grole-<roleName> <enabled>
Key parsed.
Current data:
Role: superAdmin
Enabled: True
Workspace id:
Value parsed.
Current data:
Role: superAdmin
Enabled: True
Workspace id:
Add global role: SuperAdmin.
Пример claim, распознанного как локальная роль:
- Claim: role-Applicant Reader: 656309de-e5e8-471c-a2b3-7f9ac32ba5ee
Check rule: role-<roleName> <workspaceId>
Key parsed.
Current data:
Role: Applicant Reader
Enabled: True
Workspace id:
Value parsed.
Current data:
Role: Applicant Reader
Enabled: True
Workspace id: 656309de-e5e8-471c-a2b3-7f9ac32ba5ee
Add workspace role: Applicant Reader. Workspace ID: 656309de-e5e8-471c-a2b3-7f9ac32ba5ee.