Phi*_*ppe 3 bash sftp process-substitution password-store
与我的团队一起,我们需要共享一些私钥并将它们存储在密码存储库中。
因此,我没有提取密钥并将其以明文形式存储在文件系统上,而是寻找一种方法,只将解密后的版本保存在内存中:
$ sftp -i <(pass foo) user@host
Warning: Identity file /dev/fd/63 not accessible: No such file or directory.
Run Code Online (Sandbox Code Playgroud)
知道为什么 sftp 无法读取临时文件描述符吗?如何解决?
知道为什么
sftp无法读取临时文件描述符吗?
几个事实:
<(pass foo)进程替换将导致bash创建管道,运行pass foo与它的输出连接到所述管的书写端异步命令并更换<(...)与以下形式的的路径/dev/fd/63,在这里63是文件描述符参照管的读取结束。/dev/fd/63是一个特殊的路径,它允许进程stat()重新打开由其文件描述符之一引用的文件。sftp,然后sftp本身 forks 和 execs ssh,导致63文件描述符通过继承传递。ssh将使用该函数关闭除 0、1、2 之外的所有文件描述符closefrom()。这也将关闭 fd 63。由于63在ssh进程中不再是打开的文件描述符,所以stat()on/dev/fd/63将失败并显示来自 OP 的错误。
如何解决?
将密钥临时存储在内存中的文件系统中。在我的 Debian 下systemd为我提供了 tmpfs /run/user/<myUID>。除了我(当然还有 root)以外的任何人都无法访问挂载点。
请注意,在您的用户(或 root)下运行的流氓进程可以读取该文件。但是这样的过程也可以从原始方法中的sshd文件描述符63中读取。
或者,当没有可用的安全 tmpfs 时:
创建临时fifo。注意mktemp不能直接执行此操作。安全的方法是创建一个临时私有目录,然后mkfifo在其中。
确保fifo本身的权限很窄,否则ssh会报错。
跑
sftp -i "/temp_dir/the_fifo" user@host
Run Code Online (Sandbox Code Playgroud)并行运行pass foo > "/temp_dir/the_fifo"。一个怪癖:你需要这样做两次;至少在我的 Debian 中ssh读取了两次密钥。下面的命令似乎在我的测试工作:cat ~/.ssh/id_rsa > "/temp_dir/the_fifo" && cat ~/.ssh/id_rsa > "/temp_dir/the_fifo"。可能类似的重复命令对您有用:
pass foo > "/temp_dir/the_fifo" && pass foo > "/temp_dir/the_fifo"
Run Code Online (Sandbox Code Playgroud)
您可以在之前在后台运行它sftp(除非pass是交互式的,我根本不熟悉该工具)。
最后删除fifo和目录。
尽管如此,在您的用户(或 root)下运行的流氓进程可以先读取 fifo ssh。