[neutron][nova][large scale SIG] Rootwrap daemon and privsep
Thierry Carrez
thierry at openstack.org
Fri Nov 29 17:17:46 UTC 2019
Arnaud Morin wrote:
> [...] I'd like to understand the difference with privsep daemon.
>
> Is privsep a new daemon which is supposed to replace the rootwrap one?
> Is privsep being launch after rootwrap?
> IS privsep enabled by default, so I should not care about rootwrap at
> all?
I can help with that, since I originally created rootwrap.
Rootwrap is a privilege escalation control mechanism. It serves as a way
to filter what the service user on the machine can execute as root via
sudo. The idea is that sudoers files do not provide enough granularity,
so instead of trying to describe what is allowed and what is not in
sudoers file, we basically allow calling "sudo rootwrap command" and let
rootwrap figure it out. Rootwrap reads a number of (root-owned)
configuration files and decides to allow calling the command or not.
There are two issues with this mechanism. The first is that the
performance is not great, as first you run a python executable
(rootwrap), which in turn spawns another process if the command is
allowed. If you do that for hundreds of "ip" calls as you set up
networking in neutron, this can add up pretty fast.
The second issue is that rootwrap is only as secure as its
configuration. If for example you configure rootwrap to allow the 'nova'
user to run the "chmod" command, well that's basically the same as
allowing it run anything as root. You have to use advanced filters to
further refine what it can actually do based on command parameter
analysis, and there is only so much you can control that way.
Rootwrap-daemon is a way to partially help with the first issue. Rather
than calling a new rootwrap Python process every time a command needs to
be called, you maintain a long-running rootwrap process that will
process all requests. It significantly improves performance, but it adds
inter-process communication complexity (never great in a security
system). And it does nothing to address the second issue.
Privsep is the "right" way of addressing both issues. Rather than having
the code try to call shell commands as root, privsep allows the code to
call Python functions as root. This solves the performance issue, as you
don't have the overhead of a separate Python process + shell process
every time you want to change the ownership of a file, you can just call
a Python function that will call os.chown() and get ear to syscall
efficiency. It also solves the granularity issue, by allowing to call a
function that will only do what you want to do, rather than have to find
a way to filter parameters so that the command you call cannot be abused
to do other things.
The main issue with privsep is that it requires changing the code. You
have to set it up in every project (it's now done for most), but then
every place the service calls utils.execute(command, run_as_root=True)
needs to be changed to call a privileged Python function instead.
The second issue with privsep is that it still needs root to start. The
way this is usually done is by using rootwrap itself to bootstrap
privsep... which can be confusing. There are obviously other ways to
start the process as root, but since most of those services still make
use of rootwrap anyway, that is what continues to be used for the
initial bootstrapping.
Ideally services would be completely transitioned to privsep, and we
would discontinue rootwrap.
Hoping this helps,
--
Thierry Carrez (ttx)
More information about the openstack-discuss
mailing list