Files
AWatch-rus/docs/runbook.md
T

28 KiB
Executable File
Raw Blame History

Runbook

Быстрый health-check

Proxmox web gateway

Если на host <GATEWAY_HOST> развёрнут nginx gateway, базовые проверки такие:

systemctl status nginx --no-pager
nginx -t
curl -I -sS -H 'Host: <PUBLIC_GATEWAY_FQDN>' http://127.0.0.1/
curl -k -fsS -H 'Host: <PUBLIC_GATEWAY_FQDN>' https://127.0.0.1/healthz
curl -k -I -sS -H 'Host: <PUBLIC_GATEWAY_FQDN>' https://127.0.0.1/ | head
curl -k -u "$(awk -F= '/^user=/{u=$2}/^password=/{p=$2}END{print u\":\"p}' <GATEWAY_CREDENTIALS_FILE>)" \
  -H 'Host: <PUBLIC_GATEWAY_FQDN>' -fsS https://127.0.0.1/ | grep -F '<PUBLIC_GATEWAY_FQDN>'

Playbook для повторного rollout:

ANSIBLE_HOST_KEY_CHECKING=False \
ansible-playbook -i ansible/inventory.ini ansible/deploy_proxmox_web_gateway.yml

Public gateway через pfSense

Публичная схема:

Internet -> <PUBLIC_GATEWAY_FQDN> -> pfSense WAN <WAN_IP> -> NAT 80/443 -> nginx <GATEWAY_HOST>

Нормальное состояние:

  • https://<PUBLIC_GATEWAY_FQDN>/healthz -> 200 ok без auth;
  • https://<PUBLIC_GATEWAY_FQDN>/ без auth -> 401;
  • http://<PUBLIC_GATEWAY_FQDN>/healthz -> 301 на HTTPS;
  • после Basic Auth:
    • / -> gateway index;
    • /r/file1c/brief -> 1C brief;
    • /r/grafana/api/health -> Grafana health;
    • /r/aw/api/0/info -> AW server info.

Gateway credential хранится только на <GATEWAY_HOST>:

sudo cat <GATEWAY_CREDENTIALS_FILE>

pfSense NAT backup перед автоматической правкой:

ls -1t /opt/infra-admin/backups/pfsense-gateway-nat-*.json | head

Проверка pfSense REST/API и pending firewall changes:

set -a
. <OPERATOR_HOME>/.config/tsj-bot/pfsense.env.readonly
set +a
curl -ksS -H "X-API-Key: $PFSENSE_API_KEY" "$PFSENSE_URL/api/v2/firewall/apply"

NAT должен содержать WAN tcp 443 -> <GATEWAY_HOST>:443 и WAN tcp 80 -> <GATEWAY_HOST>:80. WAN rules должны содержать pass на <GATEWAY_HOST>:80 и <GATEWAY_HOST>:443.

На Proxmox

pct status <CT_ID>
pct config <CT_ID>
pct exec <CT_ID> -- systemctl is-active activitywatch-server.service
pct exec <CT_ID> -- curl -fsS http://127.0.0.1:5600/api/0/info

На host-based инсталляции

Для подтвержденного размещения на <GATEWAY_HOST>:

ps -ef | grep -E 'aw-server-rust|pfsense-aw-poller' | grep -v grep
curl -fsS http://127.0.0.1:5600/api/0/info
ss -ltnp | grep 5600

Ожидаемо должны быть видны:

  • aw-server-rust с --webpath /opt/aw-webui-ru;
  • pfsense-aw-poller.py --config /etc/aw-pfsense/poller.json.

Внутри CT

systemctl status activitywatch-server.service --no-pager
journalctl -u activitywatch-server.service -n 100 --no-pager
curl -fsS http://127.0.0.1:5600/api/0/info
ss -ltnp | grep 5600

Расширенный DLP transport health-check

На AW-server:

/usr/local/bin/aw-health-check
/usr/local/bin/dlp-health-check --json

Что проверяет дополнительно:

  • свежесть DLP bucket-ов (aw-dlp-endpoint-signals_*, aw-file-operations_*);
  • наличие transport/self-test telemetry (queueDepth, eventsEnqueued, eventsFlushed, sendFailures) в endpoint self-test;
  • последние значения transport-счетчиков по каждому aw-dlp-endpoint-signals_* bucket;
  • runtime-срез aw-file-operations_*: последние collector_health, счетчики очереди/отправки, последние операции без полного пути;
  • runtime-срез aw-dlp-incidents_*: по умолчанию только metadata/age без тяжёлого чтения events; при ручном --incident-sample-limit > 0 — количество реальных incident events в sample, self-test count, severity/action/rule rollup и до 5 последних incidents с коротким message_excerpt;
  • API-доступность базовых сервисов.

