Skip to content

roberttkach/trbrt

Repository files navigation

License: MIT Go Version Docker

trbrt — Tribute Webhook Router

trbrt — специализированный шлюз для маршрутизации, валидации и дедупликации событий Tribute. Сервис обеспечивает идемпотентность обработки, защиту от replay-атак, буферизацию нагрузки и безопасную доставку полезной нагрузки во внутренние системы.


Архитектура и Компоненты

Система поставляется как композиция сервисов:

  • trbrt (Core): Golang-приложение. Реализует бизнес-логику, работу с SQLite, очередь отправки и метрики.
  • Nginx: Обеспечивает SSL (Let's Encrypt), сжатие, заголовки безопасности и маршрутизацию трафика.
  • Certbot: Автоматизация жизненного цикла TLS-сертификатов (ACME).
  • Prometheus: Сбор метрик с интервалом 5s.
  • Grafana: Визуализация. Провиженинг дашбордов.

Deployment (Production)

Развертывание выполняется через docker compose с оркестрацией скриптом deploy.sh.

Предварительные требования

  • ОС: Ubuntu LTS.
  • Сеть: Открытые порты TCP 80, 443.
  • DNS: A/AAAA записи для NGINX_SERVER_NAME.

Конфигурация окружения (.env)

Создайте файл .env на основе .env.example. Критические параметры:

Параметр Описание
TRIBUTE_API_KEY Секрет для валидации HMAC-SHA256 подписи.
NGINX_SERVER_NAME FQDN сервера.
LETSENCRYPT_EMAIL Email для уведомлений Let's Encrypt.
GRAFANA_ADMIN_PASSWORD Пароль администратора Grafana (admin).

Запуск

ENABLE_NFS=1 ENABLE_UFW=1 ENABLE_TLS=1 ./deploy.sh
  • ENABLE_NFS=1: Запрет запуска на сетевых ФС (SQLite требует корректных fcntl блокировок).
  • ENABLE_UFW=1: Настройка firewall (allow 22, 80, 443).
  • ENABLE_TLS=1: Выпуск сертификатов. При 0 Nginx работает в HTTP-only режиме.

HTTP API Контракт

POST /webhook/tribute

Эндпоинт приема событий.

Заголовки:

  • Content-Type: application/json
  • trbt-signature: HMAC-SHA256 (hex). Префикс sha256= допускается.

Схема события (JSON):

{
  "name": "new_subscription",
  "created_at": "2024-01-01T12:00:00Z",
  // RFC3339 / RFC3339Nano
  "sent_at": "2024-01-01T12:00:01Z",
  // RFC3339 / RFC3339Nano
  "payload": {
    "channel_id": 12345,
    // int > 0
    "telegram_user_id": 987654321,
    // int > 0
    "period": "1m",
    // string, non-empty
    "expires_at": "2024-02-01T12:00:00Z"
    // RFC3339, optional
  }
}

Временные метки нормализуются к UTC.

Коды ответов:

Код Описание
200 Успех (в т.ч. дедупликация или soft-drop).
400 Ошибка валидации JSON или нарушение Freshness policy.
401 Невалидная подпись.
413 Превышен лимит тела (TRIBUTE_MAX_BODY_BYTES).
429 Перегрузка очереди (при TRIBUTE_REJECT_ON_OVERLOAD=1).
503 Сервис не готов (Readiness) или ошибка записи в БД.

Служебные эндпоинты

  • GET /healthz: Liveness probe (Nginx -> App).
  • GET /readyz: Readiness probe. Возвращает 503, если БД недоступна, очередь переполнена или есть ошибки конфигурации.

Обработка

1. Проверка подписи и валидация

Вычисляется HMAC-SHA256(body, TRIBUTE_API_KEY). Несовпадение → 401. Валидируется структура JSON. Некорректные поля → 400.

2. Политика свежести

Проверка возраста события: |now - sent_at| <= TRIBUTE_MAX_EVENT_AGE.

  • По умолчанию: 5m.
  • При нарушении: Возвращается 400.
  • Если TRIBUTE_FRESHNESS_SOFT_DROP=1: Возвращается 200, событие игнорируется (не пишется в БД).

3. Дедупликация

Идемпотентность обеспечивается на уровне БД (SQLite Unique Index).

  • Ключ: tenant + name + channel_id + created_at.
  • Окно: TRIBUTE_DEDUPE_WINDOW (default 12h).
  • Поведение: INSERT OR IGNORE. Дубликат не считается ошибкой.

4. Форвардинг

Формат данных, отправляемых в целевую систему, зависит от TRIBUTE_COMPACT_FORWARD.

  • Full Mode (0, default): Отправляется исходный JSON веб-хука.
  • Compact Mode (1): Отправляется сокращенная структура:
    { "user_id": 123, "expires_at": "..." }

Наблюдаемость

Стек мониторинга изолирован во внутренней сети. Внешний доступ только через Nginx (/grafana/).

Prometheus

  • Версия: v3.7.3
  • Scrape Target: trbrt:8080/metrics (доступ закрыт извне).
  • Retention: 30 дней.

Grafana

  • Версия: 12.3.0
  • Доступ: https://<HOST>/grafana/. Логин admin, пароль из GRAFANA_ADMIN_PASSWORD.
  • Provisioning: Дашборды загружаются автоматически из monitoring/grafana/provisioning.

Дашборд "Tribute Webhook Router"

Ключевые метрики:

  1. Service Health: Success Rate, RPS, Saturation (очередь, память дедупликатора).
  2. Ingress: Детализация ошибок (подпись, роутинг, формат).
  3. Storage (SQLite):
    • Write Errors: Критический показатель отказа диска/прав.
    • Locks (Retries): Индикатор конкуренции за файл БД (WAL).
  4. Upstream: Latency, коды ответов, блокировки SSRF/Redirects.

Конфигурация

Все параметры задаются через переменные окружения.

Основные

Переменная Default Описание
TRIBUTE_API_KEY Required. Секрет подписи.
TRIBUTE_LOG_LEVEL debug Уровень логов (debug, info, warn, error).
TRIBUTE_MAX_BODY_BYTES 1048576 Лимит тела запроса (1MB).

Маршрутизация и Хранение

Переменная Default Описание
TRIBUTE_ROUTES_PATH /etc/trbrt/routes.json Путь к файлу маршрутов.
TRIBUTE_CHANNELS_PATH /etc/trbrt/channels.json Путь к файлу каналов.
TRIBUTE_DB_PATH /var/lib/trbrt/events.db Путь к SQLite БД.
TRIBUTE_RETENTION_DAYS 14 Срок хранения событий в БД.

Очередь и Апстрим

Переменная Default Описание
TRIBUTE_FORWARD_CONCURRENCY 64 Количество воркеров отправки.
TRIBUTE_FORWARD_QUEUE 4096 Размер буфера канала.
TRIBUTE_FORWARD_TIMEOUT 5s Таймаут запроса к апстриму.
TRIBUTE_REJECT_ON_OVERLOAD 0 1 = Отказ (429/503) при полной очереди.
TRIBUTE_UPSTREAM_HTTPS_ONLY 1 Запрет отправки на http:// URL.
TRIBUTE_COMPACT_FORWARD 0 1 = Отправлять компактный JSON.

Критерии готовности

Переменная Default Описание
TRIBUTE_READY_FAIL_ON_INVALID_SIGNATURES 0 1 = Fail readyz при всплеске невалидных подписей (атака).
TRIBUTE_READY_FAIL_ON_CONFIG_ERRORS 0 1 = Fail readyz при ошибках hot-reload конфигов.

CLI (trbrtctl)

Управление маршрутами без простоя сервиса.

# Список маршрутов
docker compose run --rm trbrtctl routes list

# Добавление маршрута
docker compose run --rm trbrtctl routes add --tenant client_A --url https://api.client-a.com/webhook

# Привязка канала к тенанту
docker compose run --rm trbrtctl channels add --tenant client_A --channel-id 123456

Deployment (Development)

Для разработки без выпуска TLS сертификатов.

Вариант A: Docker Compose (HTTP only) Закомментируйте сервис certbot и certbot-init. В nginx/conf.d/trbrt.conf не должно быть редиректа на HTTPS (или используйте порт 8080 напрямую, если он опубликован).

Вариант B: Запуск без Nginx

services:
  trbrt:
    ports:
      - "8080:8080"

Приложение будет доступно по http://127.0.0.1:8080/webhook/tribute.

Debugging

  • Pprof: Включите TRIBUTE_PPROF=1. Профайлер доступен на localhost:6060 (требует проброса порта).
  • JSON Errors: TRIBUTE_ERRORS_AS_JSON=1 включает структурное логирование ошибок в HTTP-ответах.

Лицензия

Распространяется по лицензии Mit License. Подробности смотрите в разделе LICENSE. © 2025 Robert Tkach.

About

Шлюз для маршрутизации веб-хуков Tribute с валидацией подписей, дедупликацией и защитой от атак. Go, Docker, Prometheus/Grafana

Topics

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors