Тема
Внешние права
Не реализовано; документ для согласования
Эта страница целиком описывает предлагаемый контракт. Backend пока не читает endge-access.yaml и ACCESS_CONFIG_FILE. Все поля YAML, ошибки и правила синхронизации ниже должны быть проверены до реализации.
Файл связывает доверенные атрибуты внешнего источника с ролями конфигуратора. Он поставляется как отдельная runtime-конфигурация backend, рядом с бинарником либо через mount. Изменение файла не требует пересборки бинарника, но применяется только после перезапуска.
Проект: имя, путь и режим запуска
Имя по умолчанию — endge-access.yaml в директории исполняемого файла. Путь можно переопределить переменной ACCESS_CONFIG_FILE.
text
/opt/endge/
├── service-backend
└── endge-access.yamlПример явного пути при уже настроенном окружении backend:
bash
ACCESS_CONFIG_FILE=/etc/endge/access.yaml /opt/endge/service-backendДля make run / go run используйте явный абсолютный путь: временный исполняемый файл находится не в каталоге исходников. Предлагается принимать в ACCESS_CONFIG_FILE только абсолютный путь; это исключает зависимость от рабочей директории process.
| Условие | Поведение при запуске |
|---|---|
| Переменная не задана или пуста, стандартный файл отсутствует | Режим local |
| Выбранный файл существует и валиден | Режим external |
| Явный путь указывает на отсутствующий файл | Ошибка запуска |
| Файл найден, но не читается, пуст или не соответствует схеме | Ошибка запуска |
| Неизвестная версия, адаптер, поле или дублирующийся YAML-ключ | Ошибка запуска |
| Файл внешних прав используется с dev identity | Ошибка запуска |
Явный путь полностью заменяет стандартный: файлы не объединяются. Пустой файл не включает локальный режим. Ошибка чтения не считается отсутствием файла.
При запуске backend один раз читает и валидирует конфигурацию, сохраняет в памяти режим и правила. Use case не обращается к файловой системе на каждом запросе. Автоматического наблюдения за файлом и переключателя в UI нет. В deployment рекомендуется явный путь: потеря mount тогда завершится ошибкой запуска вместо включения локального редактирования.
Проект: пример YAML
Пример содержит все четыре роли: Platform Admin, Admin, Editor и Viewer workspace. Для примера используются workspace с identity example-workspace и OIDC provider primary. Поля roles и permissions, их вложенность и значения условные: пользователь задаёт собственную структуру claims и указывает её пути в правилах.
yaml
version: 1 # Версия предлагаемой схемы файла.
adapter: oidc # Адаптер внешних прав backend, не adapterId профиля Core.
provider: primary # Должен совпадать с AUTH_PROVIDER_ID backend.
displayName: Корпоративный Keycloak # Название источника в диалоге прав.
claimsSource: access_token # Claims берутся только из проверенного access token.
rules: # Проверяются все правила; порядок не задаёт приоритет.
- id: platform-admin # Уникальное имя правила для диагностики.
when:
path: /roles # Пример массива строк из claims.
contains: platform-admin # Точное наличие строки в массиве.
grant:
scope: platform # Доступ ко всей платформе и всем workspace.
role: admin # Platform Admin; поле workspace здесь запрещено.
- id: workspace-admin # Admin только одного рабочего пространства.
when:
path: /roles
contains: workspace-admin # Роль, настроенная у внешнего провайдера.
grant:
scope: workspace # Не даёт административных прав на всю платформу.
workspace: example-workspace # Identity существующего workspace, не его название.
role: admin # Администрирование выбранного workspace.
- id: workspace-editor # Editor: чтение и изменение конфигураций.
when:
path: /permissions/workspace/edit # Пример custom claim.
equals: true # Boolean true; строка "true" не подходит.
grant:
scope: workspace
workspace: example-workspace # Замените на identity вашего workspace.
role: editor # При совпадении Admin и Editor итогом будет Admin.
- id: workspace-viewer # Viewer: только чтение конфигураций.
when:
path: /roles
contains: workspace-viewer
grant:
scope: workspace
workspace: example-workspace
role: viewer # Не ограничивает Editor, Admin или Platform Admin.Имена и пути условные. Данные пользователя, credentials и токены в файл не записываются. Имя внешнего атрибута не обязано совпадать с именем роли Endge: соответствие задаётся в grant.
В приведённом примере условия назначения выглядят так:
| Нужный доступ | Что должно быть в access token |
|---|---|
| Platform Admin | Строка platform-admin в /roles |
Admin workspace example-workspace | Строка workspace-admin в том же массиве |
Editor workspace example-workspace | Boolean true в /permissions/workspace/edit |
Viewer workspace example-workspace | Строка workspace-viewer в массиве /roles |
Добавление правила в YAML само по себе не выдаёт доступ всем пользователям: должно совпасть его условие. Для другого workspace задайте его identity и отдельное внешнее право. При отсутствии совпадений доступ не выдаётся; при нескольких ролях одного workspace выбирается admin > editor > viewer.
Проект: поля файла
| Поле | Контракт первой версии |
|---|---|
version | Целое число 1 |
adapter | Зарегистрированный адаптер внешних прав; в первом варианте только oidc |
provider | Непустой ID источника; для OIDC должен совпасть с AUTH_PROVIDER_ID |
displayName | Непустое название источника для диалога «Мои права доступа» |
claimsSource | Для первого OIDC-варианта только access_token |
rules | Массив правил; [] означает внешний режим без выдаваемых назначений |
rules[].id | Уникальное непустое имя правила для диагностики |
rules[].when | Путь и ровно один оператор: equals или contains |
rules[].grant | Одно назначение роли платформы или workspace |
Все перечисленные поля обязательны. Дополнительные поля отклоняются. В grant обязательны scope и role; workspace обязателен только при scope: workspace и запрещён при scope: platform.
Issuer, JWKS, audience, endpoints и client secret остаются в существующей OIDC-конфигурации backend. Файл маппинга ссылается на настроенный источник и не дублирует его доверенные параметры.
В файле нет назначений отдельным пользователям, встроенных скриптов, шаблонов с выполнением кода, local override или deny-правил. Отсутствие совпавших разрешений означает отсутствие доступа. Для отзыва изменяется внешний атрибут, использованный правилом.
Проект: пути и сравнения
when.path использует JSON Pointer. Путь начинается с /, сегменты разделяются /; символы ~ и / внутри имени ключа записываются как ~0 и ~1. Регистр ключей сохраняется. Автоматического раскрытия *, обхода дерева или нормализации названий нет.
Например, /permissions/workspace/edit читает вложенный boolean. Имена accessLevel и accesslevel различаются.
equals сравнивает scalar того же типа: boolean, строку или число. true не равно строке "true". contains проверяет точное наличие строки в массиве строк; он не ищет подстроку и не разбивает произвольную строку по пробелам. null, массив или объект как значение equals в первой версии не поддерживаются.
Отсутствующий claim, null, неподходящий тип и false при equals: true не дают совпадения. Они не восстанавливают старую роль и не включают Viewer по умолчанию. Некорректный JWT отклоняется до этих сравнений; отсутствие подходящей роли в корректном JWT является допустимым пустым результатом.
Проект: результат нескольких правил
Проверяются все правила. Порядок в YAML не задаёт приоритет. Для одинакового workspace совпавшие роли объединяются в одну наиболее высокую: admin > editor > viewer. Назначения разных workspace независимы. Повторяющиеся одинаковые назначения удаляются из результата.
Платформа поддерживает только admin. Platform Admin предоставляет доступ ко всем workspace; отдельная роль Viewer не ограничивает его. Нельзя получить Platform Admin только потому, что пользователь является Admin одного workspace.
Workspace задаётся фиксированным identity, без wildcard и автоматического создания. Структура проверяется при запуске; существование workspace для совпавших правил проверяется при синхронизации. Если целевой workspace не существует или недоступен для назначения, набор не применяется частично: синхронизация завершается ошибкой. Workspace следует подготовить до использования соответствующего правила.
Проект: применение к БД
Синхронизация заменяет все назначения текущего пользователя в управляемом наборе платформы и workspace, а не только создаёт отсутствующие строки. Замена атомарна. Назначения других пользователей этим входом не изменяются.
Внешний режим не имеет второго редактируемого слоя. Ручные API возвращают 403 access_managed_externally, а внутренний сценарий синхронизации сохраняет доступ к записи. UI получает итоговый набор из того же источника, по которому backend разрешает операции.
Для актуальности сохраняется происхождение снимка: provider и identity, версия применённой конфигурации, сведения о свежести проверенного токена и время синхронизации. Формат таблиц пока не фиксируется. Эти данные предотвращают откат новым запросом из старой сессии; локальные override они не создают. Сырые JWT для отображения или аудита прав не сохраняются.
Правило «последняя запись по времени HTTP-запроса побеждает» не подходит: старый токен может прийти позже нового. Одновременные обновления одного пользователя должны быть сериализованы и сравниваться по подтверждённой свежести. Конкретный механизм и случай одинакового времени выдачи токенов требуют проверки при реализации.
Проект: перезапуск и смена режима
Изменение файла начинает действовать после перезапуска. Существующая сессия не получает доступ по старому снимку без проверки соответствия новой конфигурации. Если нужные claims нельзя безопасно пересчитать из имеющихся данных, требуется refresh или новый вход до защищённого действия.
При переходе local → external прежние локальные роли не используются как fallback. Первый допущенный запрос пользователя должен синхронизировать его внешний набор. Bootstrap первого Platform Admin и legacy-параметры AUTH_PLATFORM_ADMIN_GROUPS / AUTH_PLATFORM_ADMIN_SUBJECTS во внешнем режиме не добавляют назначения.
Предлагаемая семантика перехода external → local: последний сохранённый набор становится исходным локальным набором и может редактироваться администраторами. Это осознанное принятие снимка, а не обновление из Keycloak. Данный вариант перехода требует отдельного согласования вместе с этим документом. Перед удалением файла необходимо убедиться, что сохранённый набор содержит действующего локального Platform Admin. Backend не создаёт аварийного администратора автоматически из-за смены режима.
Все экземпляры backend, работающие с одной БД, должны запускаться с одним режимом и одной версией файла. Смена режима выполняется согласованно, без одновременной работы старых и новых экземпляров с разными источниками прав.
Проект: что согласовать до кода
- Имя
endge-access.yaml, переменнуюACCESS_CONFIG_FILEи загрузку только при запуске. - Одного источника на backend, строгую схему YAML и операции
equals/contains. - Полную замену назначений, включая пустой набор, без локальных override.
- Права текущего пользователя в read-only диалоге и запрет ручных mutations.
- Обновление при входе и refresh с допустимой задержкой отзыва до истечения JWT.
- Переход между режимами, особенно принятие последнего внешнего снимка как локального.
Согласование документа утверждает требуемое поведение. Реализация, миграции и проверка на действующем OIDC provider выполняются следующим этапом.