Add support for specifying sudo passwords to both ansible & playbook. Nopasswd sudo is no longer required.
This commit is contained in:
parent
788d2bf8d1
commit
f2465e0571
7 changed files with 45 additions and 13 deletions
|
@ -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())
|
||||
|
|
|
@ -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:
|
||||
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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']
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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)
|
||||
|
|
Loading…
Reference in a new issue