fix(notify): отправка во все каналы NOTIFY_ORDER, не только первый успех
- BACKUP_WEBHOOK только если все каналы неуспешны - README/conf.example; версия 0.9.5.3
This commit is contained in:
@@ -14,14 +14,14 @@ Bash-скрипт мониторинга **SSH**, **SUDO** и событий **`
|
|||||||
- для **Telegram**: `TELEGRAM_BOT_TOKEN` и `TELEGRAM_CHAT_ID`;
|
- для **Telegram**: `TELEGRAM_BOT_TOKEN` и `TELEGRAM_CHAT_ID`;
|
||||||
- или настройте **Zabbix** / **почту** по переменным ниже при `NOTIFY_ORDER=""` (автовыбор каналов).
|
- или настройте **Zabbix** / **почту** по переменным ниже при `NOTIFY_ORDER=""` (автовыбор каналов).
|
||||||
|
|
||||||
**Обязательное условие:** после загрузки конфигурации в цепочке **`NOTIFY_CHAIN`** должен быть **минимум один** канал (`telegram`, `zabbix` или `email`). Если каналов **нет** (пустой `NOTIFY_ORDER` и ни Telegram, ни Zabbix, ни SMTP не удовлетворяют критериям «настроен», либо в `NOTIFY_ORDER` остались только неизвестные имена), скрипт **не входит** в основной цикл и завершается с кодом **1**, в stderr: **`Не настроен ни один канал отправки оповещений`**. Это же правило действует для **`--check-config`** и **`--dry-run`**. Резервный **`BACKUP_WEBHOOK_URL`** в эту проверку **не входит** — он используется только когда основные каналы уже есть, но доставка через них не удалась.
|
**Обязательное условие:** после загрузки конфигурации в цепочке **`NOTIFY_CHAIN`** должен быть **минимум один** канал (`telegram`, `zabbix` или `email`). Если каналов **нет** (пустой `NOTIFY_ORDER` и ни Telegram, ни Zabbix, ни SMTP не удовлетворяют критериям «настроен», либо в `NOTIFY_ORDER` остались только неизвестные имена), скрипт **не входит** в основной цикл и завершается с кодом **1**, в stderr: **`Не настроен ни один канал отправки оповещений`**. Это же правило действует для **`--check-config`** и **`--dry-run`**. Резервный **`BACKUP_WEBHOOK_URL`** в эту проверку **не входит** — он используется только если **ни один** канал из **`NOTIFY_CHAIN`** не смог доставить сообщение.
|
||||||
|
|
||||||
Поддерживаемые параметры:
|
Поддерживаемые параметры:
|
||||||
|
|
||||||
- `TELEGRAM_BOT_TOKEN`, `TELEGRAM_CHAT_ID`
|
- `TELEGRAM_BOT_TOKEN`, `TELEGRAM_CHAT_ID`
|
||||||
- `NOTIFY_ORDER` — явная очередь каналов оповещений (`telegram`, `zabbix`, `email` и сокращения); пусто = в цепочку попадают только настроенные каналы (порядок по умолчанию см. в `ssh-monitor.conf.example`). Если итоговая цепочка пуста — скрипт не стартует (см. раздел **«Каналы оповещений и пустой NOTIFY_CHAIN»**).
|
- `NOTIFY_ORDER` — список каналов (`telegram`, `zabbix`, `email` и сокращения **tg**, **zbx**, **mail**); при каждом оповещении скрипт **пытается отправить во все перечисленные** каналы по порядку (не «первый успешный — и стоп»). Пусто = в цепочку попадают только настроенные каналы (порядок по умолчанию см. в `ssh-monitor.conf.example`). Если итоговая цепочка пуста — скрипт не стартует (см. раздел **«Каналы оповещений и пустой NOTIFY_CHAIN»**).
|
||||||
- `ZABBIX_SERVER`, `ZABBIX_HOST_NAME`, `ZABBIX_ALERT_KEY`, `ZABBIX_SEQ_KEY` — отправка в Zabbix через `zabbix_sender`; подробнее — раздел **«Zabbix (`zabbix_sender`)»** ниже
|
- `ZABBIX_SERVER`, `ZABBIX_HOST_NAME`, `ZABBIX_ALERT_KEY`, `ZABBIX_SEQ_KEY` — отправка в Zabbix через `zabbix_sender`; подробнее — раздел **«Zabbix (`zabbix_sender`)»** ниже
|
||||||
- `BACKUP_WEBHOOK_URL` — резервная доставка JSON `{"text":"..."}` (например Slack Incoming Webhook), если каналы из **`NOTIFY_CHAIN`** недоступны или вернули ошибку; **не заменяет** обязательность хотя бы одного основного канала (см. шаг 3)
|
- `BACKUP_WEBHOOK_URL` — резервная доставка JSON `{"text":"..."}` (например Slack Incoming Webhook), если **все** каналы из **`NOTIFY_CHAIN`** не смогли доставить сообщение; **не заменяет** обязательность хотя бы одного основного канала (см. шаг 3)
|
||||||
- `LOG_FILE`, `LAST_HEARTBEAT_FILE`, `LAST_REPORT_FILE`, `LAST_SSH_CHECK_FILE`, `LAST_SUDO_CHECK_FILE`, `LAST_SECURITY_EVENTS_FILE`, `LAST_LOGIND_CHECK_FILE`, `BAN_LIST_FILE`
|
- `LOG_FILE`, `LAST_HEARTBEAT_FILE`, `LAST_REPORT_FILE`, `LAST_SSH_CHECK_FILE`, `LAST_SUDO_CHECK_FILE`, `LAST_SECURITY_EVENTS_FILE`, `LAST_LOGIND_CHECK_FILE`, `BAN_LIST_FILE`
|
||||||
- `ENABLE_LOGIND_MONITOR`, `LOGIND_NOTIFY_NEW`, `LOGIND_NOTIFY_REMOVED`, `LOGIND_NOTIFY_FAILED`, `LOGIND_SKIP_REMOTE` — см. раздел «Мониторинг systemd-logind» ниже
|
- `ENABLE_LOGIND_MONITOR`, `LOGIND_NOTIFY_NEW`, `LOGIND_NOTIFY_REMOVED`, `LOGIND_NOTIFY_FAILED`, `LOGIND_SKIP_REMOTE` — см. раздел «Мониторинг systemd-logind» ниже
|
||||||
- `DAILY_REPORT_HOUR` (0..23), `DAILY_REPORT_TZ` (опционально), `NOTIFY_TZ` (опционально), `SSH_ACCEPT_NOTIFY_DEDUP_SEC`, `DAILY_REPORT_TOP_IPS`
|
- `DAILY_REPORT_HOUR` (0..23), `DAILY_REPORT_TZ` (опционально), `NOTIFY_TZ` (опционально), `SSH_ACCEPT_NOTIFY_DEDUP_SEC`, `DAILY_REPORT_TOP_IPS`
|
||||||
@@ -38,7 +38,7 @@ Bash-скрипт мониторинга **SSH**, **SUDO** и событий **`
|
|||||||
|
|
||||||
- `TELEGRAM_BOT_TOKEN` — токен Telegram-бота для отправки уведомлений.
|
- `TELEGRAM_BOT_TOKEN` — токен Telegram-бота для отправки уведомлений.
|
||||||
- `TELEGRAM_CHAT_ID` — ID чата/пользователя, куда отправляются уведомления.
|
- `TELEGRAM_CHAT_ID` — ID чата/пользователя, куда отправляются уведомления.
|
||||||
- `NOTIFY_ORDER` — CSV имён каналов (`telegram`, `zabbix`, `email` или `tg`, `zbx`, `mail`). Пустая строка: автоматически собирается цепочка только из реально настроенных каналов (по умолчанию порядок telegram → zabbix → email; критерии «настроен» — **таблица** в разделе **«Каналы оповещений и пустой NOTIFY_CHAIN»**). Если после сборки цепочки **нет ни одного** канала, скрипт **сразу завершается** с ошибкой: **«Не настроен ни один канал отправки оповещений»** (в том числе режим `--check-config` и `--dry-run`).
|
- `NOTIFY_ORDER` — CSV имён каналов (`telegram`, `zabbix`, `email` или `tg`, `zbx`, `mail`). Для **каждого** оповещения выполняется попытка доставки **во все** перечисленные каналы (при ошибке одного остальные всё равно пробуются; неудачи пишутся в **`LOG_FILE`**). Пустая строка: автоматически собирается цепочка только из реально настроенных каналов (по умолчанию порядок telegram → zabbix → email; критерии «настроен» — **таблица** в разделе **«Каналы оповещений и пустой NOTIFY_CHAIN»**). Если после сборки цепочки **нет ни одного** канала, скрипт **сразу завершается** с ошибкой: **«Не настроен ни один канал отправки оповещений»** (в том числе режим `--check-config` и `--dry-run`).
|
||||||
- `ZABBIX_SERVER` — имя или IP сервера Zabbix для `zabbix_sender -z` (пусто = канал Zabbix отключён).
|
- `ZABBIX_SERVER` — имя или IP сервера Zabbix для `zabbix_sender -z` (пусто = канал Zabbix отключён).
|
||||||
- `ZABBIX_HOST_NAME` — имя **хоста в Zabbix**, как в конфигурации агента/шаблона (`-s` у `zabbix_sender`); должно совпадать с тем, для какого хоста созданы trapper-элементы.
|
- `ZABBIX_HOST_NAME` — имя **хоста в Zabbix**, как в конфигурации агента/шаблона (`-s` у `zabbix_sender`); должно совпадать с тем, для какого хоста созданы trapper-элементы.
|
||||||
- `ZABBIX_ALERT_KEY` — ключ **первого** trapper-элемента: в него уходит **текст** оповещения (одна строка, переводы строк заменены пробелами).
|
- `ZABBIX_ALERT_KEY` — ключ **первого** trapper-элемента: в него уходит **текст** оповещения (одна строка, переводы строк заменены пробелами).
|
||||||
|
|||||||
+22
-11
@@ -7,7 +7,7 @@ IFS=$'\n\t'
|
|||||||
# ============================================
|
# ============================================
|
||||||
|
|
||||||
CONFIG_FILE="/etc/ssh-monitor.conf"
|
CONFIG_FILE="/etc/ssh-monitor.conf"
|
||||||
SSH_MONITOR_VERSION="0.9.5.2"
|
SSH_MONITOR_VERSION="0.9.5.3"
|
||||||
|
|
||||||
TELEGRAM_BOT_TOKEN=""
|
TELEGRAM_BOT_TOKEN=""
|
||||||
TELEGRAM_CHAT_ID=""
|
TELEGRAM_CHAT_ID=""
|
||||||
@@ -291,7 +291,7 @@ is_email_configured() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
# Заполняет NOTIFY_CHAIN: при пустом NOTIFY_ORDER — только реально настроенные каналы (telegram → zabbix → email).
|
# Заполняет NOTIFY_CHAIN: при пустом NOTIFY_ORDER — только реально настроенные каналы (telegram → zabbix → email).
|
||||||
# При непустом NOTIFY_ORDER — ровно указанная очередь (имена каналов), без добавления «лишних».
|
# При непустом NOTIFY_ORDER — ровно указанный список (имена каналов), без добавления «лишних»; notify_send шлёт во ВСЕ каналы из списка.
|
||||||
refresh_notify_chain() {
|
refresh_notify_chain() {
|
||||||
NOTIFY_CHAIN=()
|
NOTIFY_CHAIN=()
|
||||||
local order_raw
|
local order_raw
|
||||||
@@ -470,7 +470,7 @@ write_log() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
# ============================================
|
# ============================================
|
||||||
# УВЕДОМЛЕНИЯ: telegram / zabbix / email (каскад по NOTIFY_CHAIN)
|
# УВЕДОМЛЕНИЯ: telegram / zabbix / email — по NOTIFY_CHAIN во все перечисленные каналы; BACKUP_WEBHOOK только если все неуспешны.
|
||||||
# ============================================
|
# ============================================
|
||||||
|
|
||||||
send_email_raw() {
|
send_email_raw() {
|
||||||
@@ -638,33 +638,44 @@ notify_send() {
|
|||||||
return 0
|
return 0
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
local any_ok=0
|
||||||
local ch
|
local ch
|
||||||
for ch in "${NOTIFY_CHAIN[@]}"; do
|
for ch in "${NOTIFY_CHAIN[@]}"; do
|
||||||
case "$ch" in
|
case "$ch" in
|
||||||
telegram)
|
telegram)
|
||||||
if send_telegram_raw "$message"; then
|
if send_telegram_raw "$message"; then
|
||||||
return 0
|
any_ok=1
|
||||||
|
else
|
||||||
|
write_log "WARN: канал telegram: не удалось отправить уведомление"
|
||||||
fi
|
fi
|
||||||
;;
|
;;
|
||||||
zabbix)
|
zabbix)
|
||||||
if send_zabbix_trapper "$message"; then
|
if send_zabbix_trapper "$message"; then
|
||||||
return 0
|
any_ok=1
|
||||||
|
else
|
||||||
|
write_log "WARN: канал zabbix: не удалось отправить (zabbix_sender, сеть, имя хоста/ключи в Zabbix)"
|
||||||
fi
|
fi
|
||||||
;;
|
;;
|
||||||
email)
|
email)
|
||||||
if send_email_raw "$message"; then
|
if send_email_raw "$message"; then
|
||||||
return 0
|
any_ok=1
|
||||||
|
else
|
||||||
|
write_log "WARN: канал email: не удалось отправить уведомление"
|
||||||
fi
|
fi
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
done
|
done
|
||||||
|
|
||||||
if send_backup_webhook_raw "$message"; then
|
if [ "$any_ok" -eq 1 ]; then
|
||||||
write_log "WARN: основные каналы недоступны, сообщение ушло в BACKUP_WEBHOOK_URL"
|
|
||||||
return 0
|
return 0
|
||||||
fi
|
fi
|
||||||
|
|
||||||
write_log "WARN: не удалось доставить уведомление (каналы: $(notify_chain_human); BACKUP_WEBHOOK не задан или недоступен)"
|
if send_backup_webhook_raw "$message"; then
|
||||||
|
write_log "WARN: все каналы из NOTIFY_CHAIN недоступны, сообщение ушло в BACKUP_WEBHOOK_URL"
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
write_log "WARN: не удалось доставить уведомление ни в один канал ($(notify_chain_human); BACKUP_WEBHOOK не задан или недоступен)"
|
||||||
return 1
|
return 1
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1620,7 +1631,7 @@ send_startup_notification() {
|
|||||||
message="${message}🚫 Автоблокировка IP после ${MAX_ATTEMPTS} попыток на ${BAN_TIME} секунд"$'\n'
|
message="${message}🚫 Автоблокировка IP после ${MAX_ATTEMPTS} попыток на ${BAN_TIME} секунд"$'\n'
|
||||||
message="${message}⚪ Белый список: ${whitelist_count} IP/подсетей"$'\n'
|
message="${message}⚪ Белый список: ${whitelist_count} IP/подсетей"$'\n'
|
||||||
message="${message}❤️ Heartbeat будет отправляться каждые 12 часов"$'\n'
|
message="${message}❤️ Heartbeat будет отправляться каждые 12 часов"$'\n'
|
||||||
message="${message}📢 Каналы уведомлений (каскад): $(notify_chain_human)"
|
message="${message}📢 Каналы уведомлений (все по списку): $(notify_chain_human)"
|
||||||
|
|
||||||
notify_send "$message"
|
notify_send "$message"
|
||||||
write_log "Скрипт мониторинга запущен (белый список: $whitelist_count записей)"
|
write_log "Скрипт мониторинга запущен (белый список: $whitelist_count записей)"
|
||||||
@@ -1678,7 +1689,7 @@ run_check_config() {
|
|||||||
printf 'Проверка конфигурации ssh-monitor\n'
|
printf 'Проверка конфигурации ssh-monitor\n'
|
||||||
printf 'SSH_MONITOR_VERSION=%s\n' "${SSH_MONITOR_VERSION:-}"
|
printf 'SSH_MONITOR_VERSION=%s\n' "${SSH_MONITOR_VERSION:-}"
|
||||||
printf 'CONFIG_FILE=%s\n' "$CONFIG_FILE"
|
printf 'CONFIG_FILE=%s\n' "$CONFIG_FILE"
|
||||||
printf 'NOTIFY_ORDER=%s (пусто = авто: только настроенные, порядок telegram,zabbix,email)\n' "${NOTIFY_ORDER:-}"
|
printf 'NOTIFY_ORDER=%s (пусто = авто: только настроенные; при событии — отправка во все каналы списка)\n' "${NOTIFY_ORDER:-}"
|
||||||
printf 'NOTIFY_CHAIN (эффективная очередь)=%s\n' "$(notify_chain_human)"
|
printf 'NOTIFY_CHAIN (эффективная очередь)=%s\n' "$(notify_chain_human)"
|
||||||
printf 'TELEGRAM: %s\n' "$([ -n "$TELEGRAM_BOT_TOKEN" ] && echo настроен || echo НЕ настроен)"
|
printf 'TELEGRAM: %s\n' "$([ -n "$TELEGRAM_BOT_TOKEN" ] && echo настроен || echo НЕ настроен)"
|
||||||
printf 'BACKUP_WEBHOOK_URL: %s\n' "$([ -n "${BACKUP_WEBHOOK_URL:-}" ] && echo настроен || echo не задан)"
|
printf 'BACKUP_WEBHOOK_URL: %s\n' "$([ -n "${BACKUP_WEBHOOK_URL:-}" ] && echo настроен || echo не задан)"
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
TELEGRAM_BOT_TOKEN="replace_with_telegram_bot_token"
|
TELEGRAM_BOT_TOKEN="replace_with_telegram_bot_token"
|
||||||
TELEGRAM_CHAT_ID="replace_with_telegram_chat_id"
|
TELEGRAM_CHAT_ID="replace_with_telegram_chat_id"
|
||||||
|
|
||||||
# Резервный webhook, если все каналы из NOTIFY_CHAIN недоступны (JSON {"text":"..."}).
|
# Резервный webhook, если ВСЕ каналы из NOTIFY_CHAIN не смогли доставить сообщение (JSON {"text":"..."}).
|
||||||
# ВАЖНО: BACKUP_WEBHOOK_URL НЕ заменяет основной канал — без хотя бы одного из telegram/zabbix/email
|
# ВАЖНО: BACKUP_WEBHOOK_URL НЕ заменяет основной канал — без хотя бы одного из telegram/zabbix/email
|
||||||
# скрипт сразу завершится с ошибкой в stderr: «Не настроен ни один канал отправки оповещений» (код 1),
|
# скрипт сразу завершится с ошибкой в stderr: «Не настроен ни один канал отправки оповещений» (код 1),
|
||||||
# в том числе при --check-config и --dry-run. Сначала настройте Telegram, Zabbix или SMTP ниже.
|
# в том числе при --check-config и --dry-run. Сначала настройте Telegram, Zabbix или SMTP ниже.
|
||||||
@@ -9,6 +9,8 @@ BACKUP_WEBHOOK_URL=""
|
|||||||
|
|
||||||
# --- Очередь оповещений (NOTIFY_ORDER) ---
|
# --- Очередь оповещений (NOTIFY_ORDER) ---
|
||||||
# CSV: telegram, zabbix, email (или сокращения tg, zbx, mail).
|
# CSV: telegram, zabbix, email (или сокращения tg, zbx, mail).
|
||||||
|
# При каждом событии скрипт ПЫТАЕТСЯ ОТПРАВИТЬ ВО ВСЕ перечисленные каналы по порядку (не только в первый успешный).
|
||||||
|
# Неудача одного канала не отменяет отправку в остальные; подробности — в LOG_FILE (WARN по каналам).
|
||||||
#
|
#
|
||||||
# Пустая строка NOTIFY_ORDER="" = авто: в цепочку NOTIFY_CHAIN попадают ТОЛЬКО реально настроенные каналы,
|
# Пустая строка NOTIFY_ORDER="" = авто: в цепочку NOTIFY_CHAIN попадают ТОЛЬКО реально настроенные каналы,
|
||||||
# порядок по умолчанию: telegram → zabbix → email (см. критерии «настроен» в README, раздел про каналы).
|
# порядок по умолчанию: telegram → zabbix → email (см. критерии «настроен» в README, раздел про каналы).
|
||||||
|
|||||||
Reference in New Issue
Block a user