仅以特定用户身份重新启动 systemd 服务?

Bev*_*vor 14 sudo polkit systemd access-control

我创建了一些基本有效的 systemd 服务:

地点:

/etc/systemd/system/multi-user.target.wants/publicapi.service
Run Code Online (Sandbox Code Playgroud)

内容:

[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
Run Code Online (Sandbox Code Playgroud)

当我尝试在命令行中以 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):
Run Code Online (Sandbox Code Playgroud)

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

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

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

按照无密码提示启动服务的方法,我要道歉,我没有足够强调真正的问题:

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

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

我从托马斯的方法开始。当我按照说明执行命令时,我不想被要求提供用户 techops 的密码时,使用 sudo 的方法有效,例如

sudo systemctl start publicapi.service
sudo systemctl stop publicapi.service
Run Code Online (Sandbox Code Playgroud)

第二种方法对我不起作用。我无法在没有密码提示的情况下启动服务,==== AUTHENTICATING FOR org.freedesktop.systemd1.manage-units ===并且当我拥有该用户的密码时,我可以以默认用户身份登录。

使用第三种方法,该服务甚至不再在启动过程中启动,所以我不确定这种方法是否适合我。我什至无法使用它,systemctl enable publicapi.service这导致我出现以下错误:

Failed to enable unit: Unit file mycuisine-publicapi.service does not exist.
Run Code Online (Sandbox Code Playgroud)

当我将所有服务移回 /etc/systemd/system/ 并执行systemctl enable publicapi.service. 然后服务在启动时再次启动。

所有这些方法或多或少都有助于绕过 techops 用户的密码提示,但是当我运行service publicapi stopsystemctl stop publicapi 使用 defaultuser 时,如果我有密码,我可以停止服务。但我的目标是完全阻止 defaultuser 启动或停止服务。

Tho*_*mas 27

要实现用户无需提供密码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
Run Code Online (Sandbox Code Playgroud)

现在,您应该能够以systemctl用户身份运行命令,techops而无需通过sudo在命令前添加密码来提供密码。

sudo systemctl start publicapi.service
sudo systemctl stop publicapi.service
sudo systemctl restart publicapi.service
Run Code Online (Sandbox Code Playgroud)

第二种方法是使用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
    
    Run Code Online (Sandbox Code Playgroud)
  • 使用polkit 0.105 及更低版本:您可以允许用户控制 systemd 单元。不幸的是,这包括所有 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
    
    Run Code Online (Sandbox Code Playgroud)

在这两种情况下,您都可以在不提供密码的情况下systemctl [start|stop|restart] publicapi.service以用户身份运行techops。在后一种情况下( polkit <= 0.105 ),用户techops可以控制任何 systemd 单元。


第三种选择是使服务成为不需要sudopolkit配置的用户服务。这使一切都在用户的控制之下,并且只有当您启动的实际服务/home/techops/publicapi start可以在没有root特权的情况下运行时才有效。

首先,您必须为用户启用延迟techops。这是在引导时启动用户服务所必需的。作为root执行:

loginctl enable-linger techops
Run Code Online (Sandbox Code Playgroud)

接下来,您必须将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
Run Code Online (Sandbox Code Playgroud)

请注意,WantedBy必须是,default.target因为multi-user.target在用户上下文中没有。

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

systemctl --user daemon-reload
systemctl --user enable publicapi.service
systemctl --user start publicapi.service
Run Code Online (Sandbox Code Playgroud)

通常,您应该将 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到您的单元文件以使用非特权用户帐户运行该进程。


Per*_*uck 7

首先,您不要将单元文件放在目录中 /etc/systemd/system/multi-user.target.wants。该目录由systemdsystemctl命令维护。将单元文件放入/etc/systemd/system,然后启用它

sudo systemctl enable publicapi.service
Run Code Online (Sandbox Code Playgroud)

这将在下方multi-user.target.wants(或任何地方, systemctl知道更好)创建一个符号链接以兑现线条

[Install]
WantedBy=multi-user.target
Run Code Online (Sandbox Code Playgroud)

在单位。

接下来,在sudoers下面创建一个文件/etc/sudoers.d

sudo visudo -f /etc/sudoers.d/techops
Run Code Online (Sandbox Code Playgroud)

具有以下内容:

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
Run Code Online (Sandbox Code Playgroud)

不要使用常规编辑器(例如sudo vim /etc/sudoers.d/techops)来编辑该文件,因为如果您将任何语法错误放入其中,您将无法sudo再次运行。visudo另一方面,在离开编辑器之前检查文件的语法。

现在用户techops可以运行

sudo systemctl start publicapi.service
Run Code Online (Sandbox Code Playgroud)

而另外两个没有提供密码。请注意,您必须完全按照sudoers文件中给定的方式键入命令和参数(除了/bin/systemctl可以缩写为 的部分systemctl)。

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