39e4c97856
Python ignores SIGPIPE on startup, because it prefers to check every write and raise an IOError exception rather than taking the signal. Most Unix subprocesses don't expect to work this way. This patch (adapted from Colin Watson's post at http://tinyurl.com/2a7mzh5) sets SIGPIPE back to the default action for quantum.agent.linux.utils.execute, quantum.common.utils.execute and quantum-rootwrap created subprocesses. Fixes bug 1053364 Change-Id: Ib805f1f8846c245b75a5ea64278c840b823c1fb2
101 lines
3.4 KiB
Python
Executable File
101 lines
3.4 KiB
Python
Executable File
#!/usr/bin/env python
|
|
# vim: tabstop=4 shiftwidth=4 softtabstop=4
|
|
|
|
# Copyright (c) 2012 Openstack, LLC.
|
|
# 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 Quantum
|
|
|
|
Filters which commands quantum is allowed to run as another user.
|
|
|
|
To use this, you should set the following in quantum.conf and the
|
|
various .ini files for the agent plugins:
|
|
root_helper=sudo quantum-rootwrap /etc/quantum/rootwrap.conf
|
|
|
|
You also need to let the quantum user run quantum-rootwrap as root in
|
|
/etc/sudoers:
|
|
quantum ALL = (root) NOPASSWD: /usr/bin/quantum-rootwrap
|
|
/etc/quantum/rootwrap.conf *
|
|
|
|
Filter specs live in /etc/quantum/rootwrap.d/*.filters, or
|
|
other locations pointed to by /etc/quantum/rootwrap.conf.
|
|
To make allowed commands node-specific, your packaging should only
|
|
install apropriate .filters for commands which are needed on each
|
|
node.
|
|
"""
|
|
|
|
import ConfigParser
|
|
import os
|
|
import signal
|
|
import subprocess
|
|
import sys
|
|
|
|
|
|
RC_UNAUTHORIZED = 99
|
|
RC_NOCOMMAND = 98
|
|
RC_BADCONFIG = 97
|
|
|
|
|
|
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)
|
|
|
|
|
|
if __name__ == '__main__':
|
|
# Split arguments, require at least a command
|
|
execname = sys.argv.pop(0)
|
|
# argv[0] required; path to conf file
|
|
if len(sys.argv) < 2:
|
|
print "%s: %s" % (execname, "No command specified")
|
|
sys.exit(RC_NOCOMMAND)
|
|
|
|
configfile = sys.argv.pop(0)
|
|
userargs = sys.argv[:]
|
|
|
|
# Load configuration
|
|
config = ConfigParser.RawConfigParser()
|
|
config.read(configfile)
|
|
try:
|
|
filters_path = config.get("DEFAULT", "filters_path").split(",")
|
|
filters = None
|
|
except ConfigParser.Error:
|
|
print "%s: Incorrect configuration file: %s" % (execname, configfile)
|
|
sys.exit(RC_BADCONFIG)
|
|
|
|
# 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, "quantum", "__init__.py")):
|
|
sys.path.insert(0, possible_topdir)
|
|
|
|
from quantum.rootwrap import wrapper
|
|
|
|
# Execute command if it matches any of the loaded filters
|
|
filters = wrapper.load_filters(filters_path)
|
|
filtermatch = wrapper.match_filter(filters, userargs)
|
|
if filtermatch:
|
|
obj = subprocess.Popen(filtermatch.get_command(userargs),
|
|
stdin=sys.stdin,
|
|
stdout=sys.stdout,
|
|
stderr=sys.stderr,
|
|
preexec_fn=_subprocess_setup,
|
|
env=filtermatch.get_environment(userargs))
|
|
obj.wait()
|
|
sys.exit(obj.returncode)
|
|
|
|
print "Unauthorized command: %s" % ' '.join(userargs)
|
|
sys.exit(RC_UNAUTHORIZED)
|