1.6. Безопасность #

1.6.1. Менеджер и агент #

Менеджер является обычным прикладным ПО и не требует привилегированного доступа к функциям операционной системы. Служба менеджера может полноценно функционировать при запуске от имени непривилегированного системного пользователя.

Для работы с репозиторием менеджеру требуется отдельная база данных, где хранится служебная информация. Также требуется пользователь СУБД со следующими правами:

  • Право LOGIN для подключения к экземпляру.

  • Права для доступа к базе данных репозитория:

    • право владения базой данных

    • право подключения к базе данных

    • отсутствие ограничений прав доступа внутри базы данных (для миграций в схеме данных)

Агент является обычным прикладным ПО, для полноценной работы которого требуется:

  • доступ к функциям операционной системы

  • доступ к управляемому экземпляру СУБД

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

Доступ к управляемому экземпляру СУБД можно разделить на следующие части:

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

    Примечание

    По умолчанию инициализацию основного каталога данных выполняет владелец postgres с правами 0600, поэтому большинство установок СУБД ограничивает доступ к этой настройке. Следовательно, оптимальным вариантом эксплуатации является запуск агента от имени системного пользователя postgres.

  • Доступ к SQL-интерфейсу экземпляра СУБД, для которого агенту требуется пользователь СУБД со следующими правами:

    • право LOGIN для подключения к экземпляру

    • право подключения ко всем базам данных экземпляра

    • включение в роли pg_monitor и pg_signal_backend

1.6.2. Сетевое взаимодействие #

Сетевое взаимодействие между менеджером и агентом может инициироваться обеими сторонами:

  • Менеджер может отправлять управляющие инструкции агентам, в ответ агенты отправляют результаты их выполнения.

  • Агенты могут отправлять менеджеру запросы на собственную регистрацию, регистрацию экземпляров СУБД, а также запросы на обновление состояния экземпляров. Менеджер, в свою очередь, должен отправить агенту ответ на запрос.

Для взаимодействия менеджер и агент используют протокол HTTPS. Менеджер по умолчанию использует порт tcp/8080, агент использует по умолчанию порт tcp/8081. Такое направление трафика следует учитывать при настройке правил сетевого доступа. Параметры адресов и портов указываются в файлах конфигурации менеджера ppem-manager.yml и агентов ppem-agent.yml.

Для безопасной передачи данных рекомендуется использовать параметры TLS.

1.6.3. Аутентификация между пользователями и менеджером #

Для работы с менеджером требуется аутентификация и авторизация пользователя. Аутентификация может выполняться следующими способами:

  • Встроенными средствами PPEM — данные о пользователях и группах хранятся в репозитории и управляются администратором PPEM.

  • Через внешний каталог LDAP (OpenLDAP или Active Directory). При использовании внешнего каталога менеджер необходимо настроить для работы с этим каталогом. Все данные о пользователях и группах хранятся во внешнем каталоге и управляются выделенным администратором каталога LDAP.

1.6.4. Аутентификация между менеджером и пользователями #

API менеджера и агента защищено авторизацией. Для выполнения запросов к API менеджер и агент проводят взаимную аутентификации и выдают токены доступа для последующей авторизации. Токены имеют ограниченное время жизни — менеджер и агенты самостоятельно отслеживают срок действия токенов и обновляют их при необходимости.

1.6.5. Схема работы аутентификации и авторизации #

Существует три типа взаимодействия, для которых требуется аутентификация и авторизация в процессе работы менеджера:

Все взаимодействия осуществляются с помощью протокола HTTP или HTTPS в зависимости от параметров PPEM.

1.6.5.1. Пользователь → Менеджер #

В рамках этого типа взаимодействия пользователи работают в веб-приложении.

1.6.5.1.1. Пользователь → менеджер: аутентификация #

Пользователь отправляет конечной точке (endpoint) менеджера запрос API POST /v1/sessions, чтобы получить токены доступа и обновления (access token и refresh token) для дальнейшей работы. Запрос API содержит учётные данные пользователя.

В базовом сценарии учётные данные проверяются в репозитории. При использовании аутентификации LDAP учётные данные сначала проверяются в службе каталогов, затем, если они не были обнаружены, выполняется проверка в репозитории.

1.6.5.1.2. Пользователь → менеджер: авторизация #

