Add support for specifying sudo passwords to both ansible & playbook. Nopasswd sudo is no longer required.

This commit is contained in:
Michael DeHaan 2012-04-13 19:06:11 -04:00
parent 788d2bf8d1
commit f2465e0571
7 changed files with 45 additions and 13 deletions

View file

@ -72,7 +72,9 @@ class Cli(object):
sshpass = None
if options.ask_pass:
sshpass = getpass.getpass(prompt="SSH password: ")
if options.ask_sudo_pass:
sudopass = getpass.getpass(prompt="sudo password: ")
if options.tree:
utils.prepare_writeable_dir(options.tree)
@ -86,7 +88,8 @@ class Cli(object):
host_list=options.inventory, timeout=options.timeout,
remote_port=options.remote_port, forks=options.forks,
background=options.seconds, pattern=pattern,
callbacks=self.callbacks, sudo=options.sudo, verbose=True,
callbacks=self.callbacks, sudo=options.sudo,
sudo_pass=sudopass, verbose=True,
transport=options.connection, debug=options.debug
)
return (runner, runner.run())

View file

@ -46,8 +46,11 @@ def main(args):
return 1
sshpass = None
sudopass = None
if options.ask_pass:
sshpass = getpass.getpass(prompt="SSH password: ")
if options.ask_sudo_pass:
sudopass = getpass.getpass(prompt="sudo password: ")
override_hosts = None
if options.override_hosts:
override_hosts = options.override_hosts.split(",")
@ -66,7 +69,8 @@ def main(args):
forks=options.forks, debug=options.debug, verbose=True,
remote_pass=sshpass, remote_port=options.remote_port,
callbacks=playbook_cb, runner_callbacks=runner_cb, stats=stats,
timeout=options.timeout, transport=options.connection
timeout=options.timeout, transport=options.connection,
sudo_pass=sudopass
)
try:

View file

@ -112,15 +112,26 @@ class ParamikoConnection(object):
sudo_chan = ssh_sudo.invoke_shell()
sudo_chan.send("sudo -s\n")
# FIXME: using sudo with a password adds more delay, someone may wish
# to optimize to see when the channel is actually ready
if self.runner.sudo_pass:
time.sleep(0.1) # this is conservative
sudo_chan.send("%s\n" % self.runner.sudo_pass)
time.sleep(0.1)
# to avoid ssh expect logic, redirect output to file and move the
# file when we are done with it...
sudo_chan.send("(%s >%s_pre 2>/dev/null ; mv %s_pre %s) &\n" % (cmd, result_file, result_file, result_file))
# FIXME: someone may wish to optimize to not background the launch, and tell when the command
# returns, removing the time.sleep(1) here
time.sleep(1)
sudo_chan.close()
self.ssh = self._get_conn()
# now load the results of the JSON execution...
# FIXME: really need some timeout logic here
# though it doesn't make since to use the SSH timeout or impose any particular
# limit. Upgrades welcome.
sftp = self.ssh.open_sftp()
while True:
# print "waiting on %s" % result_file
@ -181,6 +192,12 @@ class LocalConnection(object):
''' run a command on the local host '''
if self.runner.sudo and sudoable:
cmd = "sudo -s %s" % cmd
if self.runner.sudo_pass:
# NOTE: if someone wants to add sudo w/ password to the local connection type, they are welcome
# to do so. The primary usage of the local connection is for crontab and kickstart usage however
# so this doesn't seem to be a huge priority
raise errors.AnsibleError("sudo with password is presently only supported on the paramiko (SSH) connection type")
p = subprocess.Popen(cmd, shell=True, stdin=None,
stdout=subprocess.PIPE, stderr=subprocess.PIPE)
stdout, stderr = p.communicate()

View file

@ -19,11 +19,11 @@
import os
# control side (aka 'overlord')
DEFAULT_HOST_LIST = os.environ.get('ANSIBLE_HOSTS',
'/etc/ansible/hosts')
'/etc/ansible/hosts')
DEFAULT_MODULE_PATH = os.environ.get('ANSIBLE_LIBRARY',
'/usr/share/ansible')
'/usr/share/ansible')
DEFAULT_MODULE_NAME = 'command'
DEFAULT_PATTERN = '*'
DEFAULT_FORKS = 5
@ -32,6 +32,8 @@ DEFAULT_TIMEOUT = 10
DEFAULT_POLL_INTERVAL = 15
DEFAULT_REMOTE_USER = 'root'
DEFAULT_REMOTE_PASS = None
DEFAULT_SUDO_PASS = None
DEFAULT_REMOTE_PORT = 22
DEFAULT_TRANSPORT = 'paramiko'
DEFAULT_TRANSPORT_OPTS = ['local', 'paramiko']

