Make connection plugins use password from config (#69670)

Change:
Rather than connection plugins directly accessing play_context and pulling
the password from there, have them pull it from the config system, and
have TaskExecutor store it there for now.

Internally, it still routes through play_context for now, but this is
the first step away from that.

Test Plan:
- Local test with `ansible -c ssh`
- grep -R play_context.pass lib/ansible/plugins/connection/
- CI

Signed-off-by: Rick Elrod <rick@elrod.me>
pull/69732/head
Rick Elrod 6 years ago committed by GitHub
parent 564907d8ac
commit 8b6c02fc69
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -1010,6 +1010,13 @@ class TaskExecutor:
task_keys = self._task.dump_attrs() task_keys = self._task.dump_attrs()
if self._play_context.password:
# The connection password is threaded through the play_context for
# now. This is something we ultimately want to avoid, but the first
# step is to get connection plugins pulling the password through the
# config system instead of directly accessing play_context.
task_keys['password'] = self._play_context.password
# set options with 'templated vars' specific to this plugin and dependent ones # set options with 'templated vars' specific to this plugin and dependent ones
self._connection.set_options(task_keys=task_keys, var_options=options) self._connection.set_options(task_keys=task_keys, var_options=options)
varnames.extend(self._set_plugin_options('shell', variables, templar, task_keys)) varnames.extend(self._set_plugin_options('shell', variables, templar, task_keys))

@ -326,7 +326,7 @@ class Connection(ConnectionBase):
allow_agent = True allow_agent = True
if self._play_context.password is not None: if self.get_option('password') is not None:
allow_agent = False allow_agent = False
try: try:
@ -344,7 +344,7 @@ class Connection(ConnectionBase):
allow_agent=allow_agent, allow_agent=allow_agent,
look_for_keys=self.get_option('look_for_keys'), look_for_keys=self.get_option('look_for_keys'),
key_filename=key_filename, key_filename=key_filename,
password=self._play_context.password, password=self.get_option('password'),
timeout=self._play_context.timeout, timeout=self._play_context.timeout,
port=port, port=port,
**ssh_connect_kwargs **ssh_connect_kwargs

@ -39,6 +39,7 @@ options:
- name: ansible_password - name: ansible_password
- name: ansible_winrm_pass - name: ansible_winrm_pass
- name: ansible_winrm_password - name: ansible_winrm_password
aliases: [ password ]
port: port:
description: description:
- The port for PSRP to connect on the remote target. - The port for PSRP to connect on the remote target.

@ -399,7 +399,7 @@ def _ssh_retry(func):
cmd_summary = u"%s..." % to_text(args[0]) cmd_summary = u"%s..." % to_text(args[0])
for attempt in range(remaining_tries): for attempt in range(remaining_tries):
cmd = args[0] cmd = args[0]
if attempt != 0 and self._play_context.password and isinstance(cmd, list): if attempt != 0 and self.get_option('password') and isinstance(cmd, list):
# If this is a retry, the fd/pipe for sshpass is closed, and we need a new one # If this is a retry, the fd/pipe for sshpass is closed, and we need a new one
self.sshpass_pipe = os.pipe() self.sshpass_pipe = os.pipe()
cmd[1] = b'-d' + to_bytes(self.sshpass_pipe[0], nonstring='simplerepr', errors='surrogate_or_strict') cmd[1] = b'-d' + to_bytes(self.sshpass_pipe[0], nonstring='simplerepr', errors='surrogate_or_strict')
@ -417,7 +417,7 @@ def _ssh_retry(func):
except (AnsibleControlPersistBrokenPipeError): except (AnsibleControlPersistBrokenPipeError):
# Retry one more time because of the ControlPersist broken pipe (see #16731) # Retry one more time because of the ControlPersist broken pipe (see #16731)
cmd = args[0] cmd = args[0]
if self._play_context.password and isinstance(cmd, list): if self.get_option('password') and isinstance(cmd, list):
# This is a retry, so the fd/pipe for sshpass is closed, and we need a new one # This is a retry, so the fd/pipe for sshpass is closed, and we need a new one
self.sshpass_pipe = os.pipe() self.sshpass_pipe = os.pipe()
cmd[1] = b'-d' + to_bytes(self.sshpass_pipe[0], nonstring='simplerepr', errors='surrogate_or_strict') cmd[1] = b'-d' + to_bytes(self.sshpass_pipe[0], nonstring='simplerepr', errors='surrogate_or_strict')
@ -572,7 +572,7 @@ class Connection(ConnectionBase):
# If we want to use password authentication, we have to set up a pipe to # If we want to use password authentication, we have to set up a pipe to
# write the password to sshpass. # write the password to sshpass.
if self._play_context.password: if self.get_option('password'):
if not self._sshpass_available(): if not self._sshpass_available():
raise AnsibleError("to use the 'ssh' connection type with passwords, you must install the sshpass program") raise AnsibleError("to use the 'ssh' connection type with passwords, you must install the sshpass program")
@ -597,7 +597,7 @@ class Connection(ConnectionBase):
# sftp batch mode does not prompt for passwords so it must be disabled # sftp batch mode does not prompt for passwords so it must be disabled
# if not using controlpersist and using sshpass # if not using controlpersist and using sshpass
if binary == 'sftp' and C.DEFAULT_SFTP_BATCH_MODE: if binary == 'sftp' and C.DEFAULT_SFTP_BATCH_MODE:
if self._play_context.password: if self.get_option('password'):
b_args = [b'-o', b'BatchMode=no'] b_args = [b'-o', b'BatchMode=no']
self._add_args(b_command, b_args, u'disable batch mode for sshpass') self._add_args(b_command, b_args, u'disable batch mode for sshpass')
b_command += [b'-b', b'-'] b_command += [b'-b', b'-']
@ -631,7 +631,7 @@ class Connection(ConnectionBase):
b_args = (b"-o", b'IdentityFile="' + to_bytes(os.path.expanduser(key), errors='surrogate_or_strict') + b'"') b_args = (b"-o", b'IdentityFile="' + to_bytes(os.path.expanduser(key), errors='surrogate_or_strict') + b'"')
self._add_args(b_command, b_args, u"ANSIBLE_PRIVATE_KEY_FILE/private_key_file/ansible_ssh_private_key_file set") self._add_args(b_command, b_args, u"ANSIBLE_PRIVATE_KEY_FILE/private_key_file/ansible_ssh_private_key_file set")
if not self._play_context.password: if not self.get_option('password'):
self._add_args( self._add_args(
b_command, ( b_command, (
b"-o", b"KbdInteractiveAuthentication=no", b"-o", b"KbdInteractiveAuthentication=no",
@ -803,7 +803,7 @@ class Connection(ConnectionBase):
try: try:
# Make sure stdin is a proper pty to avoid tcgetattr errors # Make sure stdin is a proper pty to avoid tcgetattr errors
master, slave = pty.openpty() master, slave = pty.openpty()
if PY3 and self._play_context.password: if PY3 and self.get_option('password'):
# pylint: disable=unexpected-keyword-arg # pylint: disable=unexpected-keyword-arg
p = subprocess.Popen(cmd, stdin=slave, stdout=subprocess.PIPE, stderr=subprocess.PIPE, pass_fds=self.sshpass_pipe) p = subprocess.Popen(cmd, stdin=slave, stdout=subprocess.PIPE, stderr=subprocess.PIPE, pass_fds=self.sshpass_pipe)
else: else:
@ -814,7 +814,7 @@ class Connection(ConnectionBase):
p = None p = None
if not p: if not p:
if PY3 and self._play_context.password: if PY3 and self.get_option('password'):
# pylint: disable=unexpected-keyword-arg # pylint: disable=unexpected-keyword-arg
p = subprocess.Popen(cmd, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, pass_fds=self.sshpass_pipe) p = subprocess.Popen(cmd, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, pass_fds=self.sshpass_pipe)
else: else:
@ -824,10 +824,10 @@ class Connection(ConnectionBase):
# If we are using SSH password authentication, write the password into # If we are using SSH password authentication, write the password into
# the pipe we opened in _build_command. # the pipe we opened in _build_command.
if self._play_context.password: if self.get_option('password'):
os.close(self.sshpass_pipe[0]) os.close(self.sshpass_pipe[0])
try: try:
os.write(self.sshpass_pipe[1], to_bytes(self._play_context.password) + b'\n') os.write(self.sshpass_pipe[1], to_bytes(self.get_option('password')) + b'\n')
except OSError as e: except OSError as e:
# Ignore broken pipe errors if the sshpass process has exited. # Ignore broken pipe errors if the sshpass process has exited.
if e.errno != errno.EPIPE or p.poll() is None: if e.errno != errno.EPIPE or p.poll() is None:

Loading…
Cancel
Save