При успешной аутентификации дальнейшие запросы HTTP/HTTPS к менеджеру от пользователей содержат заголовок Authorization, в котором после ключевого слова Bearer через пробел указывается текст токена доступа, например:

  headers:
  Content-Type: application/json
  Authorization: "Bearer eyJhbG..."

Предоставляемый доступ определяется с помощью ролевой модели доступа RBAC (Role Based Access Control, RBAC) в соответствии с назначенными пользователю ролями:

  • Пользователям PPEM роли можно назначить напрямую или через группы PPEM, в которых они состоят.

  • LDAP-пользователям роли назначаются только через группы PPEM, в которых они состоят.

    Чтобы добавить пользователя LDAP в группу PPEM, администратору необходимо сопоставить отличительное имя (distinguished name, DN) группы LDAP этого пользователя с именем группы PPEM. После этого пользователь будет автоматически добавлен в группу PPEM при входе в веб-приложение.

    Состав групп пользователей периодически сверяется с сервером LDAP и при необходимости обновляется.

    За подробной информацией о сопоставлении групп LDAP и групп PPEM обратитесь к Интеграция с OpenLDAP и Active Directory.

1.6.5.2. Менеджер → агент #

В рамках этого типа взаимодействия менеджер отправляет агентам пакеты команд API для выполнения различных операций.

1.6.5.2.1. Менеджер → агент: аутентификация #

Менеджер отправляет конечной точке агента запрос API POST /v1/sessions, чтобы получить токены доступа и обновления для дальнейшей работы. Запрос API выполняется по URL для подключения агента к менеджеру из репозитория и содержит два параметра:

  • name: имя агента из репозитория.

  • api_key: API-ключ для подключения агента к менеджеру из репозитория.

1.6.5.2.2. Менеджер → агент: авторизация #

При успешной аутентификации дальнейшие запросы HTTP/HTTPS к агентам от менеджера содержат заголовок Authorization, в котором после ключевого слова Bearer через пробел указывается текст токена доступа, например:

  headers:
  Content-Type: application/json
  Authorization: "Bearer eyJhbG..."

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

1.6.5.3. Агент → менеджер #

В рамках этого типа взаимодействия агенты отправляют менеджеру отчёты о выполнении команд API, а также обновления информации об объектах обслуживаемых экземпляров.

1.6.5.3.1. Агент → менеджер: аутентификация #

Агент отправляет конечной точке менеджера запрос API POST /v1/sessions, чтобы получить токены доступа и обновления для дальнейшей работы. Запрос API выполняется по URL для подключения агента к менеджеру, который указан в файле конфигурации агента ppem-agent.yml с помощью параметра agent.manager.url. Запрос API содержит два параметра:

  • name: имя агента, которое указано в файле конфигурации агента ppem-agent.yml с помощью параметра agent.name.

  • api_key: ключ API для подключения агента к менеджеру, который указан в файле конфигурации агента ppem-agent.yml с помощью параметра agent.manager.api_key.

1.6.5.3.2. Агент → менеджер: авторизация #

При успешной аутентификации дальнейшие запросы HTTP/HTTPS к менеджеру от агента содержат заголовок Authorization, в котором после ключевого слова Bearer через пробел указан текст токена доступа, например:

  headers:
  Content-Type: application/json
  Authorization: "Bearer eyJhbG..."

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

Предоставляемый доступ определяется указанными в коде PPEM правилами доступа агента к ресурсам менеджера.

1.6.5.4. Время жизни токенов доступа и обновления #

Время жизни токенов доступа и обновления ограничено. Его можно указать в файле конфигурации менеджера ppem-manager.yml или агента ppem-agent.yml с помощью параметров jwt.lifetime.access и jwt.lifetime.refresh.

Когда время жизни токена доступа истекает, менеджер или агент начинает отвечать владельцу токенов ошибкой «401 Unauthorized» с кодом «ERR_AUTH_TOKEN_EXPIRED», например:

  {
  "error":{
    "code":"ERR_AUTH_TOKEN_EXPIRED",
    "title":"token is expired"
  }
  }

Чтобы получить новый токен доступа, владельцу токенов необходимо отправить конечной точке запрос API PUT /v1/sessions с токеном обновления, который был получен вместе с устаревшим токеном доступа. В результате будут получены новые токены доступа и обновления, которые можно использовать для дальнейшей работы.

Если время жизни токена обновления также истекло, владельцу токенов необходимо повторно пройти аутентификацию.

1.6.6. Ролевая модель доступа (RBAC) #

1.6.6.1. Основные положения #

Управление доступом в PPEM реализуется моделью RBAC (Role Based Access Control), которая определяет правила разграничения доступа с помощью ролей и прав. Модель устанавливает следующие базовые соглашения:

  • Объект — ресурс, к которому должен быть предоставлен или ограничен доступ.

  • Субъект — человек (пользователь) или автоматизированный агент.

  • Право — разрешение на выполнение операции над объектом.

  • Роль — рабочая функция или название, которое определяется на уровне авторизации.

Базовые соглашения определяют расширенные соглашения:

  • Правило доступа — совокупность роли, прав и связей между ними.

  • Сеанс — соответствие между субъектом и ролью.

  • Один субъект может иметь несколько ролей.

  • Одну роль можно назначить нескольким субъектам.

  • Одна роль может иметь несколько прав.

  • Одно право можно выдать нескольким ролям.

Примечание

Права не назначаются субъектам напрямую, а приобретаются субъектами через роли.

1.6.6.2. RBAC в PPEM #

Базовые утверждения:

  • Функциональность PPEM состоит из плагинов.

  • Каждый плагин позволяет управлять конкретным ресурсом.

  • Управление ресурсом включает в себя базовые CRUD-операции: создание, просмотр, редактирование, удаление.

  • Дополнительно управление ресурсом может включать в себя различные RPC-операции, их имена зависят от операции по управлению ресурсом.

  • Права предоставляют субъектам доступ к различным операциям. Управление любым ресурсом также осуществляется через права (базовый минимум):

    • РЕСУРС\_create

    • РЕСУРС\_view

    • РЕСУРС\_edit

    • РЕСУРС\_delete

  • Права включаются в роли.

  • Роли могут назначаться субъекту как в момент создания субъекта, так и позже.

  • При получении от субъекта запроса на выполнение операции плагин проверяет право субъекта на доступ к запрошенной операции.

  • Субъекты (пользователи) могут создавать собственные роли (при наличии прав) и назначать эти роли другим субъектам (пользователям).

  • Права и роли могут быть объектно-привязанными. Это означает, что можно указать роль и право, разрешающее доступ к ограниченному набору объектов.

  • Привязка к объекту может осуществляться на уровне роли (все субъекты с этой ролью имеют доступ к объекту) или на уровне пользователя (доступ к объекту имеет только один пользователь).

1.6.6.2.1. Субъекты #

Субъектами могут выступать:

  • Пользователи. Роли назначаются пользователям в момент создания. Если роли не указаны явно, может быть назначена роль по умолчанию.

  • Агенты. Эта роль назначается при создании или регистрации агента.

1.6.6.2.2. Объекты #

Объектами могут выступать как ресурсы, так и представления ресурсов в репозитории, например серверы, агенты, экземпляры, пользователи и группы пользователей.

1.6.6.2.3. Настройка прав и ролей #

При первом запуске PPEM выполняется инициализация репозитория, при которой заполняются служебные таблицы (права и роли).

При инициализации для каждого плагина устанавливается свой набор прав, ролей и отношений «роль-право». Например, для плагина accounts создаются свои права и роли для управления доступом к объектам этого плагина. Для других плагинов также создаются свои наборы прав и ролей для управления доступом к объектам этих плагинов.

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

1.6.6.3. Реализация #

Права доступа реализованы следующим набором таблиц, которые принадлежат плагину accounts:

  • privileges: права с указанием класса объектов, к которым они регулируют доступ.

  • roles: роли с указанием класса объектов, на которые нацелена роль.

  • role_privileges: отношение типа «роль-право», устанавливающее связь между ролями и входящими в них правами.

  • users: пользователи системы (субъекты).

  • user_roles: отношение типа «пользователь-роль», устанавливающее связь между пользователями и назначенными им ролями.

  • user_privileges: представление (view), отображающее связи «пользователь-право».

  • groups: группы системы.

  • group_roles: отношение типа «группа - роль», устанавливающее связь между группами и назначенными им ролями.

  • group_users: отношение типа «группа-пользователь», устанавливающее связь между группами и входящими в них пользователями.

