Перейти к содержимому

Настройка прав доступа в Камунда.РФ Пульт

Пульт разграничивает доступ на трёх независимых уровнях — включайте только те уровни, которые нужны на вашем стенде.

Уровень Что решает Где настраивается
Вход пускать пользователя в Пульт или нет группа Keycloak в crawler.auth.requiredGroup
Действия что пользователь может делать с процессами карта «действие → группа» в crawler.auth.actionGroups.mapping
Серверы и тенанты какие данные пользователь может видеть атрибут пользователя allowed_servers в Keycloak

Отдельно можно скрыть разделы интерфейса, но это настройка отображения, а не прав: она действует одинаково для всех пользователей.

Подготовьте:

  • установленный Пульт версии 1.1.6 или новее (чарт kamundarf-platform);
  • доступ администратора к реалму Keycloak, который использует Пульт;
  • файл values вашего стенда и право выполнить helm upgrade;
  • список идентификаторов серверов — значений serverId из global.platform.servers.

Пульт читает права из токена пользователя. Токен содержит два поля:

  • groups — группы пользователя; по ним Пульт определяет право на вход и на действия;
  • allowed_servers — список серверов пользователя; по нему Пульт определяет видимость данных.

Создайте группы под свои роли — например, pult-users для входа, pult-operators для операций с процессами, pult-admins для деплоя и удаления.

Добавьте пользователям многозначный атрибут allowed_servers: одна строка — один сервер.

Настройте два маппера в клиенте Пульта:

  • маппер groups типа oidc-group-membership-mapper с именем поля groups;
  • маппер allowed_servers типа oidc-usermodel-attribute-mapper с именем поля allowed_servers и признаком multivalued.

Оба маппера отдают поля и в id-токен, и в access-токен.

Пример конфигурации реалма:

userProfile:
  attributes:
    - name: "allowed_servers"
      displayName: "Allowed Servers"
      permissions:
        view: ["admin"]
        edit: ["admin"]
      multivalued: true
groups:
  - name: "pult-users"
  - name: "pult-operators"
  - name: "pult-admins"
users:
  - username: "ivanov"
    enabled: true
    groups:
      - "/pult-users"
      - "/pult-operators"
    attributes:
      allowed_servers:
        - "krf-zeebe"
clientScopes:
  - name: "allowed-servers"
    description: "List of servers the user is allowed to access. Use '*' to grant access to all servers."
    protocol: "openid-connect"
    protocolMappers:
      - name: "allowed_servers"
        protocol: "openid-connect"
        protocolMapper: "oidc-usermodel-attribute-mapper"
        config:
          "user.attribute": "allowed_servers"
          "claim.name": "allowed_servers"
          "jsonType.label": "String"
          "id.token.claim": "true"
          "access.token.claim": "true"
          "userinfo.token.claim": "true"
          "multivalued": "true"
clients:
  - clientId: kamundarf
    defaultClientScopes:
      - "allowed-servers"
    protocolMappers:
      - name: "groups"
        protocol: "openid-connect"
        protocolMapper: "oidc-group-membership-mapper"
        config:
          "claim.name": "groups"
          "id.token.claim": "true"
          "access.token.claim": "true"
          "userinfo.token.claim": "true"
          "full.path": "false"

Укажите группу, без которой вход в Пульт закрыт:

crawler:
  auth:
    requiredGroup: "pult-users"

Как это работает:

  • пользователь без группы получает 403 при входе;
  • каждый запрос к API проверяется повторно;
  • пустое значение отключает проверку — войти может любой пользователь реалма.

Параметр принимает одно значение, а не список групп. Если доступ нужен нескольким командам, включите их пользователей в одну общую группу, а различия в правах задайте на шаге 3.

Свяжите действия с группами: действие, которому группа не назначена, разрешено всем, кто вошёл в Пульт.

global:
  auth:
    actionGroups:
      mapping: &actionGroupsMapping
        Cancel: pult-operators
        Retry: pult-operators
        TerminateToken: pult-operators
        StartToken: pult-operators
        StartProcess: pult-admins
        Deploy: pult-admins
        CanUpdateVariables: pult-admins
        OpenExternalTrace: pult-operators

crawler:
  auth:
    actionGroups:
      mapping: *actionGroupsMapping

forwarder:
  auth:
    actionGroups:
      mapping: *actionGroupsMapping

Задайте карту один раз через якорь YAML и подставьте её в компоненты; timber-rack берёт её из global.auth.actionGroups.mapping самостоятельно.

Карта должна совпадать у crawler, forwarder и timber-rack: crawler и forwarder определяют по ней набор доступных действий, а crawler и timber-rack блокируют операции без нужной группы. Если карты разойдутся, пользователь увидит кнопку, но при нажатии получит ошибку 403.

Действия, которые разграничивает карта:

