如何将我的 SSH 公钥传播到服务器列表,而无需一遍又一遍地输入密码?

如何将我的 SSH 公钥传播到服务器列表,而无需一遍又一遍地输入密码?

我最近获得了对服务器列表的用户名/密码访问权限,并希望将我的 SSH 公钥传播到这些服务器,以便我可以更轻松地登录。

这样就清楚了:

  • 远程服务器上没有任何预先存在的公钥,我可以利用它来自动执行此操作
  • 这是我第一次登录这些服务器,我希望不必不断地输入我的凭据来访问它们
  • ssh-copy-id我也不想在 for 循环中一遍又一遍地输入密码。

答案1

您无需多次输入密码,而是可以使用pssh-A开关来提示输入一次,然后将密码提供给列表中的所有服务器。

笔记:但是,使用此方法不允许您使用ssh-copy-id,因此您需要推出自己的方法,将 SSH 公钥文件附加到远程帐户的~/.ssh/authorized_keys文件中。

例子

这是完成这项工作的示例:

$ cat ~/.ssh/my_id_rsa.pub                    \
    | pssh -h ips.txt -l remoteuser -A -I -i  \
    '                                         \
      umask 077;                              \
      mkdir -p ~/.ssh;                        \
      afile=~/.ssh/authorized_keys;           \
      cat - >> $afile;                        \
      sort -u $afile -o $afile                \
    '
Warning: do not enter your password if anyone else has superuser
privileges or access to your account.
Password:
[1] 23:03:58 [SUCCESS] 10.252.1.1
[2] 23:03:58 [SUCCESS] 10.252.1.2
[3] 23:03:58 [SUCCESS] 10.252.1.3
[4] 23:03:58 [SUCCESS] 10.252.1.10
[5] 23:03:58 [SUCCESS] 10.252.1.5
[6] 23:03:58 [SUCCESS] 10.252.1.6
[7] 23:03:58 [SUCCESS] 10.252.1.9
[8] 23:03:59 [SUCCESS] 10.252.1.8
[9] 23:03:59 [SUCCESS] 10.252.1.7

上面的脚本一般结构如下:

$ cat <pubkey> | pssh -h <ip file> -l <remote user> -A -I -i '...cmds to add pubkey...'

高层次pssh细节

  • cat <pubkey>将公钥文件输出到pssh
  • pssh使用-I交换机通过 STDIN 摄取数据
  • -l <remote user>是远程服务器的帐户(我们假设您在 IP 文件中的服务器上具有相同的用户名)
  • -A告诉pssh您询问您的密码,然后将其重新用于它连接到的所有服务器
  • -i告诉pssh将任何输出发送到 STDOUT 而不是将其存储在文件中(其默认行为)
  • '...cmds to add pubkey...'- 这是正在发生的事情中最棘手的部分,所以我会单独分解它(见下文)

在远程服务器上运行的命令

pssh这些是将在每台服务器上运行的命令:

'                                         \
  umask 077;                              \
  mkdir -p ~/.ssh;                        \
  afile=~/.ssh/authorized_keys;           \
  cat - >> $afile;                        \
  sort -u $afile -o $afile                \
'
为了:
  • 将远程用户的 umask 设置为 077,这样我们要创建的任何目录或文件都会相应地设置其权限,如下所示:

    $ ls -ld ~/.ssh ~/.ssh/authorized_keys
    drwx------ 2 remoteuser remoteuser 4096 May 21 22:58 /home/remoteuser/.ssh
    -rw------- 1 remoteuser remoteuser  771 May 21 23:03 /home/remoteuser/.ssh/authorized_keys
    
  • 创建目录~/.ssh并忽略警告我们(如果它已经存在)

  • 设置变量 ,$afile其路径为authorized_keys 文件
  • cat - >> $afile- 从 STDIN 获取输入并附加到authorized_keys 文件
  • sort -u $afile -o $afile- 对authorized_keys文件进行唯一排序并保存

笔记:最后一点是处理对同一服务器多次运行上述命令的情况。这将消除您的公钥被多次附加的情况。

注意单个刻度!

还要特别注意所有这些命令都嵌套在单引号内。这很重要,因为我们不想$afile在远程服务器上执行之前对其进行评估。

'               \
   ..cmds...    \
'

我扩展了上面的内容,以便在这里更容易阅读,但我通常将其全部运行在一行上,如下所示:

$ cat ~/.ssh/my_id_rsa.pub | pssh -h ips.txt -l remoteuser -A -I -i 'umask 077; mkdir -p ~/.ssh; afile=~/.ssh/authorized_keys; cat - >> $afile; sort -u $afile -o $afile'

奖励材料

通过使用,pssh您可以不必构建文件并使用提供动态内容,或者您​​可以使用另一个开关-h <(...some command...)创建 IP 列表。pssh-H "ip1 ip2 ip3"

例如:

$ cat .... | pssh -h <(grep -A1 dp15 ~/.ssh/config | grep -vE -- '#|--') ...

~/.ssh/config上面的内容可用于从我的文件中提取 IP 列表。您当然也可以用来printf生成动态内容:

$ cat .... | pssh -h <(printf "%s\n" srv0{0..9}) ....

例如:

$ printf "%s\n" srv0{0..9}
srv00
srv01
srv02
srv03
srv04
srv05
srv06
srv07
srv08
srv09

您还可以使用seq它来生成格式化的数字序列!

参考文献和类似工具pssh

如果您不想像pssh我上面那样使用,还有其他一些选项可用。

答案2

替代使用xargs,sshpassssh-copy-id:

假设您居住在凭据.txt格式 user:password@server

$ cat credentials.txt
root:[email protected]
foo:[email protected]
bar:[email protected]

你可以这样做:

tr ':@' '\n' < credentials.txt \
| xargs -L3 sh -c 'sshpass -p $1 ssh-copy-id $0@$2'

注意:记得删除凭据.txt使用后!

答案3

使用安西布尔相当简单。替换<USER>成真实的登录名即可

$ cd /path/to/public/key

$ cat<<END > hosts
  host1.example.com
  10.10.10.10
  END

$ ansible -i hosts all --ask-pass -u <USER> -m authorized_key \
      -a "user=<USER> key='$(cat id_rsa.pub)'"        

答案4

有几件事可能符合要求:

正如其他答案中提到的,sshpass这可能是最简单的解决方案。

相关内容