feat: merge missing SAC keys into config on deploy (2.1.2-SAC)

Append absent SAC variables from example instead of overwriting ssh-monitor.conf; set UseSAC=fallback on install and update.
This commit is contained in:
PTah
2026-06-21 12:20:33 +10:00
parent 65da13363d
commit 1361fd264c
4 changed files with 116 additions and 70 deletions
+3 -1
View File
@@ -1,6 +1,8 @@
# Автообновление ssh-monitor # Автообновление ssh-monitor
Скрипт **`update_ssh_monitor.sh`** в корне репозитория обновляет установленный **`/usr/local/bin/ssh-monitor`** из git-репозитория и перезапускает systemd-сервис. Конфиг **`/etc/ssh-monitor.conf`**, watchdog и таймеры **не изменяются**. Скрипт **`update_ssh_monitor.sh`** в корне репозитория обновляет установленный **`/usr/local/bin/ssh-monitor`** из git-репозитория и перезапускает systemd-сервис. Watchdog и таймеры **не изменяются**.
**Конфиг `/etc/ssh-monitor.conf`:** при первой установке копируется из `ssh-monitor.conf.example`. При каждом deploy/обновлении в **существующий** конфиг **дописываются** отсутствующие SAC-переменные (`UseSAC`, `SAC_URL`, `SAC_API_KEY`, spool, timeout и т.д.) и выставляется **`UseSAC=fallback`**. Telegram/SMTP и прочие ключи **не перезаписываются**.
Установка самого монитора и unit-файлов: [README.md](../README.md), зависимости: [install-prerequisites.ru.md](install-prerequisites.ru.md). Установка самого монитора и unit-файлов: [README.md](../README.md), зависимости: [install-prerequisites.ru.md](install-prerequisites.ru.md).
+1 -1
View File
@@ -7,7 +7,7 @@ IFS=$'\n\t'
# ============================================ # ============================================
CONFIG_FILE="/etc/ssh-monitor.conf" CONFIG_FILE="/etc/ssh-monitor.conf"
SSH_MONITOR_VERSION="2.1.1-SAC" SSH_MONITOR_VERSION="2.1.2-SAC"
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
if [ -f "$SCRIPT_DIR/sac-client.sh" ]; then if [ -f "$SCRIPT_DIR/sac-client.sh" ]; then
+108 -64
View File
@@ -74,11 +74,24 @@ update_ssh_monitor.sh — обновление или первичная уст
Лог действий: /var/log/update_script.log (в конце каждого прогона — блок «Итог обновления»). Лог действий: /var/log/update_script.log (в конце каждого прогона — блок «Итог обновления»).
При первой установке или апгрейде с UseSAC=off / пустым SAC_API_KEY / без sac-client.sh При первой установке создаётся /etc/ssh-monitor.conf из example.
example из git перезаписывает /etc/ssh-monitor.conf (старый файл — .bak.*). При обновлении в существующий конфиг дописываются отсутствующие SAC-переменные
и выставляется UseSAC=fallback (Telegram/SMTP не перезаписываются).
EOF EOF
} }
# Ключи SAC: дописываются из ssh-monitor.conf.example, если отсутствуют в /etc.
SAC_CONFIG_KEYS=(
UseSAC
SAC_URL
SAC_API_KEY
SAC_SPOOL_DIR
SAC_FAIL_COUNT_FILE
SAC_FALLBACK_FAILURES
SAC_TIMEOUT_SEC
)
SAC_USE_MODE_DEFAULT="fallback"
find_ssh_monitor_conf_example() { find_ssh_monitor_conf_example() {
local example="$UPDATE_DIR/$SCRIPT_NAME/ssh-monitor.conf.example" local example="$UPDATE_DIR/$SCRIPT_NAME/ssh-monitor.conf.example"
if [ -f "$example" ]; then if [ -f "$example" ]; then
@@ -102,28 +115,20 @@ config_conf_value() {
printf '%s\n' "$val" printf '%s\n' "$val"
} }
config_needs_sac_bootstrap() { config_example_value() {
local sac_client use_sac api_key local key="$1" example="$2"
config_conf_value "$key" "$example" 2>/dev/null || true
sac_client="${LOCAL_SCRIPT_PATH%/*}/sac-client.sh"
if [ ! -f "$sac_client" ]; then
return 0
fi
if [ ! -f "$CONFIG_FILE" ]; then
return 0
fi
use_sac=$(config_conf_value "UseSAC" "$CONFIG_FILE" 2>/dev/null || true)
api_key=$(config_conf_value "SAC_API_KEY" "$CONFIG_FILE" 2>/dev/null || true)
if [ -n "$use_sac" ] && [ "$use_sac" != "off" ] \
&& [ -n "$api_key" ] && [ "${api_key#sac_}" != "$api_key" ]; then
return 1
fi
return 0
} }
ensure_ssh_monitor_config_from_example() { backup_config_if_needed() {
local file="$1" flag_var="$2"
if [ -z "${!flag_var:-}" ] || [ "${!flag_var}" -eq 0 ]; then
cp "$file" "${file}.bak.$(date +%Y%m%d_%H%M%S)" 2>/dev/null || true
printf -v "$flag_var" '%s' 1
fi
}
ensure_ssh_monitor_config_file() {
local example local example
CONFIG_CHANGED=0 CONFIG_CHANGED=0
@@ -132,27 +137,17 @@ ensure_ssh_monitor_config_from_example() {
return 0 return 0
} }
if [ -f "$CONFIG_FILE" ] && ! config_needs_sac_bootstrap; then if [ -f "$CONFIG_FILE" ]; then
log_message "INFO" "Config $CONFIG_FILE: SAC already configured, not overwriting."
if [ "$DEPLOY_MODE" -eq 1 ]; then if [ "$DEPLOY_MODE" -eq 1 ]; then
say_info "Уже существует: $CONFIG_FILE (SAC настроен, не перезаписываем)" say_info "Уже существует: $CONFIG_FILE (дополним SAC-переменные при необходимости)"
fi fi
return 0 return 0
fi fi
if [ -f "$CONFIG_FILE" ]; then
cp "$CONFIG_FILE" "${CONFIG_FILE}.bak.$(date +%Y%m%d_%H%M%S)" 2>/dev/null || true
log_message "INFO" "Upgrading config without SAC: backup created, applying ssh-monitor.conf.example from git."
if [ "$DEPLOY_MODE" -eq 1 ]; then
say_info "Апгрейд без SAC: резервная копия, применяем example (Telegram + fallback)."
fi
else
log_message "INFO" "Creating $CONFIG_FILE from ssh-monitor.conf.example" log_message "INFO" "Creating $CONFIG_FILE from ssh-monitor.conf.example"
if [ "$DEPLOY_MODE" -eq 1 ]; then if [ "$DEPLOY_MODE" -eq 1 ]; then
say_ok "Создан $CONFIG_FILE из ssh-monitor.conf.example" say_ok "Создан $CONFIG_FILE из ssh-monitor.conf.example"
fi fi
fi
if ! cp "$example" "$CONFIG_FILE"; then if ! cp "$example" "$CONFIG_FILE"; then
log_message "INFO" "ERROR: Failed to copy ssh-monitor.conf.example to $CONFIG_FILE" log_message "INFO" "ERROR: Failed to copy ssh-monitor.conf.example to $CONFIG_FILE"
return 1 return 1
@@ -162,6 +157,72 @@ ensure_ssh_monitor_config_from_example() {
return 0 return 0
} }
sync_sac_config_keys() {
local file="$CONFIG_FILE"
local example backed_up=0
local key val current changed=0 added=0
[ -f "$file" ] || return 1
example=$(find_ssh_monitor_conf_example) || {
log_message "INFO" "WARNING: ssh-monitor.conf.example not found; SAC merge skipped"
return 0
}
if ! config_key_exists "UseSAC" "$file"; then
backup_config_if_needed "$file" backed_up
{
printf '\n# --- Security Alert Center (SAC) ---\n'
printf '# off | exclusive | dual | fallback — см. security-alert-center docs/agent-integration.md\n'
} >>"$file"
log_message "INFO" "Config $file: добавлен блок SAC (ключи отсутствовали)."
changed=1
fi
for key in "${SAC_CONFIG_KEYS[@]}"; do
if config_key_exists "$key" "$file"; then
continue
fi
val=$(config_example_value "$key" "$example")
if [ -z "$val" ] && [ "$key" != "SAC_API_KEY" ]; then
case "$key" in
UseSAC) val="$SAC_USE_MODE_DEFAULT" ;;
SAC_SPOOL_DIR) val="$SAC_SPOOL_DIR_DEFAULT" ;;
SAC_FAIL_COUNT_FILE) val="/var/lib/ssh-monitor/sac-fail.count" ;;
SAC_FALLBACK_FAILURES) val="5" ;;
SAC_TIMEOUT_SEC) val="12" ;;
SAC_URL) val="https://sac.kalinamall.ru" ;;
esac
fi
backup_config_if_needed "$file" backed_up
set_config_kv "$key" "$val" "$file"
log_message "INFO" "Config $file: добавлен ${key}=${val:-<пусто>}"
changed=1
added=$((added + 1))
done
current=$(config_conf_value "UseSAC" "$file" 2>/dev/null || true)
if [ "$current" != "$SAC_USE_MODE_DEFAULT" ]; then
backup_config_if_needed "$file" backed_up
set_config_kv "UseSAC" "$SAC_USE_MODE_DEFAULT" "$file"
log_message "INFO" "Config $file: UseSAC ${current:-<нет>}$SAC_USE_MODE_DEFAULT (deploy policy)."
changed=1
fi
if [ "$changed" -eq 0 ]; then
return 1
fi
if [ "$DEPLOY_MODE" -eq 1 ]; then
if [ "$added" -gt 0 ]; then
say_info "SAC: добавлено ключей — $added; UseSAC=$SAC_USE_MODE_DEFAULT."
else
say_info "SAC: UseSAC=$SAC_USE_MODE_DEFAULT."
fi
fi
CONFIG_CHANGED=1
return 0
}
set_config_kv() { set_config_kv() {
local key="$1" val="$2" file="$3" local key="$1" val="$2" file="$3"
if grep -qE "^[[:space:]]*${key}=" "$file" 2>/dev/null; then if grep -qE "^[[:space:]]*${key}=" "$file" 2>/dev/null; then
@@ -247,25 +308,6 @@ sync_heartbeat_interval_config() {
return 0 return 0
} }
sync_use_sac_fallback_mode() {
local file="$CONFIG_FILE"
[ -f "$file" ] || return 1
if grep -qE '^[[:space:]]*UseSAC=[[:space:]]*["'"'"']?fallback["'"'"']?[[:space:]]*(#.*)?$' "$file" 2>/dev/null; then
return 1
fi
if ! grep -qE '^[[:space:]]*UseSAC=' "$file" 2>/dev/null; then
return 1
fi
cp "$file" "${file}.bak.$(date +%Y%m%d_%H%M%S)" 2>/dev/null || true
sed -i -E 's/^[[:space:]]*UseSAC=.*/UseSAC="fallback"/' "$file"
log_message "INFO" "Config $file: UseSAC set to fallback (deploy policy on script upgrade)."
if [ "$DEPLOY_MODE" -eq 1 ]; then
say_info "UseSAC=fallback (рабочий режим SAC + локальный fallback)."
fi
CONFIG_CHANGED=1
return 0
}
parse_command_line() { parse_command_line() {
DEPLOY_MODE=0 DEPLOY_MODE=0
while [ $# -gt 0 ]; do while [ $# -gt 0 ]; do
@@ -759,7 +801,9 @@ deploy_prepare_dirs() {
deploy_install_config() { deploy_install_config() {
say_step "Конфигурация" say_step "Конфигурация"
ensure_ssh_monitor_config_from_example || return 1 ensure_ssh_monitor_config_file || return 1
sync_sac_config_keys || true
sync_heartbeat_interval_config || true
} }
deploy_install_systemd() { deploy_install_systemd() {
@@ -1103,14 +1147,20 @@ update_script() {
fi fi
CONFIG_CHANGED=0 CONFIG_CHANGED=0
if ! ensure_ssh_monitor_config_from_example; then if ! ensure_ssh_monitor_config_file; then
log_update_summary log_update_summary
return 1 return 1
fi fi
if [ "${CONFIG_CHANGED:-0}" -eq 1 ]; then if sync_sac_config_keys; then
SUMMARY_CONFIG="обновлён из example" SUMMARY_CONFIG="SAC-ключи дополнены, UseSAC=fallback"
else else
SUMMARY_CONFIG="без изменений" SUMMARY_CONFIG="SAC без изменений"
fi
sync_heartbeat_interval_config || true
if [ "${CONFIG_CHANGED:-0}" -eq 1 ] && [ "$SUMMARY_CONFIG" = "SAC без изменений" ]; then
SUMMARY_CONFIG="heartbeat/watchdog выровнены"
elif [ "${CONFIG_CHANGED:-0}" -eq 1 ] && [ "$SUMMARY_CONFIG" != "SAC без изменений" ]; then
SUMMARY_CONFIG="${SUMMARY_CONFIG}; heartbeat при необходимости"
fi fi
if [ -n "$actual_script_path" ] && [ -f "$actual_script_path" ]; then if [ -n "$actual_script_path" ] && [ -f "$actual_script_path" ]; then
@@ -1175,12 +1225,6 @@ update_script() {
script_changed=1 script_changed=1
fi fi
if [ "$script_changed" -eq 1 ]; then
sync_use_sac_fallback_mode || true
fi
# Выравнивать интервал heartbeat при каждом deploy, даже если бинарник не менялся.
sync_heartbeat_interval_config || true
if [ "$script_changed" -eq 1 ] || [ "${SAC_CLIENT_CHANGED:-0}" -eq 1 ] || [ "${CONFIG_CHANGED:-0}" -eq 1 ]; then if [ "$script_changed" -eq 1 ] || [ "${SAC_CLIENT_CHANGED:-0}" -eq 1 ] || [ "${CONFIG_CHANGED:-0}" -eq 1 ]; then
restart_ssh_monitor_service restart_ssh_monitor_service
else else
+1 -1
View File
@@ -1 +1 @@
2.1.1-SAC 2.1.2-SAC