我创建了一些基本上可以工作的 systemd 服务:
地点:
/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 4:40pm
感谢 Thomas 和 Perlduck 的全面回答。它帮助我提高了对 systemd 的了解。
按照启动服务没有密码提示的做法,我要道歉的是我没有足够强调真正的问题:
实际上,对我来说最重要的是,除了 techops 之外,任何其他用户都不应停止或启动该服务。但至少使用前两种方法我仍然可以运行service publicapi stop
并且再次收到提示==== AUTHENTICATING FOR org.freedesktop.systemd1.manage-units ===
。当我选择默认用户并知道密码时,我可以停止所有服务。我想拒绝该用户这样做,即使他有密码。重要的背景信息,可以更好地理解为什么这对我来说更重要:
defaultuser 是唯一暴露于 ssh 的用户,但该用户不能执行任何其他操作(除非您拥有这些其他用户的密码,否则更改为其他用户) 。但此时他可以启动或停止服务,但该用户不得这样做。
如果有人得到了defaultuser的密码并通过ssh登录,那么他就可以停止此时所有的服务。这就是我所说的“我希望只有技术人员可以重新启动服务”的意思。抱歉,我最初的问题并没有那么准确。我认为 sudoing techops 用户可能会绕过这个问题,但事实并非如此。问题本身不是在没有密码提示的情况下运行命令。 (当我执行时,作为 techops 用户,我可以轻松地做到这一点/home/techops/publicapi start
)。问题本身是锁定默认用户启动这些服务。
我希望任何解决方案都能做到这一点。
我从托马斯的方法开始。当我执行所解释的命令时,当我不想被要求输入用户 techops 的密码时,使用 sudo 的方法有效,例如
sudo systemctl start publicapi.service
sudo systemctl stop publicapi.service
第二种方法对我来说还不起作用。如果没有密码提示,我无法启动服务==== AUTHENTICATING FOR org.freedesktop.systemd1.manage-units ===
,并且当我知道该用户的密码时,我可以以默认用户身份登录。
使用第三种方法,该服务甚至不再在启动过程中启动,因此我不确定这种方法是否适合我。我什至无法做到这一点,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 时,如果我有密码,我可以停止服务。但我的目标是完全阻止默认用户启动或停止服务。
答案1
要实现用户无需提供密码techops
即可控制服务,您有不同的可能性。publicapi.service
哪一种适合你是无法回答的,你必须自己选择。
经典sudo
方法可能是最常用的,因为它已经存在很长时间了。您必须创建例如文件,如下所示。
请注意,插入目录仅在 中设置/etc/sudoers.d
时才处于活动状态。但如果您使用的是现代 Ubuntu 发行版,情况应该是这样。执行时:#includedir /etc/sudoers.d
/etc/sudoers
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
第二种方法是使用波尔基特(更名为政策工具包)以允许用户techops
控制systemd
服务。根据 的版本polit
,您可以让普通用户控制 systemd 单元。
要检查波尔基特版本,只需运行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 单元。不幸的是,这包括所有 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 单元。
第三种选择是使该服务成为用户服务,这不需要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
一般来说,您应该将 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
到单元文件中,以使用非特权用户帐户运行该进程。
答案2
首先,您不要将单元文件放入目录中
/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
)会要求输入密码。