Инженерные статьи

Как безопасно проверить и разрешить CI-инструмент, заблокированный Gatekeeper

Как безопасно проверить и разрешить CI-инструмент, заблокированный Gatekeeper

Задача сборки может нормально выполняться в интерактивном терминале, но после переноса на автоматический runner выдавать ошибки «невозможно открыть» или «операция не разрешена». Иногда процесс завершается сразу после запуска. Первой реакцией часто становится команда chmod +x, однако, если у файла уже есть право на выполнение, настоящей причиной блокировки обычно оказывается Gatekeeper, проверка подписи кода или атрибут карантина, сохранённый у загруженного файла. Такое часто происходит с инструментами, скачанными через браузер, артефактами, скопированными из другого сеанса, и кешем, восстановленным из архива с сохранением расширенных атрибутов.

Сначала разделите ошибки запуска на четыре категории

Не удаляйте атрибуты только потому, что файл «не запускается». Сначала соберите сведения о типе файла, правах доступа, архитектуре и расширенных атрибутах. Этих четырёх результатов достаточно, чтобы исключить большинство ошибочных диагнозов.

TOOL="/opt/build-tools/example-tool"

ls -leO@ "$TOOL"
file "$TOOL"
uname -m
xattr -l "$TOOL"

Команда ls позволяет проверить владельца и биты выполнения. Вывод file должен указывать архитектуру исполняемого файла, соответствующую архитектуре узла. Наличие com.apple.quarantine в выводе xattr означает лишь то, что файл попал в процедуру карантинной проверки, но не доказывает его безопасность. При ошибке Permission denied сначала проверьте права на проход по каталогам и ограничения на выполнение для точки монтирования. При ошибке Bad CPU type in executable нужно получить артефакт для правильной архитектуры, а не изменять атрибут карантина.

Симптом Что проверить в первую очередь Чего не следует делать сразу
Permission denied Права файла и родительских каталогов Рекурсивно удалять расширенные атрибуты
Bad CPU type file и uname -m Многократно изменять биты выполнения
Файл повреждён или не удаётся проверить Результаты проверки подписи и Gatekeeper Отключать системные проверки безопасности
Ошибка возникает только в runner Фактический путь, пользователя и источник кеша Считать интерактивную среду полностью идентичной

Атрибут карантина — это указание на происхождение файла, а не сама неисправность. Сначала докажите, что получили ожидаемый файл, и только потом решайте, разрешать ли его выполнение.

Получите однозначный результат проверки Gatekeeper

Проверьте отдельный бинарный файл или приложение

Для инструмента командной строки сначала проверьте подпись, а затем запросите решение системной политики. Для пакета приложения замените значение TOOL путём к соответствующему файлу .app.

codesign --display --verbose=4 "$TOOL"
codesign --verify --deep --strict --verbose=2 "$TOOL"
spctl --assess --type execute --verbose=4 "$TOOL"

Отсутствие подписи у внутреннего инструмента не обязательно означает проблему, но такой инструмент должен поступать из контролируемого процесса сборки, а его целостность должна подтверждаться проверкой контрольной суммы. Если сторонний предварительно собранный инструмент заявлен как подписанный, но не проходит проверку, прекратите его использование и заново получите доверенный артефакт. Нельзя маскировать изменение подписи удалением атрибута карантина.

Изучите журнал системной политики

Во всплывающих сообщениях и стандартном потоке ошибок runner причина часто опускается. Сразу после воспроизведения проблемы просмотрите последние записи политики безопасности. Так можно определить фактически проверявшийся путь и избежать ситуации, когда исследуется кеш A, а запускается файл из кеша B.

log show --last 10m \
  --predicate 'subsystem == "com.apple.security.syspolicy"' \
  --style compact

Последовательно сопоставьте путь из журнала с выводом command -v, конфигурацией runner и переменными скрипта. Особенно часто расхождения возникают из-за символических ссылок: точка входа находится в каталоге инструментов, а конечный файл берётся из старого кеша.

Подтвердите подлинность артефакта перед разрешением запуска

Самый надёжный подход — получать контрольную сумму SHA-256 от поставщика инструмента или внутреннего процесса публикации артефактов и хранить файл контрольной суммы в конфигурации репозитория вместе с версией инструмента. Не вычисляйте контрольную сумму уже скачанного файла лишь затем, чтобы проверить ею тот же самый файл. Такая проверка доказывает только отсутствие изменений между чтениями, но не подтверждает правильность источника.

