SSH代理转发与Ansible

我使用Ansible 1.5.3和Git与ssh代理转发( https://help.github.com/articles/using-ssh-agent-forwarding )。 我可以login到我使用Ansiblepipe理的服务器,并testing我的连接到git的configuration是否正确:

ubuntu@test:~$ ssh -T git@github.com Hi gituser! You've successfully authenticated, but GitHub does not provide shell access. 

我也可以使用这个帐号克隆和更新我的回购协议中的一个,这样我的gitconfiguration看起来不错,当我通过ssh直接login到服务器时,使用ssh转发。

问题:当我使用Ansible命令模块尝试上面所示的相同testing时。 它以“权限被拒绝”失败。 Ansible输出的一部分(详细logging)如下所示:

 failed: [xxx.xxxxx.com] => {"changed": true, "cmd": ["ssh", "-T", "git@github.com"], "delta": "0:00:00.585481", "end": "2014-06-09 14:11:37.410907", "rc": 255, "start": "2014-06-09 14:11:36.825426"} stderr: Permission denied (publickey). 

这里是运行这个命令的简单的手册:

 - hosts: webservers sudo: yes remote_user: ubuntu tasks: - name: Test that git ssh connection is working. command: ssh -T git@github.com 

问题:为什么当我通过ssh手动login并运行该命令时,一切工作正常,但是当通过Ansible以相同的用户运行相同的命令时失败?

如果没有人打我的话,我会很快发布答案。 虽然我使用git来演示这个问题,但是依赖于ssh代理转发的任何模块都可能发生这种情况。 Ansible并不特定,但我怀疑在这种情况下很多人会首先遇到这个问题。

通过从操作手册中删除此行来解决问题:

 sudo: yes 

在远程主机上运行sudo时,login时由ssh设置的环境variables将不再可用。 特别是,“标识用于与代理通信的UNIX域套接字的path”的SSH_AUTH_SOCK不再可见,所以ssh代理转发不起作用。

在不需要的时候避免sudo是解决问题的一种方法。 另一种方法是通过创buildsudoers文件来确保SSH_AUTH_SOCK在sudo会话期间持续存在:

 /etc/sudoers: Defaults env_keep += "SSH_AUTH_SOCK" 

你的问题的另一个答案(除了我使用Ansible 1.9的例外)可能如下:

您可能需要检查您的/etc/ansible/ansible.cfg(或其他三个可能覆盖configuration设置的潜在位置),以便transport=smart正如文档中所build议的那样 。 在前一次安装尝试期间,我已经默认transport=paramiko ,阻止我的控制机器使用OpenSSH,从而代理转发。 这可能是一个巨大的边缘情况,但谁知道? 这可能是你!

虽然我没有发现configuration的必要,但我应该注意到其他人提到你应该在你的ssh_args设置中添加-o ForwardAgent=yes ,如下所示:

 [ssh_connection] ssh_args=-o ForwardAgent=yes 

我只是为了完整而在此提及。

要扩展@ j.freckle的答案,更改sudoers文件的方法是:

 - name: Add ssh agent line to sudoers lineinfile: dest: /etc/sudoers state: present regexp: SSH_AUTH_SOCK line: Defaults env_keep += "SSH_AUTH_SOCK" 

这里有一些非常有帮助的部分答案,但经过多次讨论这个问题后,我认为概述会有所帮助。

首先,您需要确保从运行Ansible的客户端连接到目标机器时启用SSH代理转发。 即使使用transport=smart ,SSH代理转发也可能不会自动启用,具体取决于客户端的SSHconfiguration。 为了确保它,你可以更新你的~/.ansible.cfg来包含这个部分:

 [ssh_connection] ssh_args=-o ControlMaster=auto -o ControlPersist=60s -o ControlPath=/tmp/ansible-ssh-%h-%p-%r -o ForwardAgent=yes 

接下来,您可能必须处理以下事实become: yes (和become_user: root )通常会禁用代理转发,因为SSH_AUTH_SOCK环境variables已重置。 (我觉得Ansible似乎认为人们会以根为根本,因为这使得任何有用的审计都是不可能的。)有几种方法可以解决这个问题。 从Ansible 2.2开始,最简单的方法是使用sudo通过指定-E标志来保留整个环境:

 become_flags: "-E" 

但是,通过保留像PATH这样的variables,可能会产生不必要的副作用。 最env_keep方法是通过将它env_keep/etc/sudoers文件中的env_keep中来保留SSH_AUTH_SOCK

 Defaults env_keep += "SSH_AUTH_SOCK" 

用Ansible来做到这一点:

 - name: enable SSH forwarding for sudo lineinfile: dest: /etc/sudoers insertafter: '^#?\s*Defaults\s+env_keep\b' line: 'Defaults env_keep += "SSH_AUTH_SOCK"' 

这个playbook任务比其他人build议的要稍微保守一些,因为它会在任何其他默认的env_keep设置(或者在文件末尾,如果没有find的话)之后添加这个,而不改变任何现有的env_keep设置或者假设SSH_AUTH_SOCK是已经存在。