我创建了以下[email protected]
服务systemd
:
[Unit]
Description=Cryptography Setup for '%I'
After=cryptsetup-pre.target
After=dev-mapper-%i.device
Before=cryptsetup.target
Before=umount.target
BindsTo=dev-mapper-%i.device
BindsTo=dev-mapper-%i.luks.device
Conflicts=umount.target
DefaultDependencies=no
IgnoreOnIsolate=true
RequiresMountsFor=/home
[Service]
ExecStart=/usr/lib/systemd/systemd-cryptsetup attach '%I.luks' '/dev/mapper/%I' '%h/%I/secret.key' 'luks,header=%h/%I/header'
ExecStop=/usr/lib/systemd/systemd-cryptsetup detach '%I.luks'
KillMode=none
RemainAfterExit=yes
TimeoutSec=0
Type=oneshot
[Install]
WantedBy=default.target
这个想法是仅为特定用户解密某些 LUKS 加密xxx
设备xxx.luks
,该用户启用该服务,例如:
systemctl --user enable luks@xxx
不幸的是,即使测试它
systemctl --user start luks@xxx
失败,因为它总是返回退出代码1
而不说明实际原因。对我来说,很明显问题可能出在权限上。我确信,为了手动触发cryptsetup luksOpen ...
,必须抬起外壳,例如使用sudo
。确实,如果我发出
sudo systemctl start luks@xxx
它的作用就像一个魅力,同样
sudo systemctl enable luks@xxx
适用于启动阶段。
笔记:
对于这种系统范围的安装,当然需要通过替换%h
为给定用户的实际主目录来修改服务,这很丑陋并且无论如何也达不到最终目的。
现在,我知道pam_mount
哪个能够在每个用户的基础上进行类似的安装(我无法使用它,因为它不支持分离的 LUKS 标头,并且因为它实际上安装了设备,这是我不想要的),事实上,pam_systemd
启动systemctl --user
,因此肯定应该有一种方法可以在启动期间为每个用户获取权限以执行设备解密。
顺便说一下,故障症状
systemctl --user enable luks@xxx
甚至比用它进行测试的结果还要糟糕
systemctl --user start luks@xxx
(仅返回退出代码1
)。也就是说,我什至无法使用给定用户登录,因为它抱怨
Failed to create bus connection: No such file or directory
因为XDG_RUNTIME_DIR
和DBUS_SESSION_BUS_ADDRESS
不再设置,而它们应该由服务设置systemd-logind.service
。显然,luks@xxx
不知何故破坏了整个初始化过程,但由于日志中的信息不足,我无法确切地确定原因。因此,我目前对缺乏权限的怀疑仍然存在。
期待有教育意义的建议。谢谢。
答案1
另一种解决方案是编辑该sudoers
文件以添加相关用户的权限,以便在/usr/lib/systemd/systemd-cryptsetup
启用 NOPASSWD 选项的情况下以 root 权限运行。
然后,您可以编辑上面的(特定于用户的)服务文件以读取:
ExecStart=/usr/bin/sudo /usr/lib/systemd/systemd-cryptsetup attach '%I.luks' '/dev/mapper/%I' '%h/%I/secret.key' 'luks,header=%h/%I/header'
ExecStop=/usr/bin/sudo /usr/lib/systemd/systemd-cryptsetup detach '%I.luks'
我不确定您是否还必须启用!要求为了这个工作
更新:
为了提高安全性,特别是对于多用户系统,我强烈建议创建几个脚本来代表用户执行“附加”和“分离”步骤,而不是/usr/lib/systemd/systemd-cryptsetup
直接授予 sudo 访问权限,否则任何有权运行此命令的用户都可能干扰其他加密卷。
答案2
我建议Type=oneshot
RemainAfterExit=yes
为用户创建并启用一项服务,该服务使用其ExecStart
指令创建文件,并使用其ExecStop
指令删除它,例如
ExecStart="/usr/bin/touch %h/.decrypt"
ExecStop="/usr/bin/rm %h/.decrypt"
[email protected]
然后,您可以使用绝对路径为系统用户创建并启用单元文件:
PathExists="/home/user/.decrypt"
这将检查上面的用户服务创建的路径,在[email protected]
创建该单元时激活该单元,并在删除该单元时停用它,从而建立系统服务对用户服务的间接依赖关系。
请注意,为了安全运行,创建文件的目录当然应该只能由用户写入。