Clearly, sudo
would be the first choice for me in such a case. The major point appears to be that most (actual) admins don't actually use /etc/sudoers
to its fullest possible extent (User_Alias
, Runas_Alias
, Host_Alias
, Cmnd_Alias
).
Most admins end up using only some of the existing rules and adding users, or worse, simply adding users to the sudo
group for which a rule usually exists on Ubuntu setups (%sudo
...). This, of course, gives the respective users free reign and the full power of the superuser account.
Given your comment:
so I added them to /etc/sudoers
I reckon you also don't use it to the extent possible.
In a scenario such as yours I would literally script the few actions to which Bob is to be limited. In fact this is what I did on a server that I maintain, to allow two particular users to reboot a particular KVM guest on a host. The scripts would contain a hashbang with absolute path to the interpreter (e.g. #!/bin/dash
instead of #!/usr/bin/env bash
) and probably run with a shell that is used elsewhere for privileged tasks (/bin/dash
or /bin/sh
). Those are just precautions. Other than that, I would make sure to hardcode all the absolute paths to binaries and use as few of them as possible. E.g. when using bash
/dash
I would prefer builtin
s over command
s (see man bash
). You can make this maintainable by assigning a variable the absolute path and referring to the program based on that variable ($VIRSH
instead of /usr/bin/virsh
). If you can, vet the code of any external scripts before calling them. Especially if you need to call them in a privileged context. In my case I also confine the users to a particular root directory and a particular SSH subsystem as they only connect to the machine via sshd
and public key authentication. Obviously you don't need that.
Make sure to chown root: <the-script>; chmod u=rw,a=,a+rx <the-script>
to prevent anyone but root
proper from tinkering with it. Also be careful with setuid
and setgid
bits enabled on target binaries (find
can be used to spot them). Let's assume for the moment that your script resides in /usr/sbin/priv-action
.
Now edit your /etc/sudoers
. noexec
can be used to prevent other binaries than those explicitly allowed as well. There are actually plenty of additional settings, not just those I am describing here. So make sure to consult man sudoers
.
Now I prefer to name the users (User_Alias
) in my sudoers
file, but you could just as well use a Group_Alias
(man sudoers
) or an actual system group (e.g. %sudo
):
# The list is comma-separated: bob,alice,...
User_Alias LIMITED_ADMINS=bob
and then add a command alias to allow executing that particular script:
# The list is comma-separated: /usr/sbin/priv-action,/bin/bash,...
Cmnd_Alias PRIV_ACTION=/usr/sbin/priv-action
Last but not least comes the magic line to allow bob
(or rather the users listed under LIMITED_ADMINS
) to execute the privileged commands via the script:
LIMITED_ADMINS ALL=(root) PRIV_ACTION
Unlike the previous alias definitions that line requires an explanation. So let's first dig into the parts on a "User Specification" line mean. Here man sudoers
helps:
The basic structure of a user specification is who where = (as_whom) what
.
Example line (found on most Ubuntu setups):
root ALL=(ALL) ALL
This says that a user named root
(use #0
to tie it to the UID 0
) may, on all hosts, run under any user context anything but will be asked for his password (assuming default behavior). Adding the NOPASSWD
tag before the last ALL
would then also allow root
to do the same without being asked for a password (like so: root ALL=(ALL) NOPASSWD:ALL
). ALL
is an intrinsic wildcard alias for the various alias types.
But back to Bob:
LIMITED_ADMINS ALL=(root) PRIV_ACTION
would allow bob
and other listed members of the User_Alias LIMITED_ADMINS
to run (on all hosts, that's what the ALL
is for) as user root
(group implied, but could be given, see man sudoers
) the commands given in the Cmnd_Alias PRIV_ACTION
. It gets better. Still assuming you write this script, you could allow various parameters, thereby avoiding to write multiple scripts. /etc/sudoers
gladly takes shell-like wildcards to limit the possibilities of arguments allowed to be passed.
I have consistently found that admins don't use sudoers
the way it should be used, which is why I appreciated the respective "Hack" from the two books "Linux Server Hacks" and "Linux Server Hacks Volume Two", which got me started with a more sophisticated use of this great facility.
You can come up with all kinds of convoluted - which may not exactly help the security aspect - solutions for your particular case, but once you speak the basic vocabulary of /etc/sudoers
you can perform quite magic feats :)
NB: keep in mind that you can also create a new file underneath /etc/sudoers.d/
if you feel so inclined. This assumes your /etc/sudoers
contains the line:
#includedir /etc/sudoers.d
sudoers
file, you can check it's manpage for more info.sudoers
: it's not a first resort because of security concerns. Also see enzotib's answer - part of the problem was the confusion betweensudo
and PolicyKit.