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

Роли и доступ

Права оператора задаются через роли, а не на нём напрямую. Роль — это именованный набор permissions плюс необязательный scope-селектор. Оператор получает права, будучи привязанным к ролям. Вся RBAC-модель — роли, их permissions и привязки операторов — живёт в PostgreSQL и управляется через Operator API (REST/MCP/web-UI), а не правкой конфиг-файла.

Permission — это атомарное разрешённое действие. Формат — одно из двух:

  • * — полный доступ ко всем операциям (эквивалент роли cluster-admin);
  • <resource>.<action> — ровно два сегмента: ресурс и действие. Примеры: incarnation.create, soul.list, role.grant-operator, operator.revoke.

Действие может быть подстановкой * внутри ресурса — incarnation.* означает «все действия над инкарнациями». Подстановка вида *.create не поддерживается; полный доступ — это отдельный case * (без точки).

Permission соответствует одной операции Operator API: HTTP-эндпоинту и одноимённому MCP-инструменту. Например, incarnation.create управляет одним и тем же действием независимо от того, вызвано оно по HTTP, через MCP или из web-UI.

Полный список доступных permission-имён — это каталог backend-а, а не зашитая в документацию таблица. Имя за пределами каталога Keeper отвергает при загрузке роли с ошибкой unknown_permission. Web-UI и инструменты подтягивают актуальный набор из API — поэтому здесь приводится механика, а не перечень.

Группы permissions организованы по ресурсам, например:

  • управление операторами — operator.* (создание, ревокация, выпуск токенов, перечисление);
  • управление ролями — role.* (создание, изменение, удаление, привязка/отвязка операторов);
  • управление группами — synod.* (Synod);
  • работа с инкарнациями — incarnation.* (создание, запуск, чтение, история, обновление);
  • реестр хостов — soul.* (регистрация, перечисление, назначение covens, выпуск токенов);
  • регулярные запуски — cadence.*;
  • и другие семейства.

Конкретный набор действий и их семантика — то, что отдаёт каталог backend-а; сверяйтесь с ним, а не с фиксированным списком.

Permission можно сузить селектором — фильтром, ограничивающим действие подмножеством душ. Без селектора permission действует без ограничений.

Селектор пишется как on <key>=<значения> после permission. Поддерживаемые ключи:

КлючОграничивает действие…
coven=…хостами/инкарнациями с указанными Coven-метками
service=…инкарнациями указанных типов сервиса
incarnation=…конкретной инкарнацией по имени
host=…конкретным хостом (по его SID)
regex='…'…хостами, чей SID/имя совпадает с RE2-паттерном
soulprint='…'…хостами, чьи факты удовлетворяют CEL-предикату по soulprint.self.*

Несколько значений одного ключа перечисляются через запятую без пробелов и работают по ИЛИ: coven=db,cache — «coven db или cache». Значения для regex и soulprint берутся в одинарные кавычки, чтобы запятые и пробелы внутри паттерна/предиката не разрывали значение.

Пример роли, ограниченной окружением:

name: db-operator
permissions:
- "incarnation.* on service=redis-cluster,vault-cluster"
- "soul.list on coven=db"

Такой оператор может выполнять любые операции над инкарнациями сервисов redis-cluster и vault-cluster и видеть хосты с меткой db; всё остальное запрещено политикой default-deny.

Роль может задать базовый scope один раз (поле default_scope), который наследуют все её permissions. Per-permission селектор (on … прямо в строке permission) переопределяет базовый для конкретного разрешения. Это удобно, когда вся роль работает в одном окружении, но одно-два действия нужно сузить или расширить точечно.

Как scope влияет на то, какие хосты и инкарнации оператор видит в списках, — раздел Synod и Purview.

Оператор получает права, когда его AID привязан к роли (membership). Управление — через Operator API:

  • создание роли с набором permissions — permission role.create;
  • привязка оператора к существующей роли — permission role.grant-operator (по паре «роль + AID»);
  • отвязка — permission role.revoke-operator;
  • изменение набора прав роли — permission role.update;
  • удаление роли — permission role.delete;
  • перечисление ролей с их permissions и привязанными операторами — permission role.list.

Привязка идемпотентна: повторно привязать тот же AID к той же роли — безопасная операция без эффекта.

Управление ролями подчиняется двум защитам (см. Default-deny):

  • Least-privilege. Нельзя включить в роль или раздать через роль permission, которым не обладаешь сам. Попытка — 403 forbidden. Полный доступ (*) может раздавать только владелец *.
  • Self-lockout. Нельзя снять у роли права или отвязать оператора так, чтобы кластер остался без активного администратора с полным доступом — 409 would-lock-out-cluster.

Встроенная роль cluster-admin (builtin, permission *) защищена дополнительно: её нельзя удалить (role.delete) или изменить её набор прав (role.update) — попытка возвращает 409 role-builtin. Привязывать к ней и отвязывать от неё операторов можно (с тем же self-lockout-инвариантом на отвязку).

Применение прав — мгновенное по кластеру

Заголовок раздела «Применение прав — мгновенное по кластеру»

Keeper не ходит в базу на каждую проверку права: он держит снимок ролей и привязок в памяти. Любая мутация роли, набора прав или привязки рассылает сигнал инвалидации по кластеру, и все инстансы перечитывают снимок из PostgreSQL. Поэтому изменение прав вступает в силу на всех инстансах практически сразу, а не «когда-нибудь». На случай потери сигнала есть фоновое периодическое обновление снимка как страховка.

Это отдельно от срока жизни уже выданного JWT: ревокация роли влияет на проверки прав сразу, но конкретный токен оператора остаётся валидным до своего exp (Архонты → Ревокация).