From 9c5890cb780587a895a4ac6680dbb4306c30e56f Mon Sep 17 00:00:00 2001 From: Monty Taylor Date: Thu, 2 May 2013 10:26:37 -0400 Subject: Update rootwrap with code from oslo. Change-Id: I30f1b8773840c098f1e38d09bf13f0863035289e --- bin/nova-rootwrap | 4 +- nova/cmd/rootwrap.py | 128 --------------------------------- nova/openstack/common/rootwrap/cmd.py | 130 ++++++++++++++++++++++++++++++++++ setup.cfg | 2 +- 4 files changed, 133 insertions(+), 131 deletions(-) delete mode 100644 nova/cmd/rootwrap.py create mode 100755 nova/openstack/common/rootwrap/cmd.py diff --git a/bin/nova-rootwrap b/bin/nova-rootwrap index f37958ba5..5e3c4fa23 100755 --- a/bin/nova-rootwrap +++ b/bin/nova-rootwrap @@ -17,6 +17,6 @@ # limitations under the License. # Temporary shim to do a devstack transition -from nova.cmd import rootwrap +from nova.openstack.common.rootwrap import cmd -rootwrap.main() +cmd.main() diff --git a/nova/cmd/rootwrap.py b/nova/cmd/rootwrap.py deleted file mode 100644 index 0b7d0064f..000000000 --- a/nova/cmd/rootwrap.py +++ /dev/null @@ -1,128 +0,0 @@ -#!/usr/bin/env python -# vim: tabstop=4 shiftwidth=4 softtabstop=4 - -# Copyright (c) 2011 OpenStack Foundation. -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -"""Root wrapper for OpenStack services - - Filters which commands a service is allowed to run as another user. - - To use this with nova, you should set the following in - nova.conf: - rootwrap_config=/etc/nova/rootwrap.conf - - You also need to let the nova user run nova-rootwrap - as root in sudoers: - nova ALL = (root) NOPASSWD: /usr/bin/nova-rootwrap - /etc/nova/rootwrap.conf * - - Service packaging should deploy .filters files only on nodes where - they are needed, to avoid allowing more than is necessary. -""" - -import ConfigParser -import logging -import os -import pwd -import signal -import subprocess -import sys - - -RC_UNAUTHORIZED = 99 -RC_NOCOMMAND = 98 -RC_BADCONFIG = 97 -RC_NOEXECFOUND = 96 - - -def _subprocess_setup(): - # Python installs a SIGPIPE handler by default. This is usually not what - # non-Python subprocesses expect. - signal.signal(signal.SIGPIPE, signal.SIG_DFL) - - -def _exit_error(execname, message, errorcode, log=True): - print "%s: %s" % (execname, message) - if log: - logging.error(message) - return(errorcode) - - -def main(): - # Split arguments, require at least a command - execname = sys.argv.pop(0) - if len(sys.argv) < 2: - _exit_error(execname, "No command specified", RC_NOCOMMAND, log=False) - - configfile = sys.argv.pop(0) - userargs = sys.argv[:] - - # Add ../ to sys.path to allow running from branch - possible_topdir = os.path.normpath(os.path.join(os.path.abspath(execname), - os.pardir, os.pardir)) - if os.path.exists(os.path.join(possible_topdir, "nova", "__init__.py")): - sys.path.insert(0, possible_topdir) - - from nova.openstack.common.rootwrap import wrapper - - # Load configuration - try: - rawconfig = ConfigParser.RawConfigParser() - rawconfig.read(configfile) - config = wrapper.RootwrapConfig(rawconfig) - except ValueError as exc: - msg = "Incorrect value in %s: %s" % (configfile, exc.message) - _exit_error(execname, msg, RC_BADCONFIG, log=False) - except ConfigParser.Error: - _exit_error(execname, "Incorrect configuration file: %s" % configfile, - RC_BADCONFIG, log=False) - - if config.use_syslog: - wrapper.setup_syslog(execname, - config.syslog_log_facility, - config.syslog_log_level) - - # Execute command if it matches any of the loaded filters - filters = wrapper.load_filters(config.filters_path) - try: - filtermatch = wrapper.match_filter(filters, userargs, - exec_dirs=config.exec_dirs) - if filtermatch: - command = filtermatch.get_command(userargs, - exec_dirs=config.exec_dirs) - if config.use_syslog: - logging.info("(%s > %s) Executing %s (filter match = %s)" % ( - os.getlogin(), pwd.getpwuid(os.getuid())[0], - command, filtermatch.name)) - - obj = subprocess.Popen(command, - stdin=sys.stdin, - stdout=sys.stdout, - stderr=sys.stderr, - preexec_fn=_subprocess_setup, - env=filtermatch.get_environment(userargs)) - obj.wait() - return(obj.returncode) - - except wrapper.FilterMatchNotExecutable as exc: - msg = ("Executable not found: %s (filter match = %s)" - % (exc.match.exec_path, exc.match.name)) - _exit_error(execname, msg, RC_NOEXECFOUND, log=config.use_syslog) - - except wrapper.NoFilterMatched: - msg = ("Unauthorized command: %s (no filter matched)" - % ' '.join(userargs)) - _exit_error(execname, msg, RC_UNAUTHORIZED, log=config.use_syslog) diff --git a/nova/openstack/common/rootwrap/cmd.py b/nova/openstack/common/rootwrap/cmd.py new file mode 100755 index 000000000..36d87d4db --- /dev/null +++ b/nova/openstack/common/rootwrap/cmd.py @@ -0,0 +1,130 @@ +#!/usr/bin/env python +# vim: tabstop=4 shiftwidth=4 softtabstop=4 + +# Copyright (c) 2011 OpenStack Foundation. +# All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. + +"""Root wrapper for OpenStack services + + Filters which commands a service is allowed to run as another user. + + To use this with nova, you should set the following in + nova.conf: + rootwrap_config=/etc/nova/rootwrap.conf + + You also need to let the nova user run nova-rootwrap + as root in sudoers: + nova ALL = (root) NOPASSWD: /usr/bin/nova-rootwrap + /etc/nova/rootwrap.conf * + + Service packaging should deploy .filters files only on nodes where + they are needed, to avoid allowing more than is necessary. +""" + +from __future__ import print_function + +import ConfigParser +import logging +import os +import pwd +import signal +import subprocess +import sys + + +RC_UNAUTHORIZED = 99 +RC_NOCOMMAND = 98 +RC_BADCONFIG = 97 +RC_NOEXECFOUND = 96 + + +def _subprocess_setup(): + # Python installs a SIGPIPE handler by default. This is usually not what + # non-Python subprocesses expect. + signal.signal(signal.SIGPIPE, signal.SIG_DFL) + + +def _exit_error(execname, message, errorcode, log=True): + print("%s: %s" % (execname, message)) + if log: + logging.error(message) + sys.exit(errorcode) + + +def main(): + # Split arguments, require at least a command + execname = sys.argv.pop(0) + if len(sys.argv) < 2: + _exit_error(execname, "No command specified", RC_NOCOMMAND, log=False) + + configfile = sys.argv.pop(0) + userargs = sys.argv[:] + + # Add ../ to sys.path to allow running from branch + possible_topdir = os.path.normpath(os.path.join(os.path.abspath(execname), + os.pardir, os.pardir)) + if os.path.exists(os.path.join(possible_topdir, "nova", "__init__.py")): + sys.path.insert(0, possible_topdir) + + from nova.openstack.common.rootwrap import wrapper + + # Load configuration + try: + rawconfig = ConfigParser.RawConfigParser() + rawconfig.read(configfile) + config = wrapper.RootwrapConfig(rawconfig) + except ValueError as exc: + msg = "Incorrect value in %s: %s" % (configfile, exc.message) + _exit_error(execname, msg, RC_BADCONFIG, log=False) + except ConfigParser.Error: + _exit_error(execname, "Incorrect configuration file: %s" % configfile, + RC_BADCONFIG, log=False) + + if config.use_syslog: + wrapper.setup_syslog(execname, + config.syslog_log_facility, + config.syslog_log_level) + + # Execute command if it matches any of the loaded filters + filters = wrapper.load_filters(config.filters_path) + try: + filtermatch = wrapper.match_filter(filters, userargs, + exec_dirs=config.exec_dirs) + if filtermatch: + command = filtermatch.get_command(userargs, + exec_dirs=config.exec_dirs) + if config.use_syslog: + logging.info("(%s > %s) Executing %s (filter match = %s)" % ( + os.getlogin(), pwd.getpwuid(os.getuid())[0], + command, filtermatch.name)) + + obj = subprocess.Popen(command, + stdin=sys.stdin, + stdout=sys.stdout, + stderr=sys.stderr, + preexec_fn=_subprocess_setup, + env=filtermatch.get_environment(userargs)) + obj.wait() + sys.exit(obj.returncode) + + except wrapper.FilterMatchNotExecutable as exc: + msg = ("Executable not found: %s (filter match = %s)" + % (exc.match.exec_path, exc.match.name)) + _exit_error(execname, msg, RC_NOEXECFOUND, log=config.use_syslog) + + except wrapper.NoFilterMatched: + msg = ("Unauthorized command: %s (no filter matched)" + % ' '.join(userargs)) + _exit_error(execname, msg, RC_UNAUTHORIZED, log=config.use_syslog) diff --git a/setup.cfg b/setup.cfg index 9195497bd..aa9371ecb 100644 --- a/setup.cfg +++ b/setup.cfg @@ -48,7 +48,7 @@ console_scripts = nova-network = nova.cmd.network:main nova-novncproxy = nova.cmd.novncproxy:main nova-objectstore = nova.cmd.objectstore:main - nova-rootwrap = nova.cmd.rootwrap:main + nova-rootwrap = nova.openstack.common.rootwrap.cmd:main nova-scheduler = nova.cmd.scheduler:main nova-spicehtml5proxy = nova.cmd.spicehtml5proxy:main nova-xvpvncproxy = nova.cmd.xvpvncproxy:main -- cgit