<div dir="ltr">So inspired by the "Rootwrap on root-intensive nodes" thread, I went and wrote a proof-of-concept privsep daemon for neutron: <a href="https://review.openstack.org/#/c/155631">https://review.openstack.org/#/c/155631</a><br>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.<br><br><br>The basic principles guiding a few design choices were:<div>- it had to be obvious what code would run with elevated privileges</div><div>- the interface between that and the rest of the system had to be easy to understand and audit</div><div>- it had to be about as easy as just implementing a function to add new functionality</div><div><br></div><div>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.</div><div><span style="line-height:1.5"><br></span></div><div><span style="line-height:1.5">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.</span><br></div><div><span style="line-height:1.5"><br></span></div><div><span style="line-height:1.5">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:</span></div><div><span style="line-height:1.5"><br></span></div><div> from neutron.agent.privileged import daemon as privsep_daemon</div><div><span style="line-height:1.5"> def main():</span></div><div><span style="line-height:1.5"> privsep_daemon.start()</span></div><div><span style="line-height:1.5"> ...</span></div><div><span style="line-height:1.5"><br></span></div><div><span style="line-height:1.5"> </span>from neutron.agent.privileged.commands import ip_lib as priv_ip</div><div><span style="line-height:1.5"> def foo():</span></div><div><span style="line-height:1.5"> # Need to create a new veth interface pair - that usually requires root/NET_ADMIN</span></div><div><span style="line-height:1.5"> priv_ip.CreateLink('veth', 'veth0', peer='veth1')</span></div><div><br></div><div>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).</div><div>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.</div><div><br></div><div><span style="line-height:19.7999992370605px">Please discuss. </span>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.</div><div><br></div><div> - Gus</div><div><br><div>(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)</div></div><br><div class="gmail_quote">On Fri Feb 06 2015 at 5:52:44 PM Steven Dake (stdake) <<a href="mailto:stdake@cisco.com">stdake@cisco.com</a>> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><br>
<br>
On 2/4/15, 10:24 AM, "Daniel P. Berrange" <<a href="mailto:berrange@redhat.com" target="_blank">berrange@redhat.com</a>> wrote:<br>
<br>
>On Wed, Feb 04, 2015 at 09:10:06AM -0800, James E. Blair wrote:<br>
>> Thierry Carrez <<a href="mailto:thierry@openstack.org" target="_blank">thierry@openstack.org</a>> writes:<br>
>><br>
>> > You make a good point when you mention "traditional distro" here. I<br>
>> > would argue that containers are slightly changing the rules of the<br>
>> > don't-run-as-root game.<br>
>> ><br>
>> > Solution (2) aligns pretty well with container-powered OpenStack<br>
>> > deployments -- running compute nodes as root in a container (and<br>
>> > embracing abovementioned simplicity/performance gains) sounds like a<br>
>> > pretty strong combo.<br>
>><br>
>> This sounds at least a little like a suggestion that containers are a<br>
>> substitute for the security provided by running non-root. The security<br>
>> landscape around containers is complex, and while there are a lot of<br>
>> benefits, I believe the general consensus is that uid 0 processes should<br>
>> not be seen as fully isolated.<br>
>><br>
>> From <a href="https://docs.docker.com/articles/security/" target="_blank">https://docs.docker.com/<u></u>articles/security/</a> :<br>
>><br>
>> Docker containers are, by default, quite secure; especially if you<br>
>> take care of running your processes inside the containers as<br>
>> non-privileged users (i.e., non-root).<br>
>><br>
>> Which is not to say that using containers is not a good idea, but<br>
>> rather, if one does, one should avoid running as root (perhaps with<br>
>> capabilities), and use selinux (or similar).<br>
><br>
>Yep, I've seen attempts by some folks to run nova-compute and libvirtd<br>
>and QEMU inside a docker container. Because of the inherantly privileged<br>
>nature of what Nova/libvirt/qemu need to do, you end up having to share<br>
>all the host namespaces with the docker container, except for the<br>
>filesystem<br>
>namespace and even that you need to bind mount a bunch of stuff over. As<br>
>a result the container isn't really offerring any security benefit over<br>
>running the things outside the container. IOW the use of containers to<br>
>confine nova is only solving a managability problem rather than a security<br>
>problem.<br>
><br>
>Regards,<br>
>Daniel<br>
<br>
Daniel,<br>
<br>
Agree 100% - compute in containers is all about an atomic image-based<br>
upgrade and downgrade process, not about solving security problems.<br>
Ideally the services that are within containers are as secure as running<br>
natively without containers on bare metal although this might be a bit of<br>
assumption since docker does run with all Linux capabilities enabled.<br>
<br>
Regards<br>
-steve<br>
<br>
>--<br>
>|: <a href="http://berrange.com" target="_blank">http://berrange.com</a> -o-<br>
><a href="http://www.flickr.com/photos/dberrange/" target="_blank">http://www.flickr.com/photos/<u></u>dberrange/</a> :|<br>
>|: <a href="http://libvirt.org" target="_blank">http://libvirt.org</a> -o-<br>
><a href="http://virt-manager.org" target="_blank">http://virt-manager.org</a> :|<br>
>|: <a href="http://autobuild.org" target="_blank">http://autobuild.org</a> -o-<br>
><a href="http://search.cpan.org/~danberr/" target="_blank">http://search.cpan.org/~<u></u>danberr/</a> :|<br>
>|: <a href="http://entangle-photo.org" target="_blank">http://entangle-photo.org</a> -o-<br>
><a href="http://live.gnome.org/gtk-vnc" target="_blank">http://live.gnome.org/gtk-vnc</a> :|<br>
><br>
>_____________________________<u></u>______________________________<u></u>_______________<br>
>OpenStack Development Mailing List (not for usage questions)<br>
>Unsubscribe: <a href="http://OpenStack-dev-request@lists.openstack.org?subject:unsubscribe" target="_blank">OpenStack-dev-request@lists.<u></u>openstack.org?subject:<u></u>unsubscribe</a><br>
><a href="http://lists.openstack.org/cgi-bin/mailman/listinfo/openstack-dev" target="_blank">http://lists.openstack.org/<u></u>cgi-bin/mailman/listinfo/<u></u>openstack-dev</a><br>
<br>
<br>
______________________________<u></u>______________________________<u></u>______________<br>
OpenStack Development Mailing List (not for usage questions)<br>
Unsubscribe: <a href="http://OpenStack-dev-request@lists.openstack.org?subject:unsubscribe" target="_blank">OpenStack-dev-request@lists.<u></u>openstack.org?subject:<u></u>unsubscribe</a><br>
<a href="http://lists.openstack.org/cgi-bin/mailman/listinfo/openstack-dev" target="_blank">http://lists.openstack.org/<u></u>cgi-bin/mailman/listinfo/<u></u>openstack-dev</a><br>
</blockquote></div></div>