1.6.6.3.1. Таблица privileges #

Таблица имеет следующие поля:

  • id: уникальный идентификатор права.

  • name: уникальное имя права.

  • title: описание права.

  • class: класс объектов, для доступа к которым используется право.

  • source: имя плагина, который устанавливает право и в дальнейшем осуществляет проверку доступа.

Таблица заполняется менеджером с помощью миграций. Каждый плагин определяет собственный набор прав.

Для проверки прав используется HTTP middleware-обработчик. Создание, изменение и удаление прав пользователем не предусмотрено, так как проверка прав реализуется в коде менеджера.

1.6.6.3.2. Таблица roles #

Таблица имеет следующие поля:

  • id: уникальный идентификатор роли.

  • name: уникальное имя роли.

  • title: описание роли.

  • class: определяет класс объектов, для доступа к которым используется это право. Значение поля используется в пользовательском интерфейсе как подсказка, чтобы получить права соответствующего класса и список объектов этого класса.

  • source: имя плагина, который устанавливает роль. В случае пользовательских ролей устанавливается значение user.

Роли создаются менеджером с помощью миграций. Базовый набор ролей устанавливается для плагина accounts.

Пользователь через API менеджера может создавать, изменять и удалять пользовательские роли, но не может изменять или удалять роли, установленные менеджером (системные роли).

1.6.6.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.

1.6.6.3.4. Таблица users #

Таблица не имеет полей, имеющих отношение к RBAC. При создании пользователя через API менеджера можно указать список идентификаторов ролей, которые будут назначены пользователю.

1.6.6.3.5. Таблица user_roles #

Таблица устанавливает связи между пользователем и ролями и имеет следующие поля:

  • id: уникальный идентификатор связи.

  • user: идентификатор пользователя.

  • role: идентификатор роли.

  • object: уникальный идентификатор объекта произвольного класса.

Класс объекта определяется по значению поля privileges.class. Объявленный здесь идентификатор объекта ограничивает действие права, указанной в role_privileges.privilege, одним объектом и разрешает доступ к объекту пользователю, указанному в user_roles.user.

Примечание

Параметризованное объектно-привязанное отношение «роль-право» определяет доступ только к одному объекту (через указание object). Если требуется выдать доступ к N объектам, будет создано N записей в role_privileges.

1.6.6.3.6. Представление user_privileges #

Это представление показывает пользователей с ролями и правами и позволяет проверять права конкретного субъекта:

  • user: user_roles.user

  • role: user_roles.role

  • privilege: privilege.name

  • object: user_roles.objects или role_privileges.object

1.6.6.3.7. Таблица groups #

Таблица не имеет полей, имеющих отношение к RBAC.

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

1.6.6.3.8. Таблица group_roles #

Таблица устанавливает связи между группами и ролями и имеет следующие поля:

  • group_id: идентификатор группы.

  • role_id: идентификатор роли.

  • object: уникальный идентификатор объекта произвольного класса.

Класс объекта определяется по значению поля privileges.class. Объявленный здесь идентификатор объекта ограничивает действие права, указанного в role_privileges.privilege, одним объектом и разрешает доступ к объекту пользователю, указанному в group_roles.role_id.

Примечание

Параметризованное объектно-привязанное отношение «группа-роль» определяет доступ только к одному объекту (через указание object). При необходимости выдать доступ на N объектов будет создано N записей в group_roles.

1.6.6.3.9. Таблица group_users #

Таблица устанавливает связи между группами и пользователями и имеет следующие поля:

  • group_id: идентификатор группы.

  • user_id: идентификатор пользователя.

Отношения «группа-пользователь» не имеют объектных привязок.

1.6.6.4. Объектно-привязанные роли #

В общем случае предполагается, что роли могут включать в себя права, которые разрешают доступ ко всем объектам любого класса.

Для более детального контроля прав доступа в поле role_privileges.object вместе с классом можно также указать идентификатор объекта. Таким образом, действие роли и права будет распространяться только на объект с указанным идентификатором. Объект можно указать в нескольких местах:

  • Для роли в role_privileges.object, тогда доступ к объекту предоставляется всем членам роли.

  • Для пользователя в user_roles.object, тогда доступ предоставляется только для одного пользователя.

  • Для группы в group_roles.object, тогда доступ предоставляется только для пользователей группы.

1.6.6.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.