【发布时间】:2022-03-18 23:48:06
【问题描述】:
我正在尝试向ssh-agent 添加一个密钥,并希望ssh-add 从我正在使用的密钥文件中读取密码。这怎么可能?
如何通过 shell 脚本自动执行此过程?
【问题讨论】:
-
为什么不直接存储一个没有任何密码的密钥副本,在同一个地方使用与存储密码相同的权限?
我正在尝试向ssh-agent 添加一个密钥,并希望ssh-add 从我正在使用的密钥文件中读取密码。这怎么可能?
如何通过 shell 脚本自动执行此过程?
【问题讨论】:
根据您的发行版和 ssh-add 的版本,您可能能够或不使用 ssh-add 的 -p 选项以这种方式从标准输入读取密码:
cat passfile | ssh-add -p keyfile
如果这不起作用,您可以使用Expect,这是一个 Unix 工具,可以使交互式应用程序变为非交互式。你必须从你的包管理器安装它。
我已经为您编写了一个工具。只需将内容复制到一个名为 ssh-add-pass 的文件中并为其设置可执行权限 (chmod +x ssh-add-pass)。您也可以将其复制到 /usr/bin 或 /usr/local/bin 以便从 $PATH 搜索中访问。
#!/bin/bash
if [ $# -ne 2 ] ; then
echo "Usage: ssh-add-pass keyfile passfile"
exit 1
fi
eval $(ssh-agent)
pass=$(cat $2)
expect << EOF
spawn ssh-add $1
expect "Enter passphrase"
send "$pass\r"
expect eof
EOF
用法很简单:ssh-add-pass keyfile passfile
【讨论】:
eval $(ssh-agent)更改为ssh-agent bash或eval `ssh-agent -s`
eval ssh-agent -s 并且它运行了所有命令,但是在该脚本返回原始 bash 之后它丢失了那个密钥。它都依赖于产生 bash 并使用相同的 bash 来运行 ssh-add
类似于 kenorb 的答案,但不会将秘密保存在文件中:
$ SSH_ASKPASS=/path/to/ssh_give_pass.sh ssh-add $KEYFILE <<< "$KEYPASS"
ssh_give_pass.sh 在哪里:
#!/bin/bash
# Parameter $1 passed to the script is the prompt text
# READ Secret from STDIN and echo it
read SECRET
echo $SECRET
如果您在 $KEYPASSFILE 中有秘密,请先使用
将其读入变量KEYPASS=`cat $KEYPASSFILE`
还要确保 ssh_give_pass.sh 不能被未经授权的用户编辑 - 很容易记录通过脚本传递的所有秘密。
【讨论】:
DISPLAY=:0 SSH_ASKPASS=/path/to/ssh_give_pass.sh ssh-add $KEYFILE <<< "$KEYPASS"
${DISPLAY:=0}
以下是不支持-p的系统的一些解决方法:
$ PASS="my_passphrase"
$ install -vm700 <(echo "echo $PASS") "$PWD/ps.sh"
$ cat id_rsa | SSH_ASKPASS="$PWD/ps.sh" ssh-add - && rm -v "$PWD/ps.sh"
ps.sh 基本上是您打印密码的脚本。见:man ssh-add。
为了使其更安全(不要将其保存在同一个文件中),请使用mktemp 生成一个随机私有文件,使其可执行 (chmod) 并确保它在执行后将密码短语打印到标准输出.
【讨论】:
ssh-add 允许您像这样在每次调用时换出SSH_ASKPASS 二进制文件。
ps.sh 是一种安全风险,并且 rm 是一种非常弱的隐藏方式,您至少应该使用shred -u,但即使是 shred 在现代 fs 上也效率低下,例如ext4 以及更多关于 btrfs 的内容。因此,在共享内存/dev/shm 或/run/user/<uid> 中创建您的文件,并在使用后将其切碎。另一种选择是将ps.sh 放在加密文件系统上。
DISPLAY=:0 设置为 ssh-add 的手册页建议(Ubuntu 16.04)
在我的 Ubuntu 系统上,没有一个答案有效:
ssh-add 不支持 -p 选项。ssh-add 忽略了 SSH_ASKPASS,坚持在控制终端上提示输入密码。expect。对我来说有效的是:
password_source | SSH_ASKPASS=/bin/cat setsid -w ssh-add keyfile
password_source 并不是一个真正的程序:它只是代表将密码短语提供给ssh-add 的任何内容。就我而言,它是一个执行setsid 并将密码短语写入其标准输入的程序。如果您将密码保存在文件中,您有责任进行简单的修改:我不会让您伤害自己。
setsid 已安装,并分离控制终端,以便ssh-add 不会尝试使用它来提示输入密码。 -w 导致 setsid 等待 ssh-add 退出并使其返回代码可用。 /bin/cat 与 Ray Shannon 提供的脚本具有相同的效果,但使用标准工具而不是通过脚本复制其功能。
【讨论】:
有了这个最小的更改,@enrico.basis 的这个 bash 脚本对我有用
#!/bin/bash
if [ $# -ne 2 ] ; then
echo "Usage: ssh-add-pass passfile keyfile"
exit 1
fi
eval 'ssh-agent -s'
passwordToFileSSH=$1
pathFileSSH=$2
expect << EOF
spawn ssh-add $pathFileSSH
expect "Enter passphrase"
send "$passwordToFileSSH\r"
expect eof
EOF
【讨论】: