api_sync/ARCHITECTURE.md

18 KiB
Executable file
Raw Blame History

Архитектура API Sync

Обзор

API Sync — однопроходная утилита (не демон), запускаемая по cron. Поддерживает два режима запуска: основной и проверка дублей/ошибок API по ключу --cd.


Режимы запуска

./API_sync        # основной запуск
./API_sync --cd   # проверка дублирующихся доменов/алиасов + ошибок API

Пример cron-конфигурации:

# Основной запуск каждые 15 минут
*/15 * * * * install cd /home/install && /home/install/API_sync >> /var/log/API_sync.log 2>&1

# Проверка дублей и ошибок API каждый час
0 * * * *  install cd /home/install && /home/install/API_sync --cd >> /var/log/API_sync.log 2>&1

Поток выполнения

Основной режим

main()
  │
  ├─ 1. Подключение к PostgreSQL
  │
  ├─ 2. Загрузка списка клиентов (client_info)
  │
  ├─ 3. Сбор SID (apps_settings WHERE mode = 'auto')
  │
  ├─ 4. Параллельная обработка SID (worker pool)
  │       └─ processSID() для каждого SID
  │             ├─ GET /l7/resource/{sid}/global       → whois
  │             │     └─ ошибка → записывается в apiErrors
  │             ├─ GET /l7/origin/global?l7ResourceId={sid}  → origins
  │             │     └─ ошибка → записывается в apiErrors
  │             ├─ GET /l7/alias/global?l7ResourceId={sid}   → aliases
  │             │     └─ ошибка → записывается в apiErrors
  │             ├─ DNS резолв домена → проверка AntiDDOS
  │             └─ upsertAPIInfo() → сравнение + запись в API_info + алерты
  │
  ├─ 5. Отправка сводного алерта об ошибках API (если CHECK_DUPLICATES=true)
  │
  ├─ 6. Очистка устаревших SID из API_info (cleanupRemovedSIDs)
  │
  ├─ 7. Проверка дублирующихся доменов/алиасов (если CHECK_DUPLICATES=true)
  │       └─ checkDuplicateDomains() → алерт 🔴 если найдены дубли
  │
  └─ 8. Обновление WAF whitelist (updateWAFWhitelist)
        ├─ git pull
        ├─ Загрузка IP из API_info (auto-ресурсы)
        ├─ Загрузка IP из manual_info (ручные ресурсы)
        ├─ Объединение и дедупликация IP
        ├─ Фильтрация WAF-сетей (таблица ips)
        ├─ Сравнение с текущим whitelist-файлом
        ├─ Запись файла + git commit + git push
        └─ Отправка алерта об изменениях

Режим --cd

main() --cd
  │
  ├─ 1. Подключение к PostgreSQL
  │
  ├─ 2. Загрузка всех SID (apps_settings WHERE mode = 'auto')
  │
  ├─ 3. Параллельная проверка доступности API (worker pool)
  │       └─ checkSIDAvailability() для каждого SID
  │             ├─ GET /l7/resource/{sid}/global
  │             ├─ GET /l7/origin/global?l7ResourceId={sid}
  │             └─ GET /l7/alias/global?l7ResourceId={sid}
  │
  ├─ 4. Отправка сводного алерта об ошибках API (если есть)
  │
  └─ 5. checkDuplicateDomains() → алерт 🔴 если найдены дубли

Модули

main.go — точка входа и worker pool

При запуске с ключом --cd параллельно проверяет доступность API для всех SID через checkSIDAvailability(), отправляет сводный алерт об ошибках и выполняет проверку дублей. В основном режиме запускает полный цикл синхронизации с пулом воркеров. Ошибки API собираются в общий map через mutex и отправляются одним алертом после завершения всех воркеров (если CHECK_DUPLICATES=true).

config.go — конфигурация

Загружает переменные окружения из /etc/API_sync/API_sync.env через godotenv. Если файл недоступен — использует системные переменные окружения. Все переменные инициализируются в init() до старта main().

api.go — HTTP-клиент и структуры API

Содержит единственный HTTP-клиент с таймаутом 20 секунд и функцию apiGet(), которая выполняет GET-запрос к API ServicePipe с Bearer-авторизацией и десериализует JSON-ответ в переданную структуру.

Определены структуры ответов API: originItem, aliasItem, whoisReAPIonse, apiList.

database.go — работа с PostgreSQL

loadClients() — загружает список клиентов из client_info.

