是否有将密码传递给 Systemd Unit 文件的典型方法?

Sau*_*ode 17 password permissions shell-script systemd

我想使用 systemd 单元文件启动服务。此服务需要密码才能启动。我不想将密码以明文形式存储在 systemd 单元文件中,因为它是世界可读的。我也不想以交互方式提供此密码。

如果我为此编写普通脚本,我会将凭据存储在具有受限权限(400 或 600)的 root 拥有的文件中,然后将该文件作为脚本的一部分读取。是否有任何特定的 systemd 风格的方法可以做到这一点,还是应该像在常规 shell 脚本中一样遵循相同的过程?

jas*_*yan 15

根据您的要求,这里有两种可能的方法。如果你不做要被提示输入密码时,该服务被激活时,使用的EnvironmentFile指令。来自man systemd.exec

类似于 Environment= 但从文本文件中读取环境变量。文本文件应包含以换行符分隔的变量赋值。

如果确实希望得到提示,则可以使用其中一个systemd-ask-password指令。来自man systemd-ask-password

systemd-ask-password 可用于使用命令行上指定的问题消息向用户查询系统密码或密码。当从 TTY 运行时,它将在 TTY 上查询密码并将其打印到标准输出。当不使用 TTY 或使用 --no-tty 运行时,它将使用系统范围的查询机制,该机制允许活动用户通过多个代理进行响应

  • 请注意,在环境变量中传递密码存在缺陷(即使设置变量的文件受到保护),因为通常可以窥探属于其他用户的进程的环境变量(例如使用`ps ajxewww`),因此有人也许可以从那里拿起它。 (4认同)
  • @filbranden 您无法读取属于其他用户的进程的环境变量。 (2认同)

Tre*_*her 9

根据 systemd 手册(systemd.exec 等),普通环境变量不应用于凭据管理。Systemd 有一个完整的手册页描述其选项,例如 LoadCredential、LoadCredentialEncrypted、SetCredential、SetCredentialEncrypted。有关在 systemd 中执行此操作的正确方法的完整说明,请参阅https://systemd.io/CREDENTIALS/和 systemd.exec 手册页。

使用环境变量意味着不需要凭据的进程可能仍然继承或有权访问变量,并且可能导致秘密无意中暴露。我希望将 systemd 服务与 Bitwarden CLI 集成,并按照https://systemd.io/CREDENTIALS/中的说明使用 SetCredentialEncrypted 。经过几次调整(bw预计设置 HOME 环境变量)后,我的 Bitwarden 主密码在磁盘上静态加密,只有我的服务部门可以访问它来解锁我的 Bitwarden 帐户。

我就是这样做的。首先,我将 Bitwarden 主密码写入常规文件,我们将其命名为/tmp/bwmaster.pass。回想起来,最好将其写入 ramdisk,而不是 Btrfs,可能选择/run/(所有这些命令都需要 root 访问权限)。接下来,我创建了主密码的加密副本:

# systemd-creds encrypt --pretty --name=bwmp /tmp/bwmaster.pass -
Run Code Online (Sandbox Code Playgroud)

这将漂亮地打印 SetCredentialEncrypted=bwmp 简介,您可以将其添加到 systemd 服务单元文件的 [Service] 部分(直接或作为覆盖)。这是我的输出:

SetCredentialEncrypted=bwmp: \
        k6iUCUh0RJCQyvL8k8q1UyAAAAABAAAADAAAABAAAADCNQBSGbmpFUpRgngAAAAAgAAAA \
        AAAAAALACMA0AAAACAAAAAAfgAgCE+qUDoEpxT3155oWkncltAG6Wv+IQAEm7EwIhahpw \
        gAEB8dLosK741kyXWOWXQwLRfvhx6vDf7Na6JNGNW3PQkF6TZmJsUNYsWGXLgyIbgtjkd \
        0TkS0LfVOo/e6PQ32p/xfEj0b+ZGCXgtjC0Tx6sDedhU0fIfT2b+IlwBOAAgACwAAABIA \
        ID8H3RbsT7rIBH02CIgm/Gv1ukSXO3DMHmVQkDG0wEciABAAINgs66YvSM+PW+qPTnGE/ \
        8Yq67HHaX5XMmymUojmugUkPwfdFuxPusgEfTYIiCb8a/W6RJc7cMweZVCQMbTARyIAAA \
        AAWUZXjxS/vfx0BJq8RQAAyeXdSsf7ccsz+yEcMvoUm4WYZupWzt1FW93FDsUpdyi+QID \
        pqczUQ24ODMC+HP9vP7nvLHPF4uNk+iPkR5fF7Ypl5rHdcFyfm1Bqp70g
