Перейти к основному содержимому
Версия: Новая

Шлюз Salt.Box

Шлюз Salt.Box (Salt.Box Gateway) — это компонент платформы Salt.Box, реализующий API Gateway для микросервисной архитектуры.
Он обеспечивает маршрутизацию запросов, балансировку нагрузки, health-check сервисов, кэширование, а также централизованное управление доступом на основе политик OPA (Open Policy Agent) и системы разрешений приложений («пермишенов»).

Шлюз Salt.Box работает поверх фреймворка FastAPI, интегрируется с Redis для хранения состояния и кэша, а также с OPA для проверки разрешений.

подсказка

Пермишен (от англ. permission — разрешение, дозволение) — механизм безопасности, предназначенный для защиты конфиденциальности пользователей.

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

Архитектура

Компоненты шлюза Salt.Box:

  • ServiceDAO — слой доступа к данным о сервисах (Redis)
  • ProxyService — основной класс для проксирования запросов, балансировки, проверки доступа
  • BalancingStrategy — фабрика стратегий балансировки
  • AsyncOpaClient — клиент для проверки политик OPA
  • CustomRedisCache — кэширование ответов

Основные возможности

  • Динамическое обнаружение и управление сервисами (Service Discovery)
  • Балансировка нагрузки (Round Robin, Weighted RR, Random)
  • Health-check экземпляров сервисов
  • Кэширование ответов
  • Проксирование статических файлов
  • Управление доступом через OPA и пермишены
  • API для управления сервисами и экземплярами сервисов
  • Swagger/OpenAPI документация для сервисов

Динамическое обнаружение и управление сервисами

Функции управления сервисами, реализуемые шлюзом Salt.Box:

  • Регистрация/отключение/удаление сервисов и их экземпляров через API
  • Автоматическое обновление состояния (health-check)
  • Поддержка нескольких экземпляров одного сервиса

Регистрация сервиса в Discovery

Для регистрации нового сервиса (например, core) используется механизм Service Discovery.
Сервис при запуске отправляет информацию о себе (имя, точки подключения («эндпоинты»), тип, стратегия балансировки, разработчик и пр.) шлюзу Salt.Box через API или напрямую в Redis.

подсказка

Эндпоинт (от англ. endpoint — точка подключения) — конкретный сетевой адрес, URL, который определяет точку доступа к ресурсу или услуге на сервере.

Клиентское приложение обращается к конечной точке для выполнения определённых операций или получения данных.

Регистрация сервиса выполняется по следующему алгоритму:

  • Если сервис с таким именем ещё не зарегистрирован, добавляется один экземпляр сервиса.
  • Если сервис уже существует, то добавляется новый экземпляр этого сервиса, при совпадении id сервиса обновляется текущий экземпляр.
  • В SDK реализован клиент, который отправляет POST-запрос на /api/discovery/register с описанием сервиса и его экземпляра.
  • При регистрации сервис передаёт шлюзу полный список своих эндпоинтов с их настройками: политикой доступа (OPA policy), параметрами кэширования (cache_ttl), partial-query, action и др.
  • После регистрации сервис появляется в списке доступных сервисов шлюза и становится доступен для проксирования.
  • На основе зарегистрированных эндпоинтов шлюз осуществляет проверку доступа (через OPA) и кэширование ответов согласно настройкам эндпоинта.

Балансировка нагрузки

Шлюз Salt.Box поддерживает следующие стратегии балансировки нагрузки:

  • rr — Round Robin (Циклический перебор)
  • wrr — Weighted Round Robin (Взвешенный циклический перебор)
  • rand — Random (Случайная)

Стратегия задаётся для каждого сервиса, её можно менять через API.

Кэширование

  • Кэшируется только успешные ответы (200 OK), если эндпоинт поддерживает TTL.
  • Кэш хранится в Redis, namespace: gate_cache.
  • Кэш отключается для Swagger/OpenAPI и приватных эндпоинтов.

