如何让 ssh-add 从文件中读取密码?

问题描述 投票:0回答:8

我正在尝试向

ssh-agent
添加密钥,并希望
ssh-add
从我正在使用的密钥文件中读取密码。这怎么可能?

如何通过 shell 脚本自动执行此过程?

ssh ssh-agent
8个回答
54
投票

根据您的发行版和 ssh-add 的版本,您可能能够或不使用 ssh-add 的

-p
选项,以这种方式从 stdin 读取密码:

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


19
投票

与 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 不可被未经授权的用户编辑 - 可以轻松记录通过脚本传递的所有秘密。


14
投票

这里有一些针对不支持的系统的解决方法

-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
) 并确保执行后将密码打印到标准输出。


13
投票

在我的 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 提供的脚本具有相同的效果,但使用标准工具而不是使用脚本复制其功能。


0
投票

通过这个最小的更改,@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


0
投票

来到这里寻找特定的解决方案,从

pass
UNIX 密码管理器加载 ssh-add。感谢这里的精彩答案,我整理了一个为我完成此操作的脚本:

#!/usr/bin/env bash
# Get password from pass

set -euo pipefail

keyfile=$(echo "$1" | /usr/bin/env sed -n 's/Enter passphrase for \(.*\):\s*$/\1/p');
echo "Extracted key filename $keyfile" >&2
[[ -z "${keyfile}" ]] && exit 1

comment=$(/usr/bin/env ssh-keygen -l -f "$keyfile" | /usr/bin/env awk '{print $3}')
echo "Comment from keyfile $keyfile is $comment" >&2
[[ -z "${comment}" ]] && exit 1

passphrase=$(/usr/bin/env pass show "ssh/$comment")
[[ -z "${passphrase}" ]] && exit 1
echo "got passphrase for comment $comment: XXX" >&2

echo "$passphrase"

用这个调用:

env SSH_ASKPASS=/usr/local/bin/pass-ssh-askpass.sh SSH_ASKPASS_REQUIRE=force ssh-add

如果没有这里的答案,这是不可能的,所以感谢您,将其作为社区维基以实现更大的利益。

一旦我的

ssh-add
支持
-p
选项,我将研究不同的解决方案,但在那之前这将是必须要做的。

无耻插件:https://github.com/YarekTyshchenko/pass-ssh-askpass


0
投票

使用 PID 来实现环境脚本,并且不消除关键实现

ssh-add-pass.sh

#!/bin/bash

if [ $# -ne 2 ] ; then
  echo "Usage: ssh-add-pass keyfile passfile"
  exit 1
fi

if [ -z "$SSH_AGENT_PID" ]; then
    eval $(ssh-agent -s)
fi

pass=$(cat $2)

expect << EOF
  spawn ssh-add $1
  expect "Enter passphrase"
  send "$pass\r"
  expect eof
EOF

使用 ssh-add -L 进行验证


-9
投票

最好的方法是生成没有密码的密钥

© www.soinside.com 2019 - 2024. All rights reserved.