Reputation: 15503
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?
Upvotes: 94
Views: 186235
Reputation: 2605
Although the initial answer is useful and popular, it can be updated based on the newest changes.
sudo
instead of wheel
/etc
directory, but should use an extra path like /etc/sudoers.d
true/false
boolean variables to be compatible with ansible-lintThis 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
Upvotes: 11
Reputation: 456
The answers shared above were pretty helpful for me to resolve this issue I was dealing with. Taking inspiration from the aforementioned I came up with a more robust and graceful solution:
- name: "Ensure the {{ ansible_user }} User is in the "wheel" Group"
ansible.builtin.user:
name: "{{ ansible_user }}"
groups: wheel
append: true
- name: Ensure "/etc/sudoers.d/" Directory Exists
ansible.builtin.file:
path: /etc/sudoers.d
state: directory
owner: root
group: root
mode: "0750"
- name: "Allow the {{ ansible_user }} User to Use sudo Without Password"
ansible.builtin.copy:
dest: "/etc/sudoers.d/{{ ansible_user }}"
content: "{{ ansible_user }} ALL=(ALL) NOPASSWD:ALL\n"
owner: root
group: root
mode: "0440"
validate: "/usr/sbin/visudo --check --file=%s"
The solution above allows me to ensure:
The user I am "becoming" is added to the wheel
group (on RedHat distros like Fedora, the equivalent of it on Debian/Ubuntu and the rest is the sudo
group).
The /etc/sudoers.d/
directory exists (it did not on Fedora 41 Server) with appropriate access permissions.
Configure the sudoers list with my user with a directive to to require a password when using sudo
. The directive is validated before it is copied to its destination. A validation failure ensures there is no broken directives passed to the /etc/sudoers.d
directory.
Upvotes: 0
Reputation: 15503
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.
Upvotes: 184
Reputation: 1107
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
.
Upvotes: 23