0
votes

I'm trying to use ansible (version 2.1.2.0) to create named ssh access across our network of servers. Running ansible from a jump box I'm creating a set of users and creating a private/public key pair with the users module

  - user:
      name: "{{ item }}"
      shell: /bin/bash
      group: usergroup
      generate_ssh_key: yes
      ssh_key_comment: "ansible-generated for {{ item }}"
    with_items: "{{ list_of_usernames }}"

From there I would like to copy across the public key to the authorized_users file on each remote server. I'm using the authorized_key_module to fetch and copy the user's generated public key as the authorized_key on the remote servers:

  - authorized_key:
      user: "{{ item }}"
      state: present
      key: "{{ lookup('file', '/home/{{ item }}/.ssh/id_rsa.pub') }}"
    with_items:
      - "{{ list_of_usernames }}"

What I'm finding is that the lookup will fail as it is unable to access the pub file within the user's .ssh folder. It will run happily however if I run ansible as the root user (which for me is not an option I'm willing to take).

fatal: [<ipAddress>]: FAILED! => {"failed": true, "msg": "{{ lookup('file', '/home/testuser/.ssh/id_rsa.pub') }}: the file_name '/home/testuser/.ssh/id_rsa.pub' does not exist, or is not readable"}

Is there a better way to do this other than running ansible as root?

Edit: Sorry I had forgotten to mention that I'm running with become: yes

Edit #2: Below is a condensed playbook of what I'm trying to run, of course in this instance it'll add the authorized_key to the localhost but shows the error I'm facing:

---
- hosts: all
  become: yes
  vars:
    active_users: ['user1','user2']
  tasks:

  - group:
      name: "users"

  - user:
      name: "{{ item }}"
      shell: /bin/bash
      group: users
      generate_ssh_key: yes
    with_items: "{{ active_users }}"

  - authorized_key:
      user: "{{ item }}"
      state: present
      key: "{{ lookup('file', '/home/{{ item }}/.ssh/id_rsa.pub') }}"
    become: yes
    become_user: "{{ item }}"
    with_items:
      - "{{ active_users }}"
2
But how would you create new users without root privileges?Konstantin Suvorov
Sorry, I had thought to write this when I was writing the question, I am indeed using become: yesAeladru
And why you can't just do become: yes for the next task?Konstantin Suvorov
Because that gives the same result, currently trying become_user as SztupY has suggestedAeladru

2 Answers

3
votes

OK, the problem is with lookup plugin.
It is executed on ansible control host with permissions of user that run ansible-playbook and become: yes don't elevate plugins' permissions.

To overcome this, capture result of user task and use its output in further tasks:

- user:
    name: "{{ item }}"
    shell: /bin/bash
    group: docker
    generate_ssh_key: yes
    ssh_key_comment: "ansible-generated for {{ item }}"
  with_items:
    - ansible5
    - ansible6
  register: new_users
  become: yes

- debug: msg="user {{ item.item }} pubkey {{ item.ssh_public_key }}"
  with_items: "{{ new_users.results }}"

Although you need to delegate some of this tasks, the idea will be the same.

3
votes

On most linux/unix machines only two accounts have access to /home/testuser/.ssh/id_rsa.pub: root and testuser, so if you would like to modify those files you need to be either root, or testuser.

You can use privilige escalation using become. You said you don't want to run ansible as root, which is perfectly fine. You haven't mentioned if the user you are running ansible with has sudo access or not. If it does, and using sudo is fine for you then you can simply do:

  - authorized_key:
      user: "{{ item }}"
      state: present
      key: "{{ lookup('file', '/home/{{ item }}/.ssh/id_rsa.pub') }}"
    with_items:
      - "{{ list_of_usernames }}"
    become: yes

This by default will run these command as root using sudo, while keeping the rest of the tasks run by the non-root user. This is also the preferred way of doing runs with ansible.

If you don't want this, and you want to keep your user as root-free as possible, then you need to run the command as testuser (and any other user you want to modify). This would mean you still need to patch up the sudoers file to allow your ansible user to transform into any of these users (which can also open up a few security issues - albeit not as much as being able to run anything as root), after which you can do:

  - authorized_key:
      user: "{{ item }}"
      state: present
      key: "{{ lookup('file', '/home/{{ item }}/.ssh/id_rsa.pub') }}"
    with_items:
      - "{{ list_of_usernames }}"
    become: yes
    become_user: "{{ item }}"

There are some caveats using this approach, so you might want to read the full Privilege Escalation page on ansible's documentation, especially the section on Unpriviliged Users before you try this.