Интерпретация:

  • FAIL — есть критичная проблема (service/API/stale transport);
  • WARN — сигнал для оператора (например, bucket еще не активирован на хосте, queueDepth > 100, новый рост sendFailuresDelta >= 1, нет collector_health в sample), но без hard-fail.
  • sendFailures — накопительный счётчик collector-а; основной health-check предупреждает только по delta относительно сохранённого baseline в AW_DLP_HEALTH_STATE_DIR, чтобы старые восстановленные ошибки не висели вечным warning.

Пороги можно переопределить без изменения collector-ов:

/usr/local/bin/dlp-health-check --json \
  --endpoint-queue-warn-depth 100 \
  --endpoint-send-failure-warn-count 1 \
  --incident-sample-limit 0 \
  --fileops-sample-limit 20 \
  --fileops-queue-warn-depth 100 \
  --fileops-send-failure-warn-count 1

Для разового разбора последних DLP incidents можно включить sampling вручную:

/usr/local/bin/dlp-health-check --json --incident-sample-limit 20

Если AW-server медленно отдаёт большой aw-dlp-incidents_* bucket, такой запуск может вернуть incident-runtime: WARN по timeout. Это не должно использоваться как hard-fail основного мониторинга.

Проверка RU patch

grep -n 'aw-ru-patch\|aw-sw-cleanup' /opt/activitywatch/webui-ru/index.html
ls -l /opt/activitywatch/webui-ru/js/

Telegram bot: DLP режим и форензика

Для оператора DetMirAuto каноническое поведение такое:

  • Кнопка DLP должна явно показывать текущий режим и целевое действие:
  • DLP сейчас: наблюдение | включить блокировку
  • DLP сейчас: блокировка | включить наблюдение
  • DLP сейчас: смешанный | выровнять в блокировку
  • Slash-путь для проверки без переключения: /dlp_mode
  • Slash-путь для переключения: /dlp_mode_toggle

Интерпретация:

  • наблюдение = endpoint/email правила работают в monitor-поведении (alert/log), без жёсткого block;
  • блокировка = endpoint/email правила переведены в block;
  • смешанный = часть endpoint/email правил уже block, часть ещё monitor-like; нормальный следующий ход — выровнять policy.

Форензика:

  • Кнопка в меню называется Форензика Windows логов;
  • Это человеко-понятный операторский вход в bounded Hayabusa path;
  • Slash-команда остаётся прежней: /aw_dfir /path/to/package.zip HOST [CASE_ID] [MODE]

Если Telegram показывает старую клавиатуру:

  • Нажать Статус или /start;
  • Бот обязан прислать свежую custom-keyboard с актуальным DLP label;
  • Старая кнопка в чате может ещё приходить как текст, но бот должен её принять и после ответа вернуть свежую клавиатуру.

Проверить:

  • есть aw-ru-patch.js;
  • есть aw-sw-cleanup.js;
  • index.html содержит оба include;
  • service-worker.js заменён cleanup-версией.

Рабочее время (worktime)

Если в деплое включен aw_apply_worktime_settings: true, playbook применяет базовую категоризацию (classes) и view worktime.

Контрольные AQL-шаблоны для расчета рабочего времени: docs/worktime_aql_detmir.md.

Период рабочего времени задаётся переменными:

  • aw_worktime_from (например 00:00)
  • aw_worktime_to (например 17:00)

Playbook вычисляет durationDefault автоматически (включая смены через полночь) и выставляет: /api/0/settings/startOfDay и /api/0/settings/durationDefault.

Management report API

На :5610 сейчас есть два server-side отчёта:

  • классический RDP worktime:
    • /reports/worktime/today
    • форматы: json, csv, html
  • управленческий management:
    • /reports/worktime/management
    • форматы: json, csv, html

Управленческий отчёт дополнительно показывает:

  • рабочее окно отдельно от календарной активности;
  • очередь действий руководителя;
  • тренд за несколько дней;
  • свежесть источников данных;
  • executive summary Что делать сегодня.

Практические проверки:

curl -fsS 'http://127.0.0.1:5610/reports/worktime/today?day=today' | jq '.[:5]'
curl -fsS 'http://127.0.0.1:5610/reports/worktime/management?day=today' | jq '.summary,.executive'
curl -fsS 'http://127.0.0.1:5610/reports/worktime/management?format=html&day=today' | head
curl -fsS 'http://127.0.0.1:5610/reports/worktime/management?day=today&owner=Сменный%20руководитель' | jq '.filters,.summary,.owner_rollups'
curl -fsS 'http://127.0.0.1:5610/reports/worktime/management?day=today&department=Операторы%201С' | jq '.filters,.summary,.department_rollups'

Важно:

  • первый management-запрос после очистки cache может быть тяжёлым, потому что API пересчитывает trend и source freshness;
  • повторные запросы должны быть быстрыми за счёт cache в /var/lib/activitywatch/worktime-cache;
  • по умолчанию cache живёт 300 секунд и прогревается локально через aw-worktime-autoheal.service, чтобы manager-страницы не висели на cold-start;
  • default warm-path должен ходить в format=json, потому что этого достаточно для наполнения cache и это заметно легче, чем cold HTML render;
  • warm timeout по умолчанию 70 секунд и задаётся через AW_WORKTIME_MANAGEMENT_WARM_TIMEOUT_SECONDS;
  • management report поддерживает scope-фильтры owner и department; они пересчитывают summary, rows, actions и rollups под выбранный срез, а не просто прячут строки в HTML;
  • trend в filtered-view сейчас сознательно отключён: это удерживает latency в рабочем диапазоне и не заставляет сервер заново пересчитывать исторический ряд на каждый менеджерский клик;
  • alias-файл теперь может содержать не только users, но и owners; блок owners нужен для manager-facing каталога ответственных: display_name, title, department, contact, escalation_to, notes;
  • alias-файл для нормализации сотрудников по умолчанию: /etc/activitywatch/worktime-manager-aliases.json.

Типовые инциденты

Hayabusa: операторский сценарий по умолчанию

Текущий production-сценарий уже не требует ручного accept/process-inbox.

Нормальный путь для оператора:

  1. На Windows-хосте запустить:
powershell.exe -ExecutionPolicy Bypass -File C:\ProgramData\AWatch-rus\export-upload-hayabusa-to-aw-server.ps1 -HoursBack 6 -CaseId 30
  1. Сервер <AW_SERVER_HOST> сам:
  • примет zip и .meta.json в /opt/activitywatch/aw-rus-ops/drop;
  • запустит aw-hayabusa;
  • посчитает severity/score;
  • создаст case при уровне от medium;
  • отправит Telegram alert при уровне от high.
  1. Проверить результат:
systemctl is-active aw-hayabusa-drop.path
systemctl is-failed aw-hayabusa-drop.service || true
aw-hayabusa doctor
aw-hayabusa inventory
cat /opt/hayabusa/state/latest-intake.json
journalctl -u aw-hayabusa-drop.service -n 80 --no-pager
curl -fsS http://127.0.0.1:5602/api/0/dlp/cases/30

Ожидаемо:

  • latest-intake.json имеет status=ok;
  • drop после обработки пустой;
  • в case есть forensics.hayabusa;
  • Telegram alert уже уходит в операторский чат.

Production scheduled task на SHARKON2025:

  • ActivityWatch Hayabusa Upload
  • principal Администратор, LogonType=Interactive, RunLevel=Highest
  • период 6 часов, lookback 6 часов
  • нормальный LastTaskResult=0

Если LastTaskResult=3221225794 (0xC0000142) и в C:\ProgramData\AWatch-rus\logs\hayabusa-upload.log нет новой строки, скрипт не стартовал. На текущем RDP-хосте это воспроизводится даже минимальной SYSTEM-задачей с powershell.exe; пересоздать Hayabusa task как interactive/highest от Администратор, не от SYSTEM.

Если upload прошёл, но сервер не обработал пакет:

sudo systemctl reset-failed aw-hayabusa-drop.path aw-hayabusa-drop.service
sudo systemctl start aw-hayabusa-drop.path
sudo systemctl start aw-hayabusa-drop.service
find /opt/activitywatch/aw-rus-ops/drop -maxdepth 1 -type f -ls
find /opt/hayabusa/inbox/incoming -maxdepth 1 -type f -ls

drop и incoming после успешной обработки должны быть пустыми; latest intake должен указывать на последний пакет SHARKON2025.

Hayabusa: manual fallback / production validation end-to-end

