Клиент LSUS Config Agent (Linux)
lsus-config-agent — отдельный systemd-сервис для Linux-клиентов, исполняющий Ansible-плейбуки, поступающие с сервера через вкладку Конфигурации. Это «руки» модуля compliance/remediation: проверка и приведение в соответствие хостов (EDR/AV/DLP, харднинг ОС, конфиги, службы, установка ПО).
Поставляется со встроенным self-contained Ansible (vendored venv, ~15 МБ) — не требует интернета, установки ansible из репозиториев ОС или системных devel-пакетов. Зависит от lsus-client (читает из его конфигов server_url и Bearer-токен; при пустом адресе находит сервер через DNS TXT/SRV, как клиент). Версия агента синхронна версии LSUS — собирается из того же релиза.
Архитектура и принцип работы#
Master (вкладка Конфигурации)
│ POST /api/v1/clients/ansible/runs/pending (Bearer хоста)
▼
lsus-config-agent (systemd, root)
│ GET /clients/ansible/runs/<id> → spec {playbook, подпись Ed25519, assets, vault}
│ проверка подписи + sha256
│ запуск: venv/bin/ansible-playbook -c local (--check|--become)
│ POST /runs/<id>/result {status, recap, per-task, stdout_log, report}
▼
встроенный venv: ansible-core 2.19 + ansible.posix + community.general
Pull-модель
Агент сам опрашивает сервер (GET /api/v1/clients/ansible/runs/pending) — никаких входящих SSH/портов на клиенте открывать не нужно. Тот же Bearer-токен хоста, что у lsus-client. Запуск локальный: ansible-playbook -c local на самом клиенте, без SSH-push с сервера.
Ритм опроса: раз в poll_interval_seconds (по умолчанию 60 с) со случайным джиттером до poll_jitter_seconds (30 с); сервер может подсказать паузу next_poll_seconds, при ошибках — экспоненциальный backoff до max_backoff_seconds (600 с).
Ключевые свойства#
- Ed25519-подпись обязательна — каждый playbook подписывается приватным ключом сервера; агент проверяет подпись перед выполнением. Защищает от подмены контента (RCE от root — главный риск). Без подписи или при неверной подписи раннер отказывается выполнять.
- Версионирование — контент playbook'а хранится на сервере в immutable-версиях; идущие прогоны ссылаются на конкретную версию. Редактирование плейбука не ломает идущие прогоны.
- Антишторм — раскатка батчами с
throttle/jitter, lease на выполнение, экспоненциальный backoff при ошибках. - Запуск не от root — через
run_as_user+runuser(сброс привилегий), временные файлы с правами 700 — подробнее ниже.
Установка#
lsus-config-agent — отдельный пакет, ставится на Linux-клиенты после lsus-client (жёсткая зависимость).
Команды установки#
# Astra / Debian / Ubuntu (.deb)
sudo apt install ./lsus-config-agent_<версия>_amd64.deb
# РЕД ОС / ALT / CentOS (.rpm)
sudo dnf install ./lsus-config-agent-<версия>-1.x86_64.rpm
Зависимости#
| Зависимость | Назначение |
|---|---|
lsus-client >= <версия> |
Источник server_url и Bearer-токена |
Интерпретатор Python 3.12 и Ansible лежат внутри пакета. Системный Python, пакет python3-venv и отдельный python3.11 из репозитория не нужны: хватает той же системы, где уже стоит клиент. Установка не обращается в интернет.
Порядок установки
Сначала lsus-client, затем lsus-config-agent. Пакет lsus-config-agent не сможет работать без конфигов и токена lsus-client.
При установке пакет автоматически:
1. создаёт venv из bundled wheels (/var/lib/lsus-config-agent/venv);
2. устанавливает коллекции Ansible (community-general, ansible.posix);
3. настраивает SELinux (при enforcing — chcon/semanage для venv);
4. включает и запускает службу lsus-config-agent.service (если на Master не выключен тумблер «Агент конфигураций на хостах»).
Пути установки#
| Путь | Содержимое |
|---|---|
/var/lib/lsus-config-agent/ |
демон lsus_config_agent.py, раннер lsus_ansible_runner.py, venv/, work/ |
/etc/lsus-config-agent/lsus-config-agent.conf |
конфиг (%config(noreplace)) |
/usr/share/lsus-config-agent/wheels/ |
wheels для пересоздания venv |
/usr/share/lsus-config-agent/collections/ |
коллекции Ansible |
/var/log/lsus-config-agent/agent.log |
журналы |
Конфигурация#
Основной конфиг — /etc/lsus-config-agent/lsus-config-agent.conf. По умолчанию server_url и api_token в нём закомментированы — наследуются из конфигов lsus-client, а при их отсутствии сервер находится через DNS (TXT _lsus.<домен>, запас — SRV) — так же, как это делает основной клиент (см. Подготовка DNS).
Приоритет чтения настроек#
[server] server_urlиз собственного конфига (если задан);assigned_server_urlиз конфиговlsus-client— адрес, назначенный сервером. На филиале Site хост остаётся на своём Site: агент не «уводит» его обратно на Master через DNS. Адрес перечитывается при каждом опросе, поэтому назначение, появившееся уже после старта службы, подхватывается без переустановки;/etc/lsus-client/lsus-client.confили/etc/lsus-client/lsus-client-common.conf— секция[server], ключиserver_urlилиmaster_server_url;- DNS-обнаружение: TXT
_lsus.<домен>(отбор по своим IPv4 иcidr, затем SRV_lsus._tcp); домен берётся изserver_discovery_domain— сначала из собственного конфига, затем из конфигаlsus-client, иначе — из FQDN хоста; - Bearer-токен — всегда из
/etc/lsus-client/.api_token(тот же, что уlsus-client).
Пока адрес не найден
Если ни один источник не дал URL (или токен ещё не выдан), агент не падает: ждёт с нарастающим backoff (до max_backoff_seconds, по умолчанию 600) и перечитывает настройки. Текущее состояние видно в systemctl status lsus-config-agent (строка STATUS=) и в журнале /var/log/lsus-config-agent/agent.log.
Параметры конфигурации#
Ключи /etc/lsus-config-agent/lsus-config-agent.conf (все имеют значения по умолчанию — файл можно не трогать):
| Секция | Ключ | По умолчанию | Назначение |
|---|---|---|---|
[server] |
server_url |
— (наследуется) | Адрес сервера; если пуст — конфиги lsus-client, затем DNS |
[server] |
server_discovery_domain |
— (FQDN хоста) | Домен для TXT _lsus.<домен> / SRV-обнаружения |
[agent] |
poll_interval_seconds |
60 |
Период опроса очереди прогонов |
[agent] |
poll_jitter_seconds |
30 |
Случайный разброс опроса (антишторм) |
[agent] |
max_backoff_seconds |
600 |
Потолок паузы при ошибках/ожидании настроек |
[agent] |
http_timeout_seconds |
15 |
Таймаут HTTP-запросов к серверу |
[runner] |
venv_dir |
/var/lib/lsus-config-agent/venv |
Каталог встроенного Ansible |
[runner] |
work_dir |
/var/lib/lsus-config-agent/work |
Рабочий каталог прогонов (playbook, vars, vault) |
[runner] |
stdout_max_bytes |
1048576 |
Потолок вывода ansible в отчёте (1 МБ) |
[runner] |
stderr_max_bytes |
262144 |
Потолок stderr (256 КБ) |
[runner] |
max_tasks |
2000 |
Максимум задач в одном плейбуке |
[logging] |
log_dir |
/var/log/lsus-config-agent |
Каталог файлового лога |
[logging] |
log_level |
INFO |
Уровень логирования |
systemd-служба#
# /etc/systemd/system/lsus-config-agent.service
Type=notify
NotifyAccess=main
TimeoutStartSec=180
User=root
After=network.target lsus-client.service
Requires=lsus-client.service
ConditionPathExists=/var/lib/lsus-config-agent/venv/bin/ansible-playbook
Restart=always
RestartSec=10
ExecStart=/var/lib/lsus-config-agent/venv/bin/python3 /var/lib/lsus-config-agent/lsus_config_agent.py
Type=notify: ожидание адреса — не рестарты
Агент сам сообщает systemd READY=1 сразу после старта. Если server_url/DNS ещё не дали адрес, ожидание идёт внутри процесса (backoff, см. выше) — служба не падает по таймауту старта и не уходит в restart-loop. Реальные падения по-прежнему обрабатывает Restart=always.
ConditionPathExists
Сервис не стартует, пока venv не развёрнут (нет ansible-playbook). Это защита от запуска при незавершённой установке.
Встроенный Ansible (vendored venv)#
| Компонент | Версия |
|---|---|
ansible-core |
2.19.11 |
community.general |
13.2.0 (в пакете дополнительно лежит 13.1.0) |
ansible.posix |
2.2.2 (в пакете дополнительно 2.2.0/2.2.1) |
cryptography |
49.0.0 (проверка Ed25519) |
PyYAML |
6.0.3 |
Интерпретатор CPython 3.12, колёса и tarball-коллекции поставляются внутри пакета. venv создаётся при установке из /usr/lib/lsus-config-agent/python и локального каталога /usr/share/lsus-config-agent/wheels/, без обращения к PyPI. Коллекции разворачиваются ansible-galaxy collection install --offline из локальных архивов в /var/lib/lsus-config-agent/ansible/collections (вне дерева pip-пакета ansible), без обращения к galaxy.ansible.com. Зависимость community.library_inventory_filtering ставится раньше community.general. Колёса собраны под этот интерпретатор: cp312 и stable ABI cp311-abi3 для cryptography.
Поддерживаемые ОС#
| ОС | Версия | Системный Python | Особенность |
|---|---|---|---|
| РЕД ОС | 8.0.2 | как у клиента | интерпретатор службы внутри пакета |
| Astra Linux | 1.7.9 | 3.7 | отдельный python3.11 не нужен |
| Astra Linux | 1.8.5 | 3.11 | — |
| Ubuntu | 22.04 | 3.10 | отдельный python3.11 не нужен |
| Ubuntu | 24.04 | 3.12 | — |
| Debian | 12 / 13 | 3.11 / 3.13 | системный Python службой не используется |
| Oracle Linux | 8 | 3.6 | та же планка, что у клиента |
| ALT Linux | 11.1 | 3.12 (glibc 2.38) | — |
| CentOS Stream | 10 | 3.12 | SELinux enforcing |
Архитектура: x86_64. Для Windows используется отдельный .NET-агент (PowerShell вместо Ansible).
Что делает агент с run'ом#
- GET pending —
GET /api/v1/clients/ansible/runs/pending(получает список ожидающих прогонов, до 10 за раз, с учётомnext_poll_secondsот сервера). - GET spec —
GET /clients/ansible/runs/<id>(контент playbook, Ed25519-подпись,content_type,assets[], расшифрованный vault-секрет — только по TLS). - Доставка ассетов — скачивание файлов-нагрузок (сертификаты, конфиги, дистрибутивы ПО), проверка sha256 + Ed25519, установка mode/owner.
- Проверка подписи — обязательная проверка Ed25519-подписи контента playbook перед выполнением.
- Запуск —
ansible-playbook -i localhost, -c local --check|--becomeчерез venv, с таймаутом из spec (по умолчанию 1800 с). - Прогресс — live-обновления
POST /runs/<id>/progress(фаза, задача). - Артефакты — загрузка собранных файлов (логи, отчёты) обратно на сервер.
- Результат —
POST /runs/<id>/result(status, recapok/ch/fail/unr, per-task,stdout_log,report, stderr, rc):
-stdout_log— человекочитаемый вывод ansible (PLAY/TASK/MSG/PLAY RECAP, классический default-формат). Агент формирует его из распарсенного вывода JSON-callback (берёт события прогона и собирает строкиPLAY/TASK/MSG/PLAY RECAP), без повторного запуска ansible — отдельного прогона ради человекочитаемого лога нет.
-report— сырой JSON-callback (структурированные события прогона), отправляется отдельным полем. На сервере попадает в детали прогона как вкладка «сырой вывод ansible (JSON-callback)» и используется для глубокой отладки/интеграций.
Статусы прогона (AWX-выровненные)#
| Статус | Значение |
|---|---|
pending |
Создан, ждёт агента |
claimed |
Агент забрал (lease активен) |
running |
Выполняется |
successful |
Завершён без failed/changed |
changed |
Завершён, что-то изменено (apply) |
failed |
Проверка/применение упали |
error |
Ошибка агента (нет venv, нет подписи) |
timed_out |
Превышён timeout_seconds |
canceled |
Отменён оператором |
Запуск не от root#
В шаблоне/запуске можно указать run_as_user. Тогда демон (работающий под root) сбрасывает привилегии через runuser -u <user> -- и запускает плейбук от имени этого пользователя. Временные файлы (playbook, vars, vault) создаются с владельцем и правами 600. become=true пробрасывается в Ansible для эскалации внутри плейбука (требует настроенного NOPASSWD sudo на хосте).
become + sudo = root
Запуск не от root не означает «безопасно»: при become=true и наличии NOPASSWD sudo плейбук всё равно эскалирует до root. Используйте run_as_user для принципа наименьших привилегий только там, где эскалация не нужна.
Файлы: Windows-контент, ассеты и артефакты#
В «Конфигурациях» всё — файлы, просто разного назначения. Различаются
content_type/os_family и род (kind):
| Kind | Где живёт | Что это |
|---|---|---|
| playbook / script | config_playbooks (с content_type=yaml/powershell) |
Исполняемый файл; редактируется в UI («Сценарии и скрипты») |
| asset | config_assets + config_asset_versions |
Файл-нагрузка на хост (сертификат/конфиг); immutable + Ed25519 |
| distribution | config_distributions + config_distribution_versions + config_distribution_files |
Дистрибутив ПО — семейство с версиями: карточка + N версий (immutable-набор файлов, 1..N каждый) |
| artifact | config_run_artifacts |
Собранный агентом с хоста файл (для отдачи наружу) |
Windows-контент (PowerShell)#
PS-скрипт — это не отдельная сущность, а config_playbooks с
content_type='powershell'. В модалке плейбука выберите тип контента
(YAML / PowerShell) и целевую ОС (os_family=windows). Исполняет
служба конфигураций LsusConfigAgent.exe на Windows-хосте; на Linux такой плейбук
физически не попадёт в очередь благодаря os_family-guard.
Конвенция скрипта:
- Принимает
-Mode {check|apply}(check= dry-run,apply= применить). - В финале выводит в stdout один JSON-блок:
json {"status":"successful|failed|changed", "summary":{"ok":N,"changed":N,"failed":N}, "tasks":[{"name":"...","status":"ok|failed","changed":false,"msg":"..."}]} - Совместимость с PowerShell 4.0 (Windows Server 2012 R2): WMI/
netshвместо
новых cmdlet'ов. extra_varsчитает из$env:LSUS_EXTRA_VARS; собираемые файлы — в
$env:LSUS_ARTIFACTS_DIR.
Builtin-набор Windows-скриптов (6 шт.): проверка Kaspersky/firewall/UAC, сбор
фактов, реестр-хардненинг, состояние службы.
Раздаваемые файлы (файловый менеджер)#
Подвкладка «Раздаваемые файлы» — трёхзонный файловый менеджер:
- Дерево папок (слева) — иерархия с materialized path (
config_assets.folder - явные узлы в
config_asset_folders). Папки создаются, переименовываются,
перемещаются и удаляются (с подтверждением для непустых). Перетаскивание
файла на папку в дереве перемещает его. - Список файлов (центр) — файлы текущей папки: отдельные ассеты и
дистрибутивы. Мультивыбор + батч-операции (переместить/удалить). Dropzone:
перетащите внешние файлы — каждый станет отдельным ассетом в текущей папке. - Drawer деталей (справа) — вкладки «Метаданные / Версии-файлы / Привязки /
История». История (audit_logs) показывает кто/когда/что загрузил или изменил.
Ассет — immutable-версия файла с Ed25519-подписью (как плейбук, но бинарь).
Привязка к плейбуку (config_playbook_assets) декларирует: какой ассет и куда
положить перед прогоном (dest_path, mode, owner). Агент перед запуском
скачивает ассет, проверяет sha256+подпись и кладёт по пути. Upload версий —
chunked с потоковой склейкой на сервере (прямо на диск, инкрементальный sha256;
без буферизации многогигабайтных файлов в RAM).
Дистрибутив — учётная единица-семейство ПО (Firefox, VLC, …) с карточкой
(издатель/продукт/архитектура/язык/команда установки). Конкретная версия ПО
(152.0.3, 153.0, …) — отдельный immutable-снапшот (config_distribution_versions)
со своим набором файлов (1..N, immutable + Ed25519). Это зеркальный паттерн к
ассетам (config_assets/config_asset_versions): одна карточка, много версий.
Создаётся через мастер «Дистрибутив…»:
- Шаг 1 — карточка-семейство: имя/slug, издатель, продукт, версия ПО, архитектура,
язык, ОС, папка, описание. Модалка сразу показывает 5 карточек этапов
lifecycle (Определение/Предпроверка/Установка/Контроль/Удаление), включая
«Сгенерировать с AI» (ad-hoc черезstaging_tokenиз шага 2). Сразу
создаётся первая draft-версия (version=1), куда пойдут файлы. Правка
метаданных готовой карточки — на вкладке «Обзор» drawer'а; новые версии —
на вкладке «Версии». - Шаг 2 — загрузка файлов версии: несколько файлов или целая папка (через
webkitdirectory, с сохранением относительных путейrel_path) либо DnD.
Крупные файлы — потоковая chunked-загрузка (многоГБ, потоковая склейка на диск
без буферизации в RAM). Дубликатыrel_pathв пределах версии отклоняются.
При добавлении распознаваемого установщика (MSI/EXE/DEB/RPM) автопрофиль
lifecycle подмешивается в карточки этапов пофазно (не перезатирая уже
заполненные вручную этапы). Инспекция файла (POST /distributions/inspect)
также сохраняет копию прочитанного префикса файла и возвращает
staging_token— по нему кнопка «Сгенерировать с AI» на карточке этапа
получает контекст файла ещё до создания дистрибутива. - Finalize версии (по кнопке «Создать» или автоматически по загрузке
файлов) — версия закрывается (статусactive): сервер определяет
dist_type(single_file / archive / folder) и primary-файл (эвристика
setup.exe/*.msi/install*), авто-детектит версию ПО из метаданных
файла (см. ниже). Если lifecycle-контракт не готов (нераспознанный EXE,
архив/папка без известного профиля) — сервер вернёт409, версия останется
draft, а UI вместо ошибки сразу откроет карточку дистрибутива на вкладке
«Установка и проверка»: там нужно донастроить этапы (вручную или AI-генерацией)
и нажать «Завершить и активировать версию». При успешном finalize карточка
переходит вactive, и та же вкладка открывается автоматически — карточки
этапов заполнены автопрофилем, если файл распознан.
Версии дистрибутива (latest / pinned)#
Карточка хранит указатель current_version_id — latest-версию (ту, что
раздаётся, если в привязке не указано иное). В drawer деталей дистрибутива на
вкладке «Версии» доступны:
- список всех версий (label, статус, число файлов, объём, источник авто-детекта,
бейдж «текущая»); - кнопка «Добавить версию» — создаёт новую draft-версию и сразу переводит в
шаг загрузки файлов (карточку-семейство править не нужно); - кнопка «сделать latest» (promote) — назначает выбранную finalized-версию
current; кнопка finalize для draft-версий прямо из drawer; - файлы выбранной версии (с скачиванием).
Привязка к сценарию («Файлы на хост») для дистрибутива поддерживает два режима:
- latest (по умолчанию) — раздаётся
current-версия; её смена (promote
новой) автоматически подхватывается новыми прогонами без правки привязки; - pinned — фиксируется конкретная версия (
distribution_version_id); для
регламентированных окружений, где нужен точный build.
Авто-детект версии ПО (универсальный)#
При finalize версии сервер определяет version_label с многоуровневым fallback
(без новых зависимостей):
- Метаданные бинарника — для
.exe/.dll: разбор PE-ресурсаVS_VERSIONINFO
(FileVersion/ProductVersion). Для Firefox/VLC/Chrome даёт точную версию.
Для.msi— ProductVersion из summary info. - Regex имени файла —
\d+(\.\d+){1,3}(напр.vlc-3.0.20-win64.exe) либо
чисто-цифровой build (7z2407→2407). - Ручной ввод в визарде/finalize — всегда побеждает авто-детект.
Источник записывается в detected_from (metadata/filename/manual) и виден
в drawer для диагностики.
Доставка приложений (end-to-end)#
Рекомендуемый путь для администратора — мастер «Доставить на хосты» в карточке
приложения (вкладка «Обзор»), а не ручная цепочка назначений:
- Загрузка пакета (MSI/EXE/DEB/RPM) и finalize с автопрофилем lifecycle.
- Мастер: пакет → установка/проверка → хосты → канарейка → запуск.
Экспериментальный сценарий доставки ставится только на коллекции с включёнными
испытаниями (флажок в свойствах коллекции; потомки наследуют допуск). Хосты
вне таких коллекций в предпросмотре аудитории отсекаются. Окно мастера
фиксированной высоты, прокручивается тело шага. - Prepare идемпотентно создаёт managed playbook, профиль и draft release.
- Согласование ревизии (separation of duties).
- Application rollout с
target_action(install/upgrade/repair/uninstall). - Мониторинг: release → approval → rollout → waves →
config_host_distribution_state.
Настройка этапов lifecycle (карточки + AI)#
Раньше lifecycle-контракт (detect/check/install/verify/uninstall × Windows/Linux)
редактировался только как сырой JSON на отдельной вкладке — это было тяжело для
администратора и оператора. Теперь основной способ настройки — отдельная вкладка
«Установка и проверка» в карточке приложения (не путать с вкладкой «Обзор» —
там только карточка семейства, версия/пакет и чеклист готовности). Те же самые
карточки этапов (с кнопкой «Сгенерировать с AI») показываются и в модалке
«Новый дистрибутив» ещё до создания записи — см. шаг 1 мастера выше; разница
только в том, что там нет раздельных «Сохранить для версии/базовым» (всё уходит
в lifecycle_defaults вместе при «Создать»), а AI работает в ad-hoc режиме через
временный застейдженный файл. Вкладка «Установка и проверка» сверху вниз показывает:
- «Как это работает» — поток Определение → Предпроверка → Установка →
Контроль, разница между «для версии» и «базовым для всех версий». Установка
и удаление настраиваются только здесь (lifecycle JSON); отдельных полей
install_commandв карточке больше нет. - «Этапы установки и проверки» — секция с разворачиваемыми карточками
этапов:
- каждый этап — отдельная карточка с понятной формой: тумблер
«Этап включён», способ выполнения (powershell/ansible/shell/
package_manager/none), поле со скриптом/командой, коды успеха, таймаут.
Для Windows скрипт — PowerShell. Для Linuxansibleозначает, что скрипт —
настоящий YAML-список задач Ansible (модулиansible.builtin.apt/dnf/
command/…), которые вставляются как есть в собираемый playbook и
исполняются встроенным локальным Ansible агентаlsus-config-agent; коды
успеха для этой ветки не нужны — успех/неуспех этапа определяется тем,
упали задачи или нет.shell/package_manager— по-прежнему bash-команды.
Подсказка под селектором и плейсхолдер поля меняются в зависимости от
выбранного способа выполнения;
- кнопка «Сгенерировать с AI» на карточке — просит AI-ассистента заполнить
только этот этап (модель получает целевую ОС и данные пакета); результат
показывается прямо в карточке с явным указанием способа выполнения
(executor) — для Windows и Linuxshell/package_managerтакже с кодами
успеха (для Linuxansibleкоды успеха не показываются — не применимы),
плюс кнопками «Принять» (подставить в форму) и «Отклонить» —
ничего не сохраняется без ручного подтверждения. Модель проинструктирована
возвращать для Linuxexecutor=ansibleименно YAML-список задач Ansible,
а не bash; если она вернула пустой/нераспознанный executor, UI подставляет
согласованный с ОС вариант (powershellдля Windows,ansibleдля Linux);
- «Сохранить для версии» — изменения применяются только к выбранной версии
(override); «Сделать базовым для всех версий» — меняет сценарий
приложения (defaults), которым пользуются все версии без своего override;
- если AI недоступен или вернул невалидный ответ, для MSI/EXE/DEB/RPM
подставляется детерминированный автопрофиль —
генерация с AI никогда не оставляет этап пустым при распознанном пакете.
Для MSI все Windows-фазы (включаяinstall) намеренно используют executor
powershell: detect/verify/uninstall читают реестр (Get-ItemProperty),
а сама командаmsiexec /i "{{installer_path}}" /qn /norestartпроверяет
код завершения через$LASTEXITCODE— PowerShell исполняет и обычные
команды, поэтому это не ошибка распознавания. Для DEB/RPM автопрофиль —
настоящие задачи Ansible (ansible.builtin.apt/dnf, с fallback через
apt -f install/yum), executoransible— запускает lifecycle-скрипты
как настоящие Ansible-задачи;
- если версия ещёdraft(не прошла finalize, например пакет не распознан
автоматически), в конце секции показывается заметный блок с кнопкой
«Завершить и активировать версию» — после настройки этапов вручную
или через AI её можно активировать прямо здесь, без возврата в мастер. - Кнопка «Экспертный режим (JSON)» — раскрывает свёрнутый по умолчанию блок
с сырым JSON-контрактом (defaults/overrides/итоговый эффективный контракт).
Он показывает то же самое, что и карточки этапов, но предназначен для
точечных правок и просмотра, а не для повседневной настройки.
Дистрибутив привязывается к сценарию так же, как ассет
(config_playbook_assets.distribution_id, опционально distribution_version_id);
Windows .NET-агент получает в claim-спеке файлы резолвнутой версии
(rel_path + подпись + checksum + version_label для диагностики), стримит их
на диск в dest_path, проверяет sha256 и Ed25519; установка/удаление выполняются
сгенерированным playbook по lifecycle-контракту (политика lsus.software.install,
auto_install=false на привязке). Привязка доступна через UI «Файлы на хост»
(переключатель Ассет/Дистрибутив + селектор версии).
Поддержка агентами: Windows .NET-агент (сборка с config-distributions) — полная
(доставка + verify + install, latest/pinned). Linux config-агент пока не поддерживает
дистрибутивы (только обычные ассеты).
Пример E2E (демо-стенд): карточка-семейство «Mozilla Firefox» (os=windows,
lifecycle с этапом install через msiexec) → загрузка установщика 152.0.3
(88 МБ, sha256+Ed25519) → finalize (active, авто-детект версии из PE-метаданных,
версия становится current/latest) → привязка к сценарию из политики
lsus.software.install (dest_path=C:\Deploy\firefox, pinned/latest) →
apply-прогон: агент скачал файл, проверил подпись, playbook выполнил lifecycle
install (rc=0), verify подтвердил версию → Firefox 152.0.3 установлен. Позже:
загрузка версии 153.0 → promote в latest → новые прогоны автоматически ставят
153.0 без правки привязки.
Артефакты (файл с хоста наружу)#
Скрипт складывает собираемые файлы (отчёты, факты для сторонней системы) в
LSUS_ARTIFACTS_DIR; после прогона агент грузит их на сервер (single-shot /
chunked) в config_run_artifacts. Артефакты:
- read-only, TTL (по умолчанию 7 дней, чистятся воркером по
expires_at); - доступны в модалке прогона (скачать/превью);
- форвардятся во внешнюю систему через integration-gateway (эпик внешних
интеграций) —target_provider_id. Пока gateway не подключён — хранятся
инертно, доступ через API/UI.
Диагностика#
Проверка работоспособности#
# статус службы
systemctl status lsus-config-agent
# журнал службы
journalctl -u lsus-config-agent -f
# файловый лог
tail -f /var/log/lsus-config-agent/agent.log
Стартовая строка в логе при успешном запуске: lsus-config-agent <version> запущен (server=<url>).
Ручной запуск spec (dry-run)#
Для диагностики playbook'а без сервера есть CLI-обёртка:
/var/lib/lsus-config-agent/venv/bin/python3 /var/lib/lsus-config-agent/lsus_ansible_runner.py <spec.json> [output.json]
Принимает JSON spec (файл или строку), выполняет playbook через тот же AnsibleRunner, печатает результат (или пишет в output.json). Exit-код 0 при successful.
Журналы
- journal:
journalctl -u lsus-config-agent(StandardOutput=journal). - Файловый лог:
/var/log/lsus-config-agent/agent.log(ротация 5 МБ × 5 копий, уровень INFO). - Архив диагностики клиента забирает этот конфиг, файловый лог и journal, если служба установлена.
Связь с lsus-client#
| Что | Как |
|---|---|
server_url |
наследуется из конфигов lsus-client (если не задан в собственном конфиге) |
| Bearer-токен | всегда из /etc/lsus-client/.api_token (тот же, что у lsus-client) |
| Зависимость пакета | Depends: lsus-client (>= <версия>) — обязательная |
| Автономная работа | невозможна — нужен server_url/токен из lsus-client |
| Heartbeat | не шлёт; версию отправляет один раз при старте (POST /clients/ansible/version) |
Версия в `config_agent_version`
При старте агент отправляет свою версию (POST /api/v1/clients/ansible/version), сервер записывает её в колонку хоста config_agent_version — видна на вкладке «Хосты → Версии агента».
Регистрация на сервере#
lsus-config-agent не регистрируется отдельно — использует регистрацию и Bearer-токен хоста, созданные lsus-client. Просто начинает опрашивать /clients/ansible/runs/pending с тем же токеном. User-Agent во всех запросах: lsus-config-agent/<version>.
Что нужно серверу#
Чтобы вкладка Конфигурации появилась в Master и агент начал получать задания, на сервере должны быть:
- созданы плейбуки/профили (через Конструктор политик или импорт);
- создано назначение (профиль → группа/тег/хост) с режимом check/apply;
- на клиентах установлен lsus-config-agent и запущен сервис;
- в «Управление обновлениями → Клиент LSUS → Настройки» включён тумблер «Агент конфигураций на хостах» и в лицензии есть модуль «Управление конфигурациями». Если тумблер выключен, lsus-client останавливает юнит lsus-config-agent и не забирает прогоны; патч-агент при этом жив. Если пакета нет, состояние missing — патч-агент не падает.
Связанные страницы#
- Клиент LSUS — базовый агент (heartbeat, обновления).
- Конфигурации — серверная часть: профили, плейбуки, назначения, конструктор.
- Windows-агент — для Windows (PowerShell вместо Ansible).
- Развёртывание серверов — установка Master.
- Антивирус и установка обновлений — исключения для
venvагента иansible-playbook.