loadL7IDs() — загружает SID из apps_settings для конкретного клиента с mode = 'auto'.

processSID() — оркестрирует обработку одного SID: делает три запроса к API, резолвит домен для проверки AntiDDOS, вызывает upsertAPIInfo(). При ошибке API возвращает её наверх — воркер записывает в общий map ошибок.

checkSIDAvailability() — делает только три API-запроса без записи в БД и без алертов. Используется в режиме --cd для быстрой проверки доступности API по каждому SID.

sendAPIErrorsAlert() — формирует и отправляет один сводный алерт 🔴 со всеми SID у которых была ошибка API. SID отсортированы для стабильного вывода.

upsertAPIInfo() — в начале подтягивает из БД client_title (из apps_settings) и waf_provider (из client_info) для использования в алертах. Затем сравнивает новые данные со старыми и при наличии изменений формирует алерты:

  • изменение домена → строка Домен изменён: old -> new + флаг необходимости обновления WAF
  • изменение origins — через compareOrigins()
  • изменение aliases — через compareAliases() + флаг обновления WAF
  • изменение WAF-настроек (vendor, instance, enabled) — отдельный алерт

Сохранение выполняется через INSERT ... ON CONFLICT DO UPDATE (upsert по sid).

cleanupRemovedSIDs() — сравнивает все SID в API_info с актуальным списком активных SID. Записи, которых нет в активном списке (ресурс удалён из apps_settings или сменил mode), удаляются из API_info. По каждому удалённому ресурсу отправляется алерт с указанием WAF-вендора (берётся из apps_settings через LEFT JOIN).

checkDuplicateDomains() — загружает все domain_name и aliases из API_info в единую карту. Если одно и то же значение встречается у двух и более разных SID в любой комбинации полей — считается дублем. При наличии дублей отправляется алерт 🔴 с перечислением всех совпадений и их SID. В основном режиме управляется флагом CHECK_DUPLICATES, при запуске с --cd выполняется всегда.

wafVendorName() — возвращает читаемое название вендора: ptafPT AF, swSW, wmxWMX.

wafVendorWarning() — возвращает строку предупреждения для алерта об удалении ресурса с указанием конкретного WAF-вендора.

compare.go — функции сравнения

compareOrigins() — сравнивает два списка origins по IP-адресу. Определяет добавленные, удалённые и изменённые (mode/weight) записи. Возвращает отформатированную строку с изменениями и текущим состоянием origins.

compareAliases() — сравнивает два отсортированных списка доменов. Добавленные aliases оформляются как HTML-ссылки. Возвращает строку с изменениями и булев флаг наличия изменений.

dns.go — DNS-резолвер

Функция resolveDomain() возвращает первый IPv4-адрес для заданного домена. Используется в processSID() для проверки AntiDDOS: если resolvedIP совпадает с protectedIP из API — AntiDDOS активен.

notify.go — система уведомлений

sendAlert() — единая точка отправки алертов. Последовательно отправляет сообщение во все настроенные каналы. Ошибка одного канала не блокирует остальные.

TelegrambuildTelegramClient() при каждой отправке выбирает транспорт в порядке приоритета:

  1. HTTP-прокси (TELEGRAM_HTTP_PROXY) — если задан и доступен
  2. SOCKS5-прокси (TELEGRAM_SOCKS5_PROXY) — если задан и доступен
  3. Прямое подключение — fallback

Доступность проверяется реальным GET-запросом на api.telegram.org. Сообщения отправляются в формате HTML (parse_mode: HTML).

Mattermost — POST на /api/v4/posts с Bearer-токеном. HTML-теги Telegram конвертируются в Markdown через htmlToMarkdown(). Отправляется только если заполнены все три переменные: MATTERMOST_URL, MATTERMOST_BOT_TOKEN, MATTERMOST_CHANNEL_ID.

Email — через стандартный net/smtp. Поддерживает несколько адресов получателей через запятую в EMAIL_TO. При EMAIL_SKIP_TLS_VERIFY=true использует STARTTLS с отключённой проверкой сертификата. Механизм аутентификации выбирается автоматически по возможностям сервера: если сервер поддерживает LOGIN — используется он, иначе PLAIN. Реализован собственный loginAuth для совместимости с корпоративными SMTP (Exchange, Outlook). Отправляется только если заполнены EMAIL_SMTP_HOST, EMAIL_FROM, EMAIL_TO.

git.go — Git-операции

