Точки расширения безопасности

Бесплатная редакция МПК-Пересвет сохраняет прежнее поведение API: если специальный поставщик авторизации не настроен, все действия разрешены. Это сделано для того, чтобы базовая функциональность не зависела от внешнего Identity Provider, OPA или других enterprise-компонентов.

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

Переменная окружения

По умолчанию используется разрешающий поставщик:

PRS_AUTH_PROVIDER=

Платная редакция может указать Python-объект в формате module:attribute:

PRS_AUTH_PROVIDER=enterprise_security.opa_provider:OpaAuthorizationProvider

Объект должен реализовать асинхронный метод:

async def authorize(self, data: AuthorizationInput) -> AuthorizationDecision:
    ...

Если authorize возвращает AuthorizationDecision(allow=False), API возвращает HTTP 403.

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

async def amqp_publish_headers(self, data: AuthorizationInput) -> dict:
    ...

Этот метод позволяет добавить в исходящее RabbitMQ-сообщение подписанный контекст безопасности через AMQP headers, не меняя JSON-тело сообщения и не ломая совместимость бесплатной редакции.

Контекст запроса

Во время обработки HTTP-запроса ядро сохраняет текущий Request в context variable. Enterprise-поставщик может использовать его, чтобы прочитать:

  • Authorization: Bearer ...;

  • IP-адрес клиента;

  • путь и HTTP-метод;

  • служебные заголовки reverse proxy.

Middleware подключается как к отдельным сервисным FastAPI-приложениям, так и к агрегированному one_app. Поэтому enterprise provider получает контекст запроса и при запуске микросервисов по отдельности, и при запуске платформы в одном приложении.

Контекст RabbitMQ

При публикации внутренних сообщений ядро вызывает amqp_publish_headers с действием amqp.publish и ресурсом вида:

{
   "service": "tags_app_api",
   "routing_key": "prsTag.app_api.data_set.*",
   "reply": true
}

Платная редакция может вернуть, например, заголовок с подписанным actor/request context. Бесплатная редакция возвращает пустой набор заголовков.

Поле service — имя сервиса-издателя из его конфигурации. Это позволяет платной редакции строить service identity поверх RabbitMQ credentials, mTLS или service JWT.

Если сервис обрабатывает входящее RabbitMQ-сообщение и в процессе handler-а публикует следующее сообщение, amqp_publish_headers получает в environment.amqp_context контекст исходного сообщения: сервис-потребитель, routing key, headers, reply_to и correlation_id. Это нужно для multi-hop цепочек:

HTTP API -> service A -> RabbitMQ -> service B -> RabbitMQ -> service C

Платный provider может использовать этот context для переноса исходного actor-а и request id через всю цепочку внутренних сервисов.

При получении сообщения из RabbitMQ ядро вызывает authorize с действием amqp.consume до передачи сообщения конкретному handler-у. В resource попадает имя сервиса-потребителя, routing key, reply_to и correlation_id, а в environment — AMQP headers. Если поставщик вернёт allow=False, сообщение не обрабатывается; для RPC-запросов отправляется ответ с ошибкой 403.

RPC-ответы также проходят через extension points:

  • при отправке ответа handler-а вызывается amqp_publish_headers;

  • при получении ответа callback-очередью вызывается authorize с amqp.consume;

  • если enterprise provider запрещает RPC-ответ, ожидающий вызов получает error payload с кодом 403.

Эти hooks нужны именно для распределённой платной инсталляции, где микросервисы могут находиться в разных контейнерах и на разных серверах, а RabbitMQ является основным внутренним каналом связи.

Типы действий

Базовые CRUD-сервисы вызывают авторизацию с действиями вида:

  • prsObject.create / prsObject.read / prsObject.update / prsObject.delete;

  • prsTag.create / prsTag.read / prsTag.update / prsTag.delete;

  • аналогично для prsAlert, prsMethod, prsConnector, prsDataStorage, prsSchedule.

  • copy-операции используют действия вида prsObject.copy, prsTag.copy, prsAlert.copy, prsMethod.copy, prsConnector.copy.

Операционные API вызывают отдельные действия:

  • prsTag.data_get;

  • prsTag.data_set;

  • prsAlert.alarm_read;

  • prsAlert.alarm_ack;

  • prsConnector.connector_command;

  • prsConnector.connector_log_read;

  • prsConnector.service_log_read.

Внутренний контур RabbitMQ использует действия:

  • amqp.publish;

  • amqp.consume.

Назначение

Эта точка расширения предназначена для платной редакции, где поверх базового ядра подключаются:

  • аутентификация пользователей и API-клиентов;

  • ABAC/PBAC-политики;

  • обращение к внешнему PDP, например Open Policy Agent;

  • аудит решений авторизации;

  • привязка прав к LDAP-иерархии объектов, тегов, тревог и коннекторов.

Бесплатная редакция не содержит политик и не включает enforcement без явного подключения внешнего поставщика.