fix: suppress sudo Telegram during SAC agent update (v0.5.3)

This commit is contained in:
PTah
2026-07-08 12:23:29 +10:00
parent f569293d52
commit 253b80c500
4 changed files with 52 additions and 6 deletions
+37 -2
View File
@@ -15,6 +15,14 @@ from app.services.notification_severity import severity_meets_minimum
logger = logging.getLogger(__name__)
LIFECYCLE_EVENT_TYPE = "agent.lifecycle"
PRIVILEGE_SUDO_TYPE = "privilege.sudo.command"
SUDO_MAINTENANCE_MARKERS = (
"update_ssh_monitor.sh",
"update_via_sac",
"update_script.log",
"/opt/scripts/update",
"agent-update-in-progress",
)
DAILY_REPORT_EVENT_TYPES = frozenset({"report.daily.ssh", "report.daily.rdp"})
AUTH_LOGIN_SUCCESS_TYPES = frozenset({"rdp.login.success", "ssh.login.success"})
RDG_CONNECTION_TYPES = frozenset({
@@ -67,6 +75,8 @@ def notify_event(event: Event, *, db: Session | None = None) -> None:
# Heartbeat — только для UI/статуса хоста, не для Telegram/email/push.
if event.type == HEARTBEAT_TYPE:
return
if _should_suppress_sudo_notify(event, db=db):
return
if _skip_notifications_for_hidden_event(event, db):
return
policy = get_effective_notification_policy(db)
@@ -112,7 +122,7 @@ def notify_daily_report(event: Event, *, db: Session | None = None) -> None:
def _host_sac_update_running(event: Event, db: Session | None) -> bool:
"""Пока SAC выполняет agent-update на хосте — не слать lifecycle в Telegram."""
"""Пока SAC выполняет agent-update на хосте — не слать шумные TG."""
if db is None or not event.host_id:
return False
host = db.get(Host, event.host_id)
@@ -120,7 +130,8 @@ def _host_sac_update_running(event: Event, db: Session | None) -> bool:
return False
if (host.agent_update_state or "").strip().lower() == "running":
logger.info(
"notify lifecycle skipped host update running host_id=%s event_id=%s",
"notify skipped (host update running) type=%s host_id=%s event_id=%s",
event.type,
host.id,
event.event_id,
)
@@ -128,6 +139,30 @@ def _host_sac_update_running(event: Event, db: Session | None) -> bool:
return False
def _sudo_event_is_agent_maintenance(event: Event) -> bool:
details = event.details if isinstance(event.details, dict) else {}
cmd = str(details.get("command") or "").strip()
if not cmd:
cmd = str(event.summary or "").strip()
text = cmd.casefold()
return any(marker in text for marker in SUDO_MAINTENANCE_MARKERS)
def _should_suppress_sudo_notify(event: Event, *, db: Session | None) -> bool:
if event.type != PRIVILEGE_SUDO_TYPE:
return False
if _host_sac_update_running(event, db):
return True
if _sudo_event_is_agent_maintenance(event):
logger.info(
"notify sudo skipped maintenance command event_id=%s host_id=%s",
event.event_id,
event.host_id,
)
return True
return False
def _lifecycle_suppress_notifications(event: Event, *, db: Session | None = None) -> bool:
"""Не слать TG при штатном SAC/cron update (lifecycle с trigger deploy_recycle)."""
if _host_sac_update_running(event, db):
+12 -2
View File
@@ -9,6 +9,7 @@ from dataclasses import dataclass
from app.config import get_settings
from app.models import Host
SSH_MONITOR_UPDATE_STATE_FILE = "/var/lib/ssh-monitor/agent-update-in-progress"
SSH_MONITOR_UPDATE_LOG_PATH = "/var/log/update_script.log"
SSH_MONITOR_UPDATE_SCRIPT = "/opt/scripts/update_ssh_monitor.sh"
SSH_MONITOR_UPDATE_DIR = "/opt/scripts/update"
@@ -454,6 +455,15 @@ def _ssh_monitor_bootstrap_command(repo_url: str, *, git_branch: str = "main") -
)
def _ssh_monitor_mark_update_begin_prefix() -> str:
"""State-file до updater: lifecycle/sudo на агенте глушатся раньше bootstrap."""
return (
f"mkdir -p /var/lib/ssh-monitor && "
f"date +%s > {SSH_MONITOR_UPDATE_STATE_FILE} && "
f"chmod 600 {SSH_MONITOR_UPDATE_STATE_FILE} 2>/dev/null; "
)
def run_ssh_monitor_update(
*,
target: str,
@@ -498,7 +508,7 @@ def run_ssh_monitor_update(
target=target,
user=user,
password=password,
remote_cmd=bootstrap_cmd,
remote_cmd=_ssh_monitor_mark_update_begin_prefix() + bootstrap_cmd,
command_timeout_sec=900,
need_root=True,
login_shell=False,
@@ -509,7 +519,7 @@ def run_ssh_monitor_update(
target=target,
user=user,
password=password,
remote_cmd=update_cmd,
remote_cmd=_ssh_monitor_mark_update_begin_prefix() + update_cmd,
command_timeout_sec=900,
need_root=True,
login_shell=False,
+1 -1
View File
@@ -1,5 +1,5 @@
"""Единый источник версии SAC (API, health, логи, OpenAPI)."""
APP_NAME = "Security Alert Center"
APP_VERSION = "0.5.2"
APP_VERSION = "0.5.3"
APP_VERSION_LABEL = f"{APP_NAME} v.{APP_VERSION}"