0600 模式和正确的所有者并不能保证服务能打开密钥。缺失的权限通常位于其上级目录。Linux 逐组件解析路径,每一步都要先有搜索权限,才会尝试下一步。请读完整条路径,而不是列表的最后一行。

读权限是最后一步,但不是唯一一步

打开文件需要内核从根目录或工作目录穿越路径的每个组件。缺少搜索权限的目录会以权限错误中止这次穿越。文件自身的模式根本不会被查看,因此一个完全可读的密钥看起来却无法读取。错误往往在打开时出现,却不指出目录,于是最后的文件背了锅。

对目录而言,执行位表示搜索,而不是执行其内容。密钥始终是数据,本次修复的任何部分都不需要把它标记为可执行。

以服务账户身份走一遍路径

列出每个组件的所有者与模式,然后以服务的真实身份重复读取。你的 shell 与守护进程之间的差异,往往就是全部答案。跟随符号链接到真实目标,因为被检查的是解析后的路径。

namei -l /etc/openvpn/client/office.key
sudo -u vpn-reader stat -c '%A %U:%G %n' /etc/openvpn/client/office.key

服务也可能在多个阶段打开文件。部分材料在特权设置阶段读取,另一些文件则在放弃特权之后才打开。以 root shell 读取文件,并不能复现后续工作进程的访问。挂载命名空间可能呈现同一路径的不同视图,尤其是在容器内,因此请把守护进程的文件系统视图与你的视图作比较。

只改最窄的够用权限

选择能让进程访问的最小安排:对所需目录有搜索权限的受控组、服务已经拥有的受管位置,或另一种有文档说明的机制。读取文件并不需要其目录的写权限。对特权配置开放宽泛的组写权限,不是常规的穿越修复。递归 0777 也不是解决办法。

记录你改了哪个组件以及原因。没有记录原因的权限变更难以复核,也容易被遗忘。

走完路径后再看模式之外

如果模式位看起来足够,剩下的检查就是 ACL、安全策略和沙箱限制。ACL 可能授予模式位看似缺失的访问,也可能拒绝模式位看似允许的访问。这些设置属于现有配置所有者,应当窄幅调整,而不是直接关闭。根目录或工作目录的差异,也能解释某条绝对路径在一种环境下可用、在另一种环境下失败。

修复访问时不要忘记文件本身是什么。CA 证书按设计就是公开的,私钥则不是。客户端会重写的文件,也需要与只读身份密钥不同的写权限。在不打印秘密的前提下检查元数据,然后确认服务本身在改动后仍能工作。在服务文档里留一句简短说明,就能让下一个人省去同样的穿越。

相关文章