cd /opt/build-tools
shasum -a 256 -c example-tool.sha256
codesign --verify --deep --strict --verbose=2 example-tool

Внутренний инструмент собственной сборки может не иметь подписи для внешнего распространения, но необходимо как минимум сохранять версию коммита, версию скрипта сборки и ожидаемую контрольную сумму. Если инструмент распространяется в архиве, сначала проверьте архив, затем распакуйте его во временный каталог, проверьте итоговый исполняемый файл и только после этого атомарно замените файл по рабочему пути. Тогда runner не прочитает частично записанный файл во время обновления.

Удаляйте атрибут карантина только у целевого файла

Убедившись, что контрольная сумма, версия и подпись соответствуют ожидаемым, обрабатывайте только проверенный объект. Сначала прочитайте исходное значение и сохраните его в журнале задания, а затем удалите указанный атрибут.

TOOL="/opt/build-tools/example-tool"

xattr -p com.apple.quarantine "$TOOL" 2>/dev/null || true
if xattr -p com.apple.quarantine "$TOOL" >/dev/null 2>&1; then
  xattr -d com.apple.quarantine "$TOOL"
fi

spctl --assess --type execute --verbose=4 "$TOOL"
"$TOOL" --version

Не выполняйте xattr -cr . в рабочем каталоге. Эта команда одновременно удалит разные расширенные атрибуты репозитория, зависимостей, скриптов и временных артефактов. Она не только неоправданно расширит область разрешения, но и уничтожит сведения о происхождении файлов, необходимые для последующего расследования. Для пакета приложения действительно может потребоваться обработка унаследованных атрибутов внутри пакета, однако область операции всё равно следует ограничивать одним уже проверенным пакетом, а не всем корневым каталогом кеша runner.

Превратите проверки в обязательный этап установки

В стабильной облачной среде Mac CI не следует исправлять права на лету в каждом задании сборки. Выделите подготовку инструмента в отдельный этап установки: загрузите его во временный каталог, сверьте контрольную сумму, проверьте архитектуру и подпись, прочитайте состояние карантина, точечно разрешите запуск, выполните проверку версии и только после этого поместите файл в общий каталог инструментов.

Ключ кеша должен включать как минимум имя инструмента, версию, архитектуру CPU и контрольную сумму. Даже после успешного попадания в кеш выполняйте облегчённую проверку, поскольку содержимое кеша могло быть перезаписано вручную. При запуске runner можно записывать в журнал id -un, uname -m, разрешённый путь к инструменту и его версию, но нельзя выводить учётные данные или полный набор переменных окружения.

Наконец, соблюдайте три правила обработки ошибок: немедленно останавливайтесь при несовпадении контрольной суммы; заново получайте артефакт, если подпись должна присутствовать, но не проходит проверку; удаляйте целевой атрибут только тогда, когда запуск уже проверенного артефакта блокирует исключительно карантинная оценка. Такой подход требует на несколько команд больше, чем глобальное отключение проверок, зато происхождение инструмента, действие по его разрешению и фактически запущенную версию можно проверить аудитом.

Часто задаваемые вопросы

Почему macOS блокирует инструмент с правом на выполнение?

Право на выполнение относится только к разрешениям файла. Gatekeeper дополнительно оценивает карантин, подпись, происхождение и системную политику, поэтому chmod +x недостаточно.

Можно ли выполнить xattr -cr для всего рабочего каталога CI?

Нет. Команда удалит атрибуты у всех файлов, включая непроверенные артефакты. Сначала проверьте хеш и подпись, затем удалите только com.apple.quarantine у конкретной цели.

Как исключить повторную блокировку одного и того же инструмента?

Объедините загрузку, проверку хеша, распаковку и точечное разрешение в контролируемый этап установки, а ключ кеша сформируйте из версии, архитектуры и хеша.

OrbVPS облачный Mac

Запускайте сборки на выделенных физических узлах Apple Silicon

Настройте узел по модели, региону и сроку аренды. Фактическая доступность отображается в панели управления в реальном времени.

Арендовать облачный Mac