在Vagrant+Chef设置中使用带有密码的SSH密钥

13
我正在使用Vagrant运行虚拟机,并用Chef进行配置。其中一个步骤涉及克隆git仓库,但是我的ssh-key(位于我的主机上)有一个passphrase。
当我运行 vagrant up 时,克隆git仓库的过程失败,并出现以下错误:
Permission denied (publickey). fatal: The remote end hung up unexpectedly
(在主机上已添加了关键字,带有密码)
我尝试通过SSH代理转发来解决这个问题,具体如下:
config.ssh.forward_agent = true 添加到 VagrantFile 文件中
Defaults env_keep = "SSH_AUTH_SOCK" 添加到 vm 的 /etc/sudoers
现在,在 git 克隆阶段,vagrant up 仍然失败,但如果之后运行vagrant provision,它就能够成功。我猜测这是因为VM启动时设置了ssh配置,而不会重新加载。
我尝试在调整这两个设置后重新加载ssh,但没有帮助。
有什么想法如何解决这个问题吗?
谢谢。
3个回答

10

正如您所指出的那样,在初始运行期间更新sudoers已经为时过晚,因为此时chef已在sudo下运行。

相反,我编写了一个hacky食谱,它找到适当的ssh套接字并更新SSH_AUTH_SOCK环境以适应。它还禁用了严格的主机密钥检查,因此初始的出站连接会自动批准。

将其保存为一个食谱,并在第一次ssh连接之前执行(在Ubuntu上进行了测试,但应该适用于其他发行版):

Directory "/root/.ssh" do
  action :create
  mode 0700
end

File "/root/.ssh/config" do
  action :create
  content "Host *\nStrictHostKeyChecking no"
  mode 0600
end

ruby_block "Give root access to the forwarded ssh agent" do
  block do
    # find a parent process' ssh agent socket
    agents = {}
    ppid = Process.ppid
    Dir.glob('/tmp/ssh*/agent*').each do |fn|
      agents[fn.match(/agent\.(\d+)$/)[1]] = fn
    end
    while ppid != '1'
      if (agent = agents[ppid])
        ENV['SSH_AUTH_SOCK'] = agent
        break
      end
      File.open("/proc/#{ppid}/status", "r") do |file|
        ppid = file.read().match(/PPid:\s+(\d+)/)[1]
      end
    end
    # Uncomment to require that an ssh-agent be available
    # fail "Could not find running ssh agent - Is config.ssh.forward_agent enabled in Vagrantfile?" unless ENV['SSH_AUTH_SOCK']
  end
  action :create
end

你也可以创建一个已包含sudoers更新的盒子,并以此为基础创建未来的VM。


2
对于那些想在bash中执行相同操作的人,请参考:https://gist.github.com/bendavis78/5464209。请参阅此处以了解如何将其添加到您的Vagrantfile中:http://docs-v1.vagrantup.com/v1/docs/provisioners/shell.html。 - Ben Davis

3

这可能不是你想要的答案,但一个简单的解决方法是生成一个没有密码的专用部署 SSH 密钥。我更喜欢为每个应用程序使用单独和专用的部署密钥,而不是一个密钥用于多个应用程序。


1

您可以使用Vagrant运行多个配置程序(即使是相同类型的),每个配置程序都在自己的SSH连接上执行。我通常通过使用Shell配置程序来解决此问题,该程序将Added Defaults env_keep = "SSH_AUTH_SOCK"添加到vm上的/etc/sudoers中。

这是我用来执行此操作的Bash脚本:

#!/usr/bin/env bash

# Ensure that SSH_AUTH_SOCK is kept
if [ -n "$SSH_AUTH_SOCK" ]; then
  echo "SSH_AUTH_SOCK is present"
else
  echo "SSH_AUTH_SOCK is not present, adding as env_keep to /etc/sudoers"
  echo "Defaults env_keep+=\"SSH_AUTH_SOCK\"" >> "/etc/sudoers"
fi

我还没有使用过Chef provisioner进行测试,只是使用了额外的Shell provisioners...但据我所知,对于您的用例,这应该可以达到相同的效果。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接