我需要将一些文件从服务器 A 部署到服务器 B。我通过 SSH 连接到服务器 A,然后从那里通过 ssh 连接到服务器 B,使用存储在服务器 A 上的私钥,其公钥位于服务器 B 的授权密钥文件。从 A 到 B 的连接发生在服务器 A 上的 Bash shell 脚本中。
这一切都很好,很好,很简单,直到有安全意识的管理员指出我存储在服务器 A 上的 SSH 私钥没有密码保护,因此任何可能侵入我在服务器 A 上的帐户的人也可以访问服务器B,以及 C、D、E、F 和 G。我猜他说得有道理。
他建议了一个复杂的场景,在这个场景下我会添加一个密码,然后修改我的 shell 脚本以在我要调用的开头添加一行
ssh-keygen -p -f {private key file}
用密码回答我的旧密码的提示和(两个)提示我的新密码的提示,只需返回即可摆脱密码,然后在最后,在我的 scp 命令调用之后
ssh-keygen -p -f {private key file}
再次,把密码放回去
我说“Yecch!”。
好吧,我可以通过首先阅读脚本中的密码短语 ONCE 来稍微改进一下
read -s PASS_PHRASE
然后根据需要使用 ssh-keygen 的 -N 和 -P 参数提供它。
它几乎可用,但我讨厌 shell 脚本中的交互式提示。我想把它归结为一个交互式提示,但让我感到难过的部分是我必须按两次回车键才能摆脱密码短语的部分
这可以从命令行工作:
ssh-keygen -p -f {private key file} -P {pass phrase} -N ''
但不是来自 shell 脚本。在那里,似乎我必须删除 -N 参数并接受输入两个返回的需要。
这是我能做的最好的。任何人都可以改善这一点吗?或者有没有更好的方法来处理这个?我不敢相信没有。
最好的方法是无需输入密码即可安全地处理此问题,但这可能要求太多。每次脚本调用我都会解决一次。
这是骨架形式的整个脚本的简化版本
#! /bin/sh
KEYFILE=$HOME/.ssh/id_dsa
PASSPHRASE=''
unset_passphrase() {
# params
# oldpassword keyfile
echo "unset_key_password()"
cmd="ssh-keygen -p -P $1 -N '' -f $2"
echo "$cmd"
$cmd
echo
}
reset_passphrase() {
# params
# oldpassword keyfile
echo "reset_key_password()"
cmd="ssh-keygen -p -N '$1' -f $2"
echo "$cmd"
$cmd
echo
}
echo "Enter passphrase:"
read -s PASSPHRASE
unset_passphrase $PASSPHRASE $KEYFILE
# do something with ssh
reset_passphrase $PASSPHRASE $KEYFILE