Цель: подтвердить один реальный путь

  • Windows EVTX export
  • перенос пакета на <AW_SERVER_HOST>
  • intake через aw-hayabusa
  • генерация отчёта
  • привязка bounded metadata к операторскому follow-up

Минимальный production-proven сценарий:

Этот путь нужен только если:

  • надо руками прогнать старый пакет;
  • надо повторно разобрать archived zip;
  • надо отладить сам aw-hayabusa без drop-автоматики.
  1. На Windows-хосте сделать экспорт:
powershell.exe -ExecutionPolicy Bypass -File C:\ProgramData\AWatch-rus\export-evtx-for-hayabusa.ps1 -DaysBack 1
  1. Проверить, что пакет реально появился:
Get-ChildItem 'C:\ProgramData\AWatch-rus\forensics\evtx-exports' |
  Sort-Object LastWriteTime -Descending |
  Select-Object -First 5 Name,Length,LastWriteTime

Ожидаемо должен появиться zip вида:

  • HOST-YYYYMMDD-HHMMSS.zip
  1. Перенести zip на <AW_SERVER_HOST> в операторскую рабочую зону.

  2. На AW-server проверить раннер:

aw-hayabusa doctor
aw-hayabusa inventory
aw-hayabusa profiles
  1. Принять пакет:
aw-hayabusa accept --package /path/to/HOST-YYYYMMDD-HHMMSS.zip --host HOST
  1. Обработать inbox:
aw-hayabusa process-inbox --mode incident
  1. Проверить результат:
aw-hayabusa inventory
readlink -f /opt/hayabusa/state/latest-run
readlink -f /opt/hayabusa/state/latest-HOST
find /opt/hayabusa/reports/HOST -maxdepth 2 -type f | sort

Ожидаемо должны быть:

  • summary.html
  • manifest.json
  • run.log
  • timeline.jsonl или timeline.csv
  • logon-summary-*.csv
  1. Проверить traceability:
cat /opt/hayabusa/state/latest-intake.json
find /opt/hayabusa/archive/packages/HOST -maxdepth 1 -type f | sort
find /opt/hayabusa/archive/extracted/HOST -maxdepth 2 -type f | sort

Нужно зафиксировать:

  • host
  • intake_id
  • sha256
  • package_path
  • report_dir
  • status
  1. Для AW-rus/operator follow-up заносить только bounded metadata:
  • tool=hayabusa
  • host
  • mode=incident
  • status
  • intake_id
  • package_path
  • sha256
  • report_dir
  • summary_html
  • timeline_path
  • manifest_path

Не заносить в case / comments:

  • сырые EVTX
  • полный Sigma output
  • полный timeline body
  1. Если прогона не получилось, записать tuning backlog:
  • пустой/битый zip
  • нет EVTX в payload
  • слабый audit scope на Windows
  • шумный или слишком тяжёлый результат
  • неочевидная трассировка от пакета к отчёту

Acceptance для этого сценария:

  • есть хотя бы один реальный zip-пакет;
  • aw-hayabusa провёл intake и analysis без ручной импровизации;
  • артефакты трассируются от HOST до report_dir;
  • follow-up не тащит сырые forensic данные в обычные AW buckets.

Example regression proof template:

  • host=HOST-EXAMPLE
  • case_id=CASE_ID_EXAMPLE
  • intake_id=INTAKE_ID_EXAMPLE
  • sha256=SHA256_EXAMPLE
  • report_dir=/opt/hayabusa/reports/HOST-EXAMPLE/REPORT_RUN_ID_EXAMPLE
  • latest-intake.json status: ok
  • AW-rus case linkage stored under forensics.hayabusa

Типовые проблемы, найденные при validation:

  • Windows zip с backslash path separators давал unzip warning rc=1; wrapper не должен валить intake на таком предупреждении.
  • timeline режимы должны использовать rules/config, а не корень rules directory.

После live proof держать как regression checks:

aw-hayabusa doctor
aw-hayabusa inventory
cat /opt/hayabusa/state/latest-intake.json
readlink -f /opt/hayabusa/state/latest-run

DLP не виден в вебе

Быстрый чек сервера:

curl -fsS http://127.0.0.1:5600/api/0/buckets | jq -r 'keys[] | select(test("^aw-dlp-"))'
curl -fsS http://127.0.0.1:5600/api/0/buckets/aw-dlp-incidents_HOST-EXAMPLE | jq '{end:.metadata.end}'

Контролируемый тест ingest:

