0
votes

I am a dev and want to use ansible to create dev-setups in VMs for various projects (one VM per project). VM manager commands are used to create a VM from a template, the template contains a stock OS install (typically Linux) with one addition: a public ssh-key specifically for use with ansible has been placed in the VM root user's .ssh/authorized_keys file. Global vars are then used to set ssh config:

ansible_user: root 
ansible_private_key_file: keys/id_rsa_ansible

Then my ansible.cfg contains some entries for ssh-agent setup:

[ssh_connection]
ssh_args = -o ForwardAgent=yes -o ControlMaster=auto -o ControlPersist=60s

With this setup I can launch ansible scripts to perform a number of root tasks such as installing packages & creating user accounts for a set of devs.

On the VM host I am logged in using my dev-users account, say mike. The ssh-agent setup also ensures that all ssh-keys loaded for user mike are also available in the VM through the ssh connection.

I now want to perform further, dev-specific tasks as user mike on the VM (whose account now exists). The main task is to check out the project code which requires mikes ssh-key.

Using become uses sudo, which does not forward ssh-keys, so this is not an option. I do not want to push private keys around as they would need to be on the host .. and no longer be private.

The following now determines the devs username on the host & uses it in an ssh command to achieve the checkout. This nicely restricts access to those projects the dev users key works for without further config.

- name: get the devs username running the deploy
  become: false
  local_action: command whoami
  register: username_on_the_host

- name: Test checkout
  command: ssh -o StrictHostKeyChecking=no -o ForwardAgent=yes {{ username_on_the_host.stdout }}@localhost "mkdir hg && cd hg && hg clone ssh://hg//hg/my_project"

It works, but it's not a particularly clean solution.

So, finally to come to the question: Is there a cleaner way to switch ssh-session? One way might be to run a totally separate playbook with an ssh-session for the dev user - but this does not seem to be in the spirit of ansible. I want to run an entire block, task, or role as a different ssh user.

This could be achieved if the become module were to support become_method ssh which would retain the ssh-keys in the agent.

1
I think you should be able to set ansible_user in the playbook. So you'd have one file with two playbooks in them each playbook defining a different ansible_user.Tomáš Pospíšek

1 Answers

0
votes

Tomáš is absolutely right. It seems that setting ansible_user somehow switches the ssh user for the connection. Possibly it's done via an ssh mike@localhost without needing to re-establish the playbook connection, but that is speculation.

However it must be done in certain ways:

  • in a playbook we can repeat the hosts section as suggested:
- hosts: test-hosts
  roles:
     - common

- hosts: test-hosts
  vars:
    ansible_user: mike
  roles:
     - user_test
  • within a roles task, we can use set_fact (example shows getting the deploy user first):
- name: get user running the deploy
  local_action: command whoami
  register: deploy_user

- name: switch to deploy user
  set_fact:
    ansible_user: "{{ deploy_user.stdout }}"
  • However doing this in a playbook does not work - unfortunately it seems to set the var globally overriding the default setting before the first role is executes, ie here the common role is also run as user mike
- hosts: test-hosts
  roles:
     - common
     - { role: user_test, vars: { ansible_user: mike }}

In conclusion, the first 2 options seem to work!

It would be nice if the ansible documentation would be clearer about exactly what changing ansible_user does under the hood, hopefully this will be useful to those searching ...