与安赛尔的代理转发

我使用的是带有 ssh 代理转发(https://help.github.com/articles/using-ssh-agent-forwarding)的 Ansible1.5.3和 Git。我可以登录到我正在管理的服务器,并测试我到 git 的连接是否配置正确:

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

我还可以使用这个帐户克隆和更新我的一个回购协议,这样我的 git 配置看起来不错,当我直接通过 ssh 登录到我的服务器时使用 ssh 转发。

问题: 当我使用 Ansible 命令模块尝试上面显示的相同测试时。它以“拒绝许可”失败。Anble 输出的一部分(使用详细日志记录)如下所示:

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 手动登录并运行命令时,一切都正常工作,但是当同一个命令通过 Ansible 和同一个用户一起运行时,一切都失败了?

如果没有其他人抢在我前面,我将很快公布答案。尽管我使用 git 来演示这个问题,但它可能发生在任何依赖于 ssh 代理转发的模块中。这并不是 Ansible 特有的问题,但我怀疑,在这种情况下,许多人首先会遇到这个问题。

48258 次浏览

通过从剧本中删除这一行,问题得到了解决:

sudo: yes

当在远程主机上运行 sudo 时,在登录期间由 ssh 设置的环境变量不再可用。特别是 SSH _ AUTH _ SOCK,它“标识用于与代理通信的 UNIX 域套接字的路径”不再可见,因此 SSH 代理转发不起作用。

在不需要 sudo 时避免它是解决问题的一种方法。另一种方法是通过创建 sudoers 文件来确保 SSH _ AUTH _ SOCK 在 sudo 会话期间始终存在:

/etc/sudoers:


Defaults    env_keep += "SSH_AUTH_SOCK"

对于你的问题的另一个答案(除了我正在使用 Anable 1.9)可以是:

您可能需要检查/etc/anable/ansible.cfg (或其他三个可能覆盖配置设置的位置)是否有 transport=smart 按照建议的 在可能的文件中。在上一次安装尝试中,我的系统在某个时候默认为 transport=paramiko,这阻止了我的控制机器使用 OpenSSH,从而阻止了代理转发。这可能是个大案子,但谁知道呢?可能是你!

虽然我认为对于我的配置没有必要,但是我应该注意到其他人提到应该在同一个文件中将 -o ForwardAgent=yes添加到 ssh _ args 设置中,如下所示:

[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"

这里有一些非常有用的部分答案,但是在多次遇到这个问题之后,我认为一个概述将是有帮助的。

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

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

接下来,你可能需要处理这样一个事实: 由于 SSH_AUTH_SOCK环境变量被重置,become: yes(和 become_user: root)通常会禁用代理转发。(我发现令人震惊的是,安塞尔似乎认为中的人将 SSH 作为 root 用户,因为这使得任何有用的审计都变得不可能。)有几种方法可以解决这个问题。在 Ansible2.2中,最简单的方法是在使用 sudo时通过指定 -E标志来保留(整个)环境:

become_flags: "-E"

然而,通过保留像 PATH这样的变量,这可能会产生不必要的副作用。最简洁的方法是只保留 SSH_AUTH_SOCK,将它包含在 env_keep中的 /etc/sudoers文件中:

Defaults    env_keep += "SSH_AUTH_SOCK"

对安塞尔这样做:

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

这个剧本任务比其他建议的任务要保守一些,因为它在任何其他默认的 env_keep设置之后添加这个任务(或者在文件的末尾,如果没有找到的话) ,没有改变任何现有的 env_keep设置或者假设 SSH_AUTH_SOCK已经存在。