Re: [openstack-dev] [neutron][security][rootwrap] Proposal to replace rootwrap/sudo with privsep helper process (for neutron, but others too)

2015-02-15 Thread Angus Lees
On Fri Feb 13 2015 at 10:35:49 PM Miguel Ángel Ajo majop...@redhat.com
wrote:

  We have an ongoing effort in neutron to move to rootwrap-daemon.


 https://review.openstack.org/#/q/status:open+project:openstack/neutron+branch:master+topic:bp/rootwrap-daemon-mode,n,z

 Thanks for replying. I should have mentioned rootwrap-daemon in my
original post:

The main difference between this privsep proposal and rootwrap (in
daemon-mode or rootwrap classic) is that rootwrap is oriented around
command lines, and privsep is oriented around python function calls.

Using functions rather than command lines means we can move to using native
libraries more easily (as I've done here with pyroute2), which allows a
more closely integrated, performant and safer interface.  It also means we
can describe more customised behaviour in the exposed function API, leading
to fewer cross-process calls and less scope for exposing unintended
behaviour.

To pick one example, starting up a long-running daemon (assuming we wanted
to do this) from the privsep process just works without any need to work
around the privsep mechanism.

To speed up multiple system calls, and be able to spawn daemons inside
 namespaces.


Yep, rootwrap-daemon certainly removes the python rootwrap startup time;
privsep *also* removes the subprocess exec startup time for cases where we
have moved to native libraries (again, see the pyroute2 example).

I have to read a bit what are the good  bad points of privsep.

 The advantage of rootwrap-daemon, is that we don’t need to change all our
 networking libraries across neutron,
 and we kill the sudo/rootwrap spawn for every call, yet keeping
 the rootwrap permission granularity.


The good news is that privsep and rootwrap (in either mode) can coexist
just fine.  A staged migration to privsep might involve spawning the
privsep daemon via sudo on the first call to something that needs it.  This
approach means we wouldn't require adding the privsep_daemon.start() call
early in any relevant main() - and the only downside is that we retain a
(single) dependency on sudo/sudoers.

 - Gus

Miguel Ángel Ajo

 On Friday, 13 de February de 2015 at 10:54, Angus Lees wrote:

 On Fri Feb 13 2015 at 5:45:36 PM Eric Windisch e...@windisch.us wrote:

 ᐧ


 from neutron.agent.privileged.commands import ip_lib as priv_ip
 def foo():
 # Need to create a new veth interface pair - that usually requires
 root/NET_ADMIN
 priv_ip.CreateLink('veth', 'veth0', peer='veth1')

 Because we now have elevated privileges directly (on the privileged daemon
 side) without having to shell out through sudo, we can do all sorts of
 nicer things like just using netlink directly to configure networking.
 This avoids the overhead of executing subcommands, the ugliness (and
 danger) of generating command lines and regex parsing output, and make us
 less reliant on specific versions of command line tools (since the kernel
 API should be very stable).


 One of the advantages of spawning a new process is being able to use flags
 to clone(2) and to set capabilities. This basically means to create
 containers, by some definition. Anything you have in a privileged daemon
 or privileged process ideally should reduce its privilege set for any
 operation it performs. That might mean it clones itself and executes
 Python, or it may execvp an executable, but either way, the new process
 would have less-than-full-privilege.

 For instance, writing a file might require root access, but does not need
 the ability to load kernel modules. Changing network interfaces does not
 need access to the filesystem, no more than changes to the filesystem needs
 access to the network. The capabilities and namespaces mechanisms resolve
 these security conundrums and simplify principle of least privilege.


 Agreed wholeheartedly, and I'd appreciate your thoughts on how I'm using
 capabilities in this change.  The privsep daemon limits itself to a
 particular set of capabilities (and drops root). The assumption is that
 most OpenStack services commonly need the same small set of capabilities to
 perform their duties (neutron - net_admin+sys_admin for example), so it
 makes sense to reuse the same privileged process.

 If we have a single service that somehow needs to frequently use a broad
 swathe of capabilities then we might want to break it up further somehow
 between the different internal aspects (multiple privsep helpers?) - but is
 there such a case?   There's also no problems with mixing privsep for
 frequent operations with the existing sudo/rootwrap approach for
 rare/awkward cases.

  - Gus

 __
 OpenStack Development Mailing List (not for usage questions)
 Unsubscribe: openstack-dev-requ...@lists.openstack.org?subject:unsubscribe
 http://lists.openstack.org/cgi-bin/mailman/listinfo/openstack-dev


  
 __
 

Re: [openstack-dev] [neutron][security][rootwrap] Proposal to replace rootwrap/sudo with privsep helper process (for neutron, but others too)

2015-02-13 Thread Angus Lees
On Fri Feb 13 2015 at 5:45:36 PM Eric Windisch e...@windisch.us wrote:

 ᐧ


 from neutron.agent.privileged.commands import ip_lib as priv_ip
 def foo():
 # Need to create a new veth interface pair - that usually
 requires root/NET_ADMIN
 priv_ip.CreateLink('veth', 'veth0', peer='veth1')

 Because we now have elevated privileges directly (on the privileged
 daemon side) without having to shell out through sudo, we can do all sorts
 of nicer things like just using netlink directly to configure networking.
 This avoids the overhead of executing subcommands, the ugliness (and
 danger) of generating command lines and regex parsing output, and make us
 less reliant on specific versions of command line tools (since the kernel
 API should be very stable).


 One of the advantages of spawning a new process is being able to use flags
 to clone(2) and to set capabilities. This basically means to create
 containers, by some definition. Anything you have in a privileged daemon
 or privileged process ideally should reduce its privilege set for any
 operation it performs. That might mean it clones itself and executes
 Python, or it may execvp an executable, but either way, the new process
 would have less-than-full-privilege.

 For instance, writing a file might require root access, but does not need
 the ability to load kernel modules. Changing network interfaces does not
 need access to the filesystem, no more than changes to the filesystem needs
 access to the network. The capabilities and namespaces mechanisms resolve
 these security conundrums and simplify principle of least privilege.


Agreed wholeheartedly, and I'd appreciate your thoughts on how I'm using
capabilities in this change.  The privsep daemon limits itself to a
particular set of capabilities (and drops root). The assumption is that
most OpenStack services commonly need the same small set of capabilities to
perform their duties (neutron - net_admin+sys_admin for example), so it
makes sense to reuse the same privileged process.

If we have a single service that somehow needs to frequently use a broad
swathe of capabilities then we might want to break it up further somehow
between the different internal aspects (multiple privsep helpers?) - but is
there such a case?   There's also no problems with mixing privsep for
frequent operations with the existing sudo/rootwrap approach for
rare/awkward cases.

 - Gus
__
OpenStack Development Mailing List (not for usage questions)
Unsubscribe: openstack-dev-requ...@lists.openstack.org?subject:unsubscribe
http://lists.openstack.org/cgi-bin/mailman/listinfo/openstack-dev


Re: [openstack-dev] [neutron][security][rootwrap] Proposal to replace rootwrap/sudo with privsep helper process (for neutron, but others too)

2015-02-13 Thread Miguel Ángel Ajo
We have an ongoing effort in neutron to move to rootwrap-daemon.  

https://review.openstack.org/#/q/status:open+project:openstack/neutron+branch:master+topic:bp/rootwrap-daemon-mode,n,z

To speed up multiple system calls, and be able to spawn daemons inside 
namespaces.

I have to read a bit what are the good  bad points of privsep.   

The advantage of rootwrap-daemon, is that we don’t need to change all our 
networking libraries across neutron,
and we kill the sudo/rootwrap spawn for every call, yet keeping the rootwrap 
permission granularity.

Miguel Ángel Ajo


On Friday, 13 de February de 2015 at 10:54, Angus Lees wrote:

 On Fri Feb 13 2015 at 5:45:36 PM Eric Windisch e...@windisch.us 
 (mailto:e...@windisch.us) wrote:
  ᐧ

   from neutron.agent.privileged.commands import ip_lib as priv_ip
   def foo():
   # Need to create a new veth interface pair - that usually 
   requires root/NET_ADMIN
   priv_ip.CreateLink('veth', 'veth0', peer='veth1')

   Because we now have elevated privileges directly (on the privileged 
   daemon side) without having to shell out through sudo, we can do all 
   sorts of nicer things like just using netlink directly to configure 
   networking.  This avoids the overhead of executing subcommands, the 
   ugliness (and danger) of generating command lines and regex parsing 
   output, and make us less reliant on specific versions of command line 
   tools (since the kernel API should be very stable).
   
  One of the advantages of spawning a new process is being able to use flags 
  to clone(2) and to set capabilities. This basically means to create 
  containers, by some definition. Anything you have in a privileged daemon 
  or privileged process ideally should reduce its privilege set for any 
  operation it performs. That might mean it clones itself and executes 
  Python, or it may execvp an executable, but either way, the new process 
  would have less-than-full-privilege.
   
  For instance, writing a file might require root access, but does not need 
  the ability to load kernel modules. Changing network interfaces does not 
  need access to the filesystem, no more than changes to the filesystem needs 
  access to the network. The capabilities and namespaces mechanisms resolve 
  these security conundrums and simplify principle of least privilege.
  
 Agreed wholeheartedly, and I'd appreciate your thoughts on how I'm using 
 capabilities in this change.  The privsep daemon limits itself to a 
 particular set of capabilities (and drops root). The assumption is that most 
 OpenStack services commonly need the same small set of capabilities to 
 perform their duties (neutron - net_admin+sys_admin for example), so it 
 makes sense to reuse the same privileged process.
  
 If we have a single service that somehow needs to frequently use a broad 
 swathe of capabilities then we might want to break it up further somehow 
 between the different internal aspects (multiple privsep helpers?) - but is 
 there such a case?   There's also no problems with mixing privsep for 
 frequent operations with the existing sudo/rootwrap approach for rare/awkward 
 cases.
  
  - Gus  
 __
 OpenStack Development Mailing List (not for usage questions)
 Unsubscribe: openstack-dev-requ...@lists.openstack.org?subject:unsubscribe 
 (mailto:openstack-dev-requ...@lists.openstack.org?subject:unsubscribe)
 http://lists.openstack.org/cgi-bin/mailman/listinfo/openstack-dev
  
  


__
OpenStack Development Mailing List (not for usage questions)
Unsubscribe: openstack-dev-requ...@lists.openstack.org?subject:unsubscribe
http://lists.openstack.org/cgi-bin/mailman/listinfo/openstack-dev


Re: [openstack-dev] [neutron][security][rootwrap] Proposal to replace rootwrap/sudo with privsep helper process (for neutron, but others too)

2015-02-13 Thread Thierry Carrez
Angus Lees wrote:
 So inspired by the Rootwrap on root-intensive nodes thread, I went and
 wrote a proof-of-concept privsep daemon for
 neutron: https://review.openstack.org/#/c/155631

Nice work! Trying to check where the security model is actually weaker
than the one provided by rootwrap here...

If I read this correctly, one of the drawbacks compared to the rootwrap
approach is that all the functions are accessible on any node running
the privsep daemon.

When properly packaged, the rootwrap system only has the relevant filter
definition files present, which dramatically reduces what you allow to
run as root there. For example, nova-metadata nodes can only run
iptables to add a firewall rule, since that's the only filter definition
file shipped on those nodes. That's a benefit of shipping allowed
commands in the configuration, rather than in the code. With the
proposed system, the nova-metadata node running with nova-privsep would
have access to any function defined there, including the rather
permissive file manipulations that nova-compute needs.

Maybe one way to solve that would be to have several different privsep
daemons in nova to run on the various types of nodes, each with their
own set of allowed functions...

Additionally, rootwrap was extremely lean in terms of dependencies --
basically only allowing Python stdlib module imports to reduce the
envelope of code you need to trust to run things as root. Here you are
reusing the Neutron agent framework, which has a pretty long list of
module imports, which are all imported before the rights are dropped.
That means you end up blindly trusting a widely larger envelope of modules.

My suggestion would be to not run it as an agent but as a standalone
daemon with an aggressively-limited set of module imports (ideally only
stdlib).

That's all I could spot with a cursory look :)

Cheers,

-- 
Thierry Carrez (ttx)

__
OpenStack Development Mailing List (not for usage questions)
Unsubscribe: openstack-dev-requ...@lists.openstack.org?subject:unsubscribe
http://lists.openstack.org/cgi-bin/mailman/listinfo/openstack-dev


Re: [openstack-dev] [neutron][security][rootwrap] Proposal to replace rootwrap/sudo with privsep helper process (for neutron, but others too)

2015-02-12 Thread Angus Lees
So inspired by the Rootwrap on root-intensive nodes thread, I went and
wrote a proof-of-concept privsep daemon for neutron:
https://review.openstack.org/#/c/155631
There's nothing neutron-specific in the core mechanism and it could easily
be moved out into a common (oslo) library and reused across other projects.


The basic principles guiding a few design choices were:
- it had to be obvious what code would run with elevated privileges
- the interface between that and the rest of the system had to be easy to
understand and audit
- it had to be about as easy as just implementing a function to add new
functionality

The current code does the predictable things to get a privileged buddy
process: assumes you started as root, creates a socketpair, forks, keeps
limited perms and setuids the privileged process, then reads commands over
the socket.  When the socket closes (for whatever reason), the daemon exits.

Currently it scrobbles around below the neutron.agent.privileged._commands
namespace and allows you to invoke any normal function that doesn't start
start with an underscore.  I think I will change this to use some sort of
more explicit decorator, but you get the idea.

On the client side, it generates client stubs of all the same functions
below neutron.agent.privileged.commands at import-time.  Using the daemon
is then as simple as just calling the client stub:

from neutron.agent.privileged import daemon as privsep_daemon
def main():
privsep_daemon.start()
...

from neutron.agent.privileged.commands import ip_lib as priv_ip
def foo():
# Need to create a new veth interface pair - that usually requires
root/NET_ADMIN
priv_ip.CreateLink('veth', 'veth0', peer='veth1')

Because we now have elevated privileges directly (on the privileged daemon
side) without having to shell out through sudo, we can do all sorts of
nicer things like just using netlink directly to configure networking.
This avoids the overhead of executing subcommands, the ugliness (and
danger) of generating command lines and regex parsing output, and make us
less reliant on specific versions of command line tools (since the kernel
API should be very stable).
I demonstrate some of that in the above change by a set of privileged ipset
functions that still call out to commands but don't use sh -c or sudo
anywhere (so are immune to shell metacharacters in arguments), and ip_lib
functions that use pyroute2 to just call netlink directly for network
interface create/delete/update.

Please discuss.  I could have done this in a spec, but I felt the basic
concept and motivation was obvious and the code specifics were of such
importance that this was better explored in a poc change.  I can post-facto
write a spec if it turns out folks would prefer that.

 - Gus

(if you're curious, it took about a day to write the code, and then about 3
long days of debugging eventlet-related conflicts with the 3rd party
libraries I'd just pulled in.  +1 to removing eventlet, particularly in
low-concurrent-queries agent processes where we can presumably just remove
it and use system threads without any further thought)

On Fri Feb 06 2015 at 5:52:44 PM Steven Dake (stdake) std...@cisco.com
wrote:



 On 2/4/15, 10:24 AM, Daniel P. Berrange berra...@redhat.com wrote:

 On Wed, Feb 04, 2015 at 09:10:06AM -0800, James E. Blair wrote:
  Thierry Carrez thie...@openstack.org writes:
 
   You make a good point when you mention traditional distro here. I
   would argue that containers are slightly changing the rules of the
   don't-run-as-root game.
  
   Solution (2) aligns pretty well with container-powered OpenStack
   deployments -- running compute nodes as root in a container (and
   embracing abovementioned simplicity/performance gains) sounds like a
   pretty strong combo.
 
  This sounds at least a little like a suggestion that containers are a
  substitute for the security provided by running non-root.  The security
  landscape around containers is complex, and while there are a lot of
  benefits, I believe the general consensus is that uid 0 processes should
  not be seen as fully isolated.
 
  From https://docs.docker.com/articles/security/ :
 
Docker containers are, by default, quite secure; especially if you
take care of running your processes inside the containers as
non-privileged users (i.e., non-root).
 
  Which is not to say that using containers is not a good idea, but
  rather, if one does, one should avoid running as root (perhaps with
  capabilities), and use selinux (or similar).
 
 Yep, I've seen attempts by some folks to run nova-compute and libvirtd
 and QEMU inside a docker container. Because of the inherantly privileged
 nature of what Nova/libvirt/qemu need to do, you end up having to share
 all the host namespaces with the docker container, except for the
 filesystem
 namespace and even that you need to bind mount a bunch of stuff over. As
 a result the container isn't really offerring 

Re: [openstack-dev] [neutron][security][rootwrap] Proposal to replace rootwrap/sudo with privsep helper process (for neutron, but others too)

2015-02-12 Thread Robert Collins
On 13 Feb 2015 17:42, Angus Lees g...@inodes.org wrote:

 So inspired by the Rootwrap on root-intensive nodes thread, I went and
wrote a proof-of-concept privsep daemon for neutron:
https://review.openstack.org/#/c/155631
 There's nothing neutron-specific in the core mechanism and it could
easily be moved out into a common (oslo) library and reused across other
projects.

Bravo. More conceptual than a code review my questions are. msgpack rather
than protobuf ? Given your previous experience there I'm just curious.

Are you concerned that commands might call into less trusted areas of code?
Would it make sense to have the privileged commands be separate somehow to
avoid this?

Rob
__
OpenStack Development Mailing List (not for usage questions)
Unsubscribe: openstack-dev-requ...@lists.openstack.org?subject:unsubscribe
http://lists.openstack.org/cgi-bin/mailman/listinfo/openstack-dev


Re: [openstack-dev] [neutron][security][rootwrap] Proposal to replace rootwrap/sudo with privsep helper process (for neutron, but others too)

2015-02-12 Thread Eric Windisch
ᐧ


 from neutron.agent.privileged.commands import ip_lib as priv_ip
 def foo():
 # Need to create a new veth interface pair - that usually requires
 root/NET_ADMIN
 priv_ip.CreateLink('veth', 'veth0', peer='veth1')

 Because we now have elevated privileges directly (on the privileged daemon
 side) without having to shell out through sudo, we can do all sorts of
 nicer things like just using netlink directly to configure networking.
 This avoids the overhead of executing subcommands, the ugliness (and
 danger) of generating command lines and regex parsing output, and make us
 less reliant on specific versions of command line tools (since the kernel
 API should be very stable).


One of the advantages of spawning a new process is being able to use flags
to clone(2) and to set capabilities. This basically means to create
containers, by some definition. Anything you have in a privileged daemon
or privileged process ideally should reduce its privilege set for any
operation it performs. That might mean it clones itself and executes
Python, or it may execvp an executable, but either way, the new process
would have less-than-full-privilege.

For instance, writing a file might require root access, but does not need
the ability to load kernel modules. Changing network interfaces does not
need access to the filesystem, no more than changes to the filesystem needs
access to the network. The capabilities and namespaces mechanisms resolve
these security conundrums and simplify principle of least privilege.

Regards,
Eric Windisch
__
OpenStack Development Mailing List (not for usage questions)
Unsubscribe: openstack-dev-requ...@lists.openstack.org?subject:unsubscribe
http://lists.openstack.org/cgi-bin/mailman/listinfo/openstack-dev


Re: [openstack-dev] [neutron][security][rootwrap] Proposal to replace rootwrap/sudo with privsep helper process (for neutron, but others too)

2015-02-12 Thread Angus Lees
On Fri Feb 13 2015 at 4:05:33 PM Robert Collins robe...@robertcollins.net
wrote:


 On 13 Feb 2015 17:42, Angus Lees g...@inodes.org wrote:
 
  So inspired by the Rootwrap on root-intensive nodes thread, I went and
 wrote a proof-of-concept privsep daemon for neutron:
 https://review.openstack.org/#/c/155631
  There's nothing neutron-specific in the core mechanism and it could
 easily be moved out into a common (oslo) library and reused across other
 projects.

 Bravo. More conceptual than a code review my questions are. msgpack rather
 than protobuf ? Given your previous experience there I'm just curious.

I have no educated preference between the two, and I didn't know of any
high-performance precedent within openstack.  msgpack was just the first
thing I came across that seemed well supported, fast, and only handled dumb
types (no object auto-vivifying features that might backfire on us).

We could use json too if we wanted to avoid a new dependency, or presumably
numerous other choices.


  Are you concerned that commands might call into less trusted areas of
 code? Would it make sense to have the privileged commands be separate
 somehow to avoid this?

Hrm, not particularly, although we should explore any implications.  If a
standalone chunk of python imported other python libraries, then they may
have a path that ends up with them able to be called - which I figure is
similar to the current situation that also requires an explicit python
import (or some other chain of object references).  If there's a bug that
lets you escape the python level and run arbitrary C code, then it won't
matter what's already loaded and we only have the linux
capabilities/permissions mechanisms to save us.

In addition, the current simple fork/no-exec is also good for sharing most
of the pages in memory - making the overhead extremely minimal.

Oh, if you mean separate just in a filesystem/code organisation sense,
rather than a Linux process sense, then yes I do think they should be in a
separate place for ease of auditing.  in my change above I have them all
below a particular neutron.agent.privileged._commands prefix, and the
communication assumes/restricts it to this.  We can of course pick another
namespace prefix, but I agree that even with some different decorator-based
method, I don't think we should just have privileged commands scattered
anywhere throughout our regular codebase.

 - Gus
__
OpenStack Development Mailing List (not for usage questions)
Unsubscribe: openstack-dev-requ...@lists.openstack.org?subject:unsubscribe
http://lists.openstack.org/cgi-bin/mailman/listinfo/openstack-dev