If your plan is to use sudo
for privilege escalation, one wrinkle you may have to deal with is that that sudo can be set up to permit root access to some commands and not others. For example let's imagine you've got a server that runs VirtualBox, with different people managing the applications than are managing the OS. Your sudoers
file might contain something like the following:
Cmnd_Alias SAFE = /bin/true, /bin/false, /usr/bin/id, /usr/bin/who*
Cmnd_Alias SHUTDOWN = /sbin/shutdown, /sbin/halt, /sbin/reboot
Cmnd_Alias SU = /bin/su, /usr/bin/vi*, /usr/sbin/visudo
Cmnd_Alias SHELLS = /bin/sh, /bin/bash, /bin/csh, /bin/tcsh
Cmnd_Alias VBOX = /usr/bin/VBoxManage
%wheel ALL=(ALL) ALL, !SU, !SHELLS, !SHUTDOWN
%staff ALL=(ALL) !SU, !SHELLS, NOPASSWD: SAFE
%operator ALL=(ALL) SAFE, SHUTDOWN
%vboxusers ALL=(ALL) NOPASSWD: VBOX
In this case, a member of the vboxusers
unix group will always get a successful response to a sudo -nv
, because of the existence of the NOPASSWD entry for that group. But a member of that group running any other command than VBoxManage will get a password challenge and a security warning.
So you need to determine whether the command you need to run can be run without a password prompt. If you don't know how sudo is configured on the system where your script is running, the canonical test is to run the command. Running sudo -nv
will only tell you whether you are authenticated; it won't tell you what commands you have access to.
That said, if you can safely rely on a sudo configuration where, say, membership in wheel
group gives you access to all commands, for example with:
%wheel ALL=(ALL) ALL
then you can use sudo -nv
to test for escalation capabilities. But your script might have some things that it runs as root, and some things it doesn't. You might also want to consider other tools besides sudo
for privilege escalation.
One strategy might be to set a variable to preface commands if the need is there, but leave the variable blank if you're already root (i.e. running the entire script inside sudo).
if ! which sudo >/dev/null 2>/dev/null; then
PM_SU_CMD="su - root -c"
elif sudo -nv 2>/dev/null; then
PM_SU_CMD="sudo"
else
echo "ERROR: I can't get root." >&2
exit 1
fi
Of course, if we are already root, unset this to avoid potential conflict:
[ `ps -o uid= $$` -eq 0 ] && unset PM_SU_CMD
(Note that this is a query of the system's process table; we don't want to rely on the shell's environment, because that can be spoofed.)
Then, certain system utilities might be made more easily available using functions:
# Superuser versions for commands that need root privileges
find_s () { $PM_SU_CMD "/usr/bin/find $*"; }
mkdir_s () { $PM_SU_CMD "/bin/mkdir -p $1"; }
rm_s () { $PM_SU_CMD "/bin/rm $*"; }
Then within your script, you'd simply use the _s
version of things that need to be run with root privileges.
This is of course by no means the only way to solve this problem.