Oslo Rootwrap
Oslo Rootwrap is an OpenStack library providing a highly configurable privilege escalation mechanism, akin to `sudo`. It enables non-root users to execute specific commands as root, governed by filters defined in configuration files, and is crucial for secure privileged operations in OpenStack services. The current version is 7.9.0, and it is actively maintained as part of the OpenStack Oslo common libraries, following OpenStack's release cadence.
Common errors
-
oslo_rootwrap.exceptions.FileFilterNotFound: Filter not found for command: ['/usr/bin/some_script', 'arg1']
cause The command you are attempting to execute is not permitted by any of the configured filter files in `rootwrap.d`.fixAdd a new filter rule to one of your `rootwrap.d` files (e.g., `command.filters`) that explicitly allows the full command path and its arguments. Ensure the filter file is correctly parsed and accessible. -
oslo_rootwrap.exceptions.DaemonConnectionError: Error communicating with rootwrap daemon.
cause The `oslo-rootwrap` daemon could not be started or communicated with, often due to incorrect `sudo` setup, missing `rootwrap` binary, or permission issues.fixCheck the system logs for messages from `sudo` or `oslo-rootwrap`. Verify that `/usr/bin/oslo-rootwrap` exists, has correct SUID permissions, and your `sudoers` file is configured to allow its execution. Ensure `oslo_config` points to the correct `daemon_wrapper` (usually `sudo`). -
E.g., `(13, 'Permission denied')` in `execute` traceback or a generic permission error.
cause This usually indicates that the `oslo-rootwrap` binary itself cannot be executed with the necessary root privileges, or that the command it tries to run is not permitted due to incorrect filesystem permissions.fixFirst, check the SUID bit and ownership of the `oslo-rootwrap` binary (`chmod 4755 /usr/bin/oslo-rootwrap`, `chown root:root /usr/bin/oslo-rootwrap`). Next, verify that `rootwrap.conf` and all `rootwrap.d` filter files have appropriate read permissions for the user `oslo-rootwrap` will run as.
Warnings
- breaking Python 2.x support was dropped in `oslo-rootwrap` version 5.0.0. Projects migrating from older OpenStack versions using Python 2 must upgrade their environment to Python 3.x.
- gotcha Incorrect or missing rootwrap configuration files (`rootwrap.conf` and filter files in `rootwrap.d`) are the most common source of issues. `oslo-rootwrap` will deny commands that are not explicitly permitted by a filter.
- gotcha Improper file permissions or `sudo` configuration for the `oslo-rootwrap` binary can prevent it from escalating privileges. The `oslo-rootwrap` binary must be owned by root, have SUID permissions, and be invoked via `sudo` correctly.
Install
-
pip install oslo-rootwrap
Imports
- RootwrapClient
from oslo_rootwrap.client import RootwrapClient
- cfg
from oslo_config import cfg
Quickstart
import os
from oslo_config import cfg
from oslo_rootwrap import client
# Define oslo-rootwrap specific configuration options
rootwrap_group = cfg.OptGroup(
name='rootwrap',
title='Rootwrap Options for privilege escalation'
)
cfg.CONF.register_group(rootwrap_group)
cfg.CONF.register_opts([
cfg.StrOpt('rootwrap_config',
default='/etc/rootwrap.conf',
help='Path to the rootwrap configuration file.'),
cfg.StrOpt('filters_path',
default='/etc/rootwrap.d',
help='Path to the directory containing rootwrap filter files.'),
cfg.StrOpt('daemon_pid_dir',
default='/var/run/oslo-rootwrap',
help='Directory for rootwrap daemon PID files. Used only if in daemon mode.'),
cfg.StrOpt('daemon_wrapper',
default='/usr/bin/sudo',
help='Path to the sudo wrapper binary that executes the rootwrap daemon.'),
], group=rootwrap_group)
# Initialize oslo_config. In a real application, you'd usually load from files:
# cfg.CONF(project='my_app', default_config_files=['/etc/my_app/my_app.conf'])
# For this quickstart, we use registered defaults.
print("Initializing oslo_config and setting up rootwrap options...")
cfg.CONF() # This parses any command-line arguments and loads default config values
# Instantiate the RootwrapClient
try:
# The client uses the global cfg.CONF object
rootwrap_client = client.RootwrapClient(cfg.CONF)
print("RootwrapClient instantiated successfully using oslo_config.")
# Display some configured paths
print(f"Configured rootwrap config file: {cfg.CONF.rootwrap.rootwrap_config}")
print(f"Configured rootwrap filters path: {cfg.CONF.rootwrap.filters_path}")
print(f"Configured daemon wrapper (sudo path): {rootwrap_client.get_daemon_wrapper()}")
print("\n--- Important Note for Execution ---")
print("The oslo-rootwrap library requires extensive system-level setup to function:")
print("1. A 'rootwrap.conf' file (e.g., at /etc/rootwrap.conf) defining general rules.")
print("2. Filter files (e.g., in /etc/rootwrap.d/) specifying allowed commands and parameters.")
print("3. 'sudo' configured to execute the 'oslo-rootwrap' binary with SUID permissions.")
print("\nTo execute a command, you would typically use:")
print(" stdout, stderr, returncode = rootwrap_client.execute(['command', 'arg1', 'arg2'])")
print("Attempting to run `execute` without this setup will likely result in errors.")
except Exception as e:
print(f"Error during RootwrapClient instantiation: {e}")
print("Ensure oslo_config options are correctly registered and paths are valid for your setup.")