Compare commits
3
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ae048ac1c8 | ||
|
|
ded569207e | ||
|
|
55c0d06baa |
@@ -1,74 +0,0 @@
|
|||||||
name: rust-binary-build
|
|
||||||
|
|
||||||
on:
|
|
||||||
workflow_dispatch:
|
|
||||||
pull_request:
|
|
||||||
branches: [ "main" ]
|
|
||||||
paths:
|
|
||||||
- 'rust-toolchain.toml'
|
|
||||||
- 'adk-rust/**'
|
|
||||||
- 'scripts/package_rust_release_binaries.py'
|
|
||||||
- '.github/workflows/rust-binary-build.yml'
|
|
||||||
push:
|
|
||||||
tags:
|
|
||||||
- 'v*'
|
|
||||||
|
|
||||||
permissions:
|
|
||||||
contents: write
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
build-linux-x86_64:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
timeout-minutes: 60
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- name: Checkout
|
|
||||||
uses: actions/checkout@v4
|
|
||||||
|
|
||||||
- name: Install pinned Rust toolchain
|
|
||||||
run: |
|
|
||||||
rustup toolchain install 1.94.0 --profile minimal --component rustfmt --component clippy
|
|
||||||
rustup override set 1.94.0
|
|
||||||
rustup show active-toolchain
|
|
||||||
cargo +1.94.0 --version
|
|
||||||
rustc +1.94.0 --version
|
|
||||||
|
|
||||||
- name: Build release binaries
|
|
||||||
run: cargo +1.94.0 build --manifest-path adk-rust/Cargo.toml --workspace --release
|
|
||||||
|
|
||||||
- name: Package release binaries
|
|
||||||
run: |
|
|
||||||
python3 scripts/package_rust_release_binaries.py \
|
|
||||||
--release-dir adk-rust/target/release \
|
|
||||||
--out-dir dist/awatch-rus-linux-x86_64 \
|
|
||||||
--archive dist/awatch-rus-linux-x86_64-release-binaries.tar.gz \
|
|
||||||
--target linux-x86_64 \
|
|
||||||
--commit "${GITHUB_SHA}" \
|
|
||||||
--ref "${GITHUB_REF}" \
|
|
||||||
--run-id "${GITHUB_RUN_ID}"
|
|
||||||
|
|
||||||
- name: Upload release binaries artifact
|
|
||||||
uses: actions/upload-artifact@v4
|
|
||||||
with:
|
|
||||||
name: awatch-rus-linux_x86_64-release-binaries
|
|
||||||
path: |
|
|
||||||
dist/awatch-rus-linux_x86_64-release-binaries.tar.gz
|
|
||||||
dist/awatch-rus-linux_x86_64-release-binaries.tar.gz.sha256
|
|
||||||
dist/awatch-rus-linux_x86_64/BINARIES.txt
|
|
||||||
dist/awatch-rus-linux_x86_64/SHA256SUMS.txt
|
|
||||||
dist/awatch-rus-linux_x86_64/BUILD_MANIFEST.json
|
|
||||||
if-no-files-found: error
|
|
||||||
retention-days: 30
|
|
||||||
|
|
||||||
- name: Publish GitHub Release assets
|
|
||||||
if: startsWith(github.ref, 'refs/tags/v')
|
|
||||||
uses: softprops/action-gh-release@v2
|
|
||||||
with:
|
|
||||||
generate_release_notes: true
|
|
||||||
fail_on_unmatched_files: true
|
|
||||||
files: |
|
|
||||||
dist/awatch-rus-linux_x86_64-release-binaries.tar.gz
|
|
||||||
dist/awatch-rus-linux_x86_64-release-binaries.tar.gz.sha256
|
|
||||||
dist/awatch-rus-linux_x86_64/BINARIES.txt
|
|
||||||
dist/awatch-rus-linux_x86_64/SHA256SUMS.txt
|
|
||||||
dist/awatch-rus-linux_x86_64/BUILD_MANIFEST.json
|
|
||||||
@@ -1,40 +0,0 @@
|
|||||||
name: Rust clippy diagnostic
|
|
||||||
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
branches:
|
|
||||||
- codex/rust-professionalization
|
|
||||||
workflow_dispatch:
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
detmir-portal-clippy-diagnostic:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
timeout-minutes: 30
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- name: Checkout
|
|
||||||
uses: actions/checkout@v4
|
|
||||||
|
|
||||||
- name: Install Rust 1.85 with rustfmt and clippy
|
|
||||||
run: |
|
|
||||||
rustup toolchain install 1.85.0 --profile minimal --component rustfmt --component clippy
|
|
||||||
rustup default 1.85.0
|
|
||||||
|
|
||||||
- name: Capture detmir-portal clippy output
|
|
||||||
working-directory: adk-rust
|
|
||||||
run: |
|
|
||||||
set +e
|
|
||||||
cargo clippy -p detmir-portal --all-targets -- -D warnings > ../detmir-portal-clippy.log 2>&1
|
|
||||||
status=$?
|
|
||||||
echo "clippy_exit_status=${status}" > ../detmir-portal-clippy-status.txt
|
|
||||||
tail -n 240 ../detmir-portal-clippy.log
|
|
||||||
exit ${status}
|
|
||||||
|
|
||||||
- name: Upload detmir-portal clippy log
|
|
||||||
if: always()
|
|
||||||
uses: actions/upload-artifact@v4
|
|
||||||
with:
|
|
||||||
name: detmir-portal-clippy-log
|
|
||||||
path: |
|
|
||||||
detmir-portal-clippy.log
|
|
||||||
detmir-portal-clippy-status.txt
|
|
||||||
@@ -1,73 +0,0 @@
|
|||||||
name: Rust professionalization check
|
|
||||||
|
|
||||||
on:
|
|
||||||
pull_request:
|
|
||||||
branches:
|
|
||||||
- main
|
|
||||||
paths:
|
|
||||||
- 'rust-toolchain.toml'
|
|
||||||
- 'adk-rust/crates/detmir-core/**'
|
|
||||||
- 'adk-rust/crates/detmir-portal/**'
|
|
||||||
- 'scripts/check_private_config_guard.sh'
|
|
||||||
- 'scripts/check_portal_contract_sync.mjs'
|
|
||||||
- '.github/workflows/rust-professionalization-check.yml'
|
|
||||||
workflow_dispatch:
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
rust-check:
|
|
||||||
name: changed Rust crates smoke
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
timeout-minutes: 40
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- name: Checkout
|
|
||||||
uses: actions/checkout@v4
|
|
||||||
|
|
||||||
- name: Install pinned Rust toolchain
|
|
||||||
run: |
|
|
||||||
rustup toolchain install 1.94.0 --profile minimal --component rustfmt --component clippy
|
|
||||||
rustup override set 1.94.0
|
|
||||||
rustup show active-toolchain
|
|
||||||
cargo +1.94.0 --version
|
|
||||||
rustc +1.94.0 --version
|
|
||||||
|
|
||||||
- name: Cargo fmt check
|
|
||||||
working-directory: adk-rust
|
|
||||||
run: cargo +1.94.0 fmt --all -- --check
|
|
||||||
|
|
||||||
- name: Test detmir-core
|
|
||||||
working-directory: adk-rust
|
|
||||||
run: cargo +1.94.0 test -p detmir-core
|
|
||||||
|
|
||||||
- name: Test detmir-portal
|
|
||||||
working-directory: adk-rust
|
|
||||||
run: cargo +1.94.0 test -p detmir-portal
|
|
||||||
|
|
||||||
- name: Clippy detmir-core
|
|
||||||
working-directory: adk-rust
|
|
||||||
run: cargo +1.94.0 clippy -p detmir-core --all-targets -- -D warnings
|
|
||||||
|
|
||||||
- name: Clippy detmir-portal with captured log
|
|
||||||
working-directory: adk-rust
|
|
||||||
run: |
|
|
||||||
set +e
|
|
||||||
cargo +1.94.0 clippy -p detmir-portal --all-targets -- -D warnings > ../detmir-portal-clippy.log 2>&1
|
|
||||||
status=$?
|
|
||||||
echo "clippy_exit_status=${status}" > ../detmir-portal-clippy-status.txt
|
|
||||||
tail -n 80 ../detmir-portal-clippy.log
|
|
||||||
exit ${status}
|
|
||||||
|
|
||||||
- name: Upload detmir-portal clippy log
|
|
||||||
if: always()
|
|
||||||
uses: actions/upload-artifact@v4
|
|
||||||
with:
|
|
||||||
name: detmir-portal-clippy-log
|
|
||||||
path: |
|
|
||||||
detmir-portal-clippy.log
|
|
||||||
detmir-portal-clippy-status.txt
|
|
||||||
|
|
||||||
- name: Private config guard
|
|
||||||
run: bash scripts/check_private_config_guard.sh
|
|
||||||
|
|
||||||
- name: Portal contract sync
|
|
||||||
run: node scripts/check_portal_contract_sync.mjs
|
|
||||||
@@ -5,7 +5,6 @@ on:
|
|||||||
branches: [ "main" ]
|
branches: [ "main" ]
|
||||||
pull_request:
|
pull_request:
|
||||||
branches: [ "main" ]
|
branches: [ "main" ]
|
||||||
workflow_dispatch:
|
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
rust-workspace:
|
rust-workspace:
|
||||||
@@ -14,22 +13,19 @@ jobs:
|
|||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
- name: Install pinned Rust toolchain
|
- name: Install Rust 1.85
|
||||||
run: |
|
uses: dtolnay/rust-toolchain@1.85.0
|
||||||
rustup toolchain install 1.94.0 --profile minimal --component rustfmt --component clippy
|
with:
|
||||||
rustup override set 1.94.0
|
components: rustfmt, clippy
|
||||||
rustup show active-toolchain
|
|
||||||
cargo +1.94.0 --version
|
|
||||||
rustc +1.94.0 --version
|
|
||||||
|
|
||||||
- name: Format
|
- name: Format
|
||||||
run: cargo +1.94.0 fmt --manifest-path adk-rust/Cargo.toml --all -- --check
|
run: cargo fmt --manifest-path adk-rust/Cargo.toml --all -- --check
|
||||||
|
|
||||||
- name: Test
|
- name: Test
|
||||||
run: cargo +1.94.0 test --manifest-path adk-rust/Cargo.toml --workspace
|
run: cargo test --manifest-path adk-rust/Cargo.toml --workspace
|
||||||
|
|
||||||
- name: Clippy
|
- name: Clippy
|
||||||
run: cargo +1.94.0 clippy --manifest-path adk-rust/Cargo.toml --workspace --all-targets -- -D warnings
|
run: cargo clippy --manifest-path adk-rust/Cargo.toml --workspace --all-targets -- -D warnings
|
||||||
|
|
||||||
- name: Release build
|
- name: Release build
|
||||||
run: cargo +1.94.0 build --manifest-path adk-rust/Cargo.toml --workspace --release
|
run: cargo build --manifest-path adk-rust/Cargo.toml --workspace --release
|
||||||
|
|||||||
@@ -38,3 +38,82 @@
|
|||||||
Продукт относится к классу средств управления ИТ-службой,
|
Продукт относится к классу средств управления ИТ-службой,
|
||||||
ИТ-инфраструктурой и ИТ-активами. Продукт не заявляется как
|
ИТ-инфраструктурой и ИТ-активами. Продукт не заявляется как
|
||||||
сертифицированная DLP, SIEM, EDR/XDR или средство защиты информации.
|
сертифицированная DLP, SIEM, EDR/XDR или средство защиты информации.
|
||||||
|
|
||||||
|
|
||||||
|
## Профессиональные сильные стороны проекта
|
||||||
|
|
||||||
|
Ниже — краткая и профессиональная сводка ключевых преимуществ AWatch-rus,
|
||||||
|
предназначенная для реестра программного обеспечения и технического аудитa.
|
||||||
|
|
||||||
|
### 1. Архитектура и инженерный дизайн
|
||||||
|
|
||||||
|
- Rust-first, модульная архитектура: более 40 специализированных крейтов в
|
||||||
|
workspace, четкая декомпозиция ответственности и воспроизводимые сборки
|
||||||
|
(Cargo.lock).
|
||||||
|
- Разделение на логические уровни: endpoint -> серверные хранилища ->
|
||||||
|
processing -> operator -> automation, что упрощает тестирование и валидацию.
|
||||||
|
- Четкие migration-runbooks для последовательного перехода legacy-python → Rust.
|
||||||
|
|
||||||
|
### 2. Операционная зрелость
|
||||||
|
|
||||||
|
- Полноценный Ansible-ensemble для end-to-end развёртывания (Proxmox, Linux,
|
||||||
|
централизованный Windows rollout по WinRM), включая retry-политику,
|
||||||
|
smoke-тесты и валидацию после деплоя.
|
||||||
|
- Safe-run pattern: dry-run/apply planners, backup-before-delete, atomic
|
||||||
|
операции и conservative no-restart paths.
|
||||||
|
- Набор модулей для диагностики и качества (detmir-*, aw-*, quality-gate,
|
||||||
|
smoke checks) обеспечивает fast feedback при внедрении.
|
||||||
|
|
||||||
|
### 3. Безопасность и работа с evidence
|
||||||
|
|
||||||
|
- Изолированный путь evidence: opaque IDs, bearer-upload, magic validation
|
||||||
|
для изображений, размерные лимиты, SHA-256 валидация, atomic write и audit
|
||||||
|
trails.
|
||||||
|
- Security hardening guide: TLS по умолчанию, reverse-proxy, firewall
|
||||||
|
рекомендации, сервисные аккаунты и минимальные привилегии.
|
||||||
|
- Ясные границы продукта: не позиционируется как сертифицированная СЗИ/DLP;
|
||||||
|
это снижает юридические риски при регистрации и аудите.
|
||||||
|
|
||||||
|
### 4. Production-readiness и валидация пилота
|
||||||
|
|
||||||
|
- Полный комплект acceptance и pilot-checklists (30-дневный pilot success
|
||||||
|
criteria) с метриками доступности, coverage, freshness и времени реакции.
|
||||||
|
- Runbooks и операционная документация для восстановления, резервного копирования
|
||||||
|
и отката.
|
||||||
|
|
||||||
|
### 5. Наблюдаемость и качество данных
|
||||||
|
|
||||||
|
- Встроенные SLO/health monitoring, Prometheus/ Grafana витрины и
|
||||||
|
детализированные smoke/contour тесты.
|
||||||
|
- Механизмы объяснимости: UEBA v1 rule-based с reason-codes и объяснениями KPI
|
||||||
|
coverage/confidence.
|
||||||
|
|
||||||
|
### 6. Поддержка Windows/RDP и forensics
|
||||||
|
|
||||||
|
- Централизованный Windows rollout и валидация (API smoke-checks для
|
||||||
|
aw-watcher-afk/aw-watcher-window).
|
||||||
|
- Серверная автоматическая обработка Hayabusa: auto-upload, severity scoring,
|
||||||
|
case creation и уведомления (Telegram) с пороговой фильтрацией.
|
||||||
|
|
||||||
|
### 7. Документированность и готовность к реестру
|
||||||
|
|
||||||
|
- Полный набор документов для регистрации: product passport, architecture,
|
||||||
|
functional scope, dependency statement, deployment model и readiness checklist.
|
||||||
|
- Демонстрационные сценарии и фикстуры, исключающие реальные персональные и
|
||||||
|
сетевые данные — соответствует требованиям для публичных материалов.
|
||||||
|
|
||||||
|
### 8. Честное позиционирование и риски
|
||||||
|
|
||||||
|
- Прозрачность ограничений (что реализовано, что planned/future) — важный
|
||||||
|
аспект при подаче в реестр и при взаимодействии с заказчиком.
|
||||||
|
- Документированная gap-analysis и roadmap-conformance audit облегчают
|
||||||
|
процессы оценки соответствия и планирования доработок.
|
||||||
|
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
Если нужно, могу:
|
||||||
|
- добавить этот раздел как отдельный файл в docs/ (например,
|
||||||
|
docs/PROFESSIONAL_HIGHLIGHTS_RU.md), либо
|
||||||
|
- вставить в другой документ (например, в architecture или registry passport),
|
||||||
|
- сгенерировать краткую выдержку на 1 страницу для подачи в реестр.
|
||||||
|
|||||||
@@ -1,37 +1,19 @@
|
|||||||
#![deny(unsafe_op_in_unsafe_fn)]
|
|
||||||
|
|
||||||
//! Shared production primitives for AWatch-rus.
|
|
||||||
//!
|
|
||||||
//! This crate intentionally stays small and dependency-light. It contains the
|
|
||||||
//! status, exit-code and runtime-configuration guardrails that are reused by
|
|
||||||
//! operational binaries and health/check tooling. Keep business-specific portal,
|
|
||||||
//! DLP or workforce logic out of this crate.
|
|
||||||
|
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
|
|
||||||
use anyhow::{Context, Result};
|
use anyhow::{Context, Result};
|
||||||
use chrono::{DateTime, SecondsFormat, Utc};
|
use chrono::{DateTime, SecondsFormat, Utc};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
/// Normalized health/check status used by CLI tools, probes and JSON payloads.
|
|
||||||
///
|
|
||||||
/// CONTRACT: serialized values are uppercase and must remain stable because
|
|
||||||
/// deployment scripts, smoke checks and dashboards can key off these strings.
|
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
|
||||||
#[serde(rename_all = "UPPERCASE")]
|
#[serde(rename_all = "UPPERCASE")]
|
||||||
pub enum StatusLevel {
|
pub enum StatusLevel {
|
||||||
/// Component is healthy and the check passed.
|
|
||||||
Ok,
|
Ok,
|
||||||
/// Component works, but a risk or degraded condition needs attention.
|
|
||||||
Warn,
|
Warn,
|
||||||
/// Component check failed or a required dependency is unavailable.
|
|
||||||
Fail,
|
Fail,
|
||||||
/// Component did not provide enough information for a reliable status.
|
|
||||||
Unknown,
|
Unknown,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl StatusLevel {
|
impl StatusLevel {
|
||||||
/// Return the stable uppercase representation used in human and JSON output.
|
|
||||||
pub fn as_str(self) -> &'static str {
|
pub fn as_str(self) -> &'static str {
|
||||||
match self {
|
match self {
|
||||||
Self::Ok => "OK",
|
Self::Ok => "OK",
|
||||||
@@ -41,10 +23,6 @@ impl StatusLevel {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Map status to the process exit code expected by operational checks.
|
|
||||||
///
|
|
||||||
/// CONTRACT: `WARN` exits as a failed check rather than success so that
|
|
||||||
/// automation does not silently ignore degraded production state.
|
|
||||||
pub fn exit_code(self) -> i32 {
|
pub fn exit_code(self) -> i32 {
|
||||||
match self {
|
match self {
|
||||||
Self::Ok => exit_codes::OK,
|
Self::Ok => exit_codes::OK,
|
||||||
@@ -70,39 +48,23 @@ impl From<&str> for StatusLevel {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Stable process exit codes for AWatch-rus operational binaries.
|
|
||||||
///
|
|
||||||
/// CONTRACT: keep these numeric values stable. Shell scripts, systemd units,
|
|
||||||
/// smoke tests and runbooks can depend on them.
|
|
||||||
pub mod exit_codes {
|
pub mod exit_codes {
|
||||||
/// Successful execution.
|
|
||||||
pub const OK: i32 = 0;
|
pub const OK: i32 = 0;
|
||||||
/// Unexpected runtime or IO error.
|
|
||||||
pub const ERROR: i32 = 1;
|
pub const ERROR: i32 = 1;
|
||||||
/// Health/check policy failed or returned a degraded status.
|
|
||||||
pub const CHECK_FAILED: i32 = 2;
|
pub const CHECK_FAILED: i32 = 2;
|
||||||
/// A safety policy denied a requested action.
|
|
||||||
pub const POLICY_DENIED: i32 = 3;
|
pub const POLICY_DENIED: i32 = 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Return the current UTC timestamp in compact RFC3339/Zulu format.
|
|
||||||
pub fn now_utc_rfc3339() -> String {
|
pub fn now_utc_rfc3339() -> String {
|
||||||
Utc::now().to_rfc3339_opts(SecondsFormat::Secs, true)
|
Utc::now().to_rfc3339_opts(SecondsFormat::Secs, true)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Parse an RFC3339 timestamp and normalize it to UTC.
|
|
||||||
pub fn parse_utc_rfc3339(value: &str) -> Result<DateTime<Utc>> {
|
pub fn parse_utc_rfc3339(value: &str) -> Result<DateTime<Utc>> {
|
||||||
DateTime::parse_from_rfc3339(value)
|
DateTime::parse_from_rfc3339(value)
|
||||||
.with_context(|| format!("invalid RFC3339 timestamp: {value}"))
|
.with_context(|| format!("invalid RFC3339 timestamp: {value}"))
|
||||||
.map(|ts| ts.with_timezone(&Utc))
|
.map(|ts| ts.with_timezone(&Utc))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Runtime configuration guardrails.
|
|
||||||
///
|
|
||||||
/// SECURITY: these helpers are deliberately conservative. They reject empty,
|
|
||||||
/// documentation, TEST-NET and common placeholder values before a component is
|
|
||||||
/// allowed to run in production mode. This prevents demo-safe examples from
|
|
||||||
/// accidentally becoming live runtime configuration.
|
|
||||||
pub mod runtime_guard {
|
pub mod runtime_guard {
|
||||||
use anyhow::{Result, bail};
|
use anyhow::{Result, bail};
|
||||||
|
|
||||||
@@ -120,11 +82,6 @@ pub mod runtime_guard {
|
|||||||
"PASSWORD",
|
"PASSWORD",
|
||||||
];
|
];
|
||||||
|
|
||||||
/// Return true when a value looks like a public/demo placeholder.
|
|
||||||
///
|
|
||||||
/// RATIONALE: AWatch-rus documentation intentionally uses TEST-NET ranges
|
|
||||||
/// and HOST-EXAMPLE markers. Production binaries should fail closed when
|
|
||||||
/// such values reach runtime configuration.
|
|
||||||
pub fn is_runtime_placeholder(value: &str) -> bool {
|
pub fn is_runtime_placeholder(value: &str) -> bool {
|
||||||
let trimmed = value.trim();
|
let trimmed = value.trim();
|
||||||
if trimmed.is_empty() {
|
if trimmed.is_empty() {
|
||||||
@@ -149,7 +106,6 @@ pub mod runtime_guard {
|
|||||||
|| (normalized.starts_with('<') && normalized.ends_with('>'))
|
|| (normalized.starts_with('<') && normalized.ends_with('>'))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Return true when a value is unsafe for a secret-like configuration field.
|
|
||||||
pub fn is_secret_placeholder(value: &str) -> bool {
|
pub fn is_secret_placeholder(value: &str) -> bool {
|
||||||
is_runtime_placeholder(value)
|
is_runtime_placeholder(value)
|
||||||
|| matches!(
|
|| matches!(
|
||||||
@@ -158,10 +114,6 @@ pub mod runtime_guard {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Ensure a required runtime value is not empty or demo-only.
|
|
||||||
///
|
|
||||||
/// SECURITY: callers should invoke this before opening network connections,
|
|
||||||
/// starting ingestion or enabling exporters in production mode.
|
|
||||||
pub fn ensure_runtime_value(name: &str, value: &str, context: &str) -> Result<()> {
|
pub fn ensure_runtime_value(name: &str, value: &str, context: &str) -> Result<()> {
|
||||||
if is_runtime_placeholder(value) {
|
if is_runtime_placeholder(value) {
|
||||||
bail!("{name} contains an empty/example/TEST-NET value while {context}");
|
bail!("{name} contains an empty/example/TEST-NET value while {context}");
|
||||||
@@ -169,7 +121,6 @@ pub mod runtime_guard {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Ensure a required secret is not empty or an obvious placeholder.
|
|
||||||
pub fn ensure_secret_value(name: &str, value: &str, context: &str) -> Result<()> {
|
pub fn ensure_secret_value(name: &str, value: &str, context: &str) -> Result<()> {
|
||||||
if is_secret_placeholder(value) {
|
if is_secret_placeholder(value) {
|
||||||
bail!("{name} contains an empty/example secret value while {context}");
|
bail!("{name} contains an empty/example secret value while {context}");
|
||||||
@@ -177,7 +128,6 @@ pub mod runtime_guard {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Ensure an iterator of runtime values is non-empty and production-safe.
|
|
||||||
pub fn ensure_runtime_values<'a>(
|
pub fn ensure_runtime_values<'a>(
|
||||||
name: &str,
|
name: &str,
|
||||||
values: impl IntoIterator<Item = &'a String>,
|
values: impl IntoIterator<Item = &'a String>,
|
||||||
@@ -194,12 +144,6 @@ pub mod runtime_guard {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Validate a complete InfluxDB exporter configuration block.
|
|
||||||
///
|
|
||||||
/// CONTRACT: when an exporter is enabled, URL, org, bucket, token and host
|
|
||||||
/// list must all be real runtime values. A partial/demo exporter config is
|
|
||||||
/// more dangerous than a disabled exporter because it creates false
|
|
||||||
/// confidence in monitoring readiness.
|
|
||||||
pub fn ensure_influx_runtime_config(
|
pub fn ensure_influx_runtime_config(
|
||||||
prefix: &str,
|
prefix: &str,
|
||||||
url: &str,
|
url: &str,
|
||||||
|
|||||||
@@ -21,7 +21,3 @@ tiny_http.workspace = true
|
|||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
tempfile.workspace = true
|
tempfile.workspace = true
|
||||||
|
|
||||||
[lints.clippy]
|
|
||||||
comparison_chain = "allow"
|
|
||||||
search_is_some = "allow"
|
|
||||||
|
|||||||
@@ -1,8 +1,3 @@
|
|||||||
//! Liveness probe payload.
|
|
||||||
//!
|
|
||||||
//! CONTRACT: `/healthz` is intentionally shallow. It proves that the portal
|
|
||||||
//! process can answer HTTP, while dependency checks belong to `/readyz`.
|
|
||||||
|
|
||||||
use serde_json::{Value, json};
|
use serde_json::{Value, json};
|
||||||
|
|
||||||
use crate::now;
|
use crate::now;
|
||||||
|
|||||||
@@ -1,10 +1,3 @@
|
|||||||
//! Configuration and request-bound validation for production portal routes.
|
|
||||||
//!
|
|
||||||
//! RATIONALE: the portal can aggregate reports, evidence and external service
|
|
||||||
//! payloads. Query and body limits keep pilot installations responsive and make
|
|
||||||
//! expensive report routes fail closed instead of exhausting memory or blocking
|
|
||||||
//! the single-process runtime.
|
|
||||||
|
|
||||||
use std::collections::BTreeSet;
|
use std::collections::BTreeSet;
|
||||||
|
|
||||||
use anyhow::{Result, anyhow};
|
use anyhow::{Result, anyhow};
|
||||||
@@ -37,10 +30,6 @@ pub(crate) fn validate_portal_config(args: &Cli) -> Result<()> {
|
|||||||
if port == 0 {
|
if port == 0 {
|
||||||
return Err(anyhow!("invalid config port: expected 1..65535"));
|
return Err(anyhow!("invalid config port: expected 1..65535"));
|
||||||
}
|
}
|
||||||
|
|
||||||
// RATIONALE: page and date limits protect heavy report endpoints while
|
|
||||||
// preserving monthly pilot reporting. Hard upper bounds prevent accidental
|
|
||||||
// production overrides from turning the portal into an unbounded exporter.
|
|
||||||
if args.max_page_size == 0 || args.max_page_size > MAX_ALLOWED_PAGE_SIZE {
|
if args.max_page_size == 0 || args.max_page_size > MAX_ALLOWED_PAGE_SIZE {
|
||||||
return Err(anyhow!(
|
return Err(anyhow!(
|
||||||
"invalid config max_page_size: expected 1..={MAX_ALLOWED_PAGE_SIZE}"
|
"invalid config max_page_size: expected 1..={MAX_ALLOWED_PAGE_SIZE}"
|
||||||
@@ -77,10 +66,6 @@ pub(crate) fn validate_portal_config(args: &Cli) -> Result<()> {
|
|||||||
"invalid config max_request_body_bytes: expected 1024..={MAX_ALLOWED_REQUEST_BODY_BYTES}"
|
"invalid config max_request_body_bytes: expected 1024..={MAX_ALLOWED_REQUEST_BODY_BYTES}"
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
// SECURITY: environment and module names can reach metrics/log labels.
|
|
||||||
// Restrict them to short ASCII tokens to avoid label injection and runaway
|
|
||||||
// cardinality from free-form deployment names.
|
|
||||||
if !is_safe_environment_name(&args.environment) {
|
if !is_safe_environment_name(&args.environment) {
|
||||||
return Err(anyhow!(
|
return Err(anyhow!(
|
||||||
"invalid config environment: use 1..32 chars from A-Z, a-z, 0-9, _, -"
|
"invalid config environment: use 1..32 chars from A-Z, a-z, 0-9, _, -"
|
||||||
|
|||||||
@@ -1,10 +1,3 @@
|
|||||||
//! Structured HTTP access logging for the portal runtime.
|
|
||||||
//!
|
|
||||||
//! CONTRACT: logs are emitted as single-line JSON to stderr so systemd/journald,
|
|
||||||
//! container runtimes and log forwarders can parse them without scraping free
|
|
||||||
//! text. Do not log raw request bodies, secrets, evidence bytes or personal
|
|
||||||
//! payloads here.
|
|
||||||
|
|
||||||
use serde_json::{Value, json};
|
use serde_json::{Value, json};
|
||||||
use tiny_http::StatusCode;
|
use tiny_http::StatusCode;
|
||||||
|
|
||||||
@@ -28,10 +21,6 @@ pub(crate) fn log_http_request(
|
|||||||
} else {
|
} else {
|
||||||
Value::Null
|
Value::Null
|
||||||
};
|
};
|
||||||
|
|
||||||
// SECURITY: include routing/correlation fields, but do not include query
|
|
||||||
// values, request body, headers or tokens. Those can contain employee data,
|
|
||||||
// screenshots, evidence references or API keys.
|
|
||||||
eprintln!(
|
eprintln!(
|
||||||
"{}",
|
"{}",
|
||||||
json!({
|
json!({
|
||||||
|
|||||||
@@ -1,9 +1,3 @@
|
|||||||
//! In-process Prometheus-style metrics for the portal.
|
|
||||||
//!
|
|
||||||
//! CONTRACT: metric names and label keys are part of the operational contract
|
|
||||||
//! used by dashboards and smoke checks. Additive metrics are allowed; renaming
|
|
||||||
//! existing metrics requires synchronized dashboard/documentation changes.
|
|
||||||
|
|
||||||
use std::collections::BTreeMap;
|
use std::collections::BTreeMap;
|
||||||
use std::fmt::Write as FmtWrite;
|
use std::fmt::Write as FmtWrite;
|
||||||
use std::sync::{Mutex, OnceLock};
|
use std::sync::{Mutex, OnceLock};
|
||||||
@@ -185,7 +179,5 @@ pub(crate) fn render_prometheus_metrics(args: &Cli) -> String {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn prom_escape(value: &str) -> String {
|
fn prom_escape(value: &str) -> String {
|
||||||
// SECURITY: metric label values are route/module tokens, but escaping keeps
|
|
||||||
// the endpoint safe if future callers pass proxy-derived values.
|
|
||||||
value.replace('\\', "\\\\").replace('"', "\\\"")
|
value.replace('\\', "\\\\").replace('"', "\\\"")
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,14 +1,3 @@
|
|||||||
//! Production-facing portal runtime support.
|
|
||||||
//!
|
|
||||||
//! This module groups the cross-cutting concerns that must stay consistent
|
|
||||||
//! across all portal routes: health/readiness/version contracts, query and
|
|
||||||
//! configuration limits, structured logging, Prometheus-style metrics and
|
|
||||||
//! request correlation metadata.
|
|
||||||
//!
|
|
||||||
//! CONTRACT: keep this module free from role-specific business rendering. It is
|
|
||||||
//! the operational boundary around the portal, not the workforce/security report
|
|
||||||
//! implementation itself.
|
|
||||||
|
|
||||||
pub(crate) mod health;
|
pub(crate) mod health;
|
||||||
pub(crate) mod limits;
|
pub(crate) mod limits;
|
||||||
pub(crate) mod logging;
|
pub(crate) mod logging;
|
||||||
|
|||||||
@@ -1,10 +1,3 @@
|
|||||||
//! Readiness probe payload.
|
|
||||||
//!
|
|
||||||
//! CONTRACT: `/readyz` checks whether the portal is safe to receive normal
|
|
||||||
//! traffic. It must remain conservative: configuration errors and broken state
|
|
||||||
//! storage make the process `not_ready`; optional integrations can report
|
|
||||||
//! `disabled`, `not_required` or `contract_only` without failing the whole probe.
|
|
||||||
|
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
|
|
||||||
use serde_json::{Value, json};
|
use serde_json::{Value, json};
|
||||||
|
|||||||
@@ -1,8 +1,3 @@
|
|||||||
//! Request correlation and route classification for portal observability.
|
|
||||||
//!
|
|
||||||
//! CONTRACT: generated route names must not expose volatile identifiers such as
|
|
||||||
//! case IDs, candidate IDs or evidence IDs; use route templates instead.
|
|
||||||
|
|
||||||
use std::cell::RefCell;
|
use std::cell::RefCell;
|
||||||
use std::sync::atomic::{AtomicU64, Ordering};
|
use std::sync::atomic::{AtomicU64, Ordering};
|
||||||
use std::time::{Instant, SystemTime, UNIX_EPOCH};
|
use std::time::{Instant, SystemTime, UNIX_EPOCH};
|
||||||
@@ -78,7 +73,7 @@ fn request_header(request: &Request, name: &str) -> Option<String> {
|
|||||||
request
|
request
|
||||||
.headers()
|
.headers()
|
||||||
.iter()
|
.iter()
|
||||||
.find(|header| header.field.as_str().as_str().eq_ignore_ascii_case(name))
|
.find(|header| header.field.to_string().eq_ignore_ascii_case(name))
|
||||||
.map(|header| header.value.as_str().to_string())
|
.map(|header| header.value.as_str().to_string())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,8 +1,3 @@
|
|||||||
//! Build/version probe payload.
|
|
||||||
//!
|
|
||||||
//! CONTRACT: `/version` is used by smoke tests, runbooks and release evidence.
|
|
||||||
//! Keep field names stable and add new fields only in a backward-compatible way.
|
|
||||||
|
|
||||||
use serde_json::{Value, json};
|
use serde_json::{Value, json};
|
||||||
|
|
||||||
use crate::{Cli, PORTAL_SCHEMA_VERSION};
|
use crate::{Cli, PORTAL_SCHEMA_VERSION};
|
||||||
|
|||||||
+297
-542
@@ -1,667 +1,422 @@
|
|||||||
Полная инструкция по развёртыванию и поддержке AWatch-rus
|
# Полная инструкция по развёртыванию и поддержке ActivityWatch-Russian
|
||||||
|
|
||||||
Статус документа
|
Документ описывает полный цикл: Proxmox/LXC сервер, установка ActivityWatch Server, RU Web UI patch, развёртывание Windows-клиентов в другом AD-домене, валидация, сопровождение и rollback.
|
||||||
|
|
||||||
Этот документ описывает актуальный **Rust-fiWindows/PowerShell deployment flow больше не считается основным способом развёртывания, патчинга или эксплуатации. Если в репозитории остаются старые ".ps1"-файлы, они рассматриваются как legacy/history или как будущий provider-слой, но не как production runtime.
|
---
|
||||||
|
|
||||||
0. Назначение
|
## 0) Структура проекта (полные пути)
|
||||||
|
|
||||||
AWatch-rus — программный комплекс операционного контроля, технического аудита, оценки трудоотдачи сотрудников и мониторинга корпоративной ИТ-инфраструктуры на базе:
|
- `<PROJECT_ROOT>/private-config/deploy.env`
|
||||||
|
- `<PROJECT_ROOT>/proxmox/create-ct.sh`
|
||||||
|
- `<PROJECT_ROOT>/proxmox/push-aw-artifacts.sh`
|
||||||
|
- `<PROJECT_ROOT>/aw-server/install_aw_server.sh`
|
||||||
|
- `<PROJECT_ROOT>/aw-server/apply_webui_ru_patch.sh`
|
||||||
|
- `<PROJECT_ROOT>/windows/deploy-single-user.ps1`
|
||||||
|
- `<PROJECT_ROOT>/windows/deploy-domain-users.ps1`
|
||||||
|
- `<PROJECT_ROOT>/windows/deploy-ensemble.ps1`
|
||||||
|
- `<PROJECT_ROOT>/windows/hardening-recovery.ps1`
|
||||||
|
- `<PROJECT_ROOT>/windows/validate-deployment.ps1`
|
||||||
|
- `<PROJECT_ROOT>/windows/browser-domains-native-collector.ps1`
|
||||||
|
- `<PROJECT_ROOT>/windows/dlp-endpoint-signals-collector.ps1`
|
||||||
|
- `<PROJECT_ROOT>/ansible/deploy_aw_server.yml`
|
||||||
|
- `<PROJECT_ROOT>/ansible/provision_proxmox_ct_and_deploy_aw.yml`
|
||||||
|
- `<PROJECT_ROOT>/ansible/provision_proxmox_ct_matrix_and_deploy_aw.yml`
|
||||||
|
- `<PROJECT_ROOT>/ansible/deploy_aw_windows.yml`
|
||||||
|
|
||||||
- Rust backend/runtime;
|
---
|
||||||
- Rust Agent;
|
|
||||||
- Rust server-rendered HTML + HTMX-compatible JSON API;
|
|
||||||
- Grafana/Prometheus-витрин;
|
|
||||||
- модулей Workforce, Security и Forensics;
|
|
||||||
- evidence/reporting tooling;
|
|
||||||
- ActivityWatch-compatible источников данных, где это применимо.
|
|
||||||
|
|
||||||
Проект не позиционируется как сертифицированная DLP/SIEM/EDR/XDR/СЗИ. DLP, evidence, UEBA и расследовательские функции используются как внутренние аналитические и операционные модули.
|
## 1) Подготовка
|
||||||
|
|
||||||
1. Актуальная архитектура
|
### 1.1 Требования
|
||||||
|
|
||||||
1.1 Основной runtime
|
- Proxmox VE 8/9, доступ root (или sudo с правами на `pct`).
|
||||||
|
- Шаблон Debian 12 LXC на хосте Proxmox.
|
||||||
|
- Windows хост(ы) с PowerShell 5.1+ и правами локального администратора.
|
||||||
|
- Сетевой доступ Windows-клиентов до ActivityWatch Server (`5600/tcp`).
|
||||||
|
|
||||||
Основной production runtime AWatch-rus — Rust-first:
|
### 1.2 Подготовка единого файла секретов
|
||||||
|
|
||||||
- backend/runtime — Rust;
|
Скопируйте шаблон:
|
||||||
- agent — Rust;
|
|
||||||
- portal — Rust server-rendered HTML + HTMX-compatible JSON API;
|
|
||||||
- operational status/check — Rust;
|
|
||||||
- DLP server-side helpers — Rust;
|
|
||||||
- worktime helpers/exporters/prewarm — Rust;
|
|
||||||
- SLO/health/readiness helpers — Rust;
|
|
||||||
- evidence/install-kit tooling — Rust;
|
|
||||||
- auto-heal helpers — Rust, только в безопасном режиме.
|
|
||||||
|
|
||||||
1.2 Что не является основным runtime
|
```bash
|
||||||
|
cp <PROJECT_ROOT>/private-config/deploy.env.example \
|
||||||
|
<PROJECT_ROOT>/private-config/deploy.env
|
||||||
|
```
|
||||||
|
|
||||||
Не считать основным production deployment flow:
|
Заполните в файле `<PROJECT_ROOT>/private-config/deploy.env`:
|
||||||
|
|
||||||
- PowerShell deployment;
|
- все `CT_*` параметры контейнера;
|
||||||
- старые Windows ".ps1" rollout scripts;
|
- все `AW_SERVER_*` параметры сервера;
|
||||||
- ручное исправление production-файлов без release/backup;
|
- `CT_PASSWORD` (реальный пароль).
|
||||||
- прямое редактирование Web UI в "/opt" без воспроизводимого патча;
|
|
||||||
- Python/shell как основной operational runtime, если для компонента уже есть Rust-аналог.
|
|
||||||
|
|
||||||
Python, shell, Ansible или PowerShell могут оставаться в проекте только как:
|
Важно: этот файл подхватывается автоматически скриптами Proxmox.
|
||||||
|
|
||||||
- legacy compatibility;
|
---
|
||||||
- вспомогательные dev/test tools;
|
|
||||||
- миграционные сценарии;
|
|
||||||
- будущие provider-слои;
|
|
||||||
- Telegram/OCR/AI/ETL/MCP helpers, если они явно не входят в Rust-first core.
|
|
||||||
|
|
||||||
2. Типовые роли узлов
|
## 2) Развёртывание сервера в Proxmox
|
||||||
|
|
||||||
2.1 Server node
|
### 2.0 Ansible full-stack (создание CT + установка AW)
|
||||||
|
|
||||||
Серверный узел содержит:
|
Подготовьте:
|
||||||
|
|
||||||
- AWatch-rus backend/runtime;
|
- `<PROJECT_ROOT>/ansible/inventory.ini`
|
||||||
- portal;
|
- `<PROJECT_ROOT>/ansible/group_vars/all.yml`
|
||||||
- API;
|
- `<PROJECT_ROOT>/ansible/group_vars/proxmox.yml`
|
||||||
- exporters;
|
|
||||||
- health/readiness/status tooling;
|
|
||||||
- systemd units/timers;
|
|
||||||
- Grafana/Prometheus integration;
|
|
||||||
- evidence/reporting storage.
|
|
||||||
|
|
||||||
2.2 Agent node
|
Запуск:
|
||||||
|
|
||||||
Agent node содержит:
|
```bash
|
||||||
|
cd <PROJECT_ROOT>/ansible
|
||||||
|
ansible-playbook -i inventory.ini provision_proxmox_ct_and_deploy_aw.yml
|
||||||
|
```
|
||||||
|
|
||||||
- Rust Agent;
|
Этот сценарий полностью закрывает:
|
||||||
- локальную конфигурацию агента;
|
|
||||||
- systemd service или другой штатный supervisor;
|
|
||||||
- локальные логи;
|
|
||||||
- буфер/очередь, если предусмотрено конфигурацией;
|
|
||||||
- сетевой доступ до backend/API.
|
|
||||||
|
|
||||||
2.3 Monitoring node
|
- создание CT в Proxmox;
|
||||||
|
- bootstrap пакетов в CT;
|
||||||
|
- установку ActivityWatch Server;
|
||||||
|
- применение RU Web UI patch;
|
||||||
|
- проверку API.
|
||||||
|
|
||||||
Monitoring node может содержать:
|
Для массового режима (несколько CT):
|
||||||
|
|
||||||
- Prometheus;
|
```bash
|
||||||
- Grafana;
|
cd <PROJECT_ROOT>/ansible
|
||||||
- dashboards;
|
ansible-playbook -i inventory.ini provision_proxmox_ct_matrix_and_deploy_aw.yml
|
||||||
- alerting rules;
|
```
|
||||||
- external logs/metrics storage.
|
|
||||||
|
|
||||||
Monitoring node может совпадать с server node в пилотной установке.
|
### 2.1 Создать LXC контейнер
|
||||||
|
|
||||||
3. Требования
|
На узле Proxmox:
|
||||||
|
|
||||||
3.1 Базовые требования
|
```bash
|
||||||
|
cd <PROJECT_ROOT>
|
||||||
|
<PROJECT_ROOT>/proxmox/create-ct.sh
|
||||||
|
```
|
||||||
|
|
||||||
- Linux-сервер или LXC/VM.
|
По умолчанию читается:
|
||||||
- Доступ администратора к systemd.
|
|
||||||
- Rust toolchain для сборочного узла.
|
|
||||||
- Сетевой доступ между agent node и server node.
|
|
||||||
- Закрытый доступ к API и порталу через VPN, reverse proxy или внутренний контур.
|
|
||||||
- Backup/snapshot перед любым production patch.
|
|
||||||
|
|
||||||
3.2 Рекомендуемый production-подход
|
- `<PROJECT_ROOT>/private-config/deploy.env`
|
||||||
|
|
||||||
Для production не собирать проект прямо на боевом сервере, если есть отдельный build host.
|
При необходимости можно передать другой путь:
|
||||||
|
|
||||||
Рекомендуемый поток:
|
```bash
|
||||||
|
<PROJECT_ROOT>/proxmox/create-ct.sh /absolute/path/to/deploy.env
|
||||||
|
```
|
||||||
|
|
||||||
git checkout нужного commit/tag
|
### 2.2 Загрузить bootstrap-артефакты и env внутрь CT
|
||||||
→ cargo fmt / clippy / test / build
|
|
||||||
→ упаковка release artifacts
|
|
||||||
→ перенос artifacts на сервер
|
|
||||||
→ backup/snapshot
|
|
||||||
→ остановка/перезапуск нужных services
|
|
||||||
→ smoke tests
|
|
||||||
→ фиксация версии
|
|
||||||
|
|
||||||
4. Основные пути
|
```bash
|
||||||
|
cd <PROJECT_ROOT>
|
||||||
|
<PROJECT_ROOT>/proxmox/push-aw-artifacts.sh
|
||||||
|
```
|
||||||
|
|
||||||
Рекомендуемая структура на сервере:
|
Скрипт загружает в CT:
|
||||||
|
|
||||||
/opt/awatch-rus/
|
- `<CT_BOOTSTRAP_DIR>/install_aw_server.sh`
|
||||||
bin/
|
- `<CT_BOOTSTRAP_DIR>/apply_webui_ru_patch.sh`
|
||||||
etc/
|
- `<CT_BOOTSTRAP_DIR>/activitywatch-server.service`
|
||||||
portal/
|
- `<CT_BOOTSTRAP_DIR>/aw-ru-patch.js`
|
||||||
releases/
|
- `<CT_BOOTSTRAP_DIR>/aw-sw-cleanup.js`
|
||||||
evidence/
|
- `/etc/activitywatch/aw-server.env` (из `AW_SERVER_*`)
|
||||||
reports/
|
|
||||||
logs/
|
|
||||||
|
|
||||||
/etc/awatch-rus/
|
### 2.3 Установить ActivityWatch Server внутри CT
|
||||||
awatch-rus.env
|
|
||||||
agent.env
|
|
||||||
portal.env
|
|
||||||
|
|
||||||
/var/lib/awatch-rus/
|
```bash
|
||||||
data/
|
pct enter <CT_ID>
|
||||||
state/
|
bash <CT_BOOTSTRAP_DIR>/install_aw_server.sh
|
||||||
cache/
|
```
|
||||||
evidence/
|
|
||||||
reports/
|
|
||||||
|
|
||||||
/var/log/awatch-rus/
|
### 2.4 Применить RU patch Web UI
|
||||||
backend.log
|
|
||||||
agent.log
|
|
||||||
portal.log
|
|
||||||
exporter.log
|
|
||||||
|
|
||||||
Рекомендуемые runtime binaries:
|
```bash
|
||||||
|
bash <CT_BOOTSTRAP_DIR>/apply_webui_ru_patch.sh
|
||||||
|
systemctl restart activitywatch-server.service
|
||||||
|
```
|
||||||
|
|
||||||
/usr/local/bin/detmir-status
|
После применения патча доступны:
|
||||||
/usr/local/bin/detmir-check
|
|
||||||
/usr/local/bin/detmir-dlp
|
|
||||||
/usr/local/bin/detmir-auto
|
|
||||||
/usr/local/bin/detmir-heal-safe
|
|
||||||
/usr/local/bin/aw-rus-healthd
|
|
||||||
|
|
||||||
Имена конкретных бинарников должны соответствовать текущему "Cargo.toml" и фактически собранным artifacts. Если имя binary изменено, документация и systemd unit должны обновляться в том же commit.
|
- верхнее меню `DLP` в Web UI;
|
||||||
|
- DLP-страница bucket `aw-dlp-endpoint-signals_<HOST>`;
|
||||||
|
- встроенный центр `DLP review и правила`;
|
||||||
|
- служебные buckets `aw-dlp-review_<HOST>` и `aw-dlp-rules_<HOST>`.
|
||||||
|
|
||||||
5. Конфигурация
|
### 2.5 Проверка сервера
|
||||||
|
|
||||||
5.1 Общие правила
|
В CT:
|
||||||
|
|
||||||
- Не хранить production secrets в публичном репозитории.
|
```bash
|
||||||
- Не коммитить реальные hostnames, IP, логины, ФИО, токены, пароли.
|
systemctl status activitywatch-server.service --no-pager
|
||||||
- Для production использовать "/etc/awatch-rus/*.env".
|
curl -fsS http://127.0.0.1:5600/api/0/info
|
||||||
- Для demo использовать только обезличенные fixtures.
|
ss -ltnp | grep 5600
|
||||||
- Все параметры, влияющие на runtime, должны быть описаны в документации.
|
grep -n 'aw-ru-patch\|aw-sw-cleanup' /opt/activitywatch/webui-ru/index.html
|
||||||
|
```
|
||||||
|
|
||||||
5.2 Пример server env
|
Ожидается:
|
||||||
|
|
||||||
AWATCH_ENV=production
|
- сервис `active (running)`;
|
||||||
AWATCH_BIND_ADDR=127.0.0.1
|
- API отвечает JSON;
|
||||||
AWATCH_PORT=5600
|
- порт 5600 слушается;
|
||||||
AWATCH_DATA_DIR=/var/lib/awatch-rus/data
|
- в `index.html` присутствуют оба скрипта.
|
||||||
AWATCH_LOG_DIR=/var/log/awatch-rus
|
|
||||||
AWATCH_EVIDENCE_DIR=/var/lib/awatch-rus/evidence
|
|
||||||
AWATCH_REPORTS_DIR=/var/lib/awatch-rus/reports
|
|
||||||
RUST_LOG=info
|
|
||||||
|
|
||||||
5.3 Пример agent env
|
Дополнительно после первого входа в Web UI:
|
||||||
|
|
||||||
AWATCH_AGENT_ENV=production
|
- `#/home` должен показывать один корректный пункт `DLP`;
|
||||||
AWATCH_SERVER_URL=https://awatch.example.local
|
- `#/buckets/aw-dlp-endpoint-signals_<HOST>` должен открываться без ошибок;
|
||||||
AWATCH_AGENT_HOST_ID=HOSTNAME_OR_NODE_ID
|
- сохранение review/rule должно создавать buckets `aw-dlp-review_<HOST>` и `aw-dlp-rules_<HOST>`.
|
||||||
AWATCH_AGENT_DATA_DIR=/var/lib/awatch-rus/agent
|
|
||||||
AWATCH_AGENT_LOG_DIR=/var/log/awatch-rus
|
|
||||||
RUST_LOG=info
|
|
||||||
|
|
||||||
6. Сборка
|
---
|
||||||
|
|
||||||
6.1 Проверки перед сборкой
|
## 3) Развёртывание Windows-клиентов (другой AD-домен)
|
||||||
|
|
||||||
На build host:
|
### 3.1 Подготовка на Windows-хосте
|
||||||
|
|
||||||
cd /path/to/AWatch-rus
|
Скопируйте каталог:
|
||||||
|
|
||||||
git status --short
|
- `<PROJECT_ROOT>/windows`
|
||||||
cargo fmt --all -- --check
|
|
||||||
cargo clippy --workspace --all-targets -- -D warnings
|
|
||||||
cargo test --workspace
|
|
||||||
|
|
||||||
Если в репозитории есть проектные quality gates, выполнить их обязательно:
|
например в:
|
||||||
|
|
||||||
bash scripts/check_private_config_guard.sh
|
- `C:\Program Files\AWatch-rus\windows`
|
||||||
bash scripts/quality-gate.sh
|
|
||||||
|
|
||||||
Если какой-то скрипт отсутствует в текущей ветке, не создавать фиктивную замену. Зафиксировать это в release notes.
|
Откройте **elevated PowerShell**:
|
||||||
|
|
||||||
6.2 Release build
|
```powershell
|
||||||
|
Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope Process
|
||||||
|
```
|
||||||
|
|
||||||
cargo build --release --workspace
|
### 3.2 Массовое доменное развёртывание (рекомендуется)
|
||||||
|
|
||||||
Проверить artifacts:
|
Если текущий production ещё работает в старых каталогах
|
||||||
|
`C:\Program Files\ActivityWatch-Phase2` и `C:\ProgramData\ActivityWatch-Phase2`,
|
||||||
|
сначала выполните безопасную миграцию:
|
||||||
|
|
||||||
find target/release -maxdepth 1 -type f -executable -print
|
```powershell
|
||||||
|
C:\Program Files\AWatch-rus\windows\migrate-awatch-rus-paths.ps1 -WhatIf
|
||||||
|
C:\Program Files\AWatch-rus\windows\migrate-awatch-rus-paths.ps1
|
||||||
|
```
|
||||||
|
|
||||||
6.3 Упаковка artifacts
|
Скрипт остановит `ActivityWatch Recovery`/`ActivityWatch Launch *`, создаст backup в
|
||||||
|
`C:\ProgramData\AWatch-rus\migration-backups\...`, перенесёт файлы в единые пути,
|
||||||
|
пересоздаст `deployment-config.json`/scheduled tasks и запустит validation.
|
||||||
|
|
||||||
Рекомендуемый вариант:
|
Пример со списком пользователей:
|
||||||
|
|
||||||
mkdir -p dist/awatch-rus-release/bin
|
```powershell
|
||||||
cp target/release/detmir-status dist/awatch-rus-release/bin/ 2>/dev/null || true
|
C:\Program Files\AWatch-rus\windows\deploy-domain-users.ps1 `
|
||||||
cp target/release/detmir-check dist/awatch-rus-release/bin/ 2>/dev/null || true
|
-ServerHost aw.example.local `
|
||||||
cp target/release/detmir-dlp dist/awatch-rus-release/bin/ 2>/dev/null || true
|
-ServerPort 5600 `
|
||||||
cp target/release/detmir-auto dist/awatch-rus-release/bin/ 2>/dev/null || true
|
-Domain CONTOSO `
|
||||||
cp target/release/detmir-heal-safe dist/awatch-rus-release/bin/ 2>/dev/null || true
|
-UserListPath C:\Deploy\aw-users.txt `
|
||||||
cp target/release/aw-rus-healthd dist/awatch-rus-release/bin/ 2>/dev/null || true
|
-CustomRulesPath C:\Program Files\AWatch-rus\windows\web-category-rules.example.json
|
||||||
|
```
|
||||||
|
|
||||||
tar -C dist -czf awatch-rus-release.tar.gz awatch-rus-release
|
Поддерживаемые варианты:
|
||||||
sha256sum awatch-rus-release.tar.gz > awatch-rus-release.tar.gz.sha256
|
|
||||||
|
|
||||||
Не использовать "cp ... || true" в CI без последующей проверки обязательных binaries. Для ручного production release список обязательных binaries должен быть проверен явно.
|
- `-Users user01,user02`
|
||||||
|
- `-Users 'CONTOSO\user01','CONTOSO\user02'`
|
||||||
|
- `-UserListPath <txt|csv>`
|
||||||
|
|
||||||
7. Первичное развёртывание server node
|
### 3.2.1 Ensemble orchestration (рекомендуется для production)
|
||||||
|
|
||||||
7.1 Создание каталогов
|
```powershell
|
||||||
|
C:\Program Files\AWatch-rus\windows\deploy-ensemble.ps1 `
|
||||||
|
-ServerHost aw.example.local `
|
||||||
|
-ServerPort 5600 `
|
||||||
|
-Domain CONTOSO `
|
||||||
|
-Users user1,user2,user3,user4,user5 `
|
||||||
|
-ValidateAfterDeploy
|
||||||
|
```
|
||||||
|
|
||||||
sudo mkdir -p /opt/awatch-rus/bin
|
Отчёт сохраняется в:
|
||||||
sudo mkdir -p /opt/awatch-rus/releases
|
|
||||||
sudo mkdir -p /etc/awatch-rus
|
|
||||||
sudo mkdir -p /var/lib/awatch-rus/data
|
|
||||||
sudo mkdir -p /var/lib/awatch-rus/state
|
|
||||||
sudo mkdir -p /var/lib/awatch-rus/evidence
|
|
||||||
sudo mkdir -p /var/lib/awatch-rus/reports
|
|
||||||
sudo mkdir -p /var/log/awatch-rus
|
|
||||||
|
|
||||||
7.2 Установка binaries
|
- `C:\ProgramData\AWatch-rus\ensemble-report-YYYYMMDD-HHMMSS.json`
|
||||||
|
|
||||||
sudo install -m 0755 dist/awatch-rus-release/bin/* /opt/awatch-rus/bin/
|
### 3.3 Single-user развёртывание
|
||||||
|
|
||||||
Создать symlink для удобства:
|
```powershell
|
||||||
|
C:\Program Files\AWatch-rus\windows\deploy-single-user.ps1 `
|
||||||
|
-ServerHost aw.example.local `
|
||||||
|
-ServerPort 5600 `
|
||||||
|
-TargetUser 'CONTOSO\user01' `
|
||||||
|
-CustomRulesPath C:\Program Files\AWatch-rus\windows\web-category-rules.example.json
|
||||||
|
```
|
||||||
|
|
||||||
sudo ln -sf /opt/awatch-rus/bin/detmir-status /usr/local/bin/detmir-status
|
### 3.4 Recovery / hardening
|
||||||
sudo ln -sf /opt/awatch-rus/bin/detmir-check /usr/local/bin/detmir-check
|
|
||||||
sudo ln -sf /opt/awatch-rus/bin/detmir-dlp /usr/local/bin/detmir-dlp
|
|
||||||
|
|
||||||
Если binary отсутствует, не создавать пустой symlink. Сначала проверить фактический состав release artifact.
|
```powershell
|
||||||
|
C:\Program Files\AWatch-rus\windows\hardening-recovery.ps1 `
|
||||||
|
-ConfigPath C:\ProgramData\AWatch-rus\deployment-config.json
|
||||||
|
```
|
||||||
|
|
||||||
7.3 Конфигурация
|
### 3.5 Валидация deployment-а (PowerShell report)
|
||||||
|
|
||||||
sudo install -m 0640 awatch-rus.env /etc/awatch-rus/awatch-rus.env
|
```powershell
|
||||||
|
$report = C:\Program Files\AWatch-rus\windows\validate-deployment.ps1 `
|
||||||
|
-ConfigPath C:\ProgramData\AWatch-rus\deployment-config.json
|
||||||
|
$report | ConvertTo-Json -Depth 12
|
||||||
|
```
|
||||||
|
|
||||||
Проверить права:
|
---
|
||||||
|
|
||||||
sudo chown root:root /etc/awatch-rus/awatch-rus.env
|
## 4) Что должно появиться на Windows после установки
|
||||||
sudo chmod 0640 /etc/awatch-rus/awatch-rus.env
|
|
||||||
|
|
||||||
8. systemd units
|
- `C:\Program Files\AWatch-rus\bin`
|
||||||
|
- `C:\ProgramData\AWatch-rus\deployment-config.json`
|
||||||
|
- `C:\ProgramData\AWatch-rus\launch-watchers.ps1`
|
||||||
|
- `C:\ProgramData\AWatch-rus\recovery-loop.ps1`
|
||||||
|
- `C:\ProgramData\AWatch-rus\browser-domains-native-collector.ps1`
|
||||||
|
- `C:\ProgramData\AWatch-rus\web-category-rules.json`
|
||||||
|
- `C:\ProgramData\AWatch-rus\logs\`
|
||||||
|
|
||||||
8.1 Пример backend service
|
Задачи планировщика:
|
||||||
|
|
||||||
[Unit]
|
- `ActivityWatch Launch [<user>]` (per-user, при логоне)
|
||||||
Description=AWatch-rus backend/runtime
|
- `ActivityWatch Recovery` (system-level recovery)
|
||||||
After=network-online.target
|
|
||||||
Wants=network-online.target
|
|
||||||
|
|
||||||
[Service]
|
---
|
||||||
Type=simple
|
|
||||||
EnvironmentFile=/etc/awatch-rus/awatch-rus.env
|
|
||||||
ExecStart=/opt/awatch-rus/bin/awatch-rus-backend
|
|
||||||
Restart=on-failure
|
|
||||||
RestartSec=5
|
|
||||||
WorkingDirectory=/opt/awatch-rus
|
|
||||||
NoNewPrivileges=true
|
|
||||||
PrivateTmp=true
|
|
||||||
ProtectSystem=full
|
|
||||||
ProtectHome=true
|
|
||||||
ReadWritePaths=/var/lib/awatch-rus /var/log/awatch-rus
|
|
||||||
|
|
||||||
[Install]
|
## 5) Полная валидация потока данных
|
||||||
WantedBy=multi-user.target
|
|
||||||
|
|
||||||
Если фактическое имя backend binary отличается, заменить "awatch-rus-backend" на актуальное имя из release artifact.
|
### 5.1 На Windows-хосте
|
||||||
|
|
||||||
8.2 Пример health service
|
Проверить процессы:
|
||||||
|
|
||||||
[Unit]
|
```powershell
|
||||||
Description=AWatch-rus health daemon
|
Get-Process aw-watcher-afk,aw-watcher-window -ErrorAction SilentlyContinue
|
||||||
After=network-online.target
|
Get-CimInstance Win32_Process | ? { $_.CommandLine -like '*browser-domains-native-collector.ps1*' } | select ProcessId,SessionId,CommandLine
|
||||||
Wants=network-online.target
|
```
|
||||||
|
|
||||||
[Service]
|
Проверить задачи:
|
||||||
Type=simple
|
|
||||||
EnvironmentFile=/etc/awatch-rus/awatch-rus.env
|
|
||||||
ExecStart=/opt/awatch-rus/bin/aw-rus-healthd
|
|
||||||
Restart=on-failure
|
|
||||||
RestartSec=5
|
|
||||||
WorkingDirectory=/opt/awatch-rus
|
|
||||||
NoNewPrivileges=true
|
|
||||||
PrivateTmp=true
|
|
||||||
ProtectSystem=full
|
|
||||||
ProtectHome=true
|
|
||||||
ReadWritePaths=/var/lib/awatch-rus /var/log/awatch-rus
|
|
||||||
|
|
||||||
[Install]
|
```powershell
|
||||||
WantedBy=multi-user.target
|
Get-ScheduledTask | ? { $_.TaskName -like 'ActivityWatch*' } | select TaskName,State
|
||||||
|
```
|
||||||
|
|
||||||
8.3 Применение unit files
|
### 5.2 На сервере ActivityWatch API
|
||||||
|
|
||||||
sudo systemctl daemon-reload
|
```bash
|
||||||
sudo systemctl enable --now awatch-rus-backend.service
|
curl -sS http://127.0.0.1:5600/api/0/buckets | jq 'keys'
|
||||||
sudo systemctl enable --now aw-rus-healthd.service
|
```
|
||||||
|
|
||||||
Если конкретный unit не используется в текущей инсталляции, не создавать фиктивный сервис. Документировать фактический набор services.
|
Ожидаемые bucket'ы:
|
||||||
|
|
||||||
9. Развёртывание Rust Agent
|
- `aw-watcher-afk_<HOST>`
|
||||||
|
- `aw-watcher-window_<HOST>`
|
||||||
|
- `aw-watcher-web-<browser>_<HOST>`
|
||||||
|
- `aw-detmir-web-category_<HOST>` (категоризованный поток)
|
||||||
|
- `aw-dlp-endpoint-signals_<HOST>` (endpoint сигналы)
|
||||||
|
- `aw-dlp-review_<HOST>` (ручная классификация через UI)
|
||||||
|
- `aw-dlp-rules_<HOST>` (suppress/rule записи через UI)
|
||||||
|
|
||||||
9.1 Установка agent binary
|
Проверка событий браузера:
|
||||||
|
|
||||||
sudo mkdir -p /opt/awatch-rus/bin
|
```bash
|
||||||
sudo mkdir -p /etc/awatch-rus
|
curl -sS "http://127.0.0.1:5600/api/0/buckets/aw-watcher-web-edge_<HOST>/events?limit=5" | jq
|
||||||
sudo mkdir -p /var/lib/awatch-rus/agent
|
```
|
||||||
sudo mkdir -p /var/log/awatch-rus
|
|
||||||
|
|
||||||
sudo install -m 0755 awatch-rus-agent /opt/awatch-rus/bin/awatch-rus-agent
|
Проверка категоризации:
|
||||||
sudo install -m 0640 agent.env /etc/awatch-rus/agent.env
|
|
||||||
|
|
||||||
9.2 Пример agent service
|
```bash
|
||||||
|
curl -sS "http://127.0.0.1:5600/api/0/buckets/aw-detmir-web-category_<HOST>/events?limit=5" | jq
|
||||||
|
```
|
||||||
|
|
||||||
[Unit]
|
Проверка DLP review/rules:
|
||||||
Description=AWatch-rus Rust Agent
|
|
||||||
After=network-online.target
|
|
||||||
Wants=network-online.target
|
|
||||||
|
|
||||||
[Service]
|
```bash
|
||||||
Type=simple
|
curl -sS "http://127.0.0.1:5600/api/0/buckets/aw-dlp-review_<HOST>/events?limit=20" | jq
|
||||||
EnvironmentFile=/etc/awatch-rus/agent.env
|
curl -sS "http://127.0.0.1:5600/api/0/buckets/aw-dlp-rules_<HOST>/events?limit=20" | jq
|
||||||
ExecStart=/opt/awatch-rus/bin/awatch-rus-agent
|
```
|
||||||
Restart=on-failure
|
|
||||||
RestartSec=5
|
|
||||||
WorkingDirectory=/opt/awatch-rus
|
|
||||||
NoNewPrivileges=true
|
|
||||||
PrivateTmp=true
|
|
||||||
ProtectSystem=full
|
|
||||||
ProtectHome=true
|
|
||||||
ReadWritePaths=/var/lib/awatch-rus /var/log/awatch-rus
|
|
||||||
|
|
||||||
[Install]
|
Ожидаемые поля review:
|
||||||
WantedBy=multi-user.target
|
|
||||||
|
|
||||||
9.3 Запуск agent
|
- `reviewId`
|
||||||
|
- `signalType`
|
||||||
|
- `verdict`
|
||||||
|
- `category`
|
||||||
|
- `comment`
|
||||||
|
- `archived`
|
||||||
|
|
||||||
sudo systemctl daemon-reload
|
Ожидаемые поля rules:
|
||||||
sudo systemctl enable --now awatch-rus-agent.service
|
|
||||||
sudo systemctl status awatch-rus-agent.service --no-pager
|
|
||||||
|
|
||||||
10. Развёртывание портала
|
- `ruleId`
|
||||||
|
- `signalType`
|
||||||
|
- `match`
|
||||||
|
- `category`
|
||||||
|
- `comment`
|
||||||
|
- `enabled`
|
||||||
|
|
||||||
Портальный слой AWatch-rus зафиксирован как Rust server-rendered HTML + HTMX-compatible JSON API.
|
---
|
||||||
|
|
||||||
10.1 Общий порядок
|
## 6) Сопровождение (обязательно)
|
||||||
|
|
||||||
build portal/backend binary
|
### 6.1 Backup перед любыми изменениями
|
||||||
→ install binary
|
|
||||||
→ install templates/static assets, если они выделены отдельно
|
|
||||||
→ update portal env
|
|
||||||
→ restart portal service
|
|
||||||
→ smoke check HTTP/API routes
|
|
||||||
|
|
||||||
10.2 Проверка портала
|
На Proxmox:
|
||||||
|
|
||||||
curl -fsS http://127.0.0.1:5600/healthz
|
|
||||||
curl -fsS http://127.0.0.1:5600/readyz
|
|
||||||
curl -fsS http://127.0.0.1:5600/version
|
|
||||||
|
|
||||||
Если конкретные endpoints в текущей версии отличаются, использовать фактически реализованные health/readiness/version endpoints и обновить этот документ в том же commit.
|
|
||||||
|
|
||||||
11. Патчи в развернутой среде
|
|
||||||
|
|
||||||
11.1 Правило
|
|
||||||
|
|
||||||
Любой production patch применяется только через контролируемый цикл:
|
|
||||||
|
|
||||||
определить commit/tag
|
|
||||||
→ собрать release artifact
|
|
||||||
→ выполнить локальные проверки
|
|
||||||
→ сделать backup/snapshot
|
|
||||||
→ установить новые binaries/configs
|
|
||||||
→ restart/reload services
|
|
||||||
→ smoke tests
|
|
||||||
→ зафиксировать результат
|
|
||||||
→ сохранить rollback path
|
|
||||||
|
|
||||||
11.2 Перед патчем
|
|
||||||
|
|
||||||
git rev-parse HEAD
|
|
||||||
git status --short
|
|
||||||
|
|
||||||
Сохранить:
|
|
||||||
|
|
||||||
дата/время
|
|
||||||
commit/tag
|
|
||||||
кто применяет
|
|
||||||
какие services затрагиваются
|
|
||||||
какой rollback path
|
|
||||||
|
|
||||||
11.3 Backup перед патчем
|
|
||||||
|
|
||||||
Если используется Proxmox/LXC:
|
|
||||||
|
|
||||||
|
```bash
|
||||||
vzdump <CT_ID> --mode snapshot --compress zstd --storage <BACKUP_STORAGE>
|
vzdump <CT_ID> --mode snapshot --compress zstd --storage <BACKUP_STORAGE>
|
||||||
|
```
|
||||||
|
|
||||||
Внутри сервера:
|
Конфиги внутри CT:
|
||||||
|
|
||||||
sudo tar -C / -czf /root/awatch-rus-backup-$(date +%Y%m%d-%H%M%S).tgz \
|
```bash
|
||||||
etc/awatch-rus \
|
pct exec <CT_ID> -- tar -C / -czf <PRIVATE_BACKUP_DIR>/activitywatch-config-backup.tgz \
|
||||||
opt/awatch-rus \
|
etc/activitywatch \
|
||||||
var/lib/awatch-rus \
|
etc/systemd/system/activitywatch-server.service \
|
||||||
var/log/awatch-rus
|
opt/activitywatch/webui-ru \
|
||||||
|
opt/activitywatch/releases
|
||||||
|
```
|
||||||
|
|
||||||
Если данные большие, backup "/var/lib/awatch-rus" выполнять отдельной процедурой согласно backup policy.
|
### 6.2 Обновление сервера
|
||||||
|
|
||||||
11.4 Установка нового binary
|
1. Обновить `AW_SERVER_VERSION` и `AW_SERVER_DOWNLOAD_URL` в
|
||||||
|
`<PROJECT_ROOT>/private-config/deploy.env`
|
||||||
|
2. Выполнить:
|
||||||
|
|
||||||
Сохранить предыдущую версию:
|
```bash
|
||||||
|
<PROJECT_ROOT>/proxmox/push-aw-artifacts.sh
|
||||||
|
pct enter <CT_ID>
|
||||||
|
bash <CT_BOOTSTRAP_DIR>/install_aw_server.sh
|
||||||
|
bash <CT_BOOTSTRAP_DIR>/apply_webui_ru_patch.sh
|
||||||
|
systemctl restart activitywatch-server.service
|
||||||
|
```
|
||||||
|
|
||||||
sudo mkdir -p /opt/awatch-rus/releases/previous
|
3. Повторить валидацию API/UI.
|
||||||
sudo cp -a /opt/awatch-rus/bin /opt/awatch-rus/releases/previous/bin-$(date +%Y%m%d-%H%M%S)
|
|
||||||
|
|
||||||
Установить новый artifact:
|
### 6.3 Rollback
|
||||||
|
|
||||||
sudo install -m 0755 dist/awatch-rus-release/bin/* /opt/awatch-rus/bin/
|
RU patch rollback:
|
||||||
|
|
||||||
11.5 Restart services
|
```bash
|
||||||
|
cp /opt/activitywatch/webui-ru/index.html.bak.<timestamp> /opt/activitywatch/webui-ru/index.html
|
||||||
|
systemctl restart activitywatch-server.service
|
||||||
|
```
|
||||||
|
|
||||||
sudo systemctl daemon-reload
|
Полный rollback:
|
||||||
sudo systemctl restart awatch-rus-backend.service
|
|
||||||
sudo systemctl restart aw-rus-healthd.service
|
|
||||||
|
|
||||||
Если патч касается только agent:
|
- восстановить CT из snapshot/backup;
|
||||||
|
- проверить API и Web UI;
|
||||||
|
- проверить доступность для Windows-клиентов.
|
||||||
|
|
||||||
sudo systemctl restart awatch-rus-agent.service
|
---
|
||||||
|
|
||||||
Если сервис в текущем контуре называется иначе, использовать фактическое имя systemd unit.
|
## 7) Безопасность
|
||||||
|
|
||||||
12. Smoke-тесты после патча
|
- Не хранить реальные приватные параметры вне `<PROJECT_ROOT>/private-config/deploy.env`.
|
||||||
|
- Не открывать `5600/tcp` в интернет напрямую.
|
||||||
|
- Публиковать через VPN или reverse proxy с ограничением доступа.
|
||||||
|
- Перед изменениями всегда делать backup.
|
||||||
|
|
||||||
12.1 Systemd
|
---
|
||||||
|
|
||||||
systemctl --failed --no-pager
|
## 8) Короткий чек-лист ввода в эксплуатацию
|
||||||
systemctl status awatch-rus-backend.service --no-pager
|
|
||||||
systemctl status aw-rus-healthd.service --no-pager
|
|
||||||
|
|
||||||
12.2 Rust operational checks
|
1. Заполнен `<PROJECT_ROOT>/private-config/deploy.env`.
|
||||||
|
2. Выполнен `<PROJECT_ROOT>/proxmox/create-ct.sh`.
|
||||||
detmir-status --json
|
3. Выполнен `<PROJECT_ROOT>/proxmox/push-aw-artifacts.sh`.
|
||||||
detmir-check --json
|
4. В CT выполнены `<CT_BOOTSTRAP_DIR>/install_aw_server.sh` и `<CT_BOOTSTRAP_DIR>/apply_webui_ru_patch.sh`.
|
||||||
detmir-dlp --json
|
5. Сервер API/порт/UI проверены.
|
||||||
|
6. На Windows выполнен `deploy-domain-users.ps1`.
|
||||||
Если отдельная команда не установлена в данном контуре, это не считается ошибкой только при наличии документированного исключения.
|
7. Проверены процессы, задачи и bucket'ы.
|
||||||
|
8. Зафиксированы параметры и дата ввода.
|
||||||
12.3 HTTP/API
|
|
||||||
|
|
||||||
curl -fsS http://127.0.0.1:5600/healthz
|
|
||||||
curl -fsS http://127.0.0.1:5600/readyz
|
|
||||||
curl -fsS http://127.0.0.1:5600/version
|
|
||||||
|
|
||||||
12.4 Portal smoke
|
|
||||||
|
|
||||||
Проверить в браузере:
|
|
||||||
|
|
||||||
/portal
|
|
||||||
/portal/reports
|
|
||||||
/portal/architecture
|
|
||||||
|
|
||||||
Для Pilot v1 проверить роли:
|
|
||||||
|
|
||||||
executive
|
|
||||||
manager
|
|
||||||
security
|
|
||||||
forensics
|
|
||||||
admin
|
|
||||||
|
|
||||||
12.5 Data freshness
|
|
||||||
|
|
||||||
Проверить, что витрины и отчёты не пустые из-за сбоя сбора:
|
|
||||||
|
|
||||||
последние события поступают
|
|
||||||
worktime reports обновляются
|
|
||||||
DLP/security events отображаются, если включены
|
|
||||||
evidence/reporting не падает
|
|
||||||
Grafana dashboards открываются
|
|
||||||
|
|
||||||
13. Rollback
|
|
||||||
|
|
||||||
13.1 Быстрый rollback binary
|
|
||||||
|
|
||||||
Найти предыдущий backup:
|
|
||||||
|
|
||||||
ls -lah /opt/awatch-rus/releases/previous/
|
|
||||||
|
|
||||||
Восстановить:
|
|
||||||
|
|
||||||
sudo rsync -a --delete /opt/awatch-rus/releases/previous/bin-YYYYMMDD-HHMMSS/ /opt/awatch-rus/bin/
|
|
||||||
sudo systemctl restart awatch-rus-backend.service
|
|
||||||
sudo systemctl restart aw-rus-healthd.service
|
|
||||||
|
|
||||||
13.2 Rollback конфигурации
|
|
||||||
|
|
||||||
sudo cp /etc/awatch-rus/awatch-rus.env.bak /etc/awatch-rus/awatch-rus.env
|
|
||||||
sudo systemctl restart awatch-rus-backend.service
|
|
||||||
|
|
||||||
13.3 Rollback CT/VM
|
|
||||||
|
|
||||||
Если повреждение затрагивает runtime, данные или systemd-конфигурацию:
|
|
||||||
|
|
||||||
остановить сервисы
|
|
||||||
восстановить snapshot/backup
|
|
||||||
проверить health/readiness/version
|
|
||||||
проверить портал
|
|
||||||
проверить поступление данных
|
|
||||||
зафиксировать incident note
|
|
||||||
|
|
||||||
14. Monitoring
|
|
||||||
|
|
||||||
14.1 Что должно контролироваться
|
|
||||||
|
|
||||||
- service status;
|
|
||||||
- process uptime;
|
|
||||||
- API health/readiness;
|
|
||||||
- latency;
|
|
||||||
- error rate;
|
|
||||||
- freshness данных;
|
|
||||||
- заполненность диска;
|
|
||||||
- размер логов;
|
|
||||||
- успешность exporters;
|
|
||||||
- SLO status;
|
|
||||||
- agent coverage;
|
|
||||||
- отсутствие failed systemd units.
|
|
||||||
|
|
||||||
14.2 Grafana
|
|
||||||
|
|
||||||
В Grafana должны быть разделены витрины:
|
|
||||||
|
|
||||||
- executive dashboard;
|
|
||||||
- security dashboard;
|
|
||||||
- operations dashboard;
|
|
||||||
- RDP/user activity dashboard;
|
|
||||||
- data quality/freshness dashboard;
|
|
||||||
- DLP/evidence dashboard, если модуль включён.
|
|
||||||
|
|
||||||
14.3 Prometheus
|
|
||||||
|
|
||||||
Prometheus scrape должен быть доступен только из внутреннего контура мониторинга. Не открывать metrics endpoints наружу.
|
|
||||||
|
|
||||||
15. Security hardening
|
|
||||||
|
|
||||||
Обязательные правила:
|
|
||||||
|
|
||||||
- не публиковать API напрямую в интернет;
|
|
||||||
- использовать VPN/reverse proxy/access control;
|
|
||||||
- закрыть лишние порты;
|
|
||||||
- хранить secrets вне git;
|
|
||||||
- ограничить права systemd services;
|
|
||||||
- использовать отдельного service user, если это поддерживается текущей установкой;
|
|
||||||
- включить backup;
|
|
||||||
- проверять логи после каждого патча;
|
|
||||||
- не использовать demo fixtures как production data;
|
|
||||||
- не смешивать реальные ФИО/IP/hostname с публичными demo screenshots.
|
|
||||||
|
|
||||||
16. Проверка перед вводом в эксплуатацию
|
|
||||||
|
|
||||||
Минимальный checklist:
|
|
||||||
|
|
||||||
[ ] выбран commit/tag release
|
|
||||||
[ ] cargo fmt прошёл
|
|
||||||
[ ] cargo clippy прошёл
|
|
||||||
[ ] cargo test прошёл
|
|
||||||
[ ] cargo build --release прошёл
|
|
||||||
[ ] private config guard прошёл
|
|
||||||
[ ] backup/snapshot создан
|
|
||||||
[ ] binaries установлены
|
|
||||||
[ ] systemd services запущены
|
|
||||||
[ ] health/readiness/version отвечают
|
|
||||||
[ ] detmir-status/check/dlp работают
|
|
||||||
[ ] portal открывается
|
|
||||||
[ ] роли Pilot v1 проверены
|
|
||||||
[ ] Grafana dashboards открываются
|
|
||||||
[ ] данные поступают
|
|
||||||
[ ] rollback path известен
|
|
||||||
[ ] дата/commit/оператор зафиксированы
|
|
||||||
|
|
||||||
17. Что больше не использовать как основной путь
|
|
||||||
|
|
||||||
Не использовать как основной production flow:
|
|
||||||
|
|
||||||
windows/deploy-single-user.ps1
|
|
||||||
windows/deploy-domain-users.ps1
|
|
||||||
windows/deploy-ensemble.ps1
|
|
||||||
windows/validate-deployment.ps1
|
|
||||||
windows/hardening-recovery.ps1
|
|
||||||
windows/browser-domains-native-collector.ps1
|
|
||||||
windows/dlp-endpoint-signals-collector.ps1
|
|
||||||
|
|
||||||
Если эти файлы физически остаются в репозитории, они должны быть явно помечены как:
|
|
||||||
|
|
||||||
legacy
|
|
||||||
planned provider
|
|
||||||
migration-only
|
|
||||||
dev/test helper
|
|
||||||
|
|
||||||
Они не должны описываться в основном deployment manual как обязательный production-путь.
|
|
||||||
|
|
||||||
18. Короткий production runbook
|
|
||||||
|
|
||||||
18.1 Развернуть
|
|
||||||
|
|
||||||
cargo fmt --all -- --check
|
|
||||||
cargo clippy --workspace --all-targets -- -D warnings
|
|
||||||
cargo test --workspace
|
|
||||||
cargo build --release --workspace
|
|
||||||
|
|
||||||
sudo install -m 0755 target/release/<binary> /opt/awatch-rus/bin/<binary>
|
|
||||||
sudo systemctl daemon-reload
|
|
||||||
sudo systemctl restart <service>.service
|
|
||||||
|
|
||||||
18.2 Проверить
|
|
||||||
|
|
||||||
systemctl --failed --no-pager
|
|
||||||
detmir-status --json
|
|
||||||
detmir-check --json
|
|
||||||
curl -fsS http://127.0.0.1:5600/healthz
|
|
||||||
curl -fsS http://127.0.0.1:5600/readyz
|
|
||||||
curl -fsS http://127.0.0.1:5600/version
|
|
||||||
|
|
||||||
18.3 Откатить
|
|
||||||
|
|
||||||
sudo rsync -a --delete /opt/awatch-rus/releases/previous/bin-YYYYMMDD-HHMMSS/ /opt/awatch-rus/bin/
|
|
||||||
sudo systemctl restart <service>.service
|
|
||||||
|
|
||||||
19. Правило актуализации этого документа
|
|
||||||
|
|
||||||
Если меняется:
|
|
||||||
|
|
||||||
- имя binary;
|
|
||||||
- имя systemd unit;
|
|
||||||
- порт;
|
|
||||||
- endpoint;
|
|
||||||
- путь хранения данных;
|
|
||||||
- способ сборки;
|
|
||||||
- способ доставки artifacts;
|
|
||||||
- smoke-test;
|
|
||||||
- rollback procedure;
|
|
||||||
|
|
||||||
то этот файл должен обновляться в том же commit, что и изменение кода или deployment-конфигурации.
|
|
||||||
|
|||||||
@@ -1,78 +0,0 @@
|
|||||||
# GitHub-сборка Rust-бинарников AWatch-rus
|
|
||||||
|
|
||||||
## Принятое решение
|
|
||||||
|
|
||||||
Для проекта AWatch-rus каноническая release-сборка Rust-бинарников выполняется в GitHub Actions.
|
|
||||||
|
|
||||||
Локальная сборка используется для разработки и предварительной проверки. Официальным источником release-бинарников считаются только artifacts, полученные из GitHub Actions на конкретном commit или tag.
|
|
||||||
|
|
||||||
## Toolchain
|
|
||||||
|
|
||||||
Версия Rust/Cargo фиксируется в `rust-toolchain.toml`:
|
|
||||||
|
|
||||||
```toml
|
|
||||||
[toolchain]
|
|
||||||
channel = "1.94.0"
|
|
||||||
profile = "minimal"
|
|
||||||
components = ["rustfmt", "clippy"]
|
|
||||||
```
|
|
||||||
|
|
||||||
Workflow должны запускать Cargo явно:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
cargo +1.94.0 --version
|
|
||||||
rustc +1.94.0 --version
|
|
||||||
cargo +1.94.0 fmt --manifest-path adk-rust/Cargo.toml --all -- --check
|
|
||||||
cargo +1.94.0 test --manifest-path adk-rust/Cargo.toml --workspace --no-fail-fast
|
|
||||||
cargo +1.94.0 clippy --manifest-path adk-rust/Cargo.toml --workspace --all-targets -- -D warnings
|
|
||||||
cargo +1.94.0 build --manifest-path adk-rust/Cargo.toml --workspace --release
|
|
||||||
```
|
|
||||||
|
|
||||||
Это исключает ситуацию, когда GitHub runner использует старый системный Cargo.
|
|
||||||
|
|
||||||
## Workflow
|
|
||||||
|
|
||||||
Основные workflow:
|
|
||||||
|
|
||||||
- `.github/workflows/rust-workspace.yml` — fmt, tests, clippy, release build всего workspace.
|
|
||||||
- `.github/workflows/rust-professionalization-check.yml` — PR smoke для изменяемых Rust-крейтов.
|
|
||||||
- `.github/workflows/rust-binary-build.yml` — сборка release-бинарников Linux x86_64 и публикация GitHub Actions artifact.
|
|
||||||
|
|
||||||
## rust-binary-build
|
|
||||||
|
|
||||||
Workflow `rust-binary-build` запускается:
|
|
||||||
|
|
||||||
- вручную через GitHub Actions -> rust-binary-build -> Run workflow;
|
|
||||||
- автоматически при push tag вида `v*`.
|
|
||||||
|
|
||||||
Внутри workflow выполняется:
|
|
||||||
|
|
||||||
1. checkout repository;
|
|
||||||
2. установка Rust/Cargo 1.94.0;
|
|
||||||
3. вывод версий `cargo` и `rustc`;
|
|
||||||
4. format check;
|
|
||||||
5. workspace tests;
|
|
||||||
6. workspace clippy;
|
|
||||||
7. workspace release build;
|
|
||||||
8. upload artifact `awatch-rus-linux-x86_64-release-binaries`.
|
|
||||||
|
|
||||||
## Правило проекта
|
|
||||||
|
|
||||||
Перед передачей бинарников на пилот, демонстрацию или релиз нужно использовать GitHub Actions artifact, а не локально собранный файл.
|
|
||||||
|
|
||||||
Минимальные признаки корректного artifact:
|
|
||||||
|
|
||||||
- workflow завершился успешно;
|
|
||||||
- в логах указан Rust/Cargo 1.94.0;
|
|
||||||
- build выполнен из нужного commit или tag;
|
|
||||||
- artifact скачан из GitHub Actions.
|
|
||||||
|
|
||||||
## Дальнейшие улучшения
|
|
||||||
|
|
||||||
Отдельными PR можно добавить:
|
|
||||||
|
|
||||||
- SHA256SUMS для каждого бинарника;
|
|
||||||
- автоматическую публикацию в GitHub Release при tag `v*`;
|
|
||||||
- Windows x86_64 build для endpoint-компонентов;
|
|
||||||
- Linux static/musl build при необходимости;
|
|
||||||
- подпись release artifacts.
|
|
||||||
@@ -0,0 +1,89 @@
|
|||||||
|
# Профессиональные сильные стороны проекта AWatch-rus
|
||||||
|
|
||||||
|
Ниже — структурированная, формальная сводка ключевых преимуществ AWatch-rus,
|
||||||
|
подходит для включения в пакет документов при регистрации в реестре ПО и для
|
||||||
|
технического аудита.
|
||||||
|
|
||||||
|
## 1. Архитектура и инженерный дизайн
|
||||||
|
|
||||||
|
- Rust-first, модульная архитектура: более 40 специализированных крейтов в
|
||||||
|
workspace, четкая декомпозиция ответственности и воспроизводимые сборки
|
||||||
|
(Cargo.lock).
|
||||||
|
- Разделение на логические уровни: endpoint → серверные хранилища → processing
|
||||||
|
→ operator → automation, что упрощает тестирование, валидацию и аудит.
|
||||||
|
- Workspace resolver v3 и требуемая версия rust (1.85) — современный базис для
|
||||||
|
поддержки и сопровождения.
|
||||||
|
- Четкие migration-runbooks для последовательного и безопасного перехода
|
||||||
|
legacy Python → Rust.
|
||||||
|
|
||||||
|
## 2. Операционная зрелость и автоматизация
|
||||||
|
|
||||||
|
- Полноценный Ansible-ensemble для end-to-end развёртывания (Proxmox, Linux,
|
||||||
|
централизованный Windows rollout по WinRM) с retry-политикой, smoke-тестами
|
||||||
|
и пост-deploy валидацией.
|
||||||
|
- Safe-run pattern: dry-run/apply planners, backup-before-delete, atomic
|
||||||
|
операции, conservative no-restart paths — минимизация риска при операциях.
|
||||||
|
- Набор диагностических модулей (detmir-*, aw-*, quality-gate, smoke checks)
|
||||||
|
обеспечивает быстрый feedback и ускоряет внедрение.
|
||||||
|
|
||||||
|
## 3. Безопасность и обращение с evidence
|
||||||
|
|
||||||
|
- Изолированный путь evidence: opaque IDs, bearer-upload, magic validation для
|
||||||
|
PNG/JPEG, ограничение размера, SHA-256 валидация, atomic write и детальные
|
||||||
|
audit trails.
|
||||||
|
- Security hardening guide: обязательное TLS, reverse-proxy, firewall rules,
|
||||||
|
минимальные привилегии для сервисных аккаунтов и контроль доступа к
|
||||||
|
evidence-материалам.
|
||||||
|
- Позиционирование: продукт не позиционируется как сертифицированная DLP/SIEM/
|
||||||
|
EDR — это уменьшает юридические риски при регистрации и определяет четкие
|
||||||
|
ожидания заказчика.
|
||||||
|
|
||||||
|
## 4. Production-readiness и критерии приёмки
|
||||||
|
|
||||||
|
- Полный комплект acceptance и pilot-checklists (30-дневный Pilot Success
|
||||||
|
Criteria) с метриками: доступность портала, coverage источников, freshness
|
||||||
|
данных, время загрузки сценариев Executive/Reporting, доля подтверждённых
|
||||||
|
incident candidates.
|
||||||
|
- Runbooks для восстановления, backup & restore сценарии и documented rollback
|
||||||
|
steps.
|
||||||
|
|
||||||
|
## 5. Наблюдаемость, качество данных и объяснимость
|
||||||
|
|
||||||
|
- Встроенные SLO/health monitoring, Prometheus + Grafana витрины и
|
||||||
|
детализированные smoke/contour тесты для проверки консистентности данных.
|
||||||
|
- UEBA v1 — прозрачная rule-based модель с reason-codes; KPI показывают
|
||||||
|
coverage и confidence, что повышает доверие заказчика.
|
||||||
|
|
||||||
|
## 6. Поддержка Windows/RDP и forensic pipelines
|
||||||
|
|
||||||
|
- Централизованный Windows rollout: deploy-скрипты, winrm retry logic, API
|
||||||
|
smoke-checks (aw-watcher-afk / aw-watcher-window).
|
||||||
|
- Серверная Hayabusa pipeline: auto-upload EVTX, severity scoring, automatic
|
||||||
|
case creation, bounded metadata storage и Telegram-уведомления с пороговой
|
||||||
|
фильтрацией.
|
||||||
|
|
||||||
|
## 7. Документированность и готовность к реестру
|
||||||
|
|
||||||
|
- Набор документов для регистрации: product passport, architecture, functional
|
||||||
|
scope, dependency statement, deployment model, readiness checklist.
|
||||||
|
- Demo fixtures и скриншоты анонимизированы (не содержат реальных IP/логинов/ФИО)
|
||||||
|
— соответствует требованиям для публичных материалов и подачи в реестр.
|
||||||
|
|
||||||
|
## 8. Честное позиционирование и управление рисками
|
||||||
|
|
||||||
|
- Ясно задокументированы границы продукта и planned/future элементы — это
|
||||||
|
облегчает аудит и формирует реалистичные expectations у заказчика.
|
||||||
|
- Наличие gap-analysis и roadmap-conformance audit ускоряет планирование
|
||||||
|
необходимых доработок перед масштабированием.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
Файл сохранён в ветке `docs/add-professional-highlights` по пути
|
||||||
|
`docs/PROFESSIONAL_HIGHLIGHTS_RU.md`.
|
||||||
|
|
||||||
|
Далее могу:
|
||||||
|
- открыть Pull Request в main с этим изменением (рекомендуется для review),
|
||||||
|
- смержить напрямую в main (если вы хотите немедленно обновить основную ветку),
|
||||||
|
- или создать краткую 1-страничную выдержку для подачи в реестр.
|
||||||
|
|
||||||
|
Как предпочитаете поступить дальше?
|
||||||
@@ -0,0 +1,174 @@
|
|||||||
|
# Резолюция по проекту AWatch-rus
|
||||||
|
|
||||||
|
## 📋 РЕЗОЛЮЦИЯ ПО ПРОЕКТУ AWatch-rus
|
||||||
|
|
||||||
|
### 1. ОБЗОР ПРОЕКТА
|
||||||
|
|
||||||
|
**Название:** AWatch-rus — платформа операционного контроля и технического аудита
|
||||||
|
|
||||||
|
**Статус:** Активный проект в стадии Pilot v1.0
|
||||||
|
|
||||||
|
**Язык реализации:** Rust (основной backend) + Python (вспомогательные компоненты)
|
||||||
|
|
||||||
|
**Лицензия:** Apache License 2.0
|
||||||
|
|
||||||
|
**Видимость:** Открытый репозиторий
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 2. НАЗНАЧЕНИЕ И ЦЕННОСТЬ
|
||||||
|
|
||||||
|
Проект предназначен для:
|
||||||
|
- Workforce Analytics — мониторинг активности сотрудников, загруженности, использования приложений
|
||||||
|
- Security Operations — DLP-сигналы, detection событий, управление инцидентами
|
||||||
|
- Forensics & Incident Response — сбор evidence, offline-анализ через Hayabusa, расследования
|
||||||
|
|
||||||
|
**Целевая аудитория:** руководители, операторы ИБ, администраторы ИТ-инфраструктуры, forensics-специалисты
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 3. КЛЮЧЕВЫЕ КОМПОНЕНТЫ АРХИТЕКТУРЫ
|
||||||
|
|
||||||
|
| Компонент | Технология | Назначение |
|
||||||
|
|-----------|------------|-----------|
|
||||||
|
| Rust Backend | Rust runtime | Основной сервер, SLO, DLP-обработка, evidence, auto-heal |
|
||||||
|
| Windows Collector | PowerShell/Rust | Сбор данных: AFK, window-tracking, RDP-сессии, DLP-события |
|
||||||
|
| Grafana/Prometheus | Dashboards | Витрины для админов, операторов, руководителей |
|
||||||
|
| ActivityWatch | Modified base | Основа для сбора telemetry и worktime |
|
||||||
|
| Portal UI | Rust server-rendered HTML + HTMX | Веб-интерфейс на основе server-side rendering |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 4. ФУНКЦИОНАЛЬНЫЕ ВОЗМОЖНОСТИ (Implemented)
|
||||||
|
|
||||||
|
✅ Workforce Module:
|
||||||
|
- Отслеживание активности: рабочее время, простои, переключение окон
|
||||||
|
- RDP-сессии с детализацией
|
||||||
|
- Профилирование приложений и сайтов
|
||||||
|
- KPI-отчёты для руководства
|
||||||
|
|
||||||
|
✅ Security Module:
|
||||||
|
- DLP-детектирование (копирование, печать, USB)
|
||||||
|
- UEBA v1 (прозрачная rule-based модель, без ML)
|
||||||
|
- Управление очередью инцидентов
|
||||||
|
- Audit действий оператора
|
||||||
|
|
||||||
|
✅ Forensics Module:
|
||||||
|
- Hayabusa integration для EVTX-анализа
|
||||||
|
- Offline investigation packs
|
||||||
|
- Timeline и Evidence-галереи
|
||||||
|
- Расследование инцидентов
|
||||||
|
|
||||||
|
✅ Operations:
|
||||||
|
- Role-based access (executive, manager, security, forensics, admin)
|
||||||
|
- Pilot v1.0 validation
|
||||||
|
- Deployment topologies & sizing guide
|
||||||
|
- Production hardening
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 5. ПЛАНЫ И РАСШИРЕНИЕ
|
||||||
|
|
||||||
|
Planned:
|
||||||
|
- PowerShell Provider для мониторинга
|
||||||
|
- SSH Provider
|
||||||
|
- Syslog Provider
|
||||||
|
- 1C Integration Provider
|
||||||
|
- Russian OS support validation
|
||||||
|
|
||||||
|
Future:
|
||||||
|
- Extended Enterprise connectors
|
||||||
|
- SCUD/VPN integrations
|
||||||
|
- React/TypeScript Enterprise UI
|
||||||
|
- Tauri Desktop Forensics
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 6. ТЕХНИЧЕСКОЕ СОСТОЯНИЕ
|
||||||
|
|
||||||
|
| Метрика | Значение |
|
||||||
|
|---------|----------|
|
||||||
|
| Open Issues | 1 |
|
||||||
|
| Forks | 2 |
|
||||||
|
| Stars | 2 |
|
||||||
|
| Repository Size | ~10.5 MB |
|
||||||
|
| Last Push | 2026-06-12T19:17:35Z |
|
||||||
|
| Default Branch | main |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 7. DEPLOYMENT И PRODUCTION-READINESS
|
||||||
|
|
||||||
|
Инструменты развёртывания:
|
||||||
|
- Ansible playbooks (полный automation stack)
|
||||||
|
- Proxmox provisioning (CT creation)
|
||||||
|
- Windows WinRM rollout (centralized deployment)
|
||||||
|
- Docker/CT topologies (multi-node)
|
||||||
|
|
||||||
|
Документация и валидация:
|
||||||
|
- Pilot v1.0 демо-сценарии
|
||||||
|
- Enterprise deployment guide
|
||||||
|
- Security hardening & backup/recovery
|
||||||
|
- Sizing guide
|
||||||
|
- Registry readiness документы
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 8. ТЕХНИЧЕСКИЕ ПРЕИМУЩЕСТВА
|
||||||
|
|
||||||
|
- Rust-first approach — производительность, безопасность памяти, надёжность
|
||||||
|
- Server-side rendering — снижение нагрузки на клиент
|
||||||
|
- API-first — OpenAPI contracts, TypeScript declarations
|
||||||
|
- Observability — Prometheus metrics, Grafana dashboards
|
||||||
|
- Security by default — read-only по умолчанию, безопасные mutation paths
|
||||||
|
- Modular Rust workspace — четкая декомпозиция модулей
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 9. ОГРАНИЧЕНИЯ И ПОЗИЦИОНИРОВАНИЕ
|
||||||
|
|
||||||
|
Не позиционируется как:
|
||||||
|
- Сертифицированная DLP/SIEM/EDR/XDR
|
||||||
|
- ML-based UEBA
|
||||||
|
- Юридически гарантированная неизменность evidence
|
||||||
|
|
||||||
|
Позиционируется как:
|
||||||
|
- Операционная платформа контроля (Workforce + Security + Forensics)
|
||||||
|
- Pilot-ready решение для технического аудита
|
||||||
|
- Расширяемая архитектура для агентных и agentless-источников
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 10. РЕКОМЕНДАЦИИ
|
||||||
|
|
||||||
|
Для потенциальных пользователей:
|
||||||
|
1. Начать с Pilot v1 demo
|
||||||
|
2. Пройти Pilot validation checklist
|
||||||
|
3. Использовать Ansible automation для развёртывания
|
||||||
|
4. Ознакомиться с Security hardening guide
|
||||||
|
5. Планировать интеграции через role-based contracts
|
||||||
|
|
||||||
|
Для разработчиков:
|
||||||
|
1. Контрибутировать через PR согласно guidelines
|
||||||
|
2. Использовать migration runbook для изменений
|
||||||
|
3. Поддерживать quality gates и smoke tests
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 11. ИТОГОВАЯ ОЦЕНКА
|
||||||
|
|
||||||
|
- Качество кода: высокое (Rust-first, модульная архитектура)
|
||||||
|
- Документация: полная, пригодна для реестра
|
||||||
|
- Production-readiness: готов к пилоту, требуется валидация
|
||||||
|
- Сообщество: ранняя стадия
|
||||||
|
- Расширяемость: высокая
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## ✅ ИТОГОВЫЙ ВЕРДИКТ
|
||||||
|
|
||||||
|
AWatch-rus — профессиональный, хорошо структурированный проект для операционного контроля корпоративной ИТ-инфраструктуры. Проект готов к оценке и пилотному развёртыванию; перед production рекомендуется пройти валидацию по чеклистам.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
*Файл добавлён в ветку `docs/add-professional-highlights` как `docs/RELEASE_RESOLUTION_RU.md`.*
|
||||||
@@ -1,4 +0,0 @@
|
|||||||
[toolchain]
|
|
||||||
channel = "1.94.0"
|
|
||||||
profile = "minimal"
|
|
||||||
components = ["rustfmt", "clippy"]
|
|
||||||
@@ -1,143 +0,0 @@
|
|||||||
#!/usr/bin/env python3
|
|
||||||
"""Create a GitHub Actions release package from Rust release binaries."""
|
|
||||||
|
|
||||||
from __future__ import annotations
|
|
||||||
|
|
||||||
import argparse
|
|
||||||
import hashlib
|
|
||||||
import json
|
|
||||||
import shutil
|
|
||||||
import stat
|
|
||||||
import tarfile
|
|
||||||
from datetime import datetime, timezone
|
|
||||||
from pathlib import Path
|
|
||||||
|
|
||||||
SKIP_DIRS = {"deps", "build", "examples", "incremental"}
|
|
||||||
SKIP_SUFFIXES = {".d", ".rlib", ".rmeta"}
|
|
||||||
|
|
||||||
|
|
||||||
def sha256(path: Path) -> str:
|
|
||||||
digest = hashlib.sha256()
|
|
||||||
with path.open("rb") as handle:
|
|
||||||
while True:
|
|
||||||
chunk = handle.read(1024 * 1024)
|
|
||||||
if not chunk:
|
|
||||||
break
|
|
||||||
digest.update(chunk)
|
|
||||||
return digest.hexdigest()
|
|
||||||
|
|
||||||
|
|
||||||
def is_binary(path: Path) -> bool:
|
|
||||||
if not path.is_file():
|
|
||||||
return False
|
|
||||||
if path.name in SKIP_DIRS:
|
|
||||||
return False
|
|
||||||
if path.suffix in SKIP_SUFFIXES:
|
|
||||||
return False
|
|
||||||
return bool(path.stat().st_mode & stat.S_IXUSR)
|
|
||||||
|
|
||||||
|
|
||||||
def collect(release_dir: Path) -> list[Path]:
|
|
||||||
items = [item for item in sorted(release_dir.iterdir()) if is_binary(item)]
|
|
||||||
if not items:
|
|
||||||
raise SystemExit(f"No release binaries found in {release_dir}")
|
|
||||||
return items
|
|
||||||
|
|
||||||
|
|
||||||
def write(path: Path, text: str) -> None:
|
|
||||||
path.parent.mkdir(parents=True, exist_ok=True)
|
|
||||||
path.write_text(text, encoding="utf-8")
|
|
||||||
|
|
||||||
|
|
||||||
def copy_release_file(src: Path, dst: Path) -> Path:
|
|
||||||
"""Copy file contents without preserving metadata that some mounts reject."""
|
|
||||||
dst.parent.mkdir(parents=True, exist_ok=True)
|
|
||||||
shutil.copyfile(src, dst)
|
|
||||||
try:
|
|
||||||
dst.chmod(src.stat().st_mode & 0o777)
|
|
||||||
except PermissionError:
|
|
||||||
# Some removable/network filesystems reject chmod/utime metadata changes.
|
|
||||||
# The package remains valid because the archive manifest/checksums are
|
|
||||||
# based on file contents, not filesystem timestamps.
|
|
||||||
pass
|
|
||||||
return dst
|
|
||||||
|
|
||||||
|
|
||||||
def write_archive_checksum(archive: Path) -> None:
|
|
||||||
write(archive.with_suffix(archive.suffix + ".sha256"), f"{sha256(archive)} {archive.name}\n")
|
|
||||||
|
|
||||||
|
|
||||||
def create_compatibility_aliases(out_dir: Path, archive: Path) -> None:
|
|
||||||
"""Create both linux-x86_64 and linux_x86_64 artifact paths."""
|
|
||||||
out_alias = Path(str(out_dir).replace("linux-x86_64", "linux_x86_64"))
|
|
||||||
if out_alias != out_dir:
|
|
||||||
if out_alias.exists():
|
|
||||||
shutil.rmtree(out_alias)
|
|
||||||
out_alias.mkdir(parents=True)
|
|
||||||
for item in out_dir.iterdir():
|
|
||||||
if item.is_file():
|
|
||||||
copy_release_file(item, out_alias / item.name)
|
|
||||||
|
|
||||||
archive_alias = Path(str(archive).replace("linux-x86_64", "linux_x86_64"))
|
|
||||||
if archive_alias != archive:
|
|
||||||
copy_release_file(archive, archive_alias)
|
|
||||||
write_archive_checksum(archive_alias)
|
|
||||||
|
|
||||||
|
|
||||||
def main() -> None:
|
|
||||||
parser = argparse.ArgumentParser()
|
|
||||||
parser.add_argument("--release-dir", type=Path, required=True)
|
|
||||||
parser.add_argument("--out-dir", type=Path, required=True)
|
|
||||||
parser.add_argument("--archive", type=Path, required=True)
|
|
||||||
parser.add_argument("--target", default="linux-x86_64")
|
|
||||||
parser.add_argument("--commit", default="unknown")
|
|
||||||
parser.add_argument("--ref", default="unknown")
|
|
||||||
parser.add_argument("--run-id", default="unknown")
|
|
||||||
args = parser.parse_args()
|
|
||||||
|
|
||||||
release_dir = args.release_dir.resolve()
|
|
||||||
out_dir = args.out_dir.resolve()
|
|
||||||
archive = args.archive.resolve()
|
|
||||||
|
|
||||||
if out_dir.exists():
|
|
||||||
shutil.rmtree(out_dir)
|
|
||||||
out_dir.mkdir(parents=True)
|
|
||||||
|
|
||||||
binaries = collect(release_dir)
|
|
||||||
for binary in binaries:
|
|
||||||
copy_release_file(binary, out_dir / binary.name)
|
|
||||||
|
|
||||||
names = [binary.name for binary in binaries]
|
|
||||||
write(out_dir / "BINARIES.txt", "\n".join(names) + "\n")
|
|
||||||
|
|
||||||
checksum_lines = []
|
|
||||||
manifest_binaries = []
|
|
||||||
for name in names:
|
|
||||||
packaged = out_dir / name
|
|
||||||
digest = sha256(packaged)
|
|
||||||
checksum_lines.append(f"{digest} {name}")
|
|
||||||
manifest_binaries.append(
|
|
||||||
{"name": name, "size_bytes": packaged.stat().st_size, "sha256": digest}
|
|
||||||
)
|
|
||||||
write(out_dir / "SHA256SUMS.txt", "\n".join(checksum_lines) + "\n")
|
|
||||||
|
|
||||||
manifest = {
|
|
||||||
"project": "AWatch-rus",
|
|
||||||
"target": args.target,
|
|
||||||
"commit": args.commit,
|
|
||||||
"ref": args.ref,
|
|
||||||
"run_id": args.run_id,
|
|
||||||
"build_time_utc": datetime.now(timezone.utc).isoformat(timespec="seconds"),
|
|
||||||
"binaries": manifest_binaries,
|
|
||||||
}
|
|
||||||
write(out_dir / "BUILD_MANIFEST.json", json.dumps(manifest, ensure_ascii=False, indent=2) + "\n")
|
|
||||||
|
|
||||||
archive.parent.mkdir(parents=True, exist_ok=True)
|
|
||||||
with tarfile.open(archive, "w:gz") as tar:
|
|
||||||
tar.add(out_dir, arcname=out_dir.name)
|
|
||||||
write_archive_checksum(archive)
|
|
||||||
create_compatibility_aliases(out_dir, archive)
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
main()
|
|
||||||
Reference in New Issue
Block a user