oslorootwrap(1)
| OSLOROOTWRAP(1) | oslo.rootwrap | OSLOROOTWRAP(1) |
NAME
oslorootwrap - oslo.rootwrap 7.7.0
oslo.rootwrap allows fine-grained filtering of shell commands to run as root from OpenStack services.
CONTENTS
Installation
At the command line:
$ pip install oslo.rootwrap
Or, if you have virtualenvwrapper installed:
$ mkvirtualenv oslo.rootwrap $ pip install oslo.rootwrap
Using oslo.rootwrap
Usage
Rootwrap should be used as a separate Python process calling the oslo_rootwrap.cmd:main function. You can set up a specific console_script calling into oslo_rootwrap.cmd:main, called for example nova-rootwrap. To keep things simple, this document will consider that your console_script is called /usr/bin/nova-rootwrap.
The rootwrap command line should be called under sudo. It's first parameter is the configuration file to use, and the remainder of the parameters are the command line to execute:
sudo nova-rootwrap ROOTWRAP_CONFIG COMMAND_LINE
How rootwrap works
OpenStack services generally run under a specific, unprivileged user. However, sometimes they need to run a command as root. Instead of just calling sudo make me a sandwich and have a blanket sudoers permission to always escalate rights from their unprivileged users to root, those services can call sudo nova-rootwrap /etc/nova/rootwrap.conf make me a sandwich.
A sudoers entry lets the unprivileged user run nova-rootwrap as root. nova-rootwrap looks for filter definition directories in its configuration file, and loads command filters from them. Then it checks if the command requested by the OpenStack service matches one of those filters, in which case it executes the command (as root). If no filter matches, it denies the request. This allows for complex filtering of allowed commands, as well as shipping filter definitions together with the OpenStack code that needs them.
Security model
The escalation path is fully controlled by the root user. A sudoers entry (owned by root) allows the unprivileged user to run (as root) a specific rootwrap executable, and only with a specific configuration file (which should be owned by root) as its first parameter.
nova-rootwrap imports the Python modules it needs from a cleaned (and system-default) PYTHONPATH. The configuration file points to root-owned filter definition directories, which contain root-owned filters definition files. This chain ensures that the unprivileged user itself is never in control of the configuration or modules used by the nova-rootwrap executable.
Installation
All nodes wishing to run nova-rootwrap should contain a sudoers entry that lets the unprivileged user run nova-rootwrap as root, pointing to the root-owned rootwrap.conf configuration file and allowing any parameter after that. For example, Nova nodes should have this line in their sudoers file, to allow the nova user to call sudo nova-rootwrap:
nova ALL = (root) NOPASSWD: /usr/bin/nova-rootwrap /etc/nova/rootwrap.conf *
Then the node also should ship the filter definitions corresponding to its usage of nova-rootwrap. You should not install any other filters file on that node, otherwise you would allow extra unneeded commands to be run as root.
The filter file(s) corresponding to the node must be installed in one of the filters_path directories. For example, on Nova compute nodes, you should only have compute.filters installed. The file should be owned and writeable only by the root user.
Rootwrap configuration
The rootwrap.conf file is used to influence how nova-rootwrap works. Since it's in the trusted security path, it needs to be owned and writeable only by the root user. Its location is specified in the sudoers entry, and must be provided on nova-rootwrap command line as its first argument.
rootwrap.conf uses an INI file format with the following sections and parameters:
[DEFAULT] section
- filters_path
- Comma-separated list of directories containing filter definition files. All directories listed must be owned and only writeable by root. This is the only mandatory parameter. Example: filters_path=/etc/nova/rootwrap.d,/usr/share/nova/rootwrap
- exec_dirs
- Comma-separated list of directories to search executables in, in case filters do not explicitly specify a full path. If not specified, defaults to the system PATH environment variable. All directories listed must be owned and only writeable by root. Example: exec_dirs=/sbin,/usr/sbin,/bin,/usr/bin
- use_syslog
- Enable logging to syslog. Default value is False. Example: use_syslog=True
- syslog_log_facility
- Which syslog facility to use for syslog logging. Valid values include auth, authpriv, syslog, user0, user1... Default value is syslog. Example: syslog_log_facility=syslog
- syslog_log_level
- Which messages to log. INFO means log all usage, ERROR means only log unsuccessful attempts. Example: syslog_log_level=ERROR
- rlimit_nofile
- Specify rlimit for number of open file descriptors used by oslo rootwrap
and its child processes by default. This is useful in case there is a
excessively large ulimit configured for the calling process that shouldn't
inherit to oslo.rootwrap and its called processes. Will not attempt to
raise the limit. Defaults to 1024.
Ignored on platforms that do not provide "/proc/self/fd" (e.g. non-Linux).
.filters files
Filters definition files contain lists of filters that nova-rootwrap will use to allow or deny a specific command. They are generally suffixed by .filters. Since they are in the trusted security path, they need to be owned and writeable only by the root user. Their location is specified in the rootwrap.conf file.
It uses an INI file format with a [Filters] section and several lines, each with a unique parameter name (different for each filter you define):
[Filters] section
- filter_name (different for each filter)
- Comma-separated list containing first the Filter class to use, followed by that Filter arguments (which vary depending on the Filter class selected). Example: kpartx: CommandFilter, /sbin/kpartx, root
Available filter classes
CommandFilter
Basic filter that only checks the executable called. Parameters are:
- 1.
- Executable allowed
- 2.
- User to run the command under
Example: allow to run kpartx as the root user, with any parameters:
kpartx: CommandFilter, kpartx, root
RegExpFilter
Generic filter that checks the executable called, then uses a list of regular expressions to check all subsequent arguments. Parameters are:
- 1.
- Executable allowed
- 2.
- User to run the command under
- 3.
- (and following) Regular expressions to use to match first (and subsequent) command arguments
Example: allow to run /usr/sbin/tunctl, but only with three parameters with the first two being -b and -t:
tunctl: RegExpFilter, /usr/sbin/tunctl, root, tunctl, -b, -t, .*
PathFilter
Generic filter that lets you check that paths provided as parameters fall under a given directory. Parameters are:
- 1.
- Executable allowed
- 2.
- User to run the command under
- 3.
- (and following) Command arguments.
There are three types of command arguments: pass will accept any parameter value, a string will only accept the corresponding string as a parameter, except if the string starts with '/' in which case it will accept any path that resolves under the corresponding directory.
Example: allow to chown to the 'nova' user any file under /var/lib/images:
chown: PathFilter, /bin/chown, root, nova, /var/lib/images
EnvFilter
Filter allowing extra environment variables to be set by the calling code. Parameters are:
- 1.
- env
- 2.
- User to run the command under
- 3.
- (and following) name of the environment variables that can be set, suffixed by =
- 4.
- Executable allowed
Example: allow to run CONFIG_FILE=foo NETWORK_ID=bar dnsmasq ... as root:
dnsmasq: EnvFilter, env, root, CONFIG_FILE=, NETWORK_ID=, dnsmasq
ReadFileFilter
Specific filter that lets you read files as root using cat. Parameters are:
- 1.
- Path to the file that you want to read as the root user.
Example: allow to run cat /etc/iscsi/initiatorname.iscsi as root:
read_initiator: ReadFileFilter, /etc/iscsi/initiatorname.iscsi
KillFilter
Kill-specific filter that checks the affected process and the signal sent before allowing the command. Parameters are:
- 1.
- User to run kill under
- 2.
- Only affect processes running that executable
- 3.
- (and following) Signals you're allowed to send
Example: allow to send -9 or -HUP signals to /usr/sbin/dnsmasq processes:
kill_dnsmasq: KillFilter, root, /usr/sbin/dnsmasq, -9, -HUP
IpFilter
ip-specific filter that allows to run any ip command, except for ip netns (in which case it only allows the list, add and delete subcommands). Parameters are:
- 1.
- ip
- 2.
- User to run ip under
Example: allow to run any ip command except ip netns exec and ip netns monitor:
ip: IpFilter, ip, root
IpNetnsExecFilter
ip-specific filter that allows to run any otherwise-allowed command under ip netns exec. The command specified to ip netns exec must match another filter for this filter to accept it. Parameters are:
- 1.
- ip
- 2.
- User to run ip under
Example: allow to run ip netns exec <namespace> <command> as long as <command> matches another filter:
ip: IpNetnsExecFilter, ip, root
ChainingRegExpFilter
Filter that allows to run the prefix command, if the beginning of its arguments match to a list of regular expressions, and if remaining arguments are any otherwise-allowed command. Parameters are:
- 1.
- Executable allowed
- 2.
- User to run the command under
- 3.
- (and following) Regular expressions to use to match first (and subsequent) command arguments.
This filter regards the length of the regular expressions list as the number of arguments to be checked, and remaining parts are checked by other filters.
Example: allow to run /usr/bin/nice, but only with first two parameters being -n and integer, and followed by any allowed command by the other filters:
nice: ChainingRegExpFilter, /usr/bin/nice, root, nice, -n, -?\d+
Note: this filter can't be used to impose that the subcommand is always run under the prefix command. In particular, it can't enforce that a particular command is only run under "nice", since the subcommand can explicitly be called directly.
Calling rootwrap from OpenStack services
Standalone mode (sudo way)
The oslo.processutils library ships with a convenience execute() function that can be used to call shell commands as root, if you call it with the following parameters:
run_as_root=True root_helper='sudo nova-rootwrap /etc/nova/rootwrap.conf
NB: Some services ship with a utils.execute() convenience function that automatically sets root_helper based on the value of a rootwrap_config parameter, so only run_as_root=True needs to be set.
If you want to call as root a previously-unauthorized command, you will also need to modify the filters (generally shipped in the source tree under etc/rootwrap.d so that the command you want to run as root will actually be allowed by nova-rootwrap.
Daemon mode
Since 1.3.0 version oslo.rootwrap supports "daemon mode". In this mode rootwrap would start, read config file and wait for commands to be run with root privileges. All communications with the daemon should go through Client class that resides in oslo_rootwrap.client module.
Its constructor expects one argument - a list that can be passed to Popen to create rootwrap daemon process. For root_helper above it will be ["sudo", "nova-rootwrap-daemon", "/etc/neutron/rootwrap.conf"], for example. Note that it uses a separate script that points to oslo_rootwrap.cmd:daemon endpoint (instead of :main).
The class provides one method execute with following arguments:
- userargs - list of command line arguments that are to be used to run the command;
- stdin - string to be passed to standard input of child process.
The method returns 3-tuple containing:
- return code of child process;
- string containing everything captured from its stdout stream;
- string containing everything captured from its stderr stream.
The class lazily creates an instance of the daemon, connects to it and passes arguments. This daemon can die or be killed, Client will respawn it and/or reconnect to it as necessary.
CHANGES
7.7.0
- •
- add pyproject.toml to support pip 23.1
7.6.0
- •
- Update master for stable/2025.1
7.5.1
- •
- Skip installation to speed up pep8
7.5.0
- Adjust warning message for eventlet support deprecation
- deprecate eventlet monkey patching with oslo.rootwrap
- Drop workaround for Python 3.4
- reno: Update master for unmaintained/2023.1
7.4.0
- Add note about requirements lower bounds
- Run pyupgrade to clean up Python 2 syntaxes
- pre-commit: Bump versions
- Remove Python 3.8 support
- Fix outdated tox minversion
- Declare Python 3.12 support
- Extend timeout before SIGKILL
- Update master for stable/2024.2
- Fix _FunctionalBase.test_run_as
7.3.0
- Remove unused reno from test requirements
- Remove old excludes
- Update master for stable/2024.1
- reno: Update master for unmaintained/victoria
7.2.0
- Display coverage report
- Bump hacking
- Update python classifier in setup.cfg
- Add coreutils as valid value to fix KillFilter test
- Update master for stable/2023.2
7.1.0
- Bump bandit
- Revert "Moves supported python runtimes from version 3.8 to 3.10"
- Drop Beta development status
- Moves supported python runtimes from version 3.8 to 3.10
- Update master for stable/2023.1
7.0.1
- •
- Fix issues related to tox4
7.0.0
- Fix formatting of release list
- Drop python3.6/3.7 support in testing runtime
- Remove unnecessary unicode prefixes
- Update CI to use unversioned jobs template
6.3.1
- •
- CommandFilter should allow exec from full path
6.3.0
- setup.cfg: Replace dashes with underscores
- Move flake8 as a pre-commit local target
- Remove lower-constraints remnants
- Dropping lower constraints testing
- Use TOX_CONSTRAINTS_FILE
- Use py3 as the default runtime for tox
- Remove six
- Remove six.PY3
- Add Python3 wallaby unit tests
- Update master for stable/victoria
- Adding pre-commit
- ignore reno generated artifacts
6.2.0
- [goal] Migrate testing to ubuntu focal
- Bump bandit version
- Stop to use the __future__ module
6.1.0
- Fix hacking min version to 3.0.1
- Switch to newer openstackdocstheme and reno versions
- Remove the unused coding style modules
- Avoid raising a RuntimeError during the shutdown
- Align contributing doc with oslo's policy
- Bump default tox env from py37 to py38
- Add py38 package metadata
- Add release notes links to doc index
- Add Python3 victoria unit tests
- Update master for stable/ussuri
- Update hacking for Python3
6.0.2
- •
- Use unittest.mock instead of third party mock
6.0.1
- Implement "realpath" to retrieve the real absolute path
- remove outdated header
- Remove universal wheel configuration
- reword releasenote for py27 support dropping
6.0.0
- [ussuri][goal] Drop python 2.7 support and testing
- tox: Trivial cleanup
5.17.1
- reap rootwrap daemon process when it is timeout
- tox: Keeping going with docs
- Switch to Ussuri jobs
- Bump the openstackdocstheme extension to 1.20
- Sync Sphinx requirement
- Update the constraints url
5.17.0
- •
- Update master for stable/train
5.16.1
- •
- Add Python 3 Train unit tests
5.16.0
- Replace git.openstack.org URLs with opendev.org URLs
- OpenDev Migration Patch
- Dropping the py35 testing
- Always close all passed in fds beyond sensible_fd_limit on launch
- Update master for stable/stein
- Update hacking version
5.15.2
- add python 3.7 unit test job
- Use template for lower-constraints
5.15.1
- Update mailinglist from dev to discuss
- Fix portability issue
5.15.0
- Add release note for file descriptor limit change
- Clean up .gitignore references to personal tools
- Don't quote {posargs} in tox.ini
- Run rootwrap with lower fd ulimit by default
- add lib-forward-testing-python3 test job
- add python 3.6 unit test job
- import zuul job settings from project-config
- Update reno for stable/rocky
- Switch to stestr
- Add release notes link to README
- fix tox python3 overrides
5.14.1
- Make IpNetnsExecFilter more strict to detect aliases
- Remove stale pip-missing-reqs tox test
- Trivial: Update pypi url to new url
5.14.0
- set default python to python3
- fix lower constraints and uncap eventlet
- Update to support running benchmark on python3
- add lower-constraints job
- Updated from global requirements
- Update links in README
- Update reno for stable/queens
- Updated from global requirements
- Updated from global requirements
- Treat doc warnings as errors
5.13.0
- Updated from global requirements
- Follow the new PTI for document build
- Add bandit to pep8 job
5.12.1
5.12.0
- Remove -U from pip install
- Avoid tox_install.sh for constraints support
- Ignore syslog settings if /dev/log is not present
- Remove setting of version/release from releasenotes
- Updated from global requirements
5.11.0
- Protect rootwrap daemon socket against multiple threads
- Cleanup test-requirements
- Updated from global requirements
5.10.0
- Updated from global requirements
- Fix test_daemon_no_cleanup_for_uninitialized_server
- Update reno for stable/pike
- Updated from global requirements
5.9.0
- •
- Update URLs in documents according to document migration
5.8.0
- rearrange existing documentation to fit the new standard layout
- Switch from oslosphinx to openstackdocstheme
- Updated from global requirements
- Remove pbr warnerrors in favor of sphinx check
- Updated from global requirements
- Updated from global requirements
- Updated from global requirements
5.7.0
- •
- Trivial: Remove testscenarios from test-requirements.txt
5.6.0
5.5.0
- Updated from global requirements
- [Fix gate]Update test requirement
- Allow rootwrap-daemon to timeout and exit
- Don't open subdirectories rootwrap filter directories
- Avoid importing Linux specific modules on Windows
- Always check cmd which does not exist
- Updated from global requirements
- Remove support for py34
- pbr.version.VersionInfo needs package name (oslo.xyz and not oslo_xyz)
- [daemon] Close inherited filedescriptors after forking
- Update reno for stable/ocata
5.4.0
- Relax default strict option under python3.x for configparser
- Add Constraints support
- Show team and repo badges on README
5.3.0
- Updated from global requirements
- Updated from global requirements
- [TrivialFix] Replace 'assertFalse(a in b)' with 'assertNotIn(a, b)'
- Fix running unknown commands in daemon mode
- Enable release notes translation
5.2.0
- Update homepage with developer documentation page
- Enhance _program() and _program_path()
5.1.0
- Fix parameters of assertEqual are misplaced
- Remove discover from test-requirements
5.0.0
- always allow privsep-helper as a command
- Add Python 3.5 classifier and venv
- Add reno for release notes management
4.4.0
- •
- Updated from global requirements
4.3.0
- •
- Updated from global requirements
4.2.0
- •
- Updated from global requirements
4.1.0
- •
- Updated from global requirements
4.0.0
- Updated from global requirements
- Remove unused use-syslog-rfc-format option
3.2.0
- Updated from global requirements
- Updated from global requirements
- Removes MANIFEST.in as it is not needed explicitely by PBR
3.1.0
- •
- Drop python 2.6 support
3.0.1
- Updated from global requirements
- Remove python 2.6 classifier
- Remove python 2.6 and cleanup tox.ini
- Python 3: encode or decode i/o data of Popen.communicate()
2.5.0
- Fix Python 3 support for eventlet monkey-patching
- Fix Python 3 issues in tests
2.4.0
- No need for Oslo Incubator Sync
- move usage instructions into main docs
- docs - Set pbr 'warnerrors' option for doc build
- Add shields.io version/downloads links/badges into README.rst
- add pbr-generated release history to the documentation
- Fix some spelling typo in manual
- Updated from global requirements
- Python 3: Don't use BaseException.message attribute
2.3.0
- Handle renamed executables with KillFilter
- Updated from global requirements
2.2.0
- Updated from global requirements
- Updated from global requirements
- Updated from global requirements
- Updated from global requirements
- Updated from global requirements
- Updated from global requirements
- Remove test-requirements-py3.txt
- Add tox target to find missing requirements
2.1.0
- daemon: avoid raising UnboundLocalError to callers
- Updated from global requirements
- Updated from global requirements
- Log that rootwrap was spawned after check
2.0.0
- •
- Remove oslo namespace package
1.8.0
- Remove run_cross_tests.sh
- Updated from global requirements
- Remove mentions of root "tests" package from test_funcional_*
- Generate a oslo-rootwrap console script
1.7.0
- Uncap library requirements for liberty
- Speed up non-daemon rootwrap command line invocation
- Correct RST syntax errors in README.rst
- Update to latest hacking
- Avoid calling sudo just to change users
- Updated from global requirements
1.6.0
- Remove env changing support in daemon mode
- Updated from global requirements
- Updated from global requirements
- Add bug link to README
1.5.0
- Add cross-testing script
- Updated from global requirements
- Move files out of the namespace package
- Activate pep8 check that _ is imported
- Workflow documentation is now in infra-manual
1.4.0
- Updated from global requirements
- Updated from global requirements
- Correct filters examples in README.rst
- Updated from global requirements
- Fix exit of subprocess in case it was terminated by signal
- Updated from global requirements
- Support building wheels (PEP-427)
- Updated from global requirements
1.3.0
- Clean up title on main doc page
- Initial cut of documentation for oslo.rootwrap
- Add a short doc to README on how to use daemon mode
- Fix the bug tracker URL in CONTRIBUTING.rst
- warn against sorting requirements
- Updated from global requirements
1.3.0.0a2
- Add daemon mode to benchmark
- Add an option to run rootwrap as a daemon
- Refactor common parts from cmd to wrapper
- Add basic benchmark
- Remove sys.path modification
- Move test requirement coverage into tox.ini
- Enabled hacking check H305
- Continue on failure of leaf filters of chaining filters
1.3.0.0a1
- Let tests pass on distros where "ip" is in /bin
- Bump hacking to 0.9.x series
- Avoid usage of mutables as default args
- Simplify the flow in RegExpFilter
- Add ChainingRegExpFilter for prefix utilities
- Fix Python 3 support, add functional test
- Fix import grouping
- Remove unused variable 'command'
- Run py33 test env before others
1.2.0
- Avoid matching ip -s netns exec in IpFilter
- Don't use system pip things in tox
- Add Python 3 trove classifiers
- To honor RFC5424 add use_syslog_rfc_format config option
- Trivial changes from oslo-incubator
1.1.0
- Discontinue usage of oslo-rootwrap
- Add missing oslo/__init__.py
- Fix spelling errors in comments
1.0.0
- Use oslo-rootwrap in config directory names
- Ship with etc/oslo.rootwrap instead of etc/oslo
- Add a complete README.rst
- Add .gitreview for oslo.rootwrap
- Add standalone project packaging support files
- Make Rootwrap python3-compatible
- Make tests not depend on openstack.common stuff
- Move files to new locations for oslo-config
- Skip hidden files while traversion rootwrap filters
- Fix os.getlogin() problem with no tty
- Send rootwrap exit error message to stderr
- rootwrap: improve Python 3 compatibility
- Replace using tests.utils part2
- Fixes files with wrong bitmode
- Remove DnsmasqFilter and DeprecatedDnsmasqFilter
- Handle empty arglists in Filters
- Handle empty PATH environment variable
- Add IpFilter, IPNetnsExecFilter and EnvFilter
- Handle relative path arguments in Killfilter
- Enable hacking H404 test
- Enable hacking H402 test
- Update KillFilter to stop at '0' for readlink() function
- Stylistic improvements from quantum-rootwrap
- Use print_function __future__ import
- Revert common logging use in rootwrap
- Improve Python 3.x compatibility
- Replaces standard logging with common logging
- Move bin/ scripts to entrypoints
- Add PathFilter to rootwrap
- update OpenStack, LLC to OpenStack Foundation
- Fix Copyright Headers - Rename LLC to Foundation
- Replaced direct usage of stubout with BaseTestCase
- Use testtools as test base class
- Remove unused etc/openstack-common.conf.test
- Fix pep8 E125 errors
- Move rootwrap code to openstack.common
Contributing
If you would like to contribute to the development of oslo's libraries, first you must take a look to this page:
If you would like to contribute to the development of OpenStack, you must follow the steps in this page:
Once those steps have been completed, changes to OpenStack should be submitted for review via the Gerrit tool, following the workflow documented at:
Pull requests submitted through GitHub will be ignored.
Bugs should be filed on Launchpad, not GitHub:
RELEASE NOTES
Read also the oslo.rootwrap Release Notes.
INDICES AND TABLES
- Index
- Module Index
- Search Page
AUTHOR
Author name not set
COPYRIGHT
2014, OpenStack Foundation
| October 24, 2025 | 7.7.0 |
