diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..7369e4f --- /dev/null +++ b/.gitattributes @@ -0,0 +1,4 @@ +# Агентские скрипты — LF в git и на Linux (manifest SHA256 = git blob). +ssh-monitor text eol=lf +*.sh text eol=lf +version.txt text eol=lf diff --git a/README.md b/README.md index 1e5955f..85b9622 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # ssh-monitor -**Версия:** `2.2.1-SAC` +**Версия:** `2.2.2-SAC` Bash-мониторинг **SSH**, **sudo**, **systemd-logind**: Telegram/email, бан IP (ipset), ежедневный отчёт, heartbeat. diff --git a/docs/auto-update.ru.md b/docs/auto-update.ru.md index 754db40..ef6fcdb 100644 --- a/docs/auto-update.ru.md +++ b/docs/auto-update.ru.md @@ -91,13 +91,13 @@ Updater читает **`GIT_REF`**, **`GIT_VERIFY_MODE`**, **`GIT_ALLOW_RESET`** - Файл не найден → WARN, update продолжается (или exit 1 при **`RELEASE_MANIFEST_STRICT=1`**). - Копирование **`update_ssh_monitor.sh`** в `/opt/scripts/` и re-exec — только если manifest для версии был и прошёл verify. -Генерация при релизе (после **финального** коммита кода, чтобы `git_commit` в manifest совпал с HEAD): +Генерация при релизе (хеши **из git**, как на Linux после `checkout` — не с диска Windows): ```bash -git commit -m "release: 2.2.0-SAC" -./scripts/build-release-manifest.sh 2.2.0-SAC -git add release/manifest-2.2.0-SAC.json && git commit -m "release: manifest 2.2.0-SAC" -git tag 2.2.0-SAC +git add --renormalize ssh-monitor *.sh # при смене .gitattributes +./scripts/build-release-manifest.sh 2.2.2-SAC +git add release/manifest-2.2.2-SAC.json && git commit -m "release: manifest 2.2.2-SAC" +git tag 2.2.2-SAC ``` ### Примеры для прода diff --git a/release/manifest-2.2.2-SAC.json b/release/manifest-2.2.2-SAC.json new file mode 100644 index 0000000..094675c --- /dev/null +++ b/release/manifest-2.2.2-SAC.json @@ -0,0 +1,11 @@ +{ + "version": "2.2.2-SAC", + "git_commit": "", + "files": { + "ssh-monitor": "sha256:be35da47fb1cf370628795bfdfe34195a7ba098c666bd8aa092929a168a10ef6", + "sac-client.sh": "sha256:4c481effd0e50b3db8cfa3baf3c5f228892530939df6f534a5d3d3d8a79db048", + "update_ssh_monitor.sh": "sha256:510d63b43ea02e5aaa4385bcc6c9396ad99637c377c9880125cb2168e9d422cd", + "ssh-monitor-watchdog": "sha256:41aa139cab0fb275249780953fceb3f8ebe01c49bf96f901dd3cf4d2fb3a9274", + "ssh-monitor-perms.sh": "sha256:53ebf15138d59be1610e5bc14a107b942d9a7fd039683abfd2fdd0aa0b54b933" + } +} diff --git a/scripts/build-release-manifest.sh b/scripts/build-release-manifest.sh index 70abf72..c8b8d29 100644 --- a/scripts/build-release-manifest.sh +++ b/scripts/build-release-manifest.sh @@ -1,5 +1,6 @@ #!/bin/bash # Генерация release/manifest-VERSION.json (SHA256 файлов + git commit HEAD). +# Хеши считаются по содержимому git (HEAD), как после checkout на Linux-хосте. # Запуск из корня репозитория: ./scripts/build-release-manifest.sh [VERSION] set -euo pipefail @@ -27,8 +28,8 @@ FILES=( ) for f in "${FILES[@]}"; do - [ -f "$f" ] || { - echo "ERROR: нет файла $f" >&2 + git rev-parse "HEAD:$f" >/dev/null 2>&1 || [ -f "$f" ] || { + echo "ERROR: нет файла $f (ни в git HEAD, ни на диске)" >&2 exit 1 } done @@ -51,6 +52,7 @@ python3 <<'PY' import hashlib import json import os +import subprocess root = os.environ["MANIFEST_ROOT"] version = os.environ["MANIFEST_VERSION"] @@ -58,21 +60,41 @@ git_commit = os.environ.get("MANIFEST_GIT_COMMIT", "") files = os.environ["MANIFEST_FILES"].split() out = os.environ["MANIFEST_OUT"] -def sha256_file(path: str) -> str: + +def sha256_bytes(data: bytes) -> str: + h = hashlib.sha256() + h.update(data) + return h.hexdigest() + + +def file_bytes_from_git(name: str) -> bytes | None: + for ref in (f":{name}", f"HEAD:{name}"): + try: + return subprocess.check_output(["git", "-C", root, "show", ref]) + except subprocess.CalledProcessError: + continue + return None + + +def sha256_release_file(name: str) -> str: + blob = file_bytes_from_git(name) + if blob is not None: + return sha256_bytes(blob) + path = os.path.join(root, name) h = hashlib.sha256() with open(path, "rb") as f: for chunk in iter(lambda: f.read(1024 * 1024), b""): h.update(chunk) return h.hexdigest() + manifest = { "version": version, "git_commit": git_commit, "files": {}, } for name in files: - path = os.path.join(root, name) - manifest["files"][name] = f"sha256:{sha256_file(path)}" + manifest["files"][name] = f"sha256:{sha256_release_file(name)}" with open(out, "w", encoding="utf-8") as f: json.dump(manifest, f, indent=2, ensure_ascii=False) diff --git a/ssh-monitor b/ssh-monitor index abf616e..f1e3c3e 100644 --- a/ssh-monitor +++ b/ssh-monitor @@ -7,7 +7,7 @@ IFS=$'\n\t' # ============================================ CONFIG_FILE="/etc/ssh-monitor.conf" -SSH_MONITOR_VERSION="2.2.1-SAC" +SSH_MONITOR_VERSION="2.2.2-SAC" SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" if [ -f "$SCRIPT_DIR/ssh-monitor-perms.sh" ]; then diff --git a/version.txt b/version.txt index 392f1b0..93d6b9a 100644 --- a/version.txt +++ b/version.txt @@ -1 +1 @@ -2.2.1-SAC +2.2.2-SAC