7.7. Ролевая модель доступа (RBAC) #
7.7.1. Основные положения #
Управление доступом в PPEM реализуется моделью RBAC (Role Based Access Control), которая определяет правила разграничения доступа с помощью ролей и прав. Модель устанавливает следующие базовые соглашения:
Объект — ресурс, к которому должен быть предоставлен или ограничен доступ.
Субъект — человек (пользователь) или автоматизированный агент.
Право — разрешение на выполнение операции над объектом.
Роль — рабочая функция или название, которое определяется на уровне авторизации.
Базовые соглашения определяют расширенные соглашения:
Правило доступа — совокупность роли, прав и связей между ними.
Сеанс — соответствие между субъектом и ролью.
Один субъект может иметь несколько ролей.
Одну роль можно назначить нескольким субъектам.
Одна роль может иметь несколько прав.
Одно право можно выдать нескольким ролям.
Примечание
Права не назначаются субъектам напрямую, а приобретаются субъектами через роли.
7.7.2. RBAC в PPEM #
Базовые утверждения:
Функциональность PPEM состоит из плагинов.
Каждый плагин позволяет управлять конкретным ресурсом.
Управление ресурсом включает в себя базовые CRUD-операции: создание, просмотр, редактирование, удаление.
Дополнительно управление ресурсом может включать в себя различные RPC-операции, их имена зависят от операции по управлению ресурсом.
Права предоставляют субъектам доступ к различным операциям. Управление любым ресурсом также осуществляется через права (базовый минимум):
РЕСУРС\_createРЕСУРС\_viewРЕСУРС\_editРЕСУРС\_delete
Права включаются в роли.
Роли могут назначаться субъекту как в момент создания субъекта, так и позже.
При получении от субъекта запроса на выполнение операции плагин проверяет право субъекта на доступ к запрошенной операции.
Субъекты (пользователи) могут создавать собственные роли (при наличии прав) и назначать эти роли другим субъектам (пользователям).
Права и роли могут быть объектно-привязанными. Это означает, что можно указать роль и право, разрешающее доступ к ограниченному набору объектов.
Привязка к объекту может осуществляться на уровне роли (все субъекты с этой ролью имеют доступ к объекту) или на уровне пользователя (доступ к объекту имеет только один пользователь).
7.7.2.1. Субъекты #
Субъектами могут выступать:
Пользователи. Роли назначаются пользователям в момент создания. Если роли не указаны явно, может быть назначена роль по умолчанию.
Агенты. Эта роль назначается при создании или регистрации агента.
7.7.2.2. Объекты #
Объектами могут выступать как ресурсы, так и представления ресурсов в репозитории, например серверы, агенты, экземпляры, пользователи и группы пользователей.
7.7.2.3. Настройка прав и ролей #
При первом запуске PPEM выполняется инициализация репозитория, при которой заполняются служебные таблицы (права и роли).
При инициализации для каждого плагина устанавливается свой набор прав, ролей и отношений «роль-право». Например, для плагина accounts создаются свои права и роли для управления доступом к объектам этого плагина. Для других плагинов также создаются свои наборы прав и ролей для управления доступом к объектам этих плагинов.
При наличии необходимых прав пользователи могут создавать пользовательские роли, указывать наборы прав, связывать роли с объектами и назначать пользовательские роли субъектам.
7.7.3. Реализация #
Права доступа реализованы следующим набором таблиц, которые принадлежат плагину accounts:
privileges: права с указанием класса объектов, к которым они регулируют доступ.roles: роли с указанием класса объектов, на которые нацелена роль.role_privileges: отношение типа «роль-право», устанавливающее связь между ролями и входящими в них правами.users: пользователи системы (субъекты).user_roles: отношение типа «пользователь-роль», устанавливающее связь между пользователями и назначенными им ролями.user_privileges: представление (view), отображающее связи «пользователь-право».groups: группы системы.group_roles: отношение типа «группа - роль», устанавливающее связь между группами и назначенными им ролями.group_users: отношение типа «группа-пользователь», устанавливающее связь между группами и входящими в них пользователями.
7.7.3.1. Таблица privileges #
Таблица имеет следующие поля:
id: уникальный идентификатор права.name: уникальное имя права.title: описание права.class: класс объектов, для доступа к которым используется право.source: имя плагина, который устанавливает право и в дальнейшем осуществляет проверку доступа.
Таблица заполняется менеджером с помощью миграций. Каждый плагин определяет собственный набор прав.
Для проверки прав используется HTTP middleware-обработчик. Создание, изменение и удаление прав пользователем не предусмотрено, так как проверка прав реализуется в коде менеджера.
7.7.3.2. Таблица roles #
Таблица имеет следующие поля:
id: уникальный идентификатор роли.name: уникальное имя роли.title: описание роли.class: определяет класс объектов, для доступа к которым используется это право. Значение поля используется в пользовательском интерфейсе как подсказка, чтобы получить права соответствующего класса и список объектов этого класса.source: имя плагина, который устанавливает роль. В случае пользовательских ролей устанавливается значениеuser.
Роли создаются менеджером с помощью миграций. Базовый набор ролей устанавливается для плагина accounts.
Пользователь через API менеджера может создавать, изменять и удалять пользовательские роли, но не может изменять или удалять роли, установленные менеджером (системные роли).
7.7.3.3. Таблица role_privileges #
Таблица устанавливает связи между ролями и правами и имеет следующие поля:
id: уникальный идентификатор связи.role: идентификатор роли.privilege: идентификатор права.parametric: указывает, используется ли привязка к объекту.object: уникальный идентификатор объекта произвольного класса.
Класс объекта определяется по значению поля privileges.class. Объявленный здесь идентификатор объекта ограничивает действие права, указанного в role_privileges.privilege, одним объектом и разрешает доступ к объекту только участникам одной роли, указанной в role_privileges.role (доступ разрешён пользователям в user_roles.user, у которых user_roles.role = role_privileges.role).
Комбинация role, privilege и object является уникальным ключом с условием object IS NOT NULL.
Примечание
Параметризованное объектно-привязанное отношение «роль-право» определяет доступ только к одному объекту (через указание object). Если требуется выдать доступ к N объектам, будет создано N записей в role_privileges.
7.7.3.4. Таблица users #
Таблица не имеет полей, имеющих отношение к RBAC. При создании пользователя через API менеджера можно указать список идентификаторов ролей, которые будут назначены пользователю.
7.7.3.5. Таблица user_roles #
Таблица устанавливает связи между пользователем и ролями и имеет следующие поля:
id: уникальный идентификатор связи.user: идентификатор пользователя.role: идентификатор роли.object: уникальный идентификатор объекта произвольного класса.
Класс объекта определяется по значению поля privileges.class. Объявленный здесь идентификатор объекта ограничивает действие права, указанной в role_privileges.privilege, одним объектом и разрешает доступ к объекту пользователю, указанному в user_roles.user.
Примечание
Параметризованное объектно-привязанное отношение «роль-право» определяет доступ только к одному объекту (через указание object). Если требуется выдать доступ к N объектам, будет создано N записей в role_privileges.
7.7.3.6. Представление user_privileges #
Это представление показывает пользователей с ролями и правами и позволяет проверять права конкретного субъекта:
user:user_roles.userrole:user_roles.roleprivilege:privilege.nameobject:user_roles.objectsилиrole_privileges.object
7.7.3.7. Таблица groups #
Таблица не имеет полей, имеющих отношение к RBAC.
При создании группы можно указать список идентификаторов ролей, которые будут назначены группе и, как следствие, всем входящим в неё пользователям.
7.7.3.8. Таблица group_roles #
Таблица устанавливает связи между группами и ролями и имеет следующие поля:
group_id: идентификатор группы.role_id: идентификатор роли.object: уникальный идентификатор объекта произвольного класса.
Класс объекта определяется по значению поля privileges.class. Объявленный здесь идентификатор объекта ограничивает действие права, указанного в role_privileges.privilege, одним объектом и разрешает доступ к объекту пользователю, указанному в group_roles.role_id.
Примечание
Параметризованное объектно-привязанное отношение «группа-роль» определяет доступ только к одному объекту (через указание object). При необходимости выдать доступ на N объектов будет создано N записей в group_roles.
7.7.3.9. Таблица group_users #
Таблица устанавливает связи между группами и пользователями и имеет следующие поля:
group_id: идентификатор группы.user_id: идентификатор пользователя.
Отношения «группа-пользователь» не имеют объектных привязок.
7.7.4. Объектно-привязанные роли #
В общем случае предполагается, что роли могут включать в себя права, которые разрешают доступ ко всем объектам любого класса.
Для более детального контроля прав доступа в поле role_privileges.object вместе с классом можно также указать идентификатор объекта. Таким образом, действие роли и права будет распространяться только на объект с указанным идентификатором. Объект можно указать в нескольких местах:
Для роли в
role_privileges.object, тогда доступ к объекту предоставляется всем членам роли.Для пользователя в
user_roles.object, тогда доступ предоставляется только для одного пользователя.Для группы в
group_roles.object, тогда доступ предоставляется только для пользователей группы.
7.7.5. Проверка прав доступа у субъектов #
В процессе аутентификации субъекта создаётся сам сеанс, а также сессионные токены JWT. При создании токена доступа в него вкладывается user_id. Когда пользователь отправляет запросы на выполнение операций, токен доступа добавляется в заголовки запроса.
Менеджер выполняет авторизацию, извлекает из токена доступа user_id пользователя и через роли проверяет наличие права. При наличии права доступ разрешается, если права нет — запрос отклоняется.
Чтобы проверить право субъекта на выполнение операции с объектом, необходимы следующие данные:
user_idилиagent_id: идентификатор пользователя или агента.class: имя класса для объекта (тип ресурса).object: идентификатор объекта (необязательно).
Клиент в запросе указывает заголовок Authorization: Bearer и прикладывает токен доступа.
Сервер получает запрос и извлекает данные, необходимые для проверки доступа:
Значение
user_id(илиagent_id) извлекается из токена доступа.Значение
classопределяется на основе права.Значения
object:Для GET-запросов вида
/resourcesизвлекаются из URL пути и параметров запроса (ids=?).Для GET-запросов вида
/resources/objectIDизвлекаются из URL пути.Для PUT-запросов извлекаются из тела запроса.
Для DELETE-запросов вида
/resourcesизвлекаются из тела запросов (отдельное поле в объекте).
Для проверки того, что у пользователя есть конкретная право, обработчику может потребоваться карта идентификаторов операций и соответствующих им прав. Проверка выполняется через репозиторий и представление user_privileges.