Действие Что разрешает Проверка
StartProcess запустить новый экземпляр процесса отображение и операция
Cancel отменить экземпляр процесса отображение и операция
Retry повторить шаг, который остановился на инциденте отображение и операция
CanUpdateVariables изменить переменные экземпляра отображение и операция
TerminateToken отменить токен на конкретном шаге схемы отображение и операция
StartToken запустить токен на конкретном шаге схемы отображение и операция
Deploy задеплоить определение процесса на сервер отображение и операция
OpenExternalTrace открыть внешнюю трассировку процесса или инцидента отображение и операция
Resume продолжить приостановленный экземпляр только отображение

Перенос токена по схеме складывается из пары действий TerminateToken и StartToken — выдавайте их вместе.

Включите фильтр серверов и в crawler, и в forwarder:

crawler:
  features:
    serverAccessFilter: true

forwarder:
  features:
    serverAccessFilter: true

Задайте пользователям атрибут allowed_servers в Keycloak. Формат значений:

Значение Результат
* доступны все серверы
krf-zeebe доступен только сервер krf-zeebe
две строки: krf-zeebe и banana-dev доступны оба сервера

Правила:

  • сервер, которого нет в списке, не отображается в интерфейсе, а его данные недоступны через API;
  • пустой атрибут при включённом фильтре закрывает доступ ко всем серверам;
  • фильтр действует и на чтение, и на операции: на скрытом сервере пользователь не может выполнить ни одного действия.

Этот шаг нужен, только если серверы работают в режиме мультитенантности.

global:
  multitenancy:
    enabled: true

Перечислите тенанты в атрибуте allowed_servers через двоеточие:

Значение Результат
krf-zeebe все тенанты сервера krf-zeebe
krf-zeebe:tenantA,tenantB только тенанты tenantA и tenantB сервера krf-zeebe

При выключенной мультитенантности часть значения после двоеточия не учитывается, и сервер доступен целиком.

Перечислите разделы, которые не нужны вашим пользователям, и стартовый раздел:

pult:
  config:
    disabledPages:
      - reports
      - metrics
    defaultPage: instances
  • disabledPages — скрытые разделы. Допустимые значения: dashboard, files, metrics, reports. Разделы instances, incidents и processes скрыть нельзя.
  • defaultPage — раздел, который открывается по адресу / и по клику на логотип.

Скрытый раздел исчезает из меню, а при переходе по прямой ссылке пользователь видит сообщение «Раздел отключен».

Настройка общая для всех пользователей: скрыть раздел только для одной группы нельзя.

Пульт читает поле groups и сравнивает имена точно, поэтому и для входа, и в карте действий указывается ровно одно имя. Когда пользователи приходят из каталога и состоят в десятках групп, включать их в дополнительную общую группу не нужно: Keycloak умеет класть в groups вычисленное имя. Мапперы, пишущие в одно поле, дополняют друг друга, поэтому рядом с реальными группами в токене окажется и общее имя.

Способ 1 — через роль. Заведите роль (например, pult-users) и назначьте её нужным группам. Участники этих групп получают роль по членству. Добавьте в клиент маппер User Realm Role или User Client Role с именем поля groups и признаком multivalued.

Роли назначаются на стороне Keycloak и не зависят от синхронизации каталога. Маппер realm-ролей кладёт в поле и служебные роли реалма (offline_access, uma_authorization) — Пульту они не мешают, но если хочется чистого списка, используйте клиентские роли.

Способ 2 — через атрибут группы. Задайте каждой группе атрибут, например pult_groups, и перечислите в нём имена, которые группа выдаёт: pult-users, pult-operators. Добавьте маппер User Attribute с настройками: User Attributepult_groups; Token Claim Namegroups; MultivaluedOn; Aggregate attribute valuesOn.

Пользователь получает объединение значений по всем своим группам без дублей. Способ удобен тем, что одна группа выдаёт сразу несколько имён — и имя для входа, и имя под конкретные действия. Если группы федерируются из каталога, проверьте, переживают ли их атрибуты синхронизацию; если нет — используйте способ 1.

Оба способа проверены на Keycloak 26.3. Результат смотрите в токене: в поле groups должно быть общее имя рядом с реальными группами пользователя.

Роль Группы пользователя allowed_servers Что может делать
Наблюдатель pult-users * просматривать все процессы; кнопки операций не отображаются
Оператор pult-users, pult-operators * отменять экземпляры, повторять шаги, переносить токены
Администратор pult-users, pult-admins, pult-operators * выполнять все операции, включая деплой, запуск процессов и правку переменных
Оператор одного сервера pult-users, pult-operators krf-zeebe выполнять те же операции, но только на сервере krf-zeebe

Отдельно настраивать роль наблюдателя не нужно: она возникает сама, когда все нужные действия перечислены в карте actionGroups с группами, в которых пользователь не состоит.

