85

I have taken over a Ubuntu 14.04 server. It has a user called "deployer" (used with capistrano), and as such, it needs sudo privileges. With this setup, I can log into the server and do stuff like:

workstation> ssh deployer@myserver
myserver>  sudo apt-get install git
myserver> exit
workstation>

I am trying to figure out how to use Ansible (version 2.0.2.0 and python 2.7.3) to create a user called "deployer" and be able to log into the server with that id and then so sudo-ish things like "apt-get install". My playbook looks like this:

---
- hosts: example
  become: yes
  tasks:
  - name: Update apt cache
    apt:
      update_cache: yes
      cache_valid_time: 3600

  - group: name=sudo state=present

  - name: Add deployer user and add it to sudo
    user: name=deployer
          state=present
          createhome=yes
    become: yes
    become_method: "sudo"

  - name: Set up authorized keys for the deployer user
    authorized_key: user=deployer key="{{item}}"
    with_file:
      - /home/jaygodse/.ssh/id_rsa.pub

After running this playbook, I am able to ssh into the machine as "deployer", (e.g. ssh deployer@myserver) but if I run a sudo command, it always asks me for my sudo password.

I understand that the "deployer" user ultimately has to find its way into the visudo users file, but I cannot figure out which magical Ansible incantations to invoke so that I can ssh into the machine as deployer and then run a sudo command (e.g. sudo apt-get install git") without being prompted for a sudo password.

I have searched high and low, and I can't seem to find an Ansible playbook fragment which puts the user "deployer" into the sudo group without requiring a password. How is this done?

Jay Godse
  • 14,823
  • 16
  • 85
  • 128
  • Possible duplicate of [Ansible: best practice for maintaining list of sudoers](https://stackoverflow.com/questions/33359404/ansible-best-practice-for-maintaining-list-of-sudoers) – techraf Aug 21 '18 at 18:56

2 Answers2

170

Sometimes it's knowing what to ask. I didn't know as I am a developer who has taken on some DevOps work.

Apparently 'passwordless' or NOPASSWD login is a thing which you need to put in the /etc/sudoers file.

The answer to my question is at Ansible: best practice for maintaining list of sudoers.

The Ansible playbook code fragment looks like this from my problem:

- name: Make sure we have a 'wheel' group
  group:
    name: wheel
    state: present

- name: Allow 'wheel' group to have passwordless sudo
  lineinfile:
    dest: /etc/sudoers
    state: present
    regexp: '^%wheel'
    line: '%wheel ALL=(ALL) NOPASSWD: ALL'
    validate: 'visudo -cf %s'

- name: Add sudoers users to wheel group
  user:
    name=deployer
    groups=wheel
    append=yes
    state=present
    createhome=yes

- name: Set up authorized keys for the deployer user
  authorized_key: user=deployer key="{{item}}"
  with_file:
    - /home/railsdev/.ssh/id_rsa.pub

And the best part is that the solution is idempotent. It doesn't add the line

%wheel ALL=(ALL) NOPASSWD: ALL

to /etc/sudoers when the playbook is run a subsequent time. And yes...I was able to ssh into the server as "deployer" and run sudo commands without having to give a password.

SuperSandro2000
  • 481
  • 10
  • 15
Jay Godse
  • 14,823
  • 16
  • 85
  • 128
  • 71
    Please add the line `validate: 'visudo -cf %s'` to the end of your `lineinfile:` section to validate prior to saving. Messing up the sudoers file will lock you out of sudo access permanently. – Simon Woodside Dec 23 '16 at 05:46
  • 2
    `authorized_key` [accepts the key as a string](http://docs.ansible.com/ansible/latest/authorized_key_module.html) in the `key` parameter since v1.9 – Tim Nov 26 '17 at 07:19
  • 9
    You can also create/copy a file in `/etc/sudoers.d`, most distributions as a default include line for that... – Gert van den Berg Dec 08 '17 at 16:32
  • Note that the `validate` command will probably need the full path to `visudo` to work. – Matt Hughes May 24 '18 at 17:50
  • @MattHughes `validate: '/usr/sbin/visudo -cf %s'` – Jeter-work Oct 10 '18 at 18:31
  • Why do we add the user to wheel and not directly to sudo group? ```- name: "Granting Administrative Privileges" user: name: deployer groups: sudo append: yes``` – Milad Dec 02 '19 at 11:59
  • 1
    Btw. if you are wondering, what the `%s` in `validate` means, it is the destination (dest) or path of the file that is supposed to be modified. Here is the [documentation](https://docs.ansible.com/ansible/latest/modules/lineinfile_module.html). – AdamKalisz Apr 02 '20 at 09:49
  • 1
    For Ansible 2.3 and later, the parameter dest in lineinfile should be changed to path. – Indika K Aug 03 '20 at 02:41
  • you forgot to ensure that file /etc/sudoers is present – Jens Timmerman Aug 16 '20 at 15:02
  • I don't think its good to enable passwordless sudo for all sudo users. It is suitable for automation accounts but not for human user accounts. Better to just set `deployer ALL=(ALL) NOPASSWD:ALL` – openCivilisation Apr 24 '21 at 01:24
  • @SimonWoodside The Ansible's documentation page for "validate" says: _The validation command to run __before copying__ into place_. Why do you conclude it will check before __saving__? – aderchox Nov 28 '21 at 05:43
22

To create a user with sudo privileges is to put the user into /etc/sudoers, or make the user a member of a group specified in /etc/sudoers. And to make it password-less is to additionally specify NOPASSWD in /etc/sudoers.

Example of /etc/sudoers:

## Allow root to run any commands anywhere
root    ALL=(ALL)       ALL

## Allows people in group wheel to run all commands
%wheel  ALL=(ALL)       ALL

## Same thing without a password
%wheel  ALL=(ALL)       NOPASSWD: ALL

And instead of fiddling with /etc/sudoers file, we can create a new file in /etc/sudoers.d/ directory since this directory is included by /etc/sudoers by default, which avoids the possibility of breaking existing sudoers file, and also eliminates the dependency on the content inside of /etc/sudoers.

To achieve above in Ansible, refer to the following:

- name: sudo without password for wheel group
  copy:
    content: '%wheel ALL=(ALL:ALL) NOPASSWD:ALL'
    dest: /etc/sudoers.d/wheel_nopasswd
    mode: 0440

You may replace %wheel with other group names like %sudoers or other user names like deployer.

pallxk
  • 887
  • 12
  • 13
  • 1
    Thanks for this answer. I added `validate: '/usr/sbin/visudo -cf %s'` to make sure that the syntax is correct and won't block you if you have a typo. – Jack Wire Mar 25 '21 at 11:05