add some apprehension to the sudo exec module

- raise an error if sudo.salt_call is called directly, which would be an
  inductively divergent condition

- return the actual error message (along with some debug logging) when
  the command fails rather than an unhelpful json decode error.

- protect positional args and kwargs to salt-call with a `--` symbol.

- quote the args and kwargs sent to salt-call so they work as expected.

- do not load the sudo exec module if the sudo_user config is unset
This commit is contained in:
Justin Findlay 2015-06-30 01:27:25 -06:00
parent a9269c072a
commit d8f91d4a19

View file

@ -29,7 +29,13 @@ being run on ``sudo_minion``.
'''
# Import python libs
import json
try:
from shlex import quote as _cmd_quote # pylint: disable=E0611
except ImportError:
from pipes import quote as _cmd_quote
# Import salt libs
from salt.exceptions import SaltInvocationError
import salt.utils
import salt.syspaths
@ -37,7 +43,7 @@ __virtualname__ = 'sudo'
def __virtual__():
if salt.utils.which('sudo'):
if salt.utils.which('sudo') and __opts__.get('sudo_user'):
return __virtualname__
return False
@ -58,19 +64,33 @@ def salt_call(runas, fun, *args, **kwargs):
salt '*' test.ping # is run as saltdev user
'''
if fun == 'sudo.salt_call':
__context__['retcode'] = 1
raise SaltInvocationError('sudo.salt_call is not designed to be run '
'directly, but is used by the minion when '
'the sudo_user config is set.')
cmd = ['sudo',
'-u', runas,
'salt-call',
'--out', 'json',
'--metadata',
'-c', salt.syspaths.CONFIG_DIR,
'--',
fun]
for arg in args:
cmd.append(arg)
cmd.append(_cmd_quote(arg))
for key in kwargs:
cmd.append('{0}={1}'.format(key, kwargs[key]))
cmd_ret = __salt__['cmd.run_all'](cmd, python_shell=False)
cmd_meta = json.loads(cmd_ret['stdout'])['local']
ret = cmd_meta['return']
__context__['retcode'] = cmd_meta.get('retcode', 0)
cmd.append(_cmd_quote('{0}={1}'.format(key, kwargs[key])))
cmd_ret = __salt__['cmd.run_all'](cmd, use_vt=True, python_shell=False)
if cmd_ret['retcode'] == 0:
cmd_meta = json.loads(cmd_ret['stdout'])['local']
ret = cmd_meta['return']
__context__['retcode'] = cmd_meta.get('retcode', 0)
else:
ret = cmd_ret['stderr']
__context__['retcode'] = cmd_ret['retcode']
return ret