/brief opinion
Personally I believe if you aren't looking at the script before you run it, whatever side effects that happen are mostly your fault (commands running with sudo
that don't prompt you for example), but at the same time, I know it can be hard to parse and grok an entire script every time. Overall I prefer a hybrid strategy where I can balance convenience and security.
/end opinion
Keep in mind you can always run sudo -k
before calling a script to require the first implicit sudo
call to prompt for your password, though unless it also is run after every sudo
command inside the script it will ONLY prompt you for the very first call to sudo
.
There are a few ways to accomplish a safe, sane script using sudo only when necessary, some more icky/ill-advised than others. This post outlines a few examples/options that I will expand upon further. https://bitmingw.com/2017/01/22/use-sudo-in-scripts/
You can run the whole script with sudo
which as you described is "explicit", but this also means ALL the commands within the script run as root, and if it isn't well written or you forgot that $USER
might change inside the script to root
and you instead needed to use $SUDO_USER
then you could end up in a world of hurt. I've accidentally done this in the past and weird and terrible things happened and then you (and I) end up guarding your scripts with if [ $EUID -eq 0 ]; then echo "Don't run as root!"; fi
or the opposite -gt 0
and you have to remember to put one of the guards in every script you write (or learn configuration management tools like SaltStack/Puppet/Chef that can automate some of this for you).
sudo somescript.sh
The option I prefer to use is to run TEMPORARILY run sudo
with an infinite cache time so no other sudo commands run by you require a re-prompt (or possibly anybody depending on how you set it up). Ideally you would put a properly automated and tested function (or include your "cache_sudo.sh" script) early in your scripts and then remove the infinite timeout enabling sudoers.d
file as soon as the script exits (killed/finished/error) using trap
and then sudo -k
to expire the session/token after removing the file. See this answer for a example of testing and add the file only if valid.
This is the manual version, don't put this into your script.
sudo visudo -f /etc/sudoers.d/infinite_cache_myuser
#Add next line to the file
Defaults:YOUR_USER_NAME timestamp_timeout=-1
The benefits of the infinite cache is within your script you can elevate ONLY the commands that require root with sudo, while not having to "downgrade" ALL the other commands using su $MY_REGULAR_USER some_command
or sudo -u $MY_REGULAR_USER some_command
for EVERY SINGLE command. (I really dislike pointlessly repeated code to drop privileges if there is a less painful and not totally insecure way to write it to only elevate when necessary).
One way to lessen the repeated code would be define a short command "prefix" that adds sudo
or su $MY_USER
depending on whether the script will be run with sudo ./myscript.sh
or ./myscript.sh
with sudo
inside.
You could write a sudoers
rule to allow executing the target script with sudo
and no password prompt but I think this is just as bad an idea as the first option, it only helps slightly if you want to run sudo from a cron job that runs as a non-root user but needs to alter something that requires root or another user, though you'll need to read man sudoers
to learn the syntax for allowing a user to impersonate another user.
# Customize line below and add to /etc/sudoers or /etc/sudoers.d/my_script_runner
YOUR_USER_NAME ALL=(ALL:ALL) NOPASSWD:/abs/path/to/your/script
You can also allow passwordless sudo for only the commands that require it, which allows you to run the script as non-root and still access those commands.
YOUR_USER_NAME ALL=(ALL:ALL) NOPASSWD:/usr/bin/apt-get update
YOUR_USER_NAME ALL=(ALL:ALL) NOPASSWD:/usr/bin/apt-get upgrade
YOUR_USER_NAME ALL=(ALL:ALL) NOPASSWD:/usr/bin/updatedb
This option is probably my second choice behind the infinite cache trick. The downside is you are editing the sudoers file every time you find a new command that needs root, rather than just being able to add sudo
in front of the command in your script. The upside is you are only allowing passwordless sudo
when necessary, and you can still require a password for other sudo
commands thus staying much safer.
sudoedit
won't let you edit regular files as root. You can break your system and lock yourself out pretty quickly with a poorly thought out script, it only takes achmod -R
orchown -R
that ends up targeting your home folder to make things go bad fast.