← Все статьи
ИНЖЕНЕРНЫЙ БЛОГ / RBAC · 3 МИН ЧТЕНИЯ

Наследование ролей: где возникают ошибки

RBAC становится сложнее, как только одна роль включает другую, а пользователи наследуют права через группы.

Простая таблица user_roles хорошо работает до появления групп, вложенности и составных ролей. Затем эффективное право превращается в вычисляемое множество, которое меняется со временем.

Три источника роли

Пользователь может иметь прямую роль, роль своей группы и роль, вложенную в другую роль. Эти источники необходимо объединять без дублирования, учитывая область realm и максимальную глубину графа.

Почему составные роли опасны

Составная роль удобно выражает «оператор = просмотр + изменение». Но если разрешить произвольные циклы, обход ролей может стать некорректным или дорогим. Нужны проверки при создании связей и защита обхода.

Кэш меняет семантику отзыва

Кэширование вычисленных claims снижает нагрузку на БД, но после снятия роли пользователь некоторое время может получать устаревшие данные. Самый важный тест — не «роль появилась», а «роль исчезла сразу после ожидаемого события инвалидирования».

В RustCloak для RBAC предусмотрен кэш claims и методы инвалидирования пользователя и realm. Проверки должны покрывать прямые назначения, группы, default roles и модификацию составных ролей.

О чём помнить при проектировании

  • Не смешивать идентификатор пользователя и realm в многотенантных сценариях.
  • После мутаций инвалидировать все затронутые эффективные claims.
  • Проверять доступ не только по наличию роли, но и по контексту ресурса.
  • Тестировать отказные сценарии и граничную глубину вложенности.

Итог

RBAC — не только хранение связей в PostgreSQL. Это контракт консистентности: кто и когда должен увидеть изменение полномочий. Его необходимо сформулировать до выбора TTL кэша.

Составная роль — это граф

Представьте роли viewer, editor и operator, где operator включает первые две. Если editor неожиданно начнёт включать operator, появится цикл. Даже если рекурсивный SQL умеет ограничивать глубину, бизнес-операция создания такой связи должна быть осмысленно запрещена или обрабатываться по чёткой политике.

Отдельный вопрос — default roles. Они могут появляться в вычисленных правах без прямого назначения пользователю. Поэтому при разборе инцидента нельзя ограничиваться только таблицей назначений пользователю.

Группы и порядок наследования

Вложенные группы часто интуитивно понимаются по-разному: дочерняя наследует роли родительской или наоборот? Контракт наследования должен быть описан документацией и покрыт тестами. Максимальная глубина защищает запрос от неконтролируемого обхода, но сама не определяет правильную семантику.

Инвалидация должна соответствовать мутации

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

Важно учитывать и конкурентность запросов: после изменения в PostgreSQL параллельный запрос может успеть прочитать старое состояние. Нужно определить, в какой момент система обещает новую видимость разрешений и как этот момент проверяется тестами.

Кэш IdP не единственный источник устаревания

Если API использует JWT с уже встроенными ролями, отзыв доступа может быть ограничен сроком жизни токена даже после удаления записи в RBAC и инвалидирования серверного кэша. Это отдельный вопрос архитектуры: online introspection, короткие токены или дополнительные серверные проверки.

Негативные сценарии важнее обычных

  • Участники разных realm не могут быть соединены ссылкой назначения.
  • Снятие роли из группы изменяет claims всех затронутых пользователей.
  • Изменение составной роли не оставляет старый набор разрешений в кэше.
  • Слишком глубокое дерево групп и циклы завершаются предсказуемой ошибкой.
  • Повторные mutations остаются корректными и не порождают дублирования.

Что измерять

Для оценки RBAC полезнее смотреть не только среднее время вычисления claims, но и хвостовую задержку при больших деревьях, частоту промахов кэша, стоимость инвалидации и время до фактического отзыва полномочий. Без этого оптимизация скорости может незаметно превратить отзыв доступа в гонку.

Продолжить изучение

Справочные материалы по протоколам и устройству RustCloak собраны в технической Wiki.

Перейти в Wiki →