syncGitRepo() — если репозиторий не существует локально — клонирует (git clone), иначе обновляет (git pull). Автоматически настраивает user.email и user.name для коммитов.

gitCommitAndPush() — выполняет git add <whitelist_file>, git commit -m <message>, git push. Если нечего коммитить (nothing to commit) — завершается без ошибки.

whitelist.go — управление whitelist

updateWAFWhitelist() — основная функция обновления whitelist:

  1. Синхронизирует Git-репозиторий
  2. Загружает WAF-сети из таблицы ips
  3. Загружает origin IP из API_info (loadAllOrigins) и manual_info (loadManualOrigins), объединяет и дедуплицирует
  4. Фильтрует IP попадающие в WAF-сети (filterNonWAFOrigins)
  5. Сравнивает с текущим содержимым файла (compareWhitelists)
  6. При наличии изменений — перезаписывает файл, коммитит и пушит, отправляет алерт

loadAllOrigins() — загружает все origin IP из API_info (auto-ресурсы).

loadManualOrigins() — загружает все записи из manual_info как есть, без дополнительных условий. Таблица заполняется администратором вручную и программой не изменяется.

filterNonWAFOrigins() — исключает из списка IP-адреса, которые принадлежат WAF-сетям из таблицы ips. Такие адреса являются узлами самого WAF и не должны попадать в whitelist.


Алерты

Все алерты отправляются через единую функцию sendAlert(). Типы алертов:

Событие Эмодзи Содержание
Изменение origins/aliases/домена 🟡 SID, домен, TENANT, WAF provider, детали изменений, предупреждение об обновлении WAF, время
Изменение WAF-настроек инстанса SID, домен, TENANT, изменения waf_enabled/vendor/instance в формате было -> стало, время
Удаление ресурса из мониторинга 🗑 SID, домен, предупреждение с указанием конкретного WAF-вендора
Ошибки запросов к API ServicePipe 🔴 Сводный список SID с ошибками и текстом ошибки, время
Дублирующиеся домены/алиасы 🔴 Список дублей с указанием SID, время проверки
Обновление whitelist 🔄 Добавленные/удалённые IP с привязкой к SID и домену, итоговое количество

Предупреждение об обновлении WAF формируется динамически в зависимости от вендора: ptaf → PT AF, sw → SW, wmx → WMX.


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

Переменная По умолчанию Описание
BEARER_TOKEN Токен авторизации API ServicePipe
DB_HOST localhost Хост PostgreSQL
DB_PORT 5432 Порт PostgreSQL
DB_USER Пользователь БД
DB_PASSWORD Пароль БД
DB_NAME waf_info Имя БД
TELEGRAM_BOT_TOKEN Токен Telegram-бота
TELEGRAM_CHAT_ID ID чата для алертов
TELEGRAM_HTTP_PROXY HTTP-прокси для Telegram
TELEGRAM_SOCKS5_PROXY SOCKS5-прокси для Telegram
TELEGRAM_SOCKS5_USER Логин SOCKS5-прокси
TELEGRAM_SOCKS5_PASSWORD Пароль SOCKS5-прокси
MATTERMOST_URL URL Mattermost-сервера
MATTERMOST_BOT_TOKEN Токен Mattermost-бота
MATTERMOST_CHANNEL_ID ID канала Mattermost
EMAIL_SMTP_HOST SMTP-сервер
EMAIL_SMTP_PORT 587 SMTP-порт
EMAIL_SMTP_USER Логин SMTP
EMAIL_SMTP_PASSWORD Пароль SMTP
EMAIL_FROM Адрес отправителя
EMAIL_TO Адреса получателей (через запятую)
EMAIL_SKIP_TLS_VERIFY false Отключить проверку TLS-сертификата SMTP
GIT_REPO_URL URL Git-репозитория whitelist
GIT_REPO_PATH Локальный путь к репозиторию
WHITELIST_FILE whitelist_ptaf.txt Имя файла whitelist
MAX_CONCURRENT_WORKERS 5 Количество параллельных воркеров
CHECK_DUPLICATES true Включить проверку дублей и сводный алерт ошибок API в основном режиме

Зависимости

Пакет Назначение
github.com/lib/pq PostgreSQL драйвер
github.com/joho/godotenv Загрузка .env файла
golang.org/x/net SOCKS5 прокси для Telegram
net/smtp Отправка email (стандартная библиотека)
crypto/tls TLS для SMTP с отключённой проверкой сертификата