TS=$(date -u +%Y-%m-%dT%H:%M:%S.000Z)
PAYLOAD=$(jq -nc --arg ts "$TS" '{timestamp:$ts,duration:0,data:{ruleId:"selftest-dlp-incident",action:"alert",severity:"low",message:"Self-test DLP incident from runbook",signalType:"self_test",username:"AUTOTEST",sessionId:0,hostname:"HOST-EXAMPLE",source:"self-test"}}')
curl -fsS -X POST 'http://127.0.0.1:5600/api/0/buckets/aw-dlp-incidents_HOST-EXAMPLE/heartbeat?pulsetime=60' -H 'Content-Type: application/json' --data "$PAYLOAD"
curl -fsS 'http://127.0.0.1:5600/api/0/buckets/aw-dlp-incidents_HOST-EXAMPLE/events?limit=5' | jq '.[0].data'

Если API видит событие, а bucket-страница в UI показывает старые First/last event, нажать Обновить на странице bucket и раскрыть Events.

Проверка WAL failover (Windows collectors)

Цель: подтвердить, что при недоступности AW API события не теряются, а буферизуются в локальной очереди и автоматически отправляются после восстановления связи.

На RDP-хосте (<WINDOWS_HOST>) в PowerShell под администратором:

  1. Проверить/обнулить очереди:
$q1 = 'C:\ProgramData\AWatch-rus\file-operations-queue*.jsonl'
$q2 = 'C:\ProgramData\AWatch-rus\dlp-endpoint-signals-queue*.jsonl'
Get-Item $q1,$q2 | Select Name,Length,LastWriteTime
  1. Временно заблокировать исходящий доступ на AW API (:5600):
New-NetFirewallRule -DisplayName 'AWatch WAL Test Block 5600' -Direction Outbound -Action Block -Protocol TCP -RemotePort 5600 -ErrorAction SilentlyContinue
Enable-NetFirewallRule -DisplayName 'AWatch WAL Test Block 5600'
  1. Сгенерировать тест-событие file-operations:
$p = Join-Path $env:USERPROFILE 'Desktop\aw_wal_test.txt'
Set-Content -LiteralPath $p -Value ('wal-test ' + (Get-Date -Format o))
Start-Sleep -Seconds 5
  1. Убедиться, что очередь выросла:
Get-Item $q1,$q2 | Select Name,Length,LastWriteTime
  1. Снять блокировку и дождаться flush:
Disable-NetFirewallRule -DisplayName 'AWatch WAL Test Block 5600'
Start-Sleep -Seconds 20
Get-Item $q1,$q2 | Select Name,Length,LastWriteTime

Ожидаемо:

  • на шаге 4 длина как минимум одного queue-файла увеличивается;
  • на шаге 5 очередь уменьшается (в идеале до 0 или близко к фоновому уровню).
  1. Проверка на AW server:
curl -fsS 'http://<AW_SERVER_HOST>:5600/api/0/buckets/aw-file-operations_<AW_SERVER_HOST>/events?limit=10' | jq '.[0].data'

После теста удалить правило:

Remove-NetFirewallRule -DisplayName 'AWatch WAL Test Block 5600' -ErrorAction SilentlyContinue

PowerShell MCP на AWatch-rus Windows host

Для AWatch-rus Windows host <WINDOWS_HOST> интерактивный путь из Linux/Codex закреплён через SSH, а не через WSMan.

Быстрый вход:

cd <PROJECT_ROOT>
bash scripts/install_detmir_powershell_mcp.sh

После переоткрытия pwsh или новой Codex-session:

detmir-win-test
detmir-win-ps 'hostname; Get-Date -Format o'
detmir-win-shell

Канонический документ:

  • docs/POWERSHELL_MCP_REMOTE_RU.md

Правило:

  • WinRM использовать для ansible aw_windows и playbook-ов;
  • SSH использовать для powershell-windows MCP, operator PowerShell и ad-hoc remote execution.

У пользователей всплывает окно PowerShell

Ожидаемое поведение collector-ов: запуск hidden (-WindowStyle Hidden). Проверка на Windows хосте:

Get-CimInstance Win32_Process |
  Where-Object { $_.CommandLine -and ($_.CommandLine -match 'browser-domains-native-collector.ps1' -or $_.CommandLine -match 'dlp-endpoint-signals-collector.ps1') } |
  Select-Object SessionId, ProcessId, CommandLine

