From 9e43de6fc164eaddba1a9f7f5a8e3cd2ae9b3939 Mon Sep 17 00:00:00 2001 From: PTah Date: Tue, 7 Jul 2026 19:44:08 +1000 Subject: [PATCH] chore: release SAC 0.5.0 Bump version, document security hardening in README, add github snapshot push script with URL/login/IP sanitization for public mirror. --- README.md | 7 +-- README_en.md | 7 +-- backend/app/version.py | 2 +- backend/tests/test_health.py | 4 +- frontend/src/version.ts | 2 +- tools/push-github-snapshot.sh | 86 +++++++++++++++++++++++++++++++++++ 6 files changed, 98 insertions(+), 10 deletions(-) create mode 100755 tools/push-github-snapshot.sh diff --git a/README.md b/README.md index 600f0a5..900a5e5 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# Security Alert Center (SAC) +# Security Alert Center (SAC) Центральная платформа: приём событий от агентов, корреляция, UI, оповещения, управление хостами. @@ -13,7 +13,7 @@ | **security-alert-center** | Сервер SAC (Ubuntu 24.04) | | [seaca](https://git.kalinamall.ru/PapaTramp/seaca) | Android-клиент | -**Версия:** `0.4.11` · **Деплой:** `sudo /opt/sac-deploy.sh` +**Версия:** `0.5.0` · **Деплой:** `sudo /opt/sac-deploy.sh` ## Возможности @@ -25,6 +25,7 @@ - **Хосты** — статус агента, inventory, обновление ssh-monitor/RDP (SSH/WinRM), тест Git/SSH/WinRM; WinRM RDP: SAC тянет пакет с git, клиент скачивает zip с SAC, локальный `Deploy-LoginMonitor.ps1` (git на ПК не нужен) - **Мобильные** — enrollment, устройства, push; Seaca: ack/resolve, qwinsta/logoff через API SAC - **Роли** — `admin` / `monitor`; JWT, rate limit входа +- **Безопасность (0.5.0)** — проверка host key SSH, SSE через httpOnly-cookie, защита rate limit от спуфинга `X-Forwarded-For`, `SAC_SECURITY_ENFORCE`, HMAC для API-ключей ## Документация @@ -40,7 +41,7 @@ ```bash git clone https://git.kalinamall.ru/PapaTramp/security-alert-center.git /opt/security-alert-center -# deploy/env.native.example → config/sac-api.env +# deploy/env.native.example → config/sac-api.env (JWT_SECRET, CORS_ORIGINS, SAC_SECURITY_ENFORCE) cd /opt/security-alert-center/backend && python3 -m venv .venv .venv/bin/pip install -r requirements.txt && .venv/bin/alembic upgrade head ``` diff --git a/README_en.md b/README_en.md index 9c9b337..0be94ce 100644 --- a/README_en.md +++ b/README_en.md @@ -1,4 +1,4 @@ -# Security Alert Center (SAC) +# Security Alert Center (SAC) Self-hosted hub for security events from Linux and Windows agents: ingest, correlation, UI, notifications, host management. @@ -13,7 +13,7 @@ Self-hosted hub for security events from Linux and Windows agents: ingest, corre | **security-alert-center** | SAC server (Ubuntu 24.04) | | [seaca](https://git.kalinamall.ru/PapaTramp/seaca) | Android client | -**Version:** `0.4.11` · **Deploy:** `sudo /opt/sac-deploy.sh` +**Version:** `0.5.0` · **Deploy:** `sudo /opt/sac-deploy.sh` ## Features @@ -25,6 +25,7 @@ Self-hosted hub for security events from Linux and Windows agents: ingest, corre - **Hosts** — agent status, inventory, agent updates (SSH/WinRM); WinRM RDP: SAC fetches from git, client downloads zip from SAC, runs local `Deploy-LoginMonitor.ps1` (no git on PC) - **Mobile** — enrollment, devices, push; Seaca: ack/resolve, qwinsta/logoff via SAC API - **Roles** — `admin` / `monitor` +- **Security (0.5.0)** — SSH host-key verification, SSE via httpOnly cookie, anti-spoof login rate limit, `SAC_SECURITY_ENFORCE`, HMAC API keys ## Documentation @@ -39,7 +40,7 @@ Self-hosted hub for security events from Linux and Windows agents: ingest, corre ```bash git clone https://git.kalinamall.ru/PapaTramp/security-alert-center.git /opt/security-alert-center -# deploy/env.native.example -> config/sac-api.env +# deploy/env.native.example → config/sac-api.env cd /opt/security-alert-center/backend && python3 -m venv .venv .venv/bin/pip install -r requirements.txt && .venv/bin/alembic upgrade head ``` diff --git a/backend/app/version.py b/backend/app/version.py index 4a61071..42741e0 100644 --- a/backend/app/version.py +++ b/backend/app/version.py @@ -1,5 +1,5 @@ """Единый источник версии SAC (API, health, логи, OpenAPI).""" APP_NAME = "Security Alert Center" -APP_VERSION = "0.4.15" +APP_VERSION = "0.5.0" APP_VERSION_LABEL = f"{APP_NAME} v.{APP_VERSION}" diff --git a/backend/tests/test_health.py b/backend/tests/test_health.py index cc8638c..2d381fd 100644 --- a/backend/tests/test_health.py +++ b/backend/tests/test_health.py @@ -4,6 +4,6 @@ from app.version import APP_NAME, APP_VERSION, APP_VERSION_LABEL def test_version_constants(): - assert APP_VERSION == "0.4.15" + assert APP_VERSION == "0.5.0" assert APP_NAME == "Security Alert Center" - assert APP_VERSION_LABEL == "Security Alert Center v.0.4.15" + assert APP_VERSION_LABEL == "Security Alert Center v.0.5.0" diff --git a/frontend/src/version.ts b/frontend/src/version.ts index 8891de0..646b08d 100644 --- a/frontend/src/version.ts +++ b/frontend/src/version.ts @@ -1,4 +1,4 @@ /** Fallback до загрузки /health; при релизе держите в sync с backend/app/version.py */ export const APP_NAME = "Security Alert Center"; -export const APP_VERSION = "0.4.15"; +export const APP_VERSION = "0.5.0"; export const APP_VERSION_LABEL = `${APP_NAME} v.${APP_VERSION}`; diff --git a/tools/push-github-snapshot.sh b/tools/push-github-snapshot.sh new file mode 100755 index 0000000..9137c75 --- /dev/null +++ b/tools/push-github-snapshot.sh @@ -0,0 +1,86 @@ +#!/usr/bin/env bash +# Публичный snapshot на github: без prod URL, доменов, логинов, имён и внутренних IP. +set -Eeuo pipefail + +ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" +WORK="$(mktemp -d "${TMPDIR:-/tmp}/sac-github-snapshot.XXXX")" +trap 'rm -rf "$WORK"' EXIT + +REF="${1:-HEAD}" +MSG="${2:-chore: public release snapshot $(date +%F) (SAC $(git -C "$ROOT" show -s --format=%s "$REF" | sed -n 's/.*(\([0-9.]*\)).*/\1/p' | head -1))}" + +echo "[snapshot] export $REF -> $WORK" +git -C "$ROOT" archive --format=tar "$REF" \ + | tar -x -C "$WORK" \ + --exclude='.cursor' \ + --exclude='.venv' \ + --exclude='frontend/node_modules' \ + --exclude='frontend/dist' \ + --exclude='.env' \ + --exclude='deploy/.env' + +apply_sed() { + local expr=$1 + if [[ "$(uname -s)" == Darwin ]]; then + find "$WORK" -type f \( -name '*.py' -o -name '*.md' -o -name '*.ts' -o -name '*.vue' -o -name '*.sh' -o -name '*.ps1' -o -name '*.example' -o -name '*.yml' -o -name '*.json' -o -name '*.conf' \) \ + -print0 | xargs -0 sed -i '' -E "$expr" + else + find "$WORK" -type f \( -name '*.py' -o -name '*.md' -o -name '*.ts' -o -name '*.vue' -o -name '*.sh' -o -name '*.ps1' -o -name '*.example' -o -name '*.yml' -o -name '*.json' -o -name '*.conf' \) \ + -print0 | xargs -0 sed -i -E "$expr" + fi +} + +echo "[snapshot] rewrite hosts, domains, logins, IPs" +apply_sed 's#https://git\.kalinamall\.ru/PapaTramp#https://github.com/PTah#g' +apply_sed 's#git\.kalinamall\.ru/PapaTramp#github.com/PTah#g' +apply_sed 's#git\.kalinamall\.ru/papatramp#github.com/PTah#g' +apply_sed 's#git\.papatramp\.ru/PapaTramp#github.com/PTah#g' +apply_sed 's#git\.papatramp\.lan:[0-9]+/PapaTramp#github.com/PTah#g' +apply_sed 's#sac\.kalinamall\.ru#sac.example.com#g' +apply_sed 's#git\.kalinamall\.lan#github.com#g' +apply_sed 's#kalinamall-sac\.conf#origin-sac.conf#g' +apply_sed 's#remote add kalinamall#remote add origin#g' +apply_sed 's#remote set-url kalinamall#remote set-url origin#g' +apply_sed 's#B26\\\\#CONTOSO\\\\#g' +apply_sed 's#B26\\#CONTOSO\\#g' +apply_sed 's#papatramp#example.user#g' +apply_sed 's#PapaTramp#PTah#g' +apply_sed 's#192\.168\.160\.#192.0.2.#g' +apply_sed 's#192\.168\.128\.#192.0.2.#g' +apply_sed 's#192\.168\.163\.#192.0.2.#g' +apply_sed 's#password="[^"]*"#password=_TEST_PASSWORD#g' +apply_sed "s#password='[^']*'#password=_TEST_PASSWORD#g" + +if ! grep -q '_TEST_PASSWORD' "$WORK/backend/tests/conftest.py" 2>/dev/null; then + sed -i.bak '1a\ +_TEST_PASSWORD = "test-only" +' "$WORK/backend/tests/conftest.py" && rm -f "$WORK/backend/tests/conftest.py.bak" +fi + +echo "[snapshot] git commit in temp repo" +cd "$WORK" +git init -q +git checkout -q -b main +git add -A +git -c user.name="PTah" -c user.email="papatramp@gmail.com" commit -q -m "$MSG" + +echo "[snapshot] secret scan (prod patterns, tests skipped)" +while IFS= read -r -d '' f; do + case "$f" in + *.example|*env.example|backend/tests/*) continue ;; + esac + if grep -qiE '\.env$|BEGIN (RSA |OPENSSH )?PRIVATE KEY|credentials\.json|google-services\.json' "$f"; then + echo " BLOCKED: $f" + exit 1 + fi + if grep -qiE 'DATABASE_URL=postgresql.*:[^@]+@' "$f"; then + echo " BLOCKED: $f (DATABASE_URL with password)" + exit 1 + fi +done < <(find . -type f -print0) + +echo "[snapshot] push github main (force snapshot)" +git remote add github "$(git -C "$ROOT" remote get-url github)" +git push github main --force + +echo "[snapshot] OK -> github/main @ $(git rev-parse --short HEAD)"