Merge pull request #4733 from sivel/4323-sudo-pass

Add ansible_sudo_pass hostvar support. Fixes #4323
This commit is contained in:
jctanner 2013-11-05 15:01:19 -08:00
commit 8d9b53b445
7 changed files with 20 additions and 12 deletions

View file

@ -190,6 +190,8 @@ mentioned::
The default ssh user name to use.
ansible_ssh_pass
The ssh password to use (this is insecure, we strongly recommend using --ask-pass or SSH keys)
ansible_sudo_pass
The sudo password to use (this is insecure, we strongly recommend using --ask-pass or SSH keys)
ansible_connection
Connection type of the host. Candidates are local, ssh or paramiko. The default is paramiko before Ansible 1.2, and 'smart' afterwards which detects whether usage of 'ssh' would be feasible based on whether ControlPersist is supported.
ansible_ssh_private_key_file

View file

@ -585,6 +585,7 @@ class Runner(object):
actual_pass = inject.get('ansible_ssh_pass', self.remote_pass)
actual_transport = inject.get('ansible_connection', self.transport)
actual_private_key_file = inject.get('ansible_ssh_private_key_file', self.private_key_file)
self.sudo_pass = inject.get('ansible_sudo_pass', self.sudo_pass)
if self.accelerate and actual_transport != 'local':
#Fix to get the inventory name of the host to accelerate plugin
@ -624,6 +625,7 @@ class Runner(object):
actual_pass = delegate_info.get('ansible_ssh_pass', actual_pass)
actual_private_key_file = delegate_info.get('ansible_ssh_private_key_file', self.private_key_file)
actual_transport = delegate_info.get('ansible_connection', self.transport)
self.sudo_pass = delegate_info.get('ansible_sudo_pass', self.sudo_pass)
for i in delegate_info:
if i.startswith("ansible_") and i.endswith("_interpreter"):
inject[i] = delegate_info[i]

View file

@ -165,7 +165,7 @@ class Connection(object):
executable = constants.DEFAULT_EXECUTABLE
if self.runner.sudo and sudoable and sudo_user:
cmd, prompt = utils.make_sudo_cmd(sudo_user, executable, cmd)
cmd, prompt, success_key = utils.make_sudo_cmd(sudo_user, executable, cmd)
vvv("EXEC COMMAND %s" % cmd)

View file