View file

@ -54,6 +54,7 @@ class PlayBook(object):
timeout = C.DEFAULT_TIMEOUT,
remote_user = C.DEFAULT_REMOTE_USER,
remote_pass = C.DEFAULT_REMOTE_PASS,
sudo_pass = C.DEFAULT_SUDO_PASS,
remote_port = C.DEFAULT_REMOTE_PORT,
transport = C.DEFAULT_TRANSPORT,
override_hosts = None,
@ -82,9 +83,10 @@ class PlayBook(object):
self.override_hosts = override_hosts
self.extra_vars = extra_vars
self.stats = stats
self.sudo_pass = sudo_pass
self.basedir = os.path.dirname(playbook)
self.playbook = self._parse_playbook(playbook)
self.basedir = os.path.dirname(playbook)
self.playbook = self._parse_playbook(playbook)
self.host_list, self.groups = ansible.runner.Runner.parse_hosts(
host_list, override_hosts=self.override_hosts, extra_vars=self.extra_vars)
@ -288,7 +290,7 @@ class PlayBook(object):
setup_cache=SETUP_CACHE, basedir=self.basedir,
conditional=only_if, callbacks=self.runner_callbacks,
extra_vars=self.extra_vars, debug=self.debug, sudo=sudo,
transport=transport
transport=transport, sudo_pass=self.sudo_pass
)
if async_seconds == 0:
@ -450,7 +452,7 @@ class PlayBook(object):
remote_pass=self.remote_pass, remote_port=self.remote_port,
setup_cache=SETUP_CACHE,
callbacks=self.runner_callbacks, sudo=sudo, debug=self.debug,
transport=transport,
transport=transport, sudo_pass=self.sudo_pass
).run()
self.stats.compute(setup_results, setup=True)

View file

@ -73,8 +73,9 @@ class Runner(object):
module_name=C.DEFAULT_MODULE_NAME, module_args=C.DEFAULT_MODULE_ARGS,
forks=C.DEFAULT_FORKS, timeout=C.DEFAULT_TIMEOUT, pattern=C.DEFAULT_PATTERN,
remote_user=C.DEFAULT_REMOTE_USER, remote_pass=C.DEFAULT_REMOTE_PASS,
remote_port=C.DEFAULT_REMOTE_PORT, background=0, basedir=None, setup_cache=None,
transport=C.DEFAULT_TRANSPORT, conditional='True', groups={}, callbacks=None, verbose=False,
sudo_pass=C.DEFAULT_SUDO_PASS, remote_port=C.DEFAULT_REMOTE_PORT, background=0,
basedir=None, setup_cache=None, transport=C.DEFAULT_TRANSPORT,
conditional='True', groups={}, callbacks=None, verbose=False,
debug=False, sudo=False, extra_vars=None, module_vars=None):
if setup_cache is None:
@ -115,6 +116,7 @@ class Runner(object):
self.background = background
self.basedir = basedir
self.sudo = sudo
self.sudo_pass = sudo_pass
euid = pwd.getpwuid(os.geteuid())[0]
if self.transport == 'local' and self.remote_user != euid:

View file

@ -290,8 +290,10 @@ def base_parser(constants=C, usage="", output_opts=False, runas_opts=False, asyn
parser.add_option('-i', '--inventory-file', dest='inventory',
help="specify inventory host file (default=%s)" % constants.DEFAULT_HOST_LIST,
default=constants.DEFAULT_HOST_LIST)
parser.add_option('-k', '--ask-pass', default=False, action='store_true',
parser.add_option('-k', '--ask-pass', default=False, dest='ask_pass', action='store_true',
help='ask for SSH password')
parser.add_option('-K', '--ask-sudo-pass', default=False, dest='ask_sudo_pass', action='store_true',
help='ask for sudo password')
parser.add_option('-M', '--module-path', dest='module_path',
help="specify path to module library (default=%s)" % constants.DEFAULT_MODULE_PATH,
default=constants.DEFAULT_MODULE_PATH)