Авторизация — кто что может и как вы это доказываете
Control Center отвечает на два вопроса об авторизации, и они по-настоящему разные. «Может ли этот человек вызвать эту операцию?» — это про людей, роли и репозитории. «Может ли этот агент вызвать этот эффект?» — это про действия, аргументы и радиус поражения; этим занимаются Ограничения.
Эта страница — про первый вопрос и про след, который оставляют оба.
Одна точка принятия решений
Заголовок раздела «Одна точка принятия решений»Любое решение об авторизации на стороне человека проходит через одну функцию:
can(principal, permission, resource) → allow | deny + whyРазрешение — это <domain>:<tier>: tickets:write,
members:administer, repos:read. Каталог выводится, а не пишется
вручную: он вычисляется из самого набора операций (префикс имени операции
задаёт домен, минимальная роль, которую она уже требует, — уровень), поэтому
все ~550 операций получают разрешение, и никому не приходится вписывать его
руками.
Именно это свойство и стоит защищать. Благодаря ему у НОВОЙ операции проверка прав включается по умолчанию — слабое место модели с ручными аннотациями в том, что кто-то забывает, а забывают как раз проверку. Ratchet-тест фиксирует получившийся набор доменов, поэтому добавление операции с новым префиксом — это осознанное решение человека об именовании, а не случайность.
Четыре уровня точно соответствуют встроенным ролям:
| Уровень | Минимальная роль | Пример |
|---|---|---|
read |
гость | tickets:read |
write |
участник | tickets:write |
administer |
администратор | members:administer |
own |
владелец | workspace:own |
Пять встроенных ролей — владелец, администратор, участник, наблюдатель, гость — это готовые наборы поверх этого каталога. Владение — одно место на рабочее пространство, и передаётся оно явно, через Передать владение (иначе уходящий владелец неудаляем: депровизионинг через SCIM отказывается удалять владельца рабочего пространства — сначала передайте владение).
Пользовательские роли работают на вычитание. Такая роль указывает базовый
набор (admin, member, viewer или guest — но никогда owner) и набор
разрешений, УДАЛЯЕМЫХ из него, — «администратор, но без управления
участниками». Она никогда не даёт больше, чем её основа, и именно поэтому их
безопасно вводить в уже существующую установку: все существующие проверки
остаются корректной верхней границей. У участников они хранятся как
custom:<id>, а клиент, слишком старый, чтобы понять это значение,
откатывается к гостю, а не угадывает.
Под ролями лежат права на уровне репозитория (none / read / review /
write): членство в рабочем пространстве никогда молча не даёт больше прав,
чем хост кода. Их проверяет каждая поверхность, открывающая доступ к коду, —
включая те, что дотягиваются до кода сбоку, например терминал или сессия
редактора, открытая на worktree пространства.
Полномочия сервера
Заголовок раздела «Полномочия сервера»Некоторые операции вообще не про рабочее пространство: настройки всей установки, конфигурация SSO, учётные данные провайдеров, управление моделями, резервные копии всей установки. Такие операции объявляют полномочия сервера, и их отклоняют всем, кроме оператора установки (записанного владельца сервера). Так сделано намеренно: личность оператора одна, и определение у неё одно.
Журнал аудита
Заголовок раздела «Журнал аудита»Каждое решение об авторизации — и разрешение, и отказ — дописывается в журнал аудита соответствующего рабочего пространства, связанный хеш-цепочкой.
Журнал только отказов отвечает на вопрос «что мы заблокировали?», но не на вопрос «что этот агент на самом деле сделал и кто это разрешил?», а разбор инцидента начинается именно с него. Поэтому каждая запись хранит всю цепочку атрибуции: действующий субъект, человек, от имени которого он действовал, делегирование, через которое он пришёл, действие и его аргументы (в виде дайджеста), решение и правило, по которому оно принято.
Записи связаны в цепочку: хеш каждой покрывает предыдущую, поэтому правка, удаление или перестановка любой строки ломает все хеши после неё. Проверить цепочку заново пересчитывает всё и называет первое звено, которое не сходится. Журнал аудита, который нельзя проверить, — просто журнал; тот, который можно пересчитать, — доказательство.
Два следствия, о которых стоит знать:
- Таблица аудита не подпадает под очистку по возрасту. Хеш-цепочку нельзя усечь из середины. Срок хранения реализован как экспорт с последующим усечением, и после усечения остаётся контрольная точка с конечным хешем удалённого сегмента, так что сохранившееся по-прежнему проверяется вплоть до самого начала.
- Он идёт рядом с лентой активности, а не поверх неё. Лента — это то, что делали люди; журнал — то, что было разрешено и отклонено. Общий идентификатор корреляции позволяет прочитать один вызов в обоих.
Он экспортируется как JSON с разделителями-переводами строк и может потоково передаваться в SIEM (Splunk, Elastic, Sentinel — HTTP-эндпоинт с bearer-токеном). Потоковая передача по замыслу не даёт гарантий: недоступный SIEM ни в коем случае не должен блокировать вызов инструмента агентом, а надёжная проверяемая копия в любом случае лежит на диске.
Установка может задать максимальный срок жизни сеанса и тайм-аут простоя. И то и другое проверяется при проверке учётных данных устройства, через которую проходит каждый аутентифицированный канал: срок сеанса, который клиент мог бы проигнорировать, отвечает на анкету, а не на действия атакующего. Установка также может потребовать SSO — тогда ручная привязка новых устройств отключается (со страховкой от блокировки: пока нет ни одного работающего подключения SSO, запрос отклоняется).
Чем это не является
Заголовок раздела «Чем это не является»- Это не ACL на отдельные объекты. Разрешений на отдельный тикет или сообщение нет — и это намеренно. Команды на практике просят разделение на уровне репозиториев, и оно есть; общий доступ к отдельным объектам — комбинаторная поверхность, спроса на которую здесь не показано.
- Это не движок политик, который настраивают на DSL. Словарь намеренно закрыт, поэтому всю политику можно отобразить, объяснить и перечислить.
- Проверка идёт только на сервере. Клиентские проверки существуют лишь затем, чтобы не предлагать элемент управления, в котором откажут. Окончательное решение всегда за сервером.