On my NAS I’ve received sudo: sorry, you are not allowed to preserve the environment
today when running sudo -E
to transfer the environment from whatever the current shell allows sudo
to see, into the new shell.
That’s because I was copying something from a remote machine to my NAS, and I (temporarily) wanted to tell remote rsync
to use sudo rsync
on my NAS to be sure files will be replicated correctly. While this is an absolutely horrible idea to do permanently, a temporary workaround in a safe environment is that sudo rsync
should not require a root password:
ivucica ALL=NOPASSWD:/usr/bin/rsync
However, compare this to some of the defaults in /etc/sudoers
:
# User privilege specification
root ALL=(ALL:ALL) ALL
# Allow members of group sudo to execute any command
%sudo ALL=(ALL:ALL) ALL
Without reading the sudoers(5)
manpage, I decided to add ALL
at the end:
ivucica ALL=NOPASSWD:/usr/bin/rsync ALL
This seemed to work, but despite a lack of a syntax error, it’s wrong (see below): now no password is required for rsync nor for any other command.
# Wrong order:
#ivucica ALL=NOPASSWD: /usr/bin/rsync, PASSWD: ALL
# Correct order:
ivucica ALL=PASSWD: ALL, NOPASSWD: /usr/bin/rsync
The best option, however, is to remove the entry completely given that allowing rsync
root without a password is dangerous; even if someone managed to hijack my own account’s non-password NAS credentials, without the password itself they can’t do much.
However, looking online for this error, I realized I’ve never looked into the syntax of the sudoers
file. What’s Defaults env_reset
, for instance? Turns out sudoers(5)
is an interesting read. If you’re seriously going to play with editing /etc/sudoers beyond just adding a user (even just specifying the NOPASSWD
tag), please read the manpage and carefully experiment. Cover all the edge cases you can think of. Have someone else review your changes.
Here’s some interesting stuff:
#include
(and presumably #includedir
) directive to include a file can contain %h
(a hostname) in file path
- to match all users except root, instead of
ALL
we can specify ALL,!root
- you can do things like disable setting utmp (
set_utmp
) or prohibit the capability to disable env_reset
(setenv
) — which is what I did
- the first-time “lecture” status (‘has this user seen the sudo lecture?’) is in
/var/lib/sudo/lectured
and configurable using lecture_status_dir
- the password prompt can be overridden with
passprompt
and can include %H
FQDN, %h
hostname, %p
the user whose password is requested, %U
the user whom we’re switching to [caveat: PAM module’s output must match Password:
or username's Password:
- there are ways to specify directives per running host (important for standardized configs deployed across an org), per requesting user, per run-as user, per command
- there are tags to tweak execution of a command
While I haven’t actually tried all of the following, here are some “notes-to-self” on what individual fields mean. Please prefer learning the details from the manpage.
What does ALL
before =
mean? Those are the hosts. For instance, we can let roger
run anything on all the fileservers:
Host_Alias FILESERVERS = fs1, fs, fs3
Host_Alias INTERNAL_NETWORK = 192.168.55.0/255.255.255.0
Host_Alias FINANCE = 192.168.75.128/25, 192.168.75.15
roger FILESERVERS = ALL
(Just like Host_Alias
, there’s User_Alias
, Runas_Alias
and Cmnd_Alias
.)
What’s (ALL:ALL)
after =
? That’s called a Runas_Spec
and it’s saying “You can pretend to be any user of any group.” Let’s only allow roger
to run only /usr/bin/rsync
and only to do it as mainweb
:
User_Alias FINANCE_DEPLOY = james, mike
roger FILESERVERS = (mainweb) /usr/bin/rsync
richard richard-workstation = (www-data) ALL
FINANCE_DEPLOY FINANCE = (financeweb : financeservices) /usr/bin/rsync
And what’s the ALL
after (ALL:ALL)
? As demonstrated, that’s the command specification.
Alright, so what’s NOPASSWD:
? That’s a Tag_Spec
. Each command may be prefixed with zero or more tags associated with it, such as EXEC
, NOEXEC
, PASSWD
, NOPASSWD
, MAIL
, NOMAIL
. For instance:
# Allow ls and cat without password, but require a password for vi.
richard richard-workstation = (www-data) NOPASSWD: /usr/bin/ls, /usr/bin/cat, NOEXEC: PASSWD: /usr/bin/vi
richard richard-workstation = (www-data) NOPASSWD: /usr/bin/ls, /usr/bin/cat, PASSWD: /usr/bin/vi
Allowlisting only some commands results in the following when a non-allowed command is run:
Sorry, user richard is not allowed to execute '/bin/bash' as root on my.machine.hostname.
And attempting to run a command from within vi
when NOEXEC
is specified results in:
Cannot execute shell /bin/bash
There’s even a way to set things like timeouts. But, again, read the manpage for details.
As usual, this is not advice; these are personal notes from trying to resolve an immediate issue. As this is a security-sensitive feature, for even one person that reads this and configures an important system incorrectly, please note: these notes are written as a hobby. Just like you would with PAM, NSS, LDAP, Kerberos and other things, please carefully read more authoritative documentation sources; I’m not responsible for breakage you may cause with my non-advice.