Ansible: create a user with sudo privileges
Asked Answered
N

3

93

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?

Notification answered 19/5, 2016 at 20:22 Comment(1)
Possible duplicate of Ansible: best practice for maintaining list of sudoersDeputy
N
183

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.

Notification answered 19/5, 2016 at 21:35 Comment(11)
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.Ellenaellender
authorized_key accepts the key as a string in the key parameter since v1.9Unmask
You can also create/copy a file in /etc/sudoers.d, most distributions as a default include line for that...Verney
Note that the validate command will probably need the full path to visudo to work.Mc
@MattHughes validate: '/usr/sbin/visudo -cf %s' <- is this what you mean?Professorship
Why do we add the user to wheel and not directly to sudo group? - name: "Granting Administrative Privileges" user: name: deployer groups: sudo append: yesTarn
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.Dore
For Ansible 2.3 and later, the parameter dest in lineinfile should be changed to path.Centromere
you forgot to ensure that file /etc/sudoers is presentKrone
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:ALLAstatic
@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?Stipitate
M
23

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.

Malatya answered 27/4, 2019 at 2:54 Comment(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.Misconstruction
E
6

Although the initial answer is useful and popular, it can be updated based on the newest changes.

  1. There is no group wheel in most modern distributions, but sudo is quite common
  2. You don't need to touch (and break) system files in the /etc directory, but should use an extra path like /etc/sudoers.d
  3. Use true/false boolean variables to be compatible with ansible-lint
  4. I prefer to use variables for any kind of routine code, which can be copy/pasted between projects without changes.

This is the updated version:

- name: Add {{ sudo_user }} user
  user:
    name: "{{ sudo_user }}"
    groups: sudo
    append: true
    state: present
    createhome: true

- name: Make sudo without password for {{ sudo_user }} user
  copy:
    dest: /etc/sudoers.d/80-ansible-sudo-user
    content: "{{ sudo_user }} ALL=(ALL) NOPASSWD:ALL"
    mode: 0440
Exosphere answered 10/4, 2023 at 22:12 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.