Systemd и точка в логине

12 ноября 2020

Systemd предоставляет сервисам несколько инструментов для ограничения привилегий.

Во-первых, это директивы "User=" и "Group=".

Во-вторых, предоставляется множество директив для более тонкой настройки — их полный список доступен в https://www.freedesktop.org/software/systemd/man/systemd.exec.html — в основном, в разделах Credentials, Security, Sandboxing и System Call Filtering.

Однако самым простым и распространённым является понижение привилегий через "User=".

Тем неприятнее для нас было столкнуться с ограничением: systemd отказывается принимать имена, если в них содержится точка.

Обсуждение проблемы: "systemd does not allow user names with a dot in them" — https://github.com/systemd/systemd/issues/12754

Создатель systemd отказался исправлять поведение своего детища под тем предлогом, что некоторые утилиты (например, chown) воспринимают точку как разделитель между именем пользователя и группы, поэтому systemd также обязан воспринимать её как недопустимый служебный символ.

Не помогли отсылки к многолетней общепринятой практике использования логинов наподобие "b.gates" или "elon.m".

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

Нам остаётся только один вариант: не использовать "User=", а понижать привилегии непосредственно в команде, запускаемой в "ExecStartPre=".

Какими утилитами это можно сделать?

На ум приходят стандартные системные su и sudo, но они имеют серьёзные недостатки.

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

Это означает почти неизбежные проблемы с отправкой сигналов: su и sudo могут и «забыть» передать сигнал запущенному из-под них приложению, и обработать сигнал отличным от приложения образом, получив его вместе или вместо приложения.

Кроме того, sudo представляет из себя сложный универсальный комбайн с разветвлёнными настройками и не всегда очевидными параметрами по умолчанию. Например, без параметра "-E" он не передаст приложению никакие переменные окружения, кроме самых базовых (PATH, SHELL и так далее).

Нам нужен более простой инструмент:

  • без дополнительных настроек — только указанные в командной строке,
  • без дополнительных действий — только смена пользователя и группы перед запуском команды через exec.

Мы нашли его в лице gosu:

  • Написана на Go, то есть состоит из одного файла и не имеет библиотечных зависимостей.
  • Делает то, что требуется.
  • Не делает то, что не требуется.
  • Документация перечисляет те же самые предпосылки отказа от su и sudo, с которыми столкнулись мы.
  • Нам понравилось, что документация содержит не только описание самого gosu, но и список возможных альтернатив (на данный момент это setpriv, chroot и su-exec — не исключено, что одной из них мы воспользуемся в дальнейшем).


← Назад в Блог

Подпишитесь на новые статьи: