Перезапустить службу systemd только как конкретный пользователь?

9

Я создал несколько системных сервисов, которые в основном работают:

расположение:

/etc/systemd/system/multi-user.target.wants/publicapi.service

содержание:

[Unit]
Description=public api startup script

[Service]
Type=oneshot
RemainAfterExit=yes
EnvironmentFile=-/etc/environment
WorkingDirectory=/home/techops
ExecStart=/home/techops/publicapi start
ExecStop=/home/techops/publicapi stop

[Install]
WantedBy=multi-user.target

Когда я пытаюсь перезапустить службу как пользователь techops в командной строке, я получаю следующий вывод:

==== AUTHENTICATING FOR org.freedesktop.systemd1.manage-units ===
Authentication is required to start 'publicapi.service'.
Multiple identities can be used for authentication:
 1.  Myself,,, (defaultuser)
 2.  ,,, (techops)
Choose identity to authenticate as (1-2):

Я хочу, чтобы только techops мог перезапустить службы, и я хочу, чтобы это приглашение не отображалось при входе в систему как techops. Как я могу это сделать?

Я читал, что есть разные подходы с polkit-1 или sudoers, но я не уверен.

[ОБНОВЛЕНИЕ] 2019-01-27 16:40
Спасибо за этот исчерпывающий ответ Томасу и Перлдуку. Это помогло мне улучшить мои знания о systemd.

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

На самом деле, самое важное для меня - то, что никто другой, кроме techops, не должен останавливать или запускать службу. Но по крайней мере с первыми двумя подходами я все еще могу работать, service publicapi stopи я получаю подсказку ==== AUTHENTICATING FOR org.freedesktop.systemd1.manage-units ===снова. Когда я выбираю пользователя по умолчанию и знаю пароль, я могу остановить все службы. Я хочу отказать этому пользователю в этом, даже если у него есть пароль . Важная справочная информация, чтобы лучше понять, почему это важнее для меня: пользователь по
умолчанию является единственным пользователем, который имеет доступ к ssh, но этот пользователь не может делать ничего другого (кроме перехода на других пользователей, если у вас есть пароль этих других пользователей) , Но на данный момент он может запускать или останавливать сервисы, но этот пользователь не должен этого делать.
Если кто-то получит пароль от defaultuser и войдет в систему через ssh, он может остановить все службы в данный момент. Это то, что я имел в виду, «я хочу, чтобы только techops мог перезапустить сервисы». Извините, что я не был так точен в моем начальном вопросе. Я думал, что sudoing пользователь techops может обойти эту проблему, но это не так. Сама проблема не в том, чтобы запустить команду без запроса пароля. (Я мог бы легко сделать это как пользователь techops, когда я просто выполняю /home/techops/publicapi start). Сама проблема заключается в блокировке пользователя по умолчанию от запуска этих служб.

И я надеялся, что любое из решений может сделать это.

Я начал с подходов Томаса. Подход с sudo работает, когда я не хочу, чтобы у меня запрашивали пароль для пользователя, когда я выполняю команды, как описано, например,

sudo systemctl start publicapi.service
sudo systemctl stop publicapi.service

Второй подход у меня пока не работает. Я не могу запустить службу без запроса пароля, ==== AUTHENTICATING FOR org.freedesktop.systemd1.manage-units ===и я могу войти в систему как defaultuser, когда у меня есть пароль этого пользователя.

При третьем подходе сервис даже не запускается при загрузке, поэтому я не уверен, что этот подход мне подходит. Я даже не могу это сделать, systemctl enable publicapi.serviceчто приводит меня к следующей ошибке:

Failed to enable unit: Unit file mycuisine-publicapi.service does not exist.

Ошибка не возникает, когда я перемещаю все службы обратно в / etc / systemd / system / и выполняю systemctl enable publicapi.service. Затем служба запускается снова при загрузке.

Все эти подходы более или менее помогут обойти запрос пароля для пользователя techops, но когда я запускаю service publicapi stopили systemctl stop publicapi с defaultuser, я могу остановить службы, если у меня есть пароль. Но моя цель - заблокировать defaultuser от запуска или остановки служб вообще.

бувигер
источник
1
Для третьего подхода вы должны работать systemctl --user ...от имени пользователя, techopsа не от имени пользователя root. Ни мое предложение, ни предложение @PerlDuck не дают никаких sudoправ вашему defaultuser, но только пользователю techops .
Томас
1
Пользователь по умолчанию настроен как sudo? В этом случае вы должны удалить пользователя из вторичных групп и проверить свой /etc/sudoersфайл, если есть ссылка для этого пользователя.
Томас
@ Томас Ах, вот и все. Это работает как ожидалось сейчас. Спасибо.
бувигер

Ответы:

17

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


Классический sudoподход, пожалуй, наиболее используемый, так как он существует долгое время. Вы должны создать, например, файл следующим образом.
Обратите внимание, что раскрывающийся каталог /etc/sudoers.dактивен, только если #includedir /etc/sudoers.dустановлен в /etc/sudoers. Но это должно иметь место, если вы используете современный дистрибутив Ubuntu. Как rootвыполнить:

cat > /etc/sudoers.d/techops << SUDO
techops ALL= NOPASSWD: /bin/systemctl restart publicapi.service
techops ALL= NOPASSWD: /bin/systemctl stop publicapi.service
techops ALL= NOPASSWD: /bin/systemctl start publicapi.service
SUDO

Теперь вы сможете запускать systemctlкоманды от имени пользователя, techopsне вводя пароль, добавляя sudoкоманды.

sudo systemctl start publicapi.service
sudo systemctl stop publicapi.service
sudo systemctl restart publicapi.service

