Ansible结合Git使用SSH密钥转发遇两问题,求解决方案
现有配置说明
- 清单文件配置:
ansible_ssh_common_args: '-o ForwardAgent=yes -o PreferredAuthentications=publickey' - 本地客户端
.ssh/config配置:ForwardAgent yes - 客户端
ssh-agent已加载所有相关密钥 - 已配置sudoers保留SSH代理环境变量的任务:
- name: Fix sudoers for git clone tags: user when: is_linux lineinfile: path: /etc/sudoers state: present regexp: '.*SSH_AUTH_SOCK$' line: 'Defaults env_keep += "SSH_AUTH_SOCK"' validate: '/usr/sbin/visudo -cf %s'
当前Git拉取任务代码
- name: Clone project repositories tags: repos # become: true -- this breaks key forwarding # become_user: fritz git: repo: 'git@bitbucket.org:{{ item.user }}/{{ item.name }}' dest: '{{ workareas }}/{{ item.folder }}/{{ item.name }}' accept_hostkey: yes force: no with_items: '{{ repositories }}'
问题描述
问题1:become切换用户后SSH密钥转发失效
任务正常运行,但添加become: true和become_user: fritz后,密钥转发失效,会尝试使用堡垒机本地密钥导致失败。目前通过后续任务修正仓库权限,但需理解背后的运行机制。
问题2:多密钥触发认证失败错误
客户端存在大量密钥,直接在本地运行git时,通过.ssh/config配置主机与密钥关联可避免遍历密钥触发"too many authentication failures"错误:
Host bitbucket.org IdentityFile ~/.ssh/fritz@Mistral-bitbucket
但通过Ansible执行时该配置不生效,仍会遍历所有密钥,仅靠密钥顺序碰巧成功,无长期保障。
核心疑问
能否让堡垒机同时生效SSH密钥转发及本地的.ssh/config配置?
解决方案
问题1:become切换用户后密钥转发失效的处理
当使用become切换用户时,sudo默认重置多数环境变量,包括SSH_AUTH_SOCK,这是密钥转发失效的核心原因。即便配置了env_keep += "SSH_AUTH_SOCK",仍需注意两点:
- 确保该sudo规则对目标用户(fritz)全局生效;
- 目标用户需具备访问原
SSH_AUTH_SOCKsocket文件的权限(可通过setfacl添加权限)。
此外,可在任务中显式传递SSH_AUTH_SOCK环境变量,确保切换用户后代理环境保留:
- name: Clone project repositories tags: repos become: true become_user: fritz environment: SSH_AUTH_SOCK: "{{ lookup('env', 'SSH_AUTH_SOCK') }}" git: repo: 'git@bitbucket.org:{{ item.user }}/{{ item.name }}' dest: '{{ workareas }}/{{ item.folder }}/{{ item.name }}' accept_hostkey: yes force: no with_items: '{{ repositories }}'
问题2:避免多密钥遍历的处理
客户端的.ssh/config仅在本地生效,Ansible执行时调用的是堡垒机上的git命令,需在堡垒机端配置SSH规则,有两种方案:
方案1:在堡垒机部署SSH配置
通过Ansible将针对bitbucket的SSH配置同步到堡垒机目标用户的~/.ssh/config中,配置IdentitiesOnly yes强制仅使用代理中的密钥,避免遍历本地密钥:
- name: Deploy SSH config for bitbucket tags: repos become: true become_user: fritz copy: content: | Host bitbucket.org IdentitiesOnly yes dest: ~fritz/.ssh/config mode: 0600
方案2:在git模块中指定SSH参数
直接在git任务中通过ssh_opts参数强制仅使用代理认证:
- name: Clone project repositories tags: repos git: repo: 'git@bitbucket.org:{{ item.user }}/{{ item.name }}' dest: '{{ workareas }}/{{ item.folder }}/{{ item.name }}' accept_hostkey: yes force: no ssh_opts: "-o IdentitiesOnly=yes" with_items: '{{ repositories }}'
核心疑问总结
堡垒机无法直接复用客户端的.ssh/config,但通过上述方式在堡垒机端配置SSH规则,并确保become切换用户时保留SSH_AUTH_SOCK环境变量,即可同时解决密钥转发失效和多密钥认证失败的问题。
内容的提问来源于stack exchange,提问作者Fabrizio Giudici