@ -49,7 +49,7 @@ class Connection(object):
else:
local_cmd = cmd
else:
local_cmd, prompt = utils.make_sudo_cmd(sudo_user, executable, cmd)
local_cmd, prompt, success_key = utils.make_sudo_cmd(sudo_user, executable, cmd)
vvv("EXEC %s" % (local_cmd), host=self.host)
p = subprocess.Popen(local_cmd, shell=isinstance(local_cmd, basestring),
@ -63,7 +63,7 @@ class Connection(object):
fcntl.fcntl(p.stderr, fcntl.F_SETFL,
fcntl.fcntl(p.stderr, fcntl.F_GETFL) | os.O_NONBLOCK)
sudo_output = ''
while not sudo_output.endswith(prompt):
while not sudo_output.endswith(prompt) and success_key not in sudo_output:
rfd, wfd, efd = select.select([p.stdout, p.stderr], [],
[p.stdout, p.stderr], self.runner.timeout)
if p.stdout in rfd:
@ -77,7 +77,8 @@ class Connection(object):
stdout, stderr = p.communicate()
raise errors.AnsibleError('sudo output closed while waiting for password prompt:\n' + sudo_output)
sudo_output += chunk
p.stdin.write(self.runner.sudo_pass + '\n')
if success_key not in sudo_output:
p.stdin.write(self.runner.sudo_pass + '\n')
fcntl.fcntl(p.stdout, fcntl.F_SETFL, fcntl.fcntl(p.stdout, fcntl.F_GETFL) & ~os.O_NONBLOCK)
fcntl.fcntl(p.stderr, fcntl.F_SETFL, fcntl.fcntl(p.stderr, fcntl.F_GETFL) & ~os.O_NONBLOCK)

View file

@ -202,13 +202,13 @@ class Connection(object):
chan.get_pty(term=os.getenv('TERM', 'vt100'),
width=int(os.getenv('COLUMNS', 0)),
height=int(os.getenv('LINES', 0)))
shcmd, prompt = utils.make_sudo_cmd(sudo_user, executable, cmd)
shcmd, prompt, success_key = utils.make_sudo_cmd(sudo_user, executable, cmd)
vvv("EXEC %s" % shcmd, host=self.host)
sudo_output = ''
try:
chan.exec_command(shcmd)
if self.runner.sudo_pass:
while not sudo_output.endswith(prompt):
while not sudo_output.endswith(prompt) and success_key not in sudo_output:
chunk = chan.recv(bufsize)
if not chunk:
if 'unknown user' in sudo_output:
@ -218,7 +218,8 @@ class Connection(object):
raise errors.AnsibleError('ssh connection ' +
'closed waiting for password prompt')
sudo_output += chunk
chan.sendall(self.runner.sudo_pass + '\n')
if success_key not in sudo_output:
chan.sendall(self.runner.sudo_pass + '\n')
except socket.timeout:
raise errors.AnsibleError('ssh timed out waiting for sudo.\n' + sudo_output)

View file

@ -165,7 +165,7 @@ class Connection(object):
else:
ssh_cmd.append(cmd)
else:
sudocmd, prompt = utils.make_sudo_cmd(sudo_user, executable, cmd)
sudocmd, prompt, success_key = utils.make_sudo_cmd(sudo_user, executable, cmd)
ssh_cmd.append(sudocmd)
vvv("EXEC %s" % ssh_cmd, host=self.host)
@ -198,7 +198,7 @@ class Connection(object):
fcntl.fcntl(p.stdout, fcntl.F_SETFL,
fcntl.fcntl(p.stdout, fcntl.F_GETFL) | os.O_NONBLOCK)
sudo_output = ''
while not sudo_output.endswith(prompt):
while not sudo_output.endswith(prompt) and success_key not in sudo_output:
rfd, wfd, efd = select.select([p.stdout], [],
[p.stdout], self.runner.timeout)
if p.stdout in rfd:
@ -209,7 +209,8 @@ class Connection(object):
else:
stdout = p.communicate()
raise errors.AnsibleError('ssh connection error waiting for sudo password prompt')
stdin.write(self.runner.sudo_pass + '\n')
if success_key not in sudo_output:
stdin.write(self.runner.sudo_pass + '\n')
fcntl.fcntl(p.stdout, fcntl.F_SETFL, fcntl.fcntl(p.stdout, fcntl.F_GETFL) & ~os.O_NONBLOCK)
# We can't use p.communicate here because the ControlMaster may have stdout open as well

View file

@ -849,10 +849,11 @@ def make_sudo_cmd(sudo_user, executable, cmd):
# the -p option.
randbits = ''.join(chr(random.randint(ord('a'), ord('z'))) for x in xrange(32))
prompt = '[sudo via ansible, key=%s] password: ' % randbits
success_key = 'SUDO-SUCCESS-%s' % randbits
sudocmd = '%s -k && %s %s -S -p "%s" -u %s %s -c %s' % (
C.DEFAULT_SUDO_EXE, C.DEFAULT_SUDO_EXE, C.DEFAULT_SUDO_FLAGS,
prompt, sudo_user, executable or '$SHELL', pipes.quote(cmd))
return ('/bin/sh -c ' + pipes.quote(sudocmd), prompt)
prompt, sudo_user, executable or '$SHELL', pipes.quote('echo %s; %s' % (success_key, cmd)))
return ('/bin/sh -c ' + pipes.quote(sudocmd), prompt, success_key)
_TO_UNICODE_TYPES = (unicode, type(None))