Если нужно экстренно убрать снимки инцидентов:

  1. Поставить incidentCapture.screenshotEnabled = false в deployment-config.json (для каждого StateRoot).
  2. Запустить Start-ScheduledTask -TaskName 'ActivityWatch Recovery'.

Windows host: Активное время = 0s, хотя window-события есть

Симптом:

  • в Activity view за день видно Worktime = 0s;
  • Top Window Titles / Top Categories / Category Tree пустые;
  • при этом bucket aw-watcher-window_HOST-EXAMPLE содержит свежие события.

Подтвержденная причина:

  • watcher afk "залип" в status=afk без not-afk;
  • из-за этого дневная сводка не считает подтвержденную активность.

Быстрый recovery (с Linux admin host):

  1. Проверить учетку входа. Рабочую учетную запись задавать как параметр экземпляра: HOST-EXAMPLE\WINDOWS_USER_EXAMPLE.
  2. Поднять remote execution через wmiexec.py с auth-file:
cat > /tmp/detmir-windows.auth << 'EOF'
username = WINDOWS_USER_EXAMPLE
password = <PASSWORD>
domain = HOST-EXAMPLE
EOF
chmod 600 /tmp/detmir-windows.auth
  1. Запустить recovery task:
wmiexec.py -nooutput -A /tmp/detmir-windows.auth <WINDOWS_HOST> \
  "powershell -NoProfile -Command \"Start-ScheduledTask -TaskName 'ActivityWatch Recovery'\""
  1. Запустить все launch tasks:
wmiexec.py -nooutput -A /tmp/detmir-windows.auth <WINDOWS_HOST> \
  "powershell -NoProfile -Command \"Get-ScheduledTask | Where-Object TaskName -like 'ActivityWatch Launch *' | ForEach-Object { Start-ScheduledTask -TaskName \$_.TaskName }\""
  1. Подождать 10-20 секунд и проверить API на AW server (<AW_SERVER_HOST>:5600):
curl -fsS 'http://<AW_SERVER_HOST>:5600/api/0/buckets/aw-watcher-afk_HOST-EXAMPLE/events?limit=30' \
  | jq '{latest:.[0].timestamp, statuses:(group_by(.data.status)|map({status:.[0].data.status,count:length}))}'

Ожидаемо после фикса:

  • в свежих AFK-событиях появляется status=not-afk;
  • aw-watcher-window_HOST-EXAMPLE продолжает обновляться;
  • после обновления страницы UI дневная сводка перестает быть 0s.

Сервис не стартует

systemctl cat activitywatch-server.service
cat /etc/activitywatch/aw-server.env
journalctl -xeu activitywatch-server.service --no-pager

Частые причины:

  • битый URL релиза;
  • неполная распаковка архива;
  • занят порт;
  • не созданы каталоги или пользователь;
  • ошибка в env-файле.

API отвечает, но UI без русификации

Проверить:

  • патч реально вставлен в index.html;
  • browser cache/service worker очищен;
  • reverse proxy не отдаёт старую статику;
  • сервис был перезапущен после правок.

Повторное применение:

bash <CT_BOOTSTRAP_DIR>/apply_webui_ru_patch.sh
systemctl restart activitywatch-server.service

После обновления UI сломался патч

  • сравнить index.html с backup;
  • заново применить patch script;
  • проверить словарь в aw-ru-patch.js;
  • при необходимости откатить только Web UI override.

Перед любыми изменениями

  1. Сделать snapshot или vzdump.
  2. Сохранить текущий /etc/activitywatch/aw-server.env.
  3. Сохранить текущий index.html.
  4. Зафиксировать текущую версию aw-server-rust.

Критерии готовности

  • systemd unit стартует без ручного вмешательства;
  • API /api/0/info отвечает локально;
  • UI открывается;
  • русификация присутствует;
  • rollback-путь понятен оператору.

Аудит CryptoPro и готовности подписантов

Для повторяемой проверки сертификатов подписантов и встроенных лицензий CryptoPro:

cd <PROJECT_ROOT>/ansible
ansible-playbook -i inventory.ini audit_cryptopro_windows.yml

Итоговый JSON-отчёт сохраняется локально в:

/tmp/aw-rus-cryptopro-audit-<user>/rdp-prod-cryptopro-audit.json

Отчёт содержит матрицу по профилям:

  • requestedUser
  • profileUser
  • thumbprint
  • subject
  • hasPrivateKey
  • embeddedLicenseOk
  • embeddedLicenseStatus
  • container если виден
  • actionNeeded