I have an Ansible task that checks out a git repo with SSH key forwarding, and it works. But with two problems that I'd like to fix.
First a quick recap of my configuration:
ansible_ssh_common_args: '-o ForwardAgent=yes -o PreferredAuthentications=publickey'
in my inventoryForwardAgent yes
in.ssh/config
on the client- the
ssh-agent
on the client properly loaded with all the relevant keys
(edited to add this point that I at first forgotten to mention)
- the configuration suggested here: SSH Agent Forwarding with Ansible
- 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'
(end edit)
The task is straightforward:
- name: Clone project repositories
tags: repos
# become: true -- this breaks key forwarding
# become_user: fritz
git:
repo: '[email protected]:{{ item.user }}/{{ item.name }}'
dest: '{{ workareas }}/{{ item.folder }}/{{ item.name }}'
accept_hostkey: yes
force: no
with_items: '{{ repositories }}'
First problem: it does work, but when I add become/become_user
key forwarding is no more enabled: the keys installed on the bastion host are tried (and of course this fails).
It is not a big issue for me: without become
Ansible creates the repo with the wrong ownership, but I fix it in a later task. It's more a thing of understanding how Ansible works.
The second problem is more important. For a number of reasons I have a high number of keys on my client: without a specific configuration the ssh
client submits them in an unpredictable order and usually I get the server aborting with 'too many authentication failures
'. Putting into .ssh/config
the specific associations of keys to hosts fixes the problem:
Host bitbucket.org
IdentityFile ~/.ssh/fritz@Mistral-bitbucket
But this only works when running git
directly from the client; with Ansible it doesn't work, it still tries all the keys. At the moment I'm lucky and the proper key is submitted early, but there's no warranty it will be always like this.
Basically the question is: is it possible to have key forwarding and the .ssh/config
file enforced also on the bastion host?
Thanks.
CodePudding user response:
... It's more a thing of understanding how Ansible works.
Connect to your remote host manually with ssh
, then run sudo -u root ssh-add -l
and you'll see that your agent is inaccessible. This is expected behavior -- environment variables like SSH_AUTH_SOCK
don't transition across privilege escalation boundaries by default (which is exactly the situation when you use become: true
).
Running sudo
manually, we can work around this by explicitly preserving the SSH_AUTH_SOCK
environment variable. Unlike the previous command, this should work:
sudo -u root --preserve-env=SSH_AUTH_SOCK ssh-add -l
We can have Ansible run sudo
with the same options by setting the become_flags
configuration variable in our ansible.cfg
:
[privilege_escalation]
become_flags = --preserve-env=SSH_AUTH_SOCK
With that configuration in place, we can now successfully run something like:
ansible remotehost --become -a 'ssh-add -l'
Basically the question is: is it possible to have key forwarding and the
.ssh/config
file enforced also on the bastion host?
If you copy your public key to the remote server, you should be able to configure ssh on the remote system using IdentitiesOnly=yes
and IdentityFile
so that it will only use those specific keys in the agent.
For example, in ~/.ssh/config
on the remote host, you would write:
Host github.com
IdentitiesOnly yes
IdentityFile ~/my-key.pub
CodePudding user response:
@larsks suggestion for the keys worked. But I had to fix two errors that I was doing:
- Since there's no
become
the config file to use is underroot
, not under the user home (fritz
in my case). - At this point the tilde expands in the wrong way (again under
root
), so the explicit path to the home root must be used.
Summing up this task prepares things in the proper way.
Thanks to @larsks.
- name: Create SSH config file for root
tags: repos
copy:
dest: '/root/.ssh/config'
content: |
Host bitbucket.org
IdentityFile /home/fritz/.ssh/fritz@{{ ansible_hostname|capitalize }}-bitbucket