Ansible: best practice for maintaining list of sudoers

47,184

Solution 1

That line isn't actually adding an users to sudoers, merely making sure that the wheel group can have passwordless sudo for all command.

As for adding users to /etc/sudoers this is best done by adding users to necessary groups and then giving these groups the relevant access to sudo. This holds true when you aren't using Ansible too.

The user module allows you to specify an exclusive list of group or to simply append the specified groups to the current ones that the user already has. This is naturally idempotent as a user cannot be defined to be in a group multiple times.

An example play might look something like this:

- hosts: all
  vars:
    sudoers:
      - user1
      - user2
      - user3
  tasks:
    - 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: "{{ item }}"
        groups: wheel
        append: yes
      with_items: "{{ sudoers }}"

Solution 2

I prefer to use /etc/sudoers.d/ for this if possible (this is less risky, more modular and self-decriptive), so this approach looks like:

$ cat files/*
%admins ALL=(ALL) NOPASSWD: ALL

$ cat tasks/*
- name: sudoers | Create sudoers.d files
  copy:
    src: ./
    dest: /etc/sudoers.d
    owner: root
    group: root
    mode: ug+rwX,o=
    force: yes

File are pre-checked with visudo -cf file_name.

Share:
47,184
chishaku
Author by

chishaku

2+2=4

Updated on June 19, 2020

Comments

  • chishaku
    chishaku almost 4 years

    In the documentation, there is an example of using the lineinfile module to edit /etc/sudoers.

    - lineinfile: "dest=/etc/sudoers state=present regexp='^%wheel' line='%wheel ALL=(ALL) NOPASSWD: ALL'"
    

    Feels a bit hackish.

    I assumed there would be something in the user module to handle this but there doesn't appear to be any options.

    What are the best practices for adding and removing users to /etc/sudoers?

  • xenithorb
    xenithorb over 7 years
    validate: visudo -cf %s as an attribute of the lineinfile task will ensure that you don't mess something up, by running it through the validation command first.
  • Matt Hughes
    Matt Hughes almost 6 years
    Note that the validate command will probably need the full path to visudo to work.
  • Todd Walton
    Todd Walton over 4 years
    The problem with this approach is that you have to a) be sure you have the wheel group already there and already enabled in sudoers, and b) be sure that you want to put the user into the wheel group and not some other one. What if you want a user to be NOPASSWD, but limit their commands? The lineinfile module gets trickier when you need to insert a line but not at the end. (Because inserting it at the end would break the #includedir statement, which must be on the last line.)
  • AdamKalisz
    AdamKalisz about 4 years
    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.
  • maxschlepzig
    maxschlepzig over 3 years
    You are missing the filename in src: . Also, force: yes is superfluous as this is the default. Perhaps it makes sense to be more explicit about the destination as this would create /etc/sudoers.d as a file if it doesn't exist ...
  • dess
    dess over 3 years
    Thank you for the note! Actually, I'm considering following: file name isn't missed, syntax means all contents of directory; force is used for module action specifics emphasis, could be omitted; if dest: is a non-existent path and src: is a directory (which is) dest: path (directory, not file) is created.
  • maxschlepzig
    maxschlepzig over 3 years
    Ok, ./ looked like an oversight. Having a subdirectory in your files directory - such that you could use - say - src: sudoers.d - arguably would make this pattern more obvious.
  • JeremyCanfield
    JeremyCanfield almost 3 years
    Great answer. A slightly different approach would be to use the copy module instead of the lineinfile module to copy the sudoers files from the control node to each managed node. There are pros and cons to using the copy vs. lineinfile module. I tend to like the copy module to have a single, standardized file on the control node to ensure each managed node is using the same exact file. But, of course, there are possible drawbacks to using copy. Just food for thought here.
  • Darren Felton
    Darren Felton about 2 years
    Personally I prefer ansible.builtin.template over ansiblt.builtin.copy or ansible.builtin.file. While we maybe don't need variables inside the file, this allows us to report accurately at the end of the playbook if something has changed or not.