Проксирование статических файлов

Для сервисов с настроенным static_host запросы к статическим файлам проксируются напрямую.

Авторизация и управление доступом

Шлюз Salt.Box реализует централизованную систему управления доступом на основе OPA (Open Policy Agent) и пермишенов, поддерживающую модель ABAC (Attribute-Based Access Control).

Преимущества решения

  • ABAC: доступ определяется на основе атрибутов пользователя, ресурса, действия и сервиса.
  • Гибкость: политики сгруппированы по сервисам, например: core (Ядро), scheduler (Планировщик), ресурсам, например: задачи (tasks), команды (jobs), коллекции (collections) и действиям, например: read (чтение), create (создание).
  • Масштабируемость: легко добавлять новые сервисы, ресурсы, роли и условия.
  • Partial Query: OPA может возвращать фильтр для ограничения данных на уровне запроса.

Интеграция с OPA (Open Policy Agent)

Для каждого эндпоинта сервисов задаётся OPA-конфигурация: policy, action, partial-query, unknowns.
Шлюз Salt.Box формирует структуру input для OPA: subject (user), action, resource (service, path, query, body).
OPA возвращает разрешение (allow) и, при partial, query для фильтрации данных.

Пример структуры input для OPA:

{
"subject": {
"sub": "user_id",
"email": "user@example.com",
"roles": ["tasks_admin"]
},
"action": {
"method": "GET",
"name": "read"
},
"resource": {
"service_name": "core",
"path": ["tasks", "123"],
"query_params": {},
"body": null
}
}

Пример политики (Rego):

package core.tasks.read

import data.utils

default allow := false

allow if utils.base.is_admin
allow if utils.base.is_tasks_admin
allow if utils.conditions.check_user_permissions(
data.permissions,
input.resource.service_name,
"tasks",
"read",
input.subject,
object_from_api
)

Формат объекта пользователя

"subject": {
"sub": "26b9a3e6-2e80-40c7-8f84-a993a1282169",
"email": "master@example.com",
"email_verified": false,
"name": "Petr Petrov",
"roles": [
"test_common"
]
}

Пермишены

Пример пермишена

{
"is_active": true,
"service": "core",
"resource": "collections",
"action": "read",
"object_conditions": {
"slug": { "$in": ["linux", "alt"] }
},
"subject_type": "user",
"subject_conditions": {
"roles": { "$in": ["test_common"] }
},
"created": "2024-07-28T12:00:00Z",
"modified": "2024-07-28T12:00:00Z"
}

Структура пермишена:

КлючОписаниеПример
is_activeфлаг активности пермишенаfalse | true
serviceимя сервисаcore
resourceтип ресурсаcollections
actionдействиеread, create
object_conditionsусловия на объектslug должен входить в список
subject_typeтип субъектаuser
subject_conditionsусловия на пользователяроль пользователя
createdдата создания
modifiedдата изменения

Формат условий (conditions):

  • Условия задаются в виде объектов с операторами ($in, $eq, $lt и др.).
  • Можно комбинировать условия по разным полям, использовать вложенные операторы $and / $or.

    Пример 1:
    "roles": { "$in": ["test_common"] } — пользователь должен иметь одну из указанных ролей.

    Пример 2:
    "slug": { "$in": ["linux", "alt"] } — объект должен иметь slug из списка.

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

  • Гибкость: можно описывать сложные правила доступа без изменения кода.
  • Масштабируемость: легко добавлять новые условия и операторы.
  • Поддержка ABAC: условия могут учитывать любые атрибуты пользователя и объекта.
  • Централизованное управление: все права описываются в едином формате и месте.

Partial Query

Для некоторых эндпоинтов OPA возвращает partial query для фильтрации данных (например, списка задач).

Шлюз Salt.Box добавляет фильтр в query-параметры запроса к сервису.

Обновление политик OPA

Политики OPA обновляются вручную: необходимо изменить rego-файлы и перезапустить контейнер OPA для применения изменений.