253

Preface

This is a fairly complex question related to the sudoers file and the sudo command in general.

NOTE: I have made these changes on a dedicated machine running Ubuntu Desktop 13.04, that I use purely for learning purposes. I understand it's a huge security risk to enable NOPASSWD sudo.

Question

Initially, my only change to the sudoers file (/etc/sudoers) was one line, a user specification that should have enabled nicholsonjf to run all commands with sudo without having to enter a password (see the line that starts with nicholsonjf):

# This file MUST be edited with the 'visudo' command as root.
#
# Please consider adding local content in /etc/sudoers.d/ instead of
# directly modifying this file.
#
# See the man page for details on how to write a sudoers file.
#
Defaults        env_reset
Defaults        mail_badpass
Defaults        secure_path="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"

Host alias specification

User alias specification

Cmnd alias specification

User privilege specification

root ALL=(ALL:ALL) ALL nicholsonjf ALL=NOPASSWD: ALL

Members of the admin group may gain root privileges

%admin ALL=(ALL) ALL

Allow members of group sudo to execute any command

%sudo ALL=(ALL:ALL) ALL

See sudoers(5) for more information on "#include" directives:

#includedir /etc/sudoers.d

However this did not work, and I was still prompted for my password every time I ran a command as nicholsonjf. I was only able to start running sudo commands as nicholsonjf once I removed nicholsonjf from the sudo and admin groups.

Can anyone explain why this worked?

Is it because the user nicholsonjf was inheriting sudo rights from the two group specifications of admin and sudo (seen below in the sudoers file), which were overriding the nicholsonjf user specification because they were further down in the config file?

karel
  • 122,292
  • 133
  • 301
  • 332
nicholsonjf
  • 2,721

8 Answers8

328

The line you added was overridden. From man sudoers:

When multiple entries match for a user, they are applied in order. Where there are multiple matches, the last match is used (which is not necessarily the most specific match).

In your case nicholsonjf was a member of the group sudo so for him this line applied:

%sudo   ALL=(ALL:ALL) ALL

If you want to override entries in /etc/sudoers just put the new entries after them.

The new entry should look like

myuser ALL=(ALL) NOPASSWD: ALL for a single user, or

%sudo ALL=(ALL) NOPASSWD: ALL for a group.

156

For a single user, add this line at the end of your sudoers file using the sudo visudo command:

superuser ALL=(ALL) NOPASSWD:ALL

For a group

%supergroup  ALL=(ALL) NOPASSWD:ALL
61

Run this command to never prompt the current user for a password when that user uses sudo:

echo "$USER ALL=(ALL:ALL) NOPASSWD: ALL" | sudo tee "/etc/sudoers.d/dont-prompt-$USER-for-sudo-password"

It creates a file called /etc/sudoers.d/dont-prompt-<YOUR USERNAME>-for-sudo-password with the following contents:

<YOUR USERNAME> ALL=(ALL:ALL) NOPASSWD: ALL

This works because Debian's and Ubuntu's default /etc/sudoers file has this line

#includedir /etc/sudoers.d

which makes it process files in the /etc/sudoers.d/ directory. If the command above didn't work, check that no one has removed that line from your /etc/sudoers file.

2

As I was researching this, I realized that there's a line in the /etc/sudoers file that is not a comment, but a directive that makes any file or folder under the directory /etc/sudoers/* override the contents of /etc/sudoers.

This is a sneaky little directive, as it appears to be a commented line upon first glance. It looks like this:

#includedir /etc/sudoers.d

This is how I've implemented the non-root, passwordless user in an ephemeral Docker Image for use in a CICD pipeline with the base image of ubuntu:18.04:

RUN \
  useradd -U foo -m -s /bin/bash -p foo -G sudo && passwd -d foo && passwd -d root && \
  sed -i /etc/sudoers -re 's/^%sudo.*/%sudo ALL=(ALL:ALL) NOPASSWD: ALL/g' && \
  sed -i /etc/sudoers -re 's/^root.*/root ALL=(ALL:ALL) NOPASSWD: ALL/g' && \
  sed -i /etc/sudoers -re 's/^#includedir.*/## Removed the #include directive! ##"/g' && \
  echo "Customized the sudoers file for passwordless access!" && \
  echo "foo ALL=(ALL) NOPASSWD: ALL" >> /etc/sudoers && \
  echo "root ALL=(ALL) NOPASSWD: ALL" >> /etc/sudoers && \
  echo "foo user:";  su foo -c 'whoami && id' && \
  echo "root user:"; su root -c 'whoami && id'

What happens with the above code:

  • The user and group foo is created.
  • The user foo is added to the both the foo and sudo group.
  • The home directory is set to /home/foo.
  • The shell is set to /bin/bash.
  • The sed command does inline updates to the /etc/sudoers file to allow foo and root users passwordless access to the sudo group.
  • The sed command disables the #includedir directive that would allow any files in subdirectories to override these inline updates.
2

As Vince has mentioned in a comment, you can use this line:

%sudo ALL=NOPASSWD: ALL

(This is different from the lines shown in those answers, and it solved the problem for me.)

Eliah Kagan
  • 119,640
E. Fortes
  • 137
  • 3
0

One can insert a string in one line without EOF formatting at end of sudoers file or remove with sed -i:

cat >> /etc/sudoers <<<'PaSe ALL=(ALL:ALL) NOPASSWD:ALL'

Reference: https://stackoverflow.com/questions/41298208/how-to-append-a-line-at-the-end-of-etc-sudoers-file-using-shell-script-without/70039824#70039824

PaSe
  • 39
0

To give explicit permission for each command you want allow, (extending the answer of user677955)

Example to bypass passwdord prompt for sudo apt [...] in bash:

echo "$USER ALL=(ALL:ALL) NOPASSWD:$(which apt)" \
| sudo tee -a "/etc/sudoers.d/dont-prompt-$USER-for-sudo-password"

Example to bypass password prompt for sudo service [...] in fish:

echo "$USER ALL=(ALL:ALL) NOPASSWD:"(which service) \
| sudo tee -a "/etc/sudoers.d/dont-prompt-$USER-for-sudo-password"
0

Add a # to the beginning of:

@includedir /etc/sudoers.d

i.e

#@includedir /etc/sudoers.d

This fixed the issue in Debian 12 for me