able to launch desired sudo command now; something is still broken though

pull/658/head
Steven Robertson 5 years ago
parent 24b170311a
commit f1eed0163d

@ -1461,37 +1461,12 @@ class Connection(object):
by returning a 1-element list containing :attr:`python_path` + codecs by returning a 1-element list containing :attr:`python_path` + codecs
This allows emulation of existing tools where the Python invocation may This allows emulation of existing tools where the Python invocation may
be set to e.g. `['/usr/bin/env', 'python']` or be set to e.g. `['/usr/bin/env', 'python']`
`['source', '/opt/rh/rh-python36/enable, '&&', 'python']`
""" """
# if isinstance(self.options.python_path, list):
# python_path = " ".join(self.options.python_path)
# else:
# python_path = self.options.python_path
# quoting the entire command necessary to invoke python supports
# complex python_paths
# return ["'" + python_path, '-c',
# 'import codecs,os,sys;_=codecs.decode;'
# 'exec(_(_("%s".encode(),"base64"),"zip"))\'' % (encoded.decode(),)
# ]
if isinstance(self.options.python_path, list): if isinstance(self.options.python_path, list):
return self.options.python_path return self.options.python_path
return [self.options.python_path] return [self.options.python_path]
"""
return self.get_python_argv() + [
- '-c',
- 'import codecs,os,sys;_=codecs.decode;'
- 'exec(_(_("%s".encode(),"base64"),"zip"))' % (encoded.decode(),)
- ]
if isinstance(self.options.python_path, list):
- return self.options.python_path
- return [self.options.python_path]
"""
def get_boot_command(self): def get_boot_command(self):
source = inspect.getsource(self._first_stage) source = inspect.getsource(self._first_stage)
source = textwrap.dedent('\n'.join(source.strip().split('\n')[2:])) source = textwrap.dedent('\n'.join(source.strip().split('\n')[2:]))
@ -1507,7 +1482,6 @@ class Connection(object):
# codecs.decode() requires a bytes object. Since we must be compatible # codecs.decode() requires a bytes object. Since we must be compatible
# with 2.4 (no bytes literal), an extra .encode() either returns the # with 2.4 (no bytes literal), an extra .encode() either returns the
# same str (2.x) or an equivalent bytes (3.x). # same str (2.x) or an equivalent bytes (3.x).
# return self.get_python_cmd(encoded)
return self.get_python_argv() + [ return self.get_python_argv() + [
'-c', '-c',
'import codecs,os,sys;_=codecs.decode;' 'import codecs,os,sys;_=codecs.decode;'
@ -1549,8 +1523,6 @@ class Connection(object):
def start_child(self): def start_child(self):
args = self.get_boot_command() args = self.get_boot_command()
LOG.debug('%s', args)
LOG.debug('walrus')
LOG.debug('command line for %r: %s', self, Argv(args)) LOG.debug('command line for %r: %s', self, Argv(args))
try: try:
return self.create_child(args=args, **self.create_child_args) return self.create_child(args=args, **self.create_child_args)

@ -298,12 +298,10 @@ class Connection(mitogen.parent.Connection):
if self.options.ssh_args: if self.options.ssh_args:
bits += self.options.ssh_args bits += self.options.ssh_args
bits.append(self.options.hostname) bits.append(self.options.hostname)
# import pdb
# pdb.set_trace()
base = super(Connection, self).get_boot_command() base = super(Connection, self).get_boot_command()
base_parts = [] base_parts = []
for s in base: for s in base:
val = s if s in self.SHLEX_IGNORE else shlex_quote(s).strip() val = s if s in self.SHLEX_IGNORE else shlex_quote(s).strip()
base_parts.append(val) base_parts.append(val)
return bits + base_parts return bits + base_parts
# return bits + [shlex_quote(s).strip() for s in base]

@ -146,8 +146,10 @@ SUDO_OPTIONS = [
class OptionParser(optparse.OptionParser): class OptionParser(optparse.OptionParser):
def help(self): def help(self):
self.exit() self.exit()
def error(self, msg): def error(self, msg):
self.exit(msg=msg) self.exit(msg=msg)
def exit(self, status=0, msg=None): def exit(self, status=0, msg=None):
msg = 'sudo: ' + (msg or 'unsupported option') msg = 'sudo: ' + (msg or 'unsupported option')
raise mitogen.core.StreamError(msg) raise mitogen.core.StreamError(msg)
@ -167,7 +169,7 @@ def parse_sudo_flags(args):
parser = make_sudo_parser() parser = make_sudo_parser()
opts, args = parser.parse_args(args) opts, args = parser.parse_args(args)
if len(args): if len(args):
raise mitogen.core.StreamError('unsupported sudo arguments:'+str(args)) raise mitogen.core.StreamError('unsupported sudo arguments:' + str(args))
return opts return opts
@ -249,6 +251,12 @@ class Connection(mitogen.parent.Connection):
} }
child_is_immediate_subprocess = False child_is_immediate_subprocess = False
# sudo can't run bash builtins; if a supported builtin is detected
# append `-s` to the sudo command to start a shell as the desired user
SUPPORTED_BASH_BUILTINS = [
"source"
]
def _get_name(self): def _get_name(self):
return u'sudo.' + mitogen.core.to_text(self.options.username) return u'sudo.' + mitogen.core.to_text(self.options.username)
@ -256,6 +264,8 @@ class Connection(mitogen.parent.Connection):
# Note: sudo did not introduce long-format option processing until July # Note: sudo did not introduce long-format option processing until July
# 2013, so even though we parse long-format options, supply short-form # 2013, so even though we parse long-format options, supply short-form
# to the sudo command. # to the sudo command.
boot_cmd = super(Connection, self).get_boot_command()
bits = [self.options.sudo_path, '-u', self.options.username] bits = [self.options.sudo_path, '-u', self.options.username]
if self.options.preserve_env: if self.options.preserve_env:
bits += ['-E'] bits += ['-E']
@ -267,5 +277,9 @@ class Connection(mitogen.parent.Connection):
bits += ['-r', self.options.selinux_role] bits += ['-r', self.options.selinux_role]
if self.options.selinux_type: if self.options.selinux_type:
bits += ['-t', self.options.selinux_type] bits += ['-t', self.options.selinux_type]
for builtin in self.SUPPORTED_BASH_BUILTINS:
if builtin in boot_cmd:
bits += ['-s']
break
return bits + ['--'] + super(Connection, self).get_boot_command() return bits + ['--'] + boot_cmd

Loading…
Cancel
Save