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

Synod и Purview

Две операторские поверхности, надстроенные над базовой моделью «оператор → роли → permissions»:

  • Synod — группа операторов, упрощающая раздачу одинакового набора ролей команде.
  • Purview — scoped-видимость душ: какие хосты и инкарнации оператор видит в списках, исходя из своего scope.

Без групп, чтобы выдать одинаковый набор ролей нескольким операторам, пришлось бы привязывать каждую роль к каждому AID вручную — и менять «стандартный набор прав команды» проходом по всем её членам. Synod добавляет именованный промежуточный уровень: модель становится трёхуровневой — Архонт → Synod → роли.

  • Synod бандлит роли. Группа несёт набор ролей и только. Оператор добавляется в группу — и автоматически получает весь её bundle ролей.
  • Synod своего scope не несёт. Scope (селекторы on coven=… / on service=… / regex / soulprint) живёт на самих ролях (Роли и доступ); группа лишь собирает уже-scoped роли вместе. Член группы получает роли ровно с тем scope, который задан на них.
  • Группы плоские. Synod содержит операторов и роли, но не другие группы — вложенности нет.
  • Оператор может входить в несколько групп. Его эффективные роли = привязанные напрямую ∪ полученные через все его Synod-ы. Дубли идемпотентны — это объединение множеств.

Synod управляется через Operator API семейством permissions synod.*:

  • synod.create — создать группу (с описанием). Пустая группа прав не выдаёт — роли добавляются позже.
  • synod.update — изменить только описание группы. Имя группы неизменяемо (как и имена ролей и инкарнаций) — переименование не поддерживается.
  • synod.delete — удалить группу (каскадом снимаются её членство и bundle ролей).
  • synod.list — перечислить группы с их ролями и членами.
  • synod.add-operator / synod.remove-operator — добавить/убрать оператора в группе.
  • synod.grant-role / synod.revoke-role — добавить/убрать роль в bundle группы.

Семейство synod.* — без scope-селектора: управление группами это кластер-уровневая операция, как role.* и operator.*.

Поскольку член группы получает весь её bundle ролей, обе защиты RBAC (см. Default-deny) учитывают роли, полученные через Synod:

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

Группа — удобная единица отзыва: одна операция synod.remove-operator снимает с оператора весь набор ролей группы сразу, и эффект распространяется по кластеру мгновенно.

Scope роли ограничивает не только то, что оператор может трогать, но и то, что он видит. Purview — это разрешённая граница видимости оператора, собранная из scope всех его ролей (прямых и через группы).

Принцип: для оператора со scope-ограничениями запрос «покажи все души» означает «покажи всё, что доступно мне», а не буквально все души.

  • Списки сужаются по Purview. GET /v1/souls, GET /v1/incarnations и подобные отдают только узлы в границе оператора. Хост или инкарнация вне scope не попадают в список, а запрос конкретного узла вне scope отвечает 404 — существование чужих узлов не раскрывается.
  • Измерения Purview — те же, что у scope-селектора роли: covens, SID-regex, soulprint-предикаты (по фактам хоста) и предикаты по состоянию инкарнации. Несколько значений в измерении объединяются по ИЛИ.
  • Оператор без ограничений (роль с полным доступом * или без явного scope) видит все доступные души — для него Purview не сужает ничего.

Таргетинг прогонов ограничен той же границей

Заголовок раздела «Таргетинг прогонов ограничен той же границей»

Purview — это верхняя граница не только видимости, но и таргетинга. Когда оператор запускает прогон по широкому фильтру (coven=…, предикат по фактам), целевой набор хостов пересекается с его Purview — прогон не выйдет за границу оператора.

Поведение при попытке выйти за scope зависит от формы цели:

  • широкий фильтр (coven=… или предикат) — цель молча сужается до пересечения с Purview, как и списки;
  • явно перечисленные чужие хосты (оператор указал конкретные хосты вне своего scope) — отказ 403: явное указание чужого узла трактуется как попытка эскалации, а не как фильтр;
  • пустое пересечение (после сужения не осталось ни одного хоста) — 422: запрос валиден, но исполнять нечего.

Безопасное направление при неопределённости

Заголовок раздела «Безопасное направление при неопределённости»

Видимость по Purview работает fail-closed: при любой неопределённости scope результат — пустой список, а не все души. Если scope не удалось вычислить (ошибка предиката, не сконфигурированный резолвер, отсутствие прав) — оператор не видит ничего, а не получает лишнее. Сужение «спрятать лишнее» здесь всегда предпочтительнее, чем «показать чужое».