Learn through the super-clean Baeldung Pro experience:
>> Membership and Baeldung Pro.
No ads, dark-mode and 6 months free of IntelliJ Idea Ultimate to start with.
Last updated: March 18, 2024
Superusers have full control over a system. Because of this, commands like sudo enable regular users to temporarily gain the benefits of such control without introducing a general security risk.
In this tutorial, we explain how to edit the sudo configuration in /etc/sudoers from within scripts. First, we look at the configurations of both sudo and its sudoers plugin. Next, we discuss editing /etc/sudoers manually and explain why it’s not recommended. Finally, we dive into the proper way to modify a sudoers file and employ that in a script.
We tested the code in this tutorial on Debian 11 (Bullseye) with GNU Bash 5.1.4. It should work in most POSIX-compliant environments.
Before changing any settings, it’s best to understand them.
To begin with, sudo is the main tool, which supports other plugins:
The sudoers plugin is the default unless we specify otherwise. Moreover, this fact is in the main configuration file /etc/sudo.conf along with descriptions of most other options sudo supports:
$ cat /etc/sudo.conf
#
# Default /etc/sudo.conf file
#
# Sudo plugins:
# Plugin plugin_name plugin_path plugin_options ...
#
# The plugin_path is relative to /usr/lib/sudo unless
# fully qualified.
# The plugin_name corresponds to a global symbol in the plugin# that contains the plugin interface structure.
# The plugin_options are optional.
#
# The sudoers plugin is used by default if no Plugin lines are present.
#Plugin sudoers_policy sudoers.so
#Plugin sudoers_io sudoers.so
#Plugin sudoers_audit sudoers.so
[...]
Lines that don’t begin with #, Plugin, Path, Debug, or Set do not produce an error but have no effect.
As a default, the sudoers plugin has its own separate configuration file at /etc/sudoers:
$ cat /etc/sudoers
#
# 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
# 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
At the bottom, we see /etc/sudoers also includes the whole directory at /etc/sudoers.d/.
As with other such files, comment lines, which take up most of the content, start with #. Apart from the @includedir and the actual permissions settings, there are three lines of interest:
Of course, other options are available as well. In fact, we can even negate options with an ! exclamation point prefix and set Defaults for given users by appending a : colon and the relevant user designation:
Defaults:baeldung !requiretty
Finally, the core of the configuration is the permissions settings. As the comments suggest, there are four types of aliases:
Each alias identifies areas that a privilege specification affects. To specify all, we can use ALL. For example, we often have the following two rules by default:
# User privilege specification
root ALL=(ALL:ALL) ALL
# Allow members of group sudo to execute any command
%sudo ALL=(ALL:ALL) ALL
In these, let’s define what each ALL means, from left to right:
Considering the above, the default rules allow root and any sudo user to execute any command from any terminal as any user.
As with any other file, we can just directly modify /etc/sudoers with any text editor.
Of course, this is suboptimal because it can result in an error at the syntax level. Similar to the /etc/passwd file, /etc/sudoers is critical for user access and privileges. Any error in such files can lead to serious consequences:
$ echo 'BAD_SUDOERS' > /etc/sudoers
$ sudo echo Test.
/etc/sudoers:1:12: syntax error
BAD_SUDOERS
^
Alternatively, we can heed the suggestion in the comments about adding any desired changes in new files under /etc/sudoers.d/. While this preserves the main file intact, it may still introduce problems.
Even better, to catch and prevent errors, we can use a standard POSIX tool.
At the top of the /etc/sudoers file, we see an important warning comment about the (strongly) recommended command to edit the configuration: visudo.
visudo is a safe way to edit the /etc/sudoers file, as it follows a strict procedure by default:
Of course, we can modify this behavior with flags. Let’s see how.
By default, concurrent edits are not allowed. Let’s see what happens when we try to edit an already open sudoers file:
$ visudo
[...]
[1]+ Stopped visudo
$ visudo
visudo: /etc/sudoers busy, try again later
After running and backgrounding visudo, we can’t run it again, as the file is already busy.
While /etc/sudoers is the default, we can use visudo with any file by supplying its path to the –file (-f) flag:
$ visudo --file /etc/sudoers.test
Naturally, opening two different files concurrently is allowed. Further, we can combine –file with other flags.
By either assigning a value to the SUDO_EDITOR, VISUAL, or EDITOR environment variables or the Defaults editor option in /etc/sudoers, we can change the default editor for visudo:
$ cat /etc/sudoers
[...]
Defaults editor="/usr/bin/vi"
[...]
$ EDITOR=/usr/bin/vi visudo
Both options above are more or less equivalent in their final result. Importantly, we should specify a full path in editor, while EDITOR can also contain anything reachable in PATH.
Let’s explore some options which make visudo suitable for use in scripts.
By using the –check (-c) flag, we can run visudo just to validate a sudoers file:
$ visudo --check
/etc/sudoers: parsed OK
/etc/sudoers.d/README: parsed OK
Moreover, we can increase the strictness of the checks via the –strict (-s) flag. By default, visudo also checks the contents of the /etc/sudoers.d/ directory. With the –file flag, we can validate a single file:
$ visudo --check --file /etc/sudoers.test
/etc/sudoers.test:9:19: syntax error
Defaulst env_reset
^
Here, we see the detection of a trivial error. In this case, the command returns a non-zero exit code.
With the –quiet (-q) flag, we can silence visudo when performing checks:
$ visudo --quiet --check --file /etc/sudoers.test
$ echo $?
1
By using the ? question mark variable, we can confirm whether a given sudoers file is valid.
Finally, let’s see how we can use visudo without user interaction.
Naturally, we can use constructs like visudo –check –quiet && echo ‘Correct.’ or similar if statements to perform actions based on the validity of a sudoers file. However, changing the file via visudo is a bit more complex.
First, let’s write an example executable script cudo.sh to edit and validate /etc/sudoers:
#!/usr/bin/env bash
echo "$1" | (EDITOR="tee -a" visudo)
In this case, we pipe the value of the first script argument, $1, to a subshell. Basically, the latter does two things:
Importantly, using tee –append as its editor means anything we pipe in goes directly to the end of the sudoers file. After that, visudo performs its checks.
Let’s see our script in action:
$ ./cudo.sh '# Comment'
# Comment
$ tail --lines=1 /etc/sudoers
# Comment
$ ./cudo.sh 'Error'
Error
/etc/sudoers:29:6: syntax error
Error
^
$ tail --lines=1 /etc/sudoers
# Comment
With a correct addition to the file, we can find the content at the end via tail. However, introducing an error means no changes are made to /etc/sudoers. Thus, visudo offers protection from incorrect syntax when editing.
In this article, we looked at sudo, its sudoers plugin, its configuration, and various ways to change it.
In conclusion, using visudo to change a sudoers file ensures proper and safe handling of this sensitive file.