Add more usage documentation

The documentation was a bit too dry. Take some information
from mikal's blogposts and expose them in the user doc section.

Change-Id: I93a91c12e78c5d56913b0953c5a9cfa16e45a265
This commit is contained in:
Thierry Carrez 2019-04-04 15:29:47 +02:00
parent d84c76108b
commit 6c3a6e27a6
2 changed files with 109 additions and 5 deletions

View File

@ -2,7 +2,16 @@
oslo.privsep
==============
OpenStack library for privilege separation
oslo.privsep is an OpenStack library for privilege separation.
It helps applications perform actions which require more or less
privileges than they were started with in a safe, easy to code
and easy to use manner. For more information on why this is generally
a good idea please read over the `principle of least privilege`_ and
the `specification`_ which created this library.
.. _principle of least privilege: https://en.wikipedia.org/wiki/Principle_of_least_privilege
.. _specification: https://specs.openstack.org/openstack/oslo-specs/specs/liberty/privsep.html
Contents
========

View File

@ -2,14 +2,109 @@
Usage
=======
To use oslo.privsep in a project::
oslo.privsep lets you define in your code specific functions that will run
in predefined privilege contexts. This lets you run functions with more (or
less) privileges than the rest of the code. Privsep functions live in a
specific ``privsep`` submodule (for example, ``nova.privsep`` for nova).
import oslo_privsep
Defining a context
==================
You can read the following blog posts in order to know a bit more:
Contexts are defined in the ``privsep/__init__.py`` file. For example, this
defines a sys_admin_pctxt with ``CAP_CHOWN``, ``CAP_DAC_OVERRIDE``,
``CAP_DAC_READ_SEARCH``, ``CAP_FOWNER``, ``CAP_NET_ADMIN``, and
``CAP_SYS_ADMIN`` rights (equivalent to ``sudo`` rights)::
from oslo_privsep import capabilities
from oslo_privsep import priv_context
sys_admin_pctxt = priv_context.PrivContext(
'nova',
cfg_section='nova_sys_admin',
pypath=__name__ + '.sys_admin_pctxt',
capabilities=[capabilities.CAP_CHOWN,
capabilities.CAP_DAC_OVERRIDE,
capabilities.CAP_DAC_READ_SEARCH,
capabilities.CAP_FOWNER,
capabilities.CAP_NET_ADMIN,
capabilities.CAP_SYS_ADMIN],
)
Defining a privileged function
==============================
Functions are defined in files under the ``privsep/`` subdirectory, for
example in a ``privsep/motd.py`` file for functions touching the MOTD file.
They make use of a decorator pointing to the context we defined above::
import nova.privsep
@nova.privsep.sys_admin_pctxt.entrypoint
def update_motd(message):
with open('/etc/motd', 'w') as f:
f.write(message)
Privileged functions must be as simple, specialized and narrow as possible,
so as to prevent further escalation. In this example, ``update_motd(message)``
is narrow: it only allows the service to overwrite the MOTD file. If a more
generic ``update_file(filename, content)`` was created, it could be used to
overwrite any file in the filesystem, allowing easy escalation to root
rights. That would defeat the whole purpose of oslo.privsep.
Using a privileged function
===========================
To use the privileged function in the regular code, you can just call it::
import nova.privsep.motd
...
nova.privsep.motd.update_motd('This node is currently idle')
It is better to import the complete path (``import nova.privsep.motd``) rather
than the motd name (``from nova.privsep import motd``) so that it is easier to
spot that the function runs in a different privileged context.
For more details, you can read the following blog post:
* `How to make a privileged call with oslo privsep`_
* `Adding oslo privsep to a new project, a worked example`_
.. _How to make a privileged call with oslo privsep: https://www.madebymikal.com/how-to-make-a-privileged-call-with-oslo-privsep/
Converting from rootwrap to privsep
===================================
oslo.rootwrap is a precursor of oslo.privsep to allow code to run commands
under sudo if they match a predefined filter. For example, you could define
a filter that would allow you to run chmod as root using the following
filter::
chmod: CommandFilter, chmod, root
Beyond the bad performance of calling full commands in order to accomplish
simple tasks, rootwrap also led to bad security: it was difficult to filter
commands in a way that would not easily allow privilege escalation.
Replacing rootwrap filters with privsep functions is easy. The chmod filter
above can be replaced with a function that calls ``os.chmod()``. However a
straight 1:1 filter:function replacement generally results in functions that
are still too broad for good security. It is better to replace each chmod
rootwrap *call* with a narrow privsep function that will limit it to specific
files.
Sometimes it is necessary to refactor the calling code: the rootwrap design
discouraged the creation of new filters and therefore often resulted in the
creation of overly-broad calling functions.
As an example, this `patch series`_ is work-in-progress to transition Nova
from rootwrap to privsep.
For more details, you can read the following blog post:
* `Adding oslo privsep to a new project, a worked example`_
.. _patch series: https://review.openstack.org/#/q/project:openstack/nova+branch:master+topic:my-own-personal-alternative-universe
.. _Adding oslo privsep to a new project, a worked example: https://www.madebymikal.com/adding-oslo-privsep-to-a-new-project-a-worked-example/