仅以特定用户身份重新启动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):

我希望只有技术人员才能重新启动服务,并且我希望以技术人员身份登录时不出现此提示。我怎样才能做到这一点?

我读到polkit-1或sudoers有不同的方法,但是我不确定。

[UPDATE] 2019-01-27 4:40 pm
感谢您对Thomas和Perlduck的全面回答。它帮助我提高了对systemd的了解。

根据在没有密码提示的情况下启动服务的方法,我很抱歉我没有真正强调真正的问题:

实际上,对我来说最重要的是,除了techops之外,没有其他用户可以停止或启动该服务。但是至少使用前两种方法,我仍然可以运行,service publicapi stop并且==== AUTHENTICATING FOR org.freedesktop.systemd1.manage-units ===再次获得提示。当我选择默认用户并知道密码后,就可以停止所有服务。我想拒绝该用户执行此操作,即使该用户具有密码。重要的背景信息,以更好地理解为什么这对我来说是更重要的部分:
defaultuser是唯一暴露于ssh的用户,但是该用户无法执行其他任何操作(除非您拥有其他用户的密码,否则请更改为其他用户) 。但是此刻,他可以启动或停止服务,但是该用户不能这样做。
如果有人获得defaultuser的密码并通过ssh登录,则此刻他可以停止所有服务。这就是我的意思,“我希望只有技术人员才能重新启动服务”。抱歉,我最初提出的问题不那么准确。我认为,嘲笑技术用户可能会绕过此问题,但事实并非如此。问题本身是没有密码提示就不运行命令。(当我执行时,作为techops用户,我可以轻松地做到这一点/home/techops/publicapi start)。问题本身就是阻止defaultuser启动这些服务。

我希望任何解决方案都能做到这一点。

我从托马斯的方法开始。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 stopsystemctl stop publicapi 使用defaultuser时,如果我有密码,则可以停止服务。但是我的目标是完全阻止defaultuser启动或停止服务。


1
对于第三种方法,您必须以systemctl --user ...用户techops身份而不是以root 用户身份运行。无论是我的建议还是@PerlDuck的建议,都没有授予sudodefaultuser的任何权限,而只授予了techops用户。
托马斯

1
是否将defaultuser 配置为sudo?在这种情况下,您应该从辅助组中删除该用户,并检查您的/etc/sudoers文件是否有该用户的参考。
托马斯

@Thomas啊,就是这样。现在可以正常工作了。谢谢。
Bevor

Answers:


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或更低版本的特定systemd单元的访问,但是也许其他人可以澄清一下。
    为此,您可以将文件创建为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单元。


第三个选择是使服务的用户服务,它并不需要sudopolkit配置。这将一切置于用户的控制之下,并且仅在您启动的实际服务/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.targetmulti-user.target,因为用户上下文中没有。

现在,重新加载配置并启用服务。再次作为用户techops执行命令。

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

通常,您不应将systemd单元/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)
Thomas

感谢您的回复。这部分地回答了我的问题,但我仍然有最初的问题。(我更新了问题)
Bevor

对不起,.pkla不能正常工作。这需要一个[section]条目。更新的答案。
Thomas Thomas

5

首先,您没有在目录中放置单位文件 /etc/systemd/system/multi-user.target.wants。该目录由systemdsystemctl命令维护。放入单位文件/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可缩短为just 的部分除外systemctl)。

例如,sudo /bin/systemctl start publicapi(whithout .service)会要求输入密码。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.