Systemd

僅以特定使用者身份重新啟動 systemd 服務?

  • August 4, 2020

我創建了一些基本上可以工作的 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 有不同的方法,但我不確定。

$$ UPDATE $$2019-01-27 4:40pm

感謝您對 Thomas 和 Perlduck 的全面回答。它幫助我提高了我對 systemd 的了解。

根據在沒有密碼提示的情況下啟動服務的方法,我很抱歉我沒有足夠強調真正的問題:

實際上,對我來說最重要的是,除了 techops 之外,沒有其他使用者應該停止或啟動該服務。但至少前兩種方法我仍然可以執行service publicapi stop並且我再次得到提示==== AUTHENTICATING FOR org.freedesktop.systemd1.manage-units ===。當我選擇預設使用者並知道密碼時,我可以停止所有服務。我想拒絕這個使用者這樣做,即使他有密碼。重要的背景資訊,以更好地理解為什麼這對我來說更重要:

預設使用者是唯一暴露於 ssh 的使用者,但該使用者不能做任何其他事情(如果您擁有這些其他使用者的密碼,則更改為其他使用者除外) . 但此時,他可以啟動或停止服務,但該使用者不得這樣做。

如果有人得到defaultuser的密碼並通過ssh登錄,那麼他現在可以停止所有服務。這就是我所說的“我希望只有技術人員可以重新啟動服務”的意思。抱歉,我最初的問題並不那麼準確。我認為對 techops 使用者進行 sudo 可能會繞過這個問題,但事實並非如此。問題本身不是在沒有密碼提示的情況下執行命令。(當我剛剛執行時,我可以很容易地以 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 stopsystemctl stop publicapi 使用 defaultuser 時,如果我有密碼,我可以停止服務。但我的目標是完全阻止預設使用者啟動或停止服務。

為了實現使用者無需提供密碼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

第二種方法是使用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 單元。不幸的是,這包括所有 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 &gt; ~/.config/systemd/user/publicapi.service &lt;&lt; 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到您的單元文件以使用非特權使用者帳戶執行該程序。

引用自:https://unix.stackexchange.com/questions/496982