Home > Back-end >  Ansible and git with SSH key forwarding - works, but with two problems to solve
Ansible and git with SSH key forwarding - works, but with two problems to solve

Time:01-30

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 inventory
  • ForwardAgent 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)

- 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:

  1. Since there's no become the config file to use is under root, not under the user home (fritz in my case).
  2. 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
  • Related