70

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

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

我还可以使用此帐户克隆和更新我的一个存储库,因此当我通过 ssh 直接登录到我的服务器时,我的 git 配置看起来不错并使用 ssh 转发。

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

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 特有的,但我怀疑很多人会在这种情况下首先遇到这个问题。

4

4 回答 4

51

通过从剧本中删除这一行来解决问题:

sudo: yes

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

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

/etc/sudoers:

     Defaults    env_keep += "SSH_AUTH_SOCK"
于 2014-06-10T06:15:41.257 回答
44

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

首先,您需要确保从运行 Ansible 的客户端连接到目标计算机时启用了 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

接下来,您可能必须处理become: yes(and become_user: root) 通常会禁用代理转发这一事实,因为SSH_AUTH_SOCK环境变量已重置。(我发现Ansible 似乎假设人们将以 root 身份进行 SSH 感到震惊,因为这使得任何有用的审计都变得不可能。)有几种方法可以解决这个问题。从 Ansible 2.2 开始,最简单的方法是在使用时sudo通过指定-E标志来保留(整个)环境:

become_flags: "-E"

但是,通过保留变量(如PATH. 最干净的方法是仅SSH_AUTH_SOCK通过将其包含在env_keep文件中来保留/etc/sudoers

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

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

于 2017-02-02T16:16:17.977 回答
29

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

您可能需要按照 ansible docs 中的transport=smart 建议检查您的 /etc/ansible/ansible.cfg (或其他三个可以覆盖配置设置的潜在位置)。在之前的安装尝试中,我的默认设置为,阻止我的控制机器使用 OpenSSH,从而阻止代理转发。这可能是一个巨大的边缘案例,但谁知道呢?可能是你!transport=paramiko

虽然我发现我的配置没有必要,但我应该注意到其他人已经提到您应该-o ForwardAgent=yes在同一个文件中添加到您的 ssh_args 设置,如下所示:

[ssh_connection]
ssh_args=-o ForwardAgent=yes

为了完整起见,我在这里仅提及它。

于 2015-03-02T23:36:04.970 回答
16

要扩展@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"
于 2015-06-11T18:49:16.910 回答