【问题标题】:SSH Agent Forwarding with Ansible使用 Ansible 进行 SSH 代理转发
【发布时间】:2014-07-30 05:18:42
【问题描述】:

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

【问题讨论】:

    标签: git ssh ansible ssh-agent


    【解决方案1】:

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

    sudo: yes
    

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

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

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

    【讨论】:

    • 可能需要明确设置sudo: no
    • 如果你使用 SSH_AUTH_SOCK 至少要注意安全风险serverfault.com/a/371788/67801
    • @SystematicFrank:链接中的安全风险是 chmod 777,而不是 SSH_AUTH_SOCK
    • 这对我有用。我使用以下命令将其自动化: - name: enable SSH creds passthrough lineinfile: dest=/etc/sudoers regexp='^#?Defaults\Wenv_keep[^$]' line='Defaults env_keep += " SSH_AUTH_SOCK"'
    【解决方案2】:

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

    首先,您需要确保在从运行 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(和become_user: root)通常会禁用代理转发这一事实,因为SSH_AUTH_SOCK 环境变量已重置。 (我对Ansible seems to assume 以 root 身份使用 SSH 感到震惊,因为这使得任何有用的审计都变得不可能。)有几种方法可以解决这个问题。从 Ansible 2.2 开始,最简单的方法是在使用 sudo 时通过指定 -E 标志来保留(整个)环境:

    become_flags: "-E"
    

    但是,通过保留 PATH 之类的变量,这可能会产生不必要的副作用。最干净的方法是仅保留 SSH_AUTH_SOCK,方法是将其包含在您的 /etc/sudoers 文件中的 env_keep 中:

    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 设置之后添加这个(或者在文件末尾,如果没有找到),而不更改任何现有的 @ 987654338@ 设置或假设 SSH_AUTH_SOCK 已经存在。

    【讨论】:

    • @AlouaniYounes 当我升级到 Ansible 2.4 后它继续为我工作。
    • @trevor-robison 哦,你让我很开心。将 ssh_connection 设置添加到我的 ansible.cfg 效果非常好,非常感谢! :)
    • Sudo 还允许通过标志只保留某些环境变量。因此,become_flags ansible 设置中的-E 可以替换为更具体的--preserve-env=SSH_AUTH_SOCK。这有助于减少保持整个环境的副作用。
    【解决方案3】:

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

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

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

    [ssh_connection]
    ssh_args=-o ForwardAgent=yes
    

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

    【讨论】:

    • 我必须将ssh_args 添加到我的ansible.cfg 才能使SSH 代理转发完全正常工作。感谢您是唯一提出建议的人!我在 OSX 10.10 上,运行 Ansible 1.9.1
    • 如果您指定ssh_args,这将阻止 ansible 提供自己的,包括设置持久连接的参数。这可能会导致大幅减速。将添加的相关参数是-o ControlMaster=auto -o ControlPersist=60s -o ControlPath=/tmp/ansible-ssh-%h-%p-%r
    • 有时sudo_flags 也有问题,默认设置为sudo_flags = -H -S -n,它可能会因“sudo: a password is required”而失败。这种情况下需要设置sudo_flags = -H -S去掉-n选项。
    • 我理解使用ssh_extra_args=-o ForwardAgent=yes可以防止减速(由qqx提到)。
    【解决方案4】:

    为了扩展@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 fwding,另一个用于实际获取与此 env var 集的连接?
    • 听起来不错。我总是最终多次运行并注释掉剧本,ssh 进入盒子并手动检查。从来都不是一帆风顺的。
    • 为了避免多次运行,我最终将此步骤放在了我在全新服务器安装中运行的脚本中。毕竟在我可以用 ansible 设置我的服务器之前需要设置一些东西......
    猜你喜欢
    • 2012-08-20
    • 1970-01-01
    • 1970-01-01
    • 2015-07-09
    • 1970-01-01
    • 2012-08-10
    • 1970-01-01
    • 2018-09-14
    • 2014-02-26
    相关资源
    最近更新 更多