18 KiB
Executable file
Архитектура 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() — возвращает читаемое название вендора: ptaf → PT AF, sw → SW, wmx → WMX.
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() — единая точка отправки алертов. Последовательно отправляет сообщение во все настроенные каналы. Ошибка одного канала не блокирует остальные.
Telegram — buildTelegramClient() при каждой отправке выбирает транспорт в порядке приоритета:
- HTTP-прокси (
TELEGRAM_HTTP_PROXY) — если задан и доступен - SOCKS5-прокси (
TELEGRAM_SOCKS5_PROXY) — если задан и доступен - Прямое подключение — 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:
- Синхронизирует Git-репозиторий
- Загружает WAF-сети из таблицы
ips - Загружает origin IP из
API_info(loadAllOrigins) иmanual_info(loadManualOrigins), объединяет и дедуплицирует - Фильтрует IP попадающие в WAF-сети (
filterNonWAFOrigins) - Сравнивает с текущим содержимым файла (
compareWhitelists) - При наличии изменений — перезаписывает файл, коммитит и пушит, отправляет алерт
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 с отключённой проверкой сертификата |