293 lines
16 KiB
Markdown
293 lines
16 KiB
Markdown
# Ansible ensemble for AWatch-rus
|
||
|
||
Эта директория содержит Ansible-ensemble для полного развёртывания AWatch-rus:
|
||
|
||
- деплой на уже существующий Debian host/CT;
|
||
- полный цикл с нуля в Proxmox: создание CT + bootstrap + установка ActivityWatch + RU patch;
|
||
- централизованное развёртывание Windows/RDP collector'ов по WinRM;
|
||
- развёртывание внешнего pfSense poller'а на Debian/Ubuntu utility VM.
|
||
|
||
## Файлы
|
||
|
||
- `ansible/deploy_aw_server.yml` — основной playbook для уже существующего Debian/CT host.
|
||
- `ansible/provision_proxmox_ct_and_deploy_aw.yml` — полный playbook для Proxmox.
|
||
- `ansible/provision_proxmox_ct_matrix_and_deploy_aw.yml` — массовый полный playbook (несколько CT).
|
||
- `ansible/deploy_aw_windows.yml` — WinRM playbook для развёртывания Windows/RDP collector'ов.
|
||
- `ansible/deploy_aw_pfsense_poller.yml` — развёртывание pfSense poller'а.
|
||
- `ansible/deploy_grafana_dashboards.yml` — импорт version-controlled Grafana dashboard'ов через HTTP API.
|
||
- `ansible/deploy_tsj_guardian_bot_proxmox.yml` — развёртывание TSJ Guardian Telegram Bot на Proxmox host.
|
||
- `ansible/install_full_stack.yml` — полный установочный playbook (оркестратор всех этапов).
|
||
- `ansible/inventory.example.ini` — шаблон inventory.
|
||
- `ansible/group_vars/*.example.yml` — шаблоны переменных.
|
||
|
||
## Быстрый запуск
|
||
|
||
1. Скопируйте шаблоны:
|
||
- `cp ansible/inventory.example.ini ansible/inventory.ini`
|
||
- `cp ansible/group_vars/all.example.yml ansible/group_vars/all.yml`
|
||
2. Заполните значения в `inventory.ini` и `group_vars/all.yml`.
|
||
3. Запустите:
|
||
|
||
```bash
|
||
cd ansible
|
||
ansible-playbook -i inventory.ini deploy_aw_server.yml
|
||
```
|
||
|
||
## Секреты (пароли) безопасно
|
||
|
||
Рекомендуемый способ не хранить пароли в репозитории — перед запуском экспортировать их в переменные окружения:
|
||
|
||
- Linux `aw_server` (SSH пароль root): `AW_SSH_PASSWORD`
|
||
- Windows `aw_windows` (WinRM пароль): `AW_WINRM_PASSWORD`
|
||
|
||
В `group_vars/aw_server.yml` и `group_vars/windows.yml` они читаются через `lookup('env', ...)`.
|
||
|
||
## Полный установочный playbook (всё за один запуск)
|
||
|
||
Если нужно прогнать полный цикл одной командой:
|
||
|
||
```bash
|
||
cd ansible
|
||
ansible-playbook -i inventory.ini install_full_stack.yml
|
||
```
|
||
|
||
Что делает:
|
||
|
||
- `provision_proxmox_ct_and_deploy_aw.yml` (если есть хосты в группе `[proxmox]`);
|
||
- `deploy_aw_server.yml` (группа `[aw_server]`);
|
||
- `deploy_aw_windows.yml` (группа `[aw_windows]`);
|
||
- `deploy_aw_pfsense_poller.yml` (группа `[aw_pfsense_pollers]`);
|
||
- `deploy_grafana_dashboards.yml` (группа `[grafana]`).
|
||
|
||
Пустые группы в `inventory.ini` безопасны: соответствующий play будет пропущен.
|
||
|
||
## Полный запуск с нуля в Proxmox
|
||
|
||
1. Подготовьте inventory и vars:
|
||
- `cp ansible/inventory.example.ini ansible/inventory.ini`
|
||
- `cp ansible/group_vars/all.example.yml ansible/group_vars/all.yml`
|
||
- `cp ansible/group_vars/proxmox.example.yml ansible/group_vars/proxmox.yml`
|
||
2. Заполните `group_vars/proxmox.yml` и `group_vars/all.yml`.
|
||
3. Запустите playbook:
|
||
|
||
```bash
|
||
cd ansible
|
||
ansible-playbook -i inventory.ini provision_proxmox_ct_and_deploy_aw.yml
|
||
```
|
||
|
||
## Массовый запуск (матрица CT)
|
||
|
||
1. Подготовьте матрицу:
|
||
- `cp ansible/group_vars/proxmox-matrix.example.yml ansible/group_vars/proxmox-matrix.yml`
|
||
2. Заполните `proxmox-matrix.yml`.
|
||
3. Запустите:
|
||
|
||
```bash
|
||
cd ansible
|
||
ansible-playbook -i inventory.ini provision_proxmox_ct_matrix_and_deploy_aw.yml
|
||
```
|
||
|
||
## Windows/RDP rollout (WinRM)
|
||
|
||
Важно:
|
||
|
||
- `WinRM` здесь остаётся транспортом для `Ansible deploy` и `validation`;
|
||
- для интерактивной PowerShell-работы из Linux/Codex по AWatch-rus используйте project MCP-over-SSH путь, а не `WSMan`;
|
||
- каноника лежит в `docs/POWERSHELL_MCP_REMOTE_RU.md` и `scripts/install_detmir_powershell_mcp.sh`.
|
||
|
||
1. Подготовьте inventory и vars:
|
||
- `cp ansible/inventory.example.ini ansible/inventory.ini`
|
||
- `cp ansible/group_vars/windows.example.yml ansible/group_vars/windows.yml`
|
||
2. Заполните `inventory.ini` (секция `[aw_windows]`) и `group_vars/windows.yml`.
|
||
- Для русской локализации Windows часто нужен `ansible_user=Администратор` (а не `Administrator`).
|
||
- Если WinRM закрыт, playbook не сможет стартовать и нужно сначала открыть `5985/5986` и `wsman`.
|
||
3. Запустите:
|
||
|
||
```bash
|
||
cd ansible
|
||
AW_WINRM_PASSWORD='...' bash ./run_deploy_aw_windows.sh
|
||
```
|
||
|
||
`run_deploy_aw_windows.sh` автоматически:
|
||
- очищает proxy env (`http_proxy/https_proxy/...`), чтобы WinRM не уходил в локальный прокси;
|
||
- включает OpenSSL legacy provider, если на хосте отключён `MD4` (нужно для NTLM в pywinrm).
|
||
- перезапускает `ansible-playbook` при временных WinRM/NTLM сбоях (по умолчанию 5 попыток, пауза 30 сек).
|
||
|
||
Параметры retry:
|
||
- `AW_DEPLOY_RETRIES` (по умолчанию `5`);
|
||
- `AW_DEPLOY_RETRY_DELAY_SEC` (по умолчанию `30`).
|
||
|
||
Playbook:
|
||
|
||
- выгружает полный `windows/*` toolkit на целевой хост в InnoSetup-compatible каталог `C:\Program Files\AWatch-rus\windows`, включая DLP и `worktime-session-collector.ps1`;
|
||
- если найден legacy config `C:\ProgramData\ActivityWatch-Phase2\deployment-config.json`, выполняет безопасную миграцию через `migrate-awatch-rus-paths.ps1`: backup, остановка задач, перенос данных, переписывание путей, пересоздание scheduled tasks и validation;
|
||
- выполняет `deploy-ensemble.ps1` (deploy + hardening/recovery) с policy/rules из AWatch-rus toolkit;
|
||
- после deploy принудительно запускает `ActivityWatch Recovery` и managed `ActivityWatch Launch *` задачи;
|
||
- включает (`Enable-ScheduledTask`) `ActivityWatch Recovery` и managed `ActivityWatch Launch *` задачи перед запуском (иначе WebUI может показывать `Active time: 0s`);
|
||
- оставляет `ActivityWatch Recovery` включённым даже при активном `AWatchRusCollectorGuard`: guard является основным контроллером, recovery остаётся fallback/bootstrap path;
|
||
- выполняет API smoke-check bucket `aw-watcher-afk_<COMPUTERNAME>` и ожидает свежие события;
|
||
- выполняет API smoke-check bucket `aw-watcher-window_<COMPUTERNAME>` и ожидает свежие события (по умолчанию включено);
|
||
- запускает `validate-deployment.ps1`;
|
||
- забирает JSON-отчёт в локальную директорию (`/tmp/aw-rus-validation-<USER>` по умолчанию).
|
||
- настраивает scheduled task `ActivityWatch Hayabusa Upload` с периодом и lookback по vars.
|
||
|
||
Дополнительные флаги:
|
||
|
||
- `aw_windows_afk_enabled: false` — не запускать `aw-watcher-afk`;
|
||
- `aw_windows_window_enabled: false` — не запускать `aw-watcher-window`;
|
||
- `aw_windows_incident_capture_enabled: false` — отключить блок incidentCapture;
|
||
- `aw_windows_incident_screenshot_enabled: false` — не делать скриншот при DLP-инциденте;
|
||
- `aw_windows_incident_artifacts_root: 'C:\...\incident-artifacts'` — переопределить путь артефактов;
|
||
- `aw_windows_deploy_root: 'C:\Program Files\AWatch-rus'` — каталог toolkit, совпадает с InnoSetup `{app}`;
|
||
- `aw_windows_install_root: 'C:\Program Files\AWatch-rus\bin'` — каталог бинарников, совпадает с InnoSetup `AwDefaultInstallRoot`;
|
||
- `aw_windows_state_root: 'C:\ProgramData\AWatch-rus'` — каталог состояния/отчётов, совпадает с InnoSetup `AwDefaultStateRoot`;
|
||
- `aw_windows_validation_remote_path: '{{ aw_windows_state_root }}\aw_validate_ansible.json'` — отчёт Ansible-валидации хранится рядом с `ensemble-report-*.json`;
|
||
- `aw_windows_migration_enabled: true` — включить guard миграции текущего production из `ActivityWatch-Phase2` в единый `AWatch-rus`;
|
||
- `aw_windows_legacy_install_root` / `aw_windows_legacy_state_root` — старые production paths, откуда выполняется перенос;
|
||
- `aw_windows_migration_report_remote_path` — JSON-отчёт о миграции на Windows-хосте;
|
||
- `aw_windows_package_version`, `aw_windows_package_url`, `aw_windows_package_zip_path` — версия и источник Windows-пакета ActivityWatch;
|
||
- `aw_windows_api_smoke_check_bucket: ""` — автоматически использовать `aw-watcher-afk_<COMPUTERNAME>`;
|
||
- `aw_windows_api_smoke_check_window_enabled: true` — включить дополнительный smoke-check `aw-watcher-window_<COMPUTERNAME>`;
|
||
- `aw_windows_api_smoke_check_window_bucket: ""` — переопределить bucket для window smoke-check;
|
||
- `aw_windows_api_smoke_check_min_events: 1` — минимум событий, ожидаемых в smoke-check;
|
||
- `aw_windows_fail_on_validation_error: true` — завершать playbook ошибкой, если `validate-deployment.ps1` возвращает `overallOk=false`;
|
||
- `aw_windows_skip_hardening: true` — пропустить `hardening-recovery.ps1` внутри ensemble-скрипта.
|
||
- `aw_windows_hayabusa_auto_upload_enabled: true` — включить авто-upload EVTX на AW-server;
|
||
- `aw_windows_hayabusa_auto_upload_interval_hours: 6` — период scheduled task;
|
||
- `aw_windows_hayabusa_auto_upload_hours_back: 6` — lookback для каждого запуска;
|
||
- `aw_windows_hayabusa_auto_upload_mode: "incident"` — mode для server-side processing;
|
||
- `aw_windows_hayabusa_auto_upload_task_name: "ActivityWatch Hayabusa Upload"` — имя scheduled task.
|
||
- `aw_windows_hayabusa_auto_upload_run_as_user: "Администратор"` — production principal для scheduled task на RDP-хосте. На `SHARKON2025` запуск `powershell.exe` из `SYSTEM` возвращал `0xC0000142`, поэтому авто-upload должен идти как interactive/highest task от локального администратора.
|
||
|
||
## Server-side Hayabusa auto-case и Telegram alerting
|
||
|
||
На стороне `deploy_aw_server.yml` теперь есть server-side контур:
|
||
|
||
- `aw-hayabusa-drop.path`
|
||
- `aw-hayabusa-drop.service`
|
||
- `aw-hayabusa-autoprocess`
|
||
- `aw-hayabusa-case-alert`
|
||
|
||
Что делает контур:
|
||
|
||
- автоматически подхватывает `zip` из `/opt/activitywatch/aw-rus-ops/drop`;
|
||
- запускает `aw-hayabusa`;
|
||
- считает severity/score по `timeline.jsonl`;
|
||
- создаёт или обновляет case;
|
||
- пишет bounded metadata в `forensics.hayabusa`;
|
||
- отправляет Telegram alert.
|
||
|
||
Для Windows direct upload пользователь `awops` на AW-server должен иметь право записи в `/opt/activitywatch/aw-rus-ops/drop`; нормальное состояние каталога: owner/group `awops:awops`, mode `0750`. Unit `aw-hayabusa-drop.service` работает от root и после обработки очищает `drop`.
|
||
|
||
Основные vars:
|
||
|
||
- `aw_hayabusa_auto_case_enabled: true`
|
||
- `aw_hayabusa_auto_case_min_severity: "medium"`
|
||
- `aw_hayabusa_telegram_enabled: true`
|
||
- `aw_hayabusa_telegram_min_severity: "high"`
|
||
- `aw_hayabusa_telegram_bot_token`
|
||
- `aw_hayabusa_telegram_chat_ids`
|
||
|
||
## Развёртывание pfSense poller
|
||
|
||
1. Подготовьте vars:
|
||
- `cp ansible/group_vars/pfsense-poller.example.yml ansible/group_vars/pfsense-poller.yml`
|
||
2. Добавьте inventory group `[aw_pfsense_pollers]`.
|
||
3. Запустите:
|
||
|
||
```bash
|
||
cd ansible
|
||
ansible-playbook -i inventory.ini deploy_aw_pfsense_poller.yml
|
||
```
|
||
|
||
Playbook:
|
||
|
||
- ставит `python3`;
|
||
- копирует `pfsense-aw-poller.py`;
|
||
- пишет `/etc/aw-pfsense/poller.json`;
|
||
- поднимает `aw-pfsense-poller.service`.
|
||
|
||
## Импорт Grafana dashboard'ов
|
||
|
||
1. Подготовьте inventory и vars:
|
||
- `cp ansible/inventory.example.ini ansible/inventory.ini`
|
||
- `cp ansible/group_vars/grafana.example.yml ansible/group_vars/grafana.yml`
|
||
2. Укажите в inventory группу `[grafana]` и переменную `grafana_url`.
|
||
3. Экспортируйте пароль Grafana API:
|
||
|
||
```bash
|
||
export GRAFANA_ADMIN_PASSWORD='...'
|
||
```
|
||
|
||
4. Запустите:
|
||
|
||
```bash
|
||
cd ansible
|
||
ansible-playbook -i inventory.ini deploy_grafana_dashboards.yml
|
||
```
|
||
|
||
Playbook:
|
||
|
||
- проверяет `GET /api/health`;
|
||
- создает или актуализирует folder `AWatch-rus` в Grafana;
|
||
- импортирует dashboard JSON из каталога `grafana/`;
|
||
- верифицирует доступность dashboard'ов по `uid` через Grafana API.
|
||
|
||
По умолчанию импортируются:
|
||
|
||
- `AWatch-rus: Работа пользователей в RDP`
|
||
- `AWatch-rus: DLP и ИБ обзор`
|
||
- `AWatch-rus: ИБ сводка для руководства`
|
||
- `AW-rus: DLP обзор`
|
||
|
||
Подробная документация: `docs/GRAFANA_DASHBOARDS_RU.md`
|
||
|
||
## Развёртывание TSJ Guardian Bot на Proxmox
|
||
|
||
1. Подготовьте vars:
|
||
- `cp ansible/group_vars/proxmox-bot.example.yml ansible/group_vars/proxmox-bot.yml`
|
||
2. Заполните минимум:
|
||
- `telegram_bot_token`
|
||
- `telegram_allowed_chat_ids`
|
||
- `tsj_bot_source_local_path`
|
||
3. Убедитесь, что в inventory есть группа `[proxmox]`.
|
||
Для текущего контура AW-Rus bot ожидает Proxmox host `<GATEWAY_HOST>`.
|
||
Рабочая модель для этого контура: `igor` + `sudo`, а не обязательный `root` login.
|
||
4. При необходимости задайте recovery-команды для AW-Rus:
|
||
- `tsj_bot_aw_rus_worktime_heal_cmd`
|
||
- `tsj_bot_aw_rus_dlp_heal_cmd`
|
||
5. Запустите:
|
||
|
||
```bash
|
||
cd ansible
|
||
ansible-playbook -i inventory.ini deploy_tsj_guardian_bot_proxmox.yml
|
||
```
|
||
|
||
После актуального production hardening:
|
||
|
||
- bot различает `worktime idle` и реальную деградацию;
|
||
- bot поддерживает отдельный `AW_RUS_DLP_HEAL_CMD`;
|
||
- redeploy не должен терять runtime env-ключи, связанные с proxy, FS checks и AI escalation.
|
||
|
||
## Результат
|
||
|
||
- Установлен ActivityWatch Server.
|
||
- Создан systemd-unit `activitywatch-server.service`.
|
||
- Установлен RU Web UI patch.
|
||
- Для Web UI используется checksum-based cache-bust для `ru-patch-v5.js` и `sw-cleanup.js`, чтобы браузер не держал старую DLP/русскую статику после деплоя.
|
||
- На `#/home` Web UI делит хосты на `Windows RDP` и `Virtual servers + Proxmox`.
|
||
- Выполнена валидация API `http://127.0.0.1:5600/api/0/info`.
|
||
- Для полного сценария CT создаётся автоматически через `pct create`.
|
||
- На Windows/RDP host развёрнуты AFK/window watchers, browser domain collector, DLP endpoint collector и worktime session collector.
|
||
- Проверочный JSON-отчёт Windows playbook должен иметь `overallOk=true`.
|
||
|
||
## Prod rollout одной командой
|
||
|
||
Для ручного запуска с dry-run и логированием используйте:
|
||
|
||
```bash
|
||
bash scripts/prod_rollout.sh
|
||
```
|
||
|
||
Скрипт попросит `AW_SSH_PASSWORD` и `AW_WINRM_PASSWORD` интерактивно (ввод скрыт) и сложит логи в `.rollout-logs/`.
|