Run Code Online (Sandbox Code Playgroud)

将其存储在我的服务单元文件中后,我安全地删除了临时纯文本文件:

# shred -uz /tmp/bwmaster.pass
Run Code Online (Sandbox Code Playgroud)

man shred有关这方面的更多详细信息,请参阅。当我这样做时,我使用 Bitwarden 来存储我的 Borg 加密备份凭证。我编写了以下服务文件:

[Unit]
Wants=network.target
After=network-online.target
[Service]
Type=oneshot
SetCredentialEncrypted=bwmp: \
        k6iUCUh0RJCQyvL8k8q1UyAAAAABAAAADAAAABAAAADCNQBSGbmpFUpRgngAAAAAgAAAA \
        AAAAAALACMA0AAAACAAAAAAfgAgCE+qUDoEpxT3155oWkncltAG6Wv+IQAEm7EwIhahpw \
        gAEB8dLosK741kyXWOWXQwLRfvhx6vDf7Na6JNGNW3PQkF6TZmJsUNYsWGXLgyIbgtjkd \
        0TkS0LfVOo/e6PQ32p/xfEj0b+ZGCXgtjC0Tx6sDedhU0fIfT2b+IlwBOAAgACwAAABIA \
        ID8H3RbsT7rIBH02CIgm/Gv1ukSXO3DMHmVQkDG0wEciABAAINgs66YvSM+PW+qPTnGE/ \
        8Yq67HHaX5XMmymUojmugUkPwfdFuxPusgEfTYIiCb8a/W6RJc7cMweZVCQMbTARyIAAA \
        AAWUZXjxS/vfx0BJq8RQAAyeXdSsf7ccsz+yEcMvoUm4WYZupWzt1FW93FDsUpdyi+QID \
        pqczUQ24ODMC+HP9vP7nvLHPF4uNk+iPkR5fF7Ypl5rHdcFyfm1Bqp70g
Environment=BWMPATH=%d/bwmp
ExecStart=/usr/local/sbin/borg.sh
Run Code Online (Sandbox Code Playgroud)

我的borg.service文件还有更多内容,但我只包含了本主题的重要部分。根据手册,应该有一个可以在脚本中引用的 $CREDENTIAL_PATH/bwmp 文件,但是直到我像上面那样定义了 BWMPATH 环境变量之后我才能让它工作。这可能是因为bw命令 (Bitwarden CLI) 工具需要设置 HOME 变量,因此我在脚本中设置了它(只有 root 会运行borg.sh)。

请参阅 systemd.exec 和https://systemd.io/CREDENTIALS手册,了解其工作原理的具体信息。该systemd-creds命令将自动使用 TPMv2 芯片(如果您的系统中可用)以及密钥文件。我不确定我的系统是否有 TPMv2 芯片,这是我稍后会探索的内容。

这对我在 Arch Linux、systemd 251.3-1(一周左右没有更新)上有效。如果您使用的是其他版本,则该版本可能不存在。


slm*_*slm 6

除了@jasonwryan 的第二个建议之外,还有第三种替代方案。

摘自 Michael Hampton 在 ServerFault 上的回答 -如何在 systemd 服务中设置环境变量?

当前执行此操作的最佳方法是运行systemctl edit myservice,这将为您创建一个覆盖文件或让您编辑现有文件。

在正常安装中,这将创建一个目录/etc/systemd/system/myservice.service.d,并在该目录内创建一个名称以.conf(通常为override.conf)结尾的文件,在该文件中,您可以添加或覆盖发行版附带的单元的任何部分。

例如,在一个文件中/etc/systemd/system/myservice.service.d/myenv.conf

[Service]
Environment="SECRET=pGNqduRFkB4K9C2vijOmUDa2kPtUhArN"
Environment="ANOTHER_SECRET=JP8YLOc2bsNlrGuD6LVTq7L36obpjzxd"
Run Code Online (Sandbox Code Playgroud)

另请注意,如果该目录存在且为空,您的服务将被禁用!如果您不打算将某些内容放入该目录中,请确保该目录不存在。

  • 请注意,嵌入式配置文件“/etc/systemd/system/myservice.service.d/*.conf”的内容对每个用户都是可见的(请参阅“systemctl show myservice.service | grep Environment=”) (3认同)

eck*_*kes 6

顺便提一下,systemd 274 支持特殊的内存凭证文件,请参阅systemd.exec (5) 手册页中的LoadCredential=和设置,这也适用于 .service 单元。LoadCredentialEncrypted=