Второй способ заключается в использовании PolKit (был переименован из PolicyKit ), чтобы позволить пользователю techopsконтролировать systemdслужбы. В зависимости от версии politвы можете предоставить обычным пользователям контроль над единицами systemd.
Чтобы проверить версию polkit , просто запустите pkaction --version.

  • с помощью polkit версии 0.106 и выше вы можете разрешить пользователям контролировать определенные модули systemd.
    Для этого вы можете создать правило как root:

    cat > /etc/polkit-1/rules.d/10-techops.rules << POLKIT
    polkit.addRule(function(action, subject) {
        if (action.id == "org.freedesktop.systemd1.manage-units" &&
            action.lookup("unit") == "publicapi.service" &&
            subject.user == "techops") {
            return polkit.Result.YES;
        }
    });
    POLKIT
    
  • с версией polkit 0.105 и ниже : вы можете разрешить пользователям управлять модулями systemd. К сожалению, это относится ко всем системным модулям, и вы можете этого не делать. Не уверен, есть ли способ ограничить доступ к определенным системным устройствам с версией 0.105 или ниже, но, возможно, кто-то еще может уточнить.
    Чтобы включить это, вы можете создать файл как root:

    cat > /etc/polkit-1/localauthority/50-local.d/org.freedesktop.systemd1.pkla << POLKIT
    [Allow user techops to run systemctl commands]
    Identity=unix-user:techops
    Action=org.freedesktop.systemd1.manage-units
    ResultInactive=no
    ResultActive=no
    ResultAny=yes
    POLKIT
    

В обоих случаях вы можете работать systemctl [start|stop|restart] publicapi.serviceот имени пользователя techopsбез указания пароля. В последнем случае (polkit <= 0.105) пользователь techopsможет управлять любым модулем systemd.


Третий вариант - сделать сервис пользовательским сервисом, который не нуждается sudoни в polkitнастройках. Таким образом все становится под контролем пользователя и работает только в том случае, если ваша действующая служба, с которой запускается, /home/techops/publicapi startможет работать без rootпривилегий.

Сначала вы должны включить задержку для пользователя techops. Это необходимо для запуска службы пользователя при загрузке. Как rootвыполнить:

loginctl enable-linger techops

Затем вы должны переместить systemdфайл модуля в techopsкаталог пользователя. Как пользователь, techopsвыполните команды следующим образом.

mkdir -p ~/.config/systemd/user

cat > ~/.config/systemd/user/publicapi.service << UNIT
[Unit]
Description=public api startup script

[Service]
Type=oneshot
RemainAfterExit=yes
EnvironmentFile=-/etc/environment
WorkingDirectory=/home/techops
ExecStart=/home/techops/publicapi start
ExecStop=/home/techops/publicapi stop

[Install]
WantedBy=default.target
UNIT

Обратите внимание, что WantedByдолжно быть так, default.targetкак нет multi-user.targetв пользовательском контексте.

Теперь перезагрузите конфигурацию и включите сервис. Снова, как пользователь techopsвыполняет команды.

systemctl --user daemon-reload
systemctl --user enable publicapi.service
systemctl --user start publicapi.service

Как правило, вы должны размещать свои системные модули /etc/systemd/system/не в /etc/systemd/system/multi-user.target.wants. При выполнении будет systemctl enable publicapi.serviceсоздана символическая ссылка etc/systemd/system/multi-user.target.wantsили какая-либо цель, указанная для этого подразделения.

Как уже упоминалось, если сама служба / процесс может быть запущена без привилегий root, вам следует рассмотреть возможность добавления User=techopsв файл модуля для запуска процесса с непривилегированной учетной записью пользователя.

Томас
источник
Отлично. Вы даже подумали о другой цели WantedBy для пользовательских единиц. Очевидно, это не первый файл, который вы написали :-)
PerlDuck
Танки @PerlDuck. = 0)
Томас
Спасибо за ответ. Это частично отвечает на мой вопрос, но у меня все еще есть первоначальная проблема. (Я обновил вопрос)
бувигер
Извините, что .pklaне работает. Для этого нужна [section]запись. Обновленный ответ.
Томас
5

Прежде всего, вы не помещаете файл модуля в каталог /etc/systemd/system/multi-user.target.wants. Этот каталог поддерживается systemdи systemctlкомандами. /etc/systemd/systemВместо этого поместите файл модуля и затем включите его

sudo systemctl enable publicapi.service

Это создаст символическую ссылку ниже multi-user.target.wants(или там, где она systemctlзнает лучше), чтобы соблюдать строки

[Install]
WantedBy=multi-user.target

в блоке.

Далее создайте sudoersфайл ниже /etc/sudoers.d:

sudo visudo -f /etc/sudoers.d/techops

со следующим содержанием:

Cmnd_Alias HANDLE_PUBLICAPI = \
    /bin/systemctl start   publicapi.service \
    /bin/systemctl stop    publicapi.service \
    /bin/systemctl restart publicapi.service

techops ALL = (root) NOPASSWD: HANDLE_PUBLICAPI

Не используйте обычный редактор (например sudo vim /etc/sudoers.d/techops) для редактирования этого файла, потому что, если вы добавите в него какие-либо синтаксические ошибки, вы не сможете запустить его sudoснова. visudoс другой стороны, проверяет синтаксис файла перед тем, как покинуть редактор.

Теперь пользователь techopsможет запустить

sudo systemctl start publicapi.service

и два других без указания пароля. Обратите внимание, что вы должны ввести команду и параметры точно так, как указано в sudoersфайле (за исключением /bin/systemctlчасти, которая может быть сокращена до просто systemctl).

Например, sudo /bin/systemctl start publicapi(без .service) будет запрашивать пароль.

PerlDuck
источник