feat: unify daily SSH report format with SAC; DAILY_REPORT_ENABLED toggle
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
+38
-18
@@ -52,6 +52,7 @@ MAIL_SMTP_SSL="0"
|
||||
LOG_FILE="/var/log/ssh_monitor.log"
|
||||
LAST_HEARTBEAT_FILE="/var/log/last_heartbeat.txt"
|
||||
LAST_REPORT_FILE="/var/log/last_daily_report.txt"
|
||||
DAILY_REPORT_ENABLED=1
|
||||
DAILY_REPORT_HOUR=9
|
||||
DAILY_REPORT_TOP_IPS=5
|
||||
# Пусто = календарь и час отчёта в зоне процесса (как `date`, обычно совпадает с /etc/localtime).
|
||||
@@ -183,6 +184,7 @@ load_config() {
|
||||
local cfg_log_file="${LOG_FILE}"
|
||||
local cfg_last_heartbeat_file="${LAST_HEARTBEAT_FILE}"
|
||||
local cfg_last_report_file="${LAST_REPORT_FILE}"
|
||||
local cfg_daily_report_enabled="${DAILY_REPORT_ENABLED:-1}"
|
||||
local cfg_daily_report_hour="${DAILY_REPORT_HOUR}"
|
||||
local cfg_daily_report_top_ips="${DAILY_REPORT_TOP_IPS}"
|
||||
local cfg_daily_report_tz="${DAILY_REPORT_TZ}"
|
||||
@@ -258,6 +260,7 @@ load_config() {
|
||||
IPSET_NAME_V6="${IPSET_NAME_V6:-$cfg_ipset_name_v6}"
|
||||
IPSET_MAXELEM="${IPSET_MAXELEM:-$cfg_ipset_maxelem}"
|
||||
|
||||
DAILY_REPORT_ENABLED="$(trim_value "${DAILY_REPORT_ENABLED:-$cfg_daily_report_enabled}")"
|
||||
DAILY_REPORT_HOUR="${DAILY_REPORT_HOUR:-$cfg_daily_report_hour}"
|
||||
DAILY_REPORT_TOP_IPS="${DAILY_REPORT_TOP_IPS:-$cfg_daily_report_top_ips}"
|
||||
DAILY_REPORT_TZ="$(trim_value "${DAILY_REPORT_TZ:-$cfg_daily_report_tz}")"
|
||||
@@ -1732,30 +1735,35 @@ send_daily_report() {
|
||||
ban_line="🚫 Автобан IP: отключён (ENABLE_IP_BAN=0)"
|
||||
fi
|
||||
|
||||
local message=" 📊 ЕЖЕДНЕВНЫЙ ОТЧЕТ SSH МОНИТОРИНГА "$'\n'
|
||||
message="${message}🕐 Время отчета: ${current_time}"$'\n'
|
||||
message="${message}"$'\n'
|
||||
message="${message} 📈 СТАТИСТИКА ЗА ПОСЛЕДНИЕ 24 ЧАСА: "$'\n'
|
||||
message="${message} ✅ Успешных SSH подключений: ${successful_logins:-0}"$'\n'
|
||||
message="${message} ❌ Неудачных попыток SSH: ${failed_logins:-0}"$'\n'
|
||||
message="${message} ⚠️ Команд через sudo: ${sudo_commands:-0}"$'\n'
|
||||
message="${message} ${ban_line}"$'\n'
|
||||
message="${message}"$'\n'
|
||||
message="${message} 🧾 ТОП-${DAILY_REPORT_TOP_IPS} IP ПО НЕУДАЧНЫМ ПОПЫТКАМ:"$'\n'
|
||||
local message=""
|
||||
message+="📊 ЕЖЕДНЕВНЫЙ ОТЧЕТ SSH МОНИТОРИНГА"$'\n'
|
||||
message+="🖥️ Сервер: $(server_display_name_with_ip)"$'\n'
|
||||
message+="🕐 Время отчета: ${current_time}"$'\n'
|
||||
message+=""$'\n'
|
||||
message+="📈 СТАТИСТИКА ЗА ПОСЛЕДНИЕ 24 ЧАСА:"$'\n'
|
||||
message+=" ✅ Успешных SSH подключений: ${successful_logins:-0}"$'\n'
|
||||
message+=" ❌ Неудачных попыток SSH: ${failed_logins:-0}"$'\n'
|
||||
message+=" ⚠️ Команд через sudo: ${sudo_commands:-0}"$'\n'
|
||||
message+=" ${ban_line}"$'\n'
|
||||
message+=""$'\n'
|
||||
message+="🧾 ТОП-${DAILY_REPORT_TOP_IPS:-5} IP ПО НЕУДАЧНЫМ ПОПЫТКАМ:"$'\n'
|
||||
if [ -n "$top_lines" ]; then
|
||||
message="${message}${top_lines}"$'\n'
|
||||
message+="${top_lines}"$'\n'
|
||||
else
|
||||
message="${message} (нет данных)"$'\n'
|
||||
message+=" (нет данных)"$'\n'
|
||||
fi
|
||||
message="${message}"$'\n'
|
||||
message="${message} 👥 АКТИВНЫЕ ПОЛЬЗОВАТЕЛИ (${active_count}):"$'\n'
|
||||
message+=""$'\n'
|
||||
message+="👥 АКТИВНЫЕ ПОЛЬЗОВАТЕЛИ (${active_count}):"$'\n'
|
||||
|
||||
if [ -n "$active_sessions" ]; then
|
||||
message="${message}${active_sessions}"$'\n'
|
||||
message+="${active_sessions}"$'\n'
|
||||
else
|
||||
message="${message} Нет активных пользователей"$'\n'
|
||||
message+=" (нет данных)"$'\n'
|
||||
fi
|
||||
|
||||
local active_users_json
|
||||
active_users_json="$(printf '%s' "$active_sessions" | python3 -c 'import json,sys; print(json.dumps([l.strip() for l in sys.stdin.read().splitlines() if l.strip()]))' 2>/dev/null || echo '[]')"
|
||||
|
||||
local sac_summary sac_details_json
|
||||
sac_summary="SSH 24ч: успех ${successful_logins:-0}, неудач ${failed_logins:-0}, sudo ${sudo_commands:-0}"
|
||||
sac_details_json="$(
|
||||
@@ -1765,18 +1773,27 @@ send_daily_report() {
|
||||
SAC_SUDO="${sudo_commands:-0}" \
|
||||
SAC_BANS="${active_bans:-0}" \
|
||||
SAC_ACTIVE="${active_count:-0}" \
|
||||
SAC_ACTIVE_USERS="$active_users_json" \
|
||||
python3 <<'PY'
|
||||
import html
|
||||
import json
|
||||
import os
|
||||
|
||||
body = os.environ.get("SAC_REPORT_BODY", "")
|
||||
active_users = json.loads(os.environ.get("SAC_ACTIVE_USERS", "[]") or "[]")
|
||||
ok = int(os.environ.get("SAC_OK", "0") or 0)
|
||||
fail = int(os.environ.get("SAC_FAIL", "0") or 0)
|
||||
stats = {
|
||||
"successful_ssh": int(os.environ.get("SAC_OK", "0") or 0),
|
||||
"failed_ssh": int(os.environ.get("SAC_FAIL", "0") or 0),
|
||||
"platform": "ssh",
|
||||
"successful_logins": ok,
|
||||
"failed_logins": fail,
|
||||
"successful_ssh": ok,
|
||||
"failed_ssh": fail,
|
||||
"sudo_commands": int(os.environ.get("SAC_SUDO", "0") or 0),
|
||||
"active_bans": int(os.environ.get("SAC_BANS", "0") or 0),
|
||||
"active_sessions": int(os.environ.get("SAC_ACTIVE", "0") or 0),
|
||||
"active_users": active_users,
|
||||
"generated_by": "agent",
|
||||
}
|
||||
escaped = html.escape(body)
|
||||
report_html = '<div class="agent-report">' + escaped.replace("\n", "<br>\n") + "</div>"
|
||||
@@ -1819,6 +1836,9 @@ read_last_report_date() {
|
||||
}
|
||||
|
||||
check_daily_report() {
|
||||
if [ "${DAILY_REPORT_ENABLED:-1}" != "1" ]; then
|
||||
return 0
|
||||
fi
|
||||
local today
|
||||
today=$(report_date '+%F')
|
||||
local last_date
|
||||
|
||||
Reference in New Issue
Block a user