Перейти к содержимому

core.archive

← Каталог модулей

soul-sidesoulstack.filesfilesroot требуется

Распаковка архивов (tar/tar.gz/tar.bz2/zip) в каталог.

core.archive распаковывает архив path в каталог dest средствами Go stdlib in-process — без внешних tar/unzip и без подпроцессов, что даёт per-entry контроль безопасности (zip-slip/zip-bomb/symlink), недоступный backend-утилитам. format опционален — auto-detect по расширению path. Идемпотентно: SHA-256 исходного архива пишется в маркер <dest>/.soul-archive.sha256, тот же архив повторно не распаковывается (changed=false). Soul-side.

Требования

  • Rootтребуется
  • Сторонаsoul-side
  • Коллекцияsoulstack.files
  • Категорияfiles
Capabilitiesfs_write_root

Состояния

core.archive.extracted — Архив path распакован в каталог dest (tar/tar.gz/tar.bz2/zip).

Меняется, когда

Маркера <dest>/.soul-archive.sha256 нет либо его хэш ≠ хэшу текущего архива. Проверка grounded по хэшу архива — целостность распакованных файлов в dest не сверяется.

Не меняется, когда

Маркер на месте и его хэш совпал с текущим архивом.

Параметры

ПараметрТипОбяз. / дефолтОписание
pathstringrequiredПуть к архиву-источнику.
deststringrequiredКаталог распаковки.
formatstringoptionalФормат (tar|tar.gz|tar.bz2|zip); опущено — auto-detect по расширению.
max_sizestringoptionalЛимит суммарного распакованного размера (число байт или N[KiB|MiB|GiB]); по умолчанию 1GiB. Защита от zip-bomb.
max_entriesintegeroptionalЛимит числа записей в архиве; по умолчанию 100000. Защита от zip-bomb.
max_ratiointegeroptionalЛимит отношения распакованных байт к сжатым (compression ratio); по умолчанию 100, 0 — отключено. Защита от zip-bomb с маленьким сжатым размером.

Пример — Распаковать скачанный tarball; format auto-detect по .tar.gz

- name: Extract node_exporter tarball
module: core.archive.extracted
params:
path: /tmp/node_exporter-1.9.0.tar.gz
dest: /tmp/node_exporter-1.9.0
max_size: "500MiB"

Output

ПолеТипОписание
pathstring
deststring
sha256string
extractedtrue

Справочник

Поддерживаемые форматы

format опционален — при отсутствии определяется по суффиксу path; нераспознанный суффикс → шаг падает (cannot auto-detect format).

ФорматРасширения (auto-detect)Примечание
tar.tar
tar.gz.tar.gz, .tgz
tar.bz2.tar.bz2, .tbz2только распаковка (bzip2 в stdlib decompress-only)
zip.zip

Заметки

  • Распаковка in-process на Go stdlib (archive/tar, archive/zip, compress/gzip, compress/bzip2) — без внешних tar/unzip и без порождения подпроцессов. Хостовые утилиты распаковки не нужны, зато есть per-entry контроль безопасности, недоступный backend-утилитам.
  • max_size принимает голое число (байты) либо число с бинарным суффиксом KiB/MiB/GiB (регистр суффикса не важен). Десятичные SI-суффиксы (KB/MB/GB) и дроби не поддерживаются — нераспознанный суффикс или мусор → явная ошибка invalid size, а не тихий отброс хвоста.
  • Маркер .soul-archive.sha256 лежит внутри dest — учитывайте при последующей сверке содержимого каталога другими шагами. changed=true проверяет «архив тот же» (хэш маркера), а не «все файлы внутри dest на месте».
  • Неподдерживаемые типы записей (hardlink, устройства block/char, fifo, socket) → явная ошибка (unsupported type), а не тихий пропуск. Служебные PAX/GNU-заголовки и sparse-метаданные молча игнорируются.
  • dest создаётся (MkdirAll, mode 0755), если не существует.

Безопасность и умолчания

  • zip-slip / path-traversal — fail-fast: целевой путь каждой записи строится через filepath-securejoin относительно dest плюс лексический детект escape; запись с .. либо абсолютным путём наружу → шаг падает целиком (entry escapes dest), уже распакованные файлы остаются, маркер не пишется. Не тихий clamp — запись наружу не создаётся.
  • zip-bomb — лимиты max_size (дефолт 1GiB, суммарный распакованный размер), max_entries (дефолт 100000, число записей) и max_ratio (дефолт 100, 0 — выкл; отношение распакованных байт к сжатым). Превышение любого → шаг падает с указанием пробитого лимита.
  • symlink — within-dest only: symlink из архива создаётся, только если его target (резолвнутый относительно директории самого symlink-а) остаётся внутри dest; абсолютный или выводящий за dest target → шаг падает. Запись «сквозь» symlink-каталог из того же архива fail-closed (securejoin резолвит по уже лежащему на диске пути) — target-каталог адресуйте напрямую.
  • setuid / setgid / sticky маскируются всегда (mode применяется как entry.Mode() & 0o777) — архив не может протащить исполняемый файл с setuid-root. owner/group из архива не берутся — файлы получают владельца процесса soul-агента.
  • Checksum — для идемпотентности, не для верификации источника: SHA-256 считается по уже лежащему на диске архиву («тот же ли архив, что в прошлый раз»), против доверенного эталонного хэша/подписи не сверяется. Для недоверенных артефактов сверяйте подпись/хэш отдельным шагом (register + failed_when:) до распаковки и распаковывайте в изолированный непривилегированный dest.
  • Привилегии: манифест объявляет только fs_write_root, но не run_as_root и не exec_subprocess (подпроцессы не порождаются); для распаковки в системные пути агент на практике работает под root — тем ценнее setuid-маскинг и within-dest-инварианты.

См. также