Обновите релиз:

helm upgrade --install <release> <chart> --values values.yaml

Права берутся из токена пользователя, поэтому изменения в Keycloak вступают в силу, когда crawler обновляет токен по refresh-токену, — не позже, чем истечёт срок жизни id-токена в настройках реалма. Повторный вход применяет их сразу.

Проверьте результат:

  1. Войдите под пользователем без группы из requiredGroup. Пульт отвечает 403 на входе, а на запрос к API с таким токеном — 401.
  2. Войдите под наблюдателем. Кнопки операций не отображаются.
  3. Вызовите операцию через API под пользователем без нужной группы. Сервис отвечает 403 с текстом Action '<действие>' requires group '<группа>'.
  4. Откройте список серверов под пользователем с ограниченным allowed_servers. В списке только его серверы.

Что смотреть в логах crawler:

Что видно в логе Значение
Group check enabled, required group: <группа> проверка входа включена
app.required-group is not set — group check disabled проверка входа выключена
OAuth2 login rejected: group '<группа>' missing in id_token пользователь не состоит в группе входа
JWT rejected: group '<группа>' missing in groups claim в токене запроса нет группы входа
запись аудита с "kind":"http_audit" и "status":403 запрос отклонён проверкой прав
Параметр values Назначение Значение по умолчанию
crawler.auth.requiredGroup группа для входа в Пульт пусто, проверка выключена
crawler.auth.actionGroups.mapping обязательная карта «действие → группа» для crawler пусто, все действия разрешены
global.auth.actionGroups.mapping та же карта для forwarder и timber-rack; crawler её не читает пусто
forwarder.auth.actionGroups.mapping карта для forwarder, перекрывает значение из global пусто
crawler.features.serverAccessFilter фильтр серверов в crawler false
forwarder.features.serverAccessFilter фильтр серверов в forwarder false
global.multitenancy.enabled фильтр тенантов внутри сервера false
pult.config.disabledPages скрытые разделы интерфейса пусто
pult.config.defaultPage стартовый раздел пусто, интерфейс открывает dashboard

Можно ли перечислить в requiredGroup несколько групп? Нет. Параметр принимает одно значение, и Пульт сравнивает его с содержимым поля groups точно, игнорируя только ведущий символ /. Различия в правах между командами задавайте картой действий: она допускает свою группу для каждого действия.

Пользователи приходят из AD и состоят в разных группах. Как настроить вход, не собирая их в одну группу вручную? Пульту нужно одно: чтобы в поле groups у сотрудника оказалась строка с именем группы из requiredGroup. Собирать людей в общую группу для этого не обязательно — в Keycloak несколько групп сводятся к одному имени в токене. Два рабочих способа описаны выше, в разделе «Общее имя доступа для нескольких групп AD».

Ещё один вариант — вовсе не ограничивать вход: оставьте requiredGroup пустым и разграничивайте доступ картой действий и атрибутом allowed_servers. Интерфейс тогда открывается любому пользователю реалма, но без allowed_servers он не видит ни одного сервера.

Можно ли указать в карте actionGroups несколько групп на одно действие? Нет. Одно действие — одна группа; перечисление через запятую Пульт воспримет как имя группы целиком. Ограничение касается только условия «или» внутри одного действия: сам пользователь может состоять в любом числе групп, а разные действия можно назначить разным группам.

Можно ли дать пользователю полный доступ к серверу А и только просмотр на сервере Б? Нет. Права на действия распространяются одинаково на все серверы, которые доступны пользователю. Сервер настраивается только целиком: он либо доступен, либо скрыт. Чтобы разделить права по серверам, заведите разных пользователей.

Что произойдёт, если действие не указано в карте actionGroups? Его может выполнять любой пользователь, вошедший в Пульт. Карта работает по принципу «указано — ограничено».

Что увидит пользователь с пустым атрибутом allowed_servers? При включённом serverAccessFilter ему недоступен ни один сервер. При выключенном фильтре доступны все серверы.

Можно ли скрыть раздел интерфейса только для одной группы? Нет. Список disabledPages действует на всех пользователей.

Пользователь видит кнопку, но получает ошибку 403. Почему? Карты actionGroups у crawler и forwarder различаются. Задайте карту через якорь YAML и подставьте её в оба компонента.

Задали карту действий, а операции всё равно выполняются. Почему? Карта задана только в global.auth.actionGroups.mapping. Crawler читает её из crawler.auth.actionGroups.mapping и значение из global не наследует.

Изменили группы пользователя — права не изменились. Почему? Права читаются из токена. Дождитесь обновления токена или попросите пользователя выйти и войти заново.

Как отключить разграничение прав целиком? Оставьте requiredGroup и карту actionGroups пустыми, а serverAccessFilter — в значении false. Тогда Пульт пустит любого пользователя реалма и разрешит ему все действия.