Москва: проверенные б/у ноутбуки с гарантией и проверкой перед оплатой
+7 906 722-94-45

Главная → Статьи → RBAC: ролевая модель доступа на практике

RBAC: как спроектировать ролевую модель доступа и не утонуть в разрешениях

RBAC: роли, разрешения и ресурсы, иерархия ролей, привязка к бизнес-процессам, типичные ошибки проектирования и миграция с проверок в коде.

Прямой ответ

RBAC (role-based access control) — модель, в которой права выдаются не конкретному пользователю, а роли, а пользователь получает роль. Это решает практическую задачу: при смене должности или приходе нового сотрудника меняется одна привязка, а не десятки разрешений.

Базовые сущности:

  • Subject — кто обращается: пользователь, сервис, API-ключ.
  • Role — набор разрешений, соответствующий функции: support_agent, billing_manager, readonly_analyst.
  • Permission — право на действие над ресурсом, обычно в форме действие:ресурс, например read:invoice, refund:payment.
  • Resource — объект или тип объекта: конкретный счёт, все счета, раздел настроек.

Три уровня RBAC по классификации NIST:

  1. Core. Есть пользователи, роли и разрешения; роль даёт набор разрешений.
  2. Hierarchical. Роли наследуют разрешения других ролей: manager включает всё из support_agent плюс свои права.
  3. Constrained. Добавляются ограничения: разделение обязанностей (один человек не может и завести платёж, и одобрить его), взаимоисключающие роли, лимит числа участников роли.

Ключевые принципы проектирования:

  • Роли от функций, а не от людей. Роль «Иван» — признак того, что модель сломана. Роль описывает, что человек делает, а не кто он.
  • Разрешения позитивные. Модель отвечает на вопрос «что разрешено», а не «что запрещено». Запреты как основа быстро превращаются в непроверяемый набор исключений.
  • Проверка в одном месте. Все проверки прав проходят через единую точку (middleware, декоратор, сервис авторизации). Проверки, размазанные по контроллерам, рано или поздно расходятся.
  • Проверка на уровне действия, а не страницы. Скрытие кнопки в интерфейсе не является контролем доступа: запрос можно отправить напрямую.

Когда RBAC недостаточно: если доступ зависит от атрибутов объекта и контекста («менеджер видит только своих клиентов», «операция доступна только в рабочее время»), нужна атрибутивная модель либо комбинированная схема «роль + условия», где роль задаёт базовый набор прав, а проверка атрибутов объекта сужает его до конкретной записи.

Практика: схема и проверка

Минимальная схема в PostgreSQL:

CREATE TABLE roles (
  id   SERIAL PRIMARY KEY,
  code TEXT NOT NULL UNIQUE
);

CREATE TABLE permissions (
  id     SERIAL PRIMARY KEY,
  action TEXT NOT NULL,          -- read | write | refund | approve
  resource TEXT NOT NULL,        -- invoice | payment | settings
  UNIQUE (action, resource)
);

CREATE TABLE role_permissions (
  role_id       INT REFERENCES roles(id),
  permission_id INT REFERENCES permissions(id),
  PRIMARY KEY (role_id, permission_id)
);

CREATE TABLE user_roles (
  user_id BIGINT NOT NULL,
  role_id INT REFERENCES roles(id),
  granted_at TIMESTAMPTZ NOT NULL DEFAULT now(),
  granted_by BIGINT,
  PRIMARY KEY (user_id, role_id)
);

Проверка в одном месте:

def require(user, action: str, resource: str) -> None:
    if not has_permission(user, action, resource):
        audit(user, action, resource, allowed=False)
        raise PermissionError(f"{action}:{resource}")

Рекомендации:

  1. Не плодите роли. Рост числа ролей быстрее числа функций — признак «ролевого взрыва»: под каждый частный случай создаётся отдельная роль. Лечится вводом разрешений и, при необходимости, условий.
  2. Иерархию используйте осторожно. Глубокая иерархия затрудняет ответ на вопрос «что умеет эта роль». Практика: не больше двух уровней и явная документация наследования.
  3. Фиксируйте выдачу ролей в журнале. Кто, кому, когда и на основании чего выдал роль — обязательное поле аудита, см. audit log.
  4. Проверяйте доступ на каждом запросе. Кэширование прав допустимо, но срок жизни кэша должен быть коротким, иначе отозванная роль продолжает работать.
  5. Сервисы — тоже субъекты. Межсервисные вызовы проверяются по тем же правилам, с отдельными идентификаторами — см. API-ключи.

Практический сценарий: права проверялись в коде и разошлись

Контекст: приложение выросло из прототипа; проверки вида if user.is_admin or user.role == "manager" разбросаны по 40 местам. Поддержка жалуется, что часть операций недоступна, а часть доступна не тем.

  1. Диагностика. Выписали все проверки из кода и обнаружили три разных определения «менеджера» и два места, где проверяется только is_admin. Одно место вообще не проверяло права — операция была доступна любому аутентифицированному пользователю.
  2. Проектирование. Составили матрицу «функция → действия»: кто может читать, создавать, изменять, одобрять. На её основе выделили 6 ролей и 23 разрешения в форме действие:ресурс.
  3. Миграция. Ввели единую функцию проверки и middleware; заменили все точечные условия вызовами этой функции. Для совместимости на время оставили старый флаг is_admin как роль admin со всеми разрешениями.
  4. Проверка. Написали тесты на матрицу: для каждой роли и каждого эндпоинта проверяется ожидаемый код ответа. Такие тесты удобно гонять на Testcontainers с реальной БД.
  5. Результат. Расхождения исчезли, добавление новой роли перестало требовать правок кода: достаточно записей в таблицах. Проверки остались в одном месте, поэтому ревью прав стало возможным.

Вывод: ценность RBAC не в таблицах, а в единой точке проверки и в том, что роли описывают функции. Модель, которую нельзя объяснить бизнесу одним предложением, спроектирована неверно.

FAQ

Сколько ролей нормально? Ориентир — число различимых функций в продукте, обычно от 3 до 15. Больше двадцати ролей почти всегда означает, что часть «ролей» на самом деле комбинации разрешений, и их стоит выразить через права, а не через новые роли.

Что делать с исключениями для отдельных пользователей? Исключения допустимы, но должны быть явными и ограниченными по времени: отдельная таблица «персональные разрешения» с датой истечения и причиной. Иначе через год никто не помнит, почему у одного пользователя больше прав.

Нужен ли RBAC, если пользователей мало? Если пользователей меньше десяти и все делают одно и то же, достаточно двух ролей: admin и user. Полноценная модель оправдана, когда появляются разные функции и требования к разделению обязанностей.

Как RBAC связан с уязвимостями доступа? Некорректная реализация RBAC — прямой путь к broken access control, одному из наиболее распространённых классов уязвимостей. Что проверять в первую очередь — в статье про OWASP Top 10 глазами разработчика.

Источники: Wikipedia (RBAC), NIST INCITS 359, OWASP — ссылки в шапке.