From d0993e991849d1e3529b14544a8941ec96126c1b Mon Sep 17 00:00:00 2001 From: "michael.dsilva" Date: Fri, 23 Aug 2024 09:56:33 +1000 Subject: [PATCH 1/3] allow ansible_ssh_password as it is documented as valid in current ansible documentation Co-authored-by: Alex Willmer --- ansible_mitogen/transport_config.py | 1 + docs/ansible_detailed.rst | 6 ++++-- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/ansible_mitogen/transport_config.py b/ansible_mitogen/transport_config.py index 39a4b604..39df3f6a 100644 --- a/ansible_mitogen/transport_config.py +++ b/ansible_mitogen/transport_config.py @@ -678,6 +678,7 @@ class MitogenViaSpec(Spec): def password(self): return optional_secret( + self._host_vars.get('ansible_ssh_password') or self._host_vars.get('ansible_ssh_pass') or self._host_vars.get('ansible_password') ) diff --git a/docs/ansible_detailed.rst b/docs/ansible_detailed.rst index fed347c8..d818edd7 100644 --- a/docs/ansible_detailed.rst +++ b/docs/ansible_detailed.rst @@ -306,7 +306,8 @@ container. * Intermediary machines cannot use login and become passwords that were supplied to Ansible interactively. If an intermediary requires a password, it must be supplied via ``ansible_ssh_pass``, - ``ansible_password``, or ``ansible_become_pass`` inventory variables. + ``ansible_ssh_password``, ``ansible_password``, or + ``ansible_become_pass`` inventory variables. * Automatic tunnelling of SSH-dependent actions, such as the ``synchronize`` module, is not yet supported. This will be addressed in a @@ -1011,7 +1012,8 @@ Like the :ans:conn:`ssh` except connection delegation is supported. * ``ansible_port``, ``ssh_port`` * ``ansible_ssh_executable``, ``ssh_executable`` * ``ansible_ssh_private_key_file`` -* ``ansible_ssh_pass``, ``ansible_password`` (default: assume passwordless) +* ``ansible_ssh_pass``, ``ansible_ssh_password``, ``ansible_password`` + (default: assume passwordless) * ``ssh_args``, ``ssh_common_args``, ``ssh_extra_args`` * ``mitogen_mask_remote_name``: if :data:`True`, mask the identity of the Ansible controller process on remote machines. To simplify diagnostics, From 3bdd3e237a95ae8a88681a46bfe97ccc4ed1204b Mon Sep 17 00:00:00 2001 From: Alex Willmer Date: Wed, 4 Sep 2024 10:53:18 +0100 Subject: [PATCH 2/3] tests: Coverage of support for ansible_ssh_password variable --- docs/contributors.rst | 1 + tests/ansible/integration/ssh/password.yml | 21 ++++++++++++++++++--- 2 files changed, 19 insertions(+), 3 deletions(-) diff --git a/docs/contributors.rst b/docs/contributors.rst index e40607a0..4e9e58bd 100644 --- a/docs/contributors.rst +++ b/docs/contributors.rst @@ -132,6 +132,7 @@ sponsorship and outstanding future-thinking of its early adopters.
  • Lewis Bellwood — Happy to be apart of a great project.
  • luto
  • Mayeu a.k.a Matthieu Maury
  • +
  • Michael D'Silva
  • @nathanhruby
  • Orion Poplawski
  • Philippe Kueck
  • diff --git a/tests/ansible/integration/ssh/password.yml b/tests/ansible/integration/ssh/password.yml index cf9396e0..9b7dcf8a 100644 --- a/tests/ansible/integration/ssh/password.yml +++ b/tests/ansible/integration/ssh/password.yml @@ -16,6 +16,12 @@ ansible_ssh_pass: user1_password ping: + - meta: reset_connection + - name: ansible_ssh_password + vars: + ansible_ssh_password: user1_password + ping: + - meta: reset_connection - name: absent password should fail ping: @@ -34,13 +40,22 @@ ansible_password: wrong ansible_ssh_pass: user1_password - # Tests that ansible_ssh_pass has priority over ansible_password + - meta: reset_connection + - name: Highest priority password variable should override all others + vars: + ansible_password: wrong + ansible_ssh_pass: wrong + ansible_ssh_password: user1_password + ping: + + # Tests that ansible_ssh_password has priority over others # and that a wrong password causes a target to be marked unreachable. - meta: reset_connection - - name: ansible_password should not override + - name: Lower priority password variables should not override vars: ansible_password: user1_password - ansible_ssh_pass: wrong + ansible_ssh_pass: user1_password + ansible_ssh_password: wrong ping: ignore_errors: true ignore_unreachable: true From 551690ee1dd47aee18a448202f8ae8b9c6f016c1 Mon Sep 17 00:00:00 2001 From: Alex Willmer Date: Mon, 16 Sep 2024 00:32:29 +0100 Subject: [PATCH 3/3] ansible_mitogen: Handle templated connection passwords and ansible_ssh_password This switches `ansible_mitogen.transport_config.PlayContextSpec.password()` to Ansible's plugin option framework. As a result - The relatively recent `ansible_ssh_password` variable is now respected. - The SSH connection password can be templated and specified as a play variable. Task variables will probably also work, but testing was blocked by #1132. There is a chance this change will cause a regression in another connection plugin (e.g. mitogen_docker), but nothing turned up in the test suite. I intend ot migrate other connection configuration to `ansible_mitogen.transport_config.PlayContextSpec._connect_option()`, the next candidate is the remote port. fixes #1106 --- .../plugins/connection/mitogen_ssh.py | 27 +++++-------------- ansible_mitogen/transport_config.py | 13 ++++++++- docs/changelog.rst | 2 ++ tests/ansible/hosts/default.hosts | 14 ++++++++++ tests/ansible/integration/ssh/all.yml | 2 ++ .../integration/ssh/templated_by_inv.yml | 7 +++++ .../ssh/templated_by_play_taskvar.yml | 10 +++++++ tests/ansible/templates/test-targets.j2 | 19 +++++++++++++ 8 files changed, 72 insertions(+), 22 deletions(-) create mode 100644 tests/ansible/integration/ssh/templated_by_inv.yml create mode 100644 tests/ansible/integration/ssh/templated_by_play_taskvar.yml diff --git a/ansible_mitogen/plugins/connection/mitogen_ssh.py b/ansible_mitogen/plugins/connection/mitogen_ssh.py index 75f2d42f..f6a27a6e 100644 --- a/ansible_mitogen/plugins/connection/mitogen_ssh.py +++ b/ansible_mitogen/plugins/connection/mitogen_ssh.py @@ -32,35 +32,20 @@ __metaclass__ = type import os.path import sys +from ansible.plugins.connection.ssh import ( + DOCUMENTATION as _ansible_ssh_DOCUMENTATION, +) + DOCUMENTATION = """ + name: mitogen_ssh author: David Wilson - connection: mitogen_ssh short_description: Connect over SSH via Mitogen description: - This connects using an OpenSSH client controlled by the Mitogen for Ansible extension. It accepts every option the vanilla ssh plugin accepts. - version_added: "2.5" options: - ssh_args: - type: str - vars: - - name: ssh_args - - name: ansible_ssh_args - - name: ansible_mitogen_ssh_args - ssh_common_args: - type: str - vars: - - name: ssh_args - - name: ansible_ssh_common_args - - name: ansible_mitogen_ssh_common_args - ssh_extra_args: - type: str - vars: - - name: ssh_args - - name: ansible_ssh_extra_args - - name: ansible_mitogen_ssh_extra_args -""" +""" + _ansible_ssh_DOCUMENTATION.partition('options:\n')[2] try: import ansible_mitogen diff --git a/ansible_mitogen/transport_config.py b/ansible_mitogen/transport_config.py index 39df3f6a..a3336365 100644 --- a/ansible_mitogen/transport_config.py +++ b/ansible_mitogen/transport_config.py @@ -62,6 +62,7 @@ from __future__ import unicode_literals __metaclass__ = type import abc +import logging import os import ansible.utils.shlex import ansible.constants as C @@ -74,6 +75,9 @@ from ansible.module_utils.parsing.convert_bool import boolean import mitogen.core +LOG = logging.getLogger(__name__) + + def run_interpreter_discovery_if_necessary(s, task_vars, action, rediscover_python): """ Triggers ansible python interpreter discovery if requested. @@ -412,6 +416,13 @@ class PlayContextSpec(Spec): # used to run interpreter discovery self._action = connection._action + def _connection_option(self, name): + try: + return self._connection.get_option(name, hostvars=self._task_vars) + except KeyError: + LOG.debug('Used PlayContext fallback for option=%r', name) + return getattr(self._play_context, name) + def transport(self): return self._transport @@ -449,7 +460,7 @@ class PlayContextSpec(Spec): return optional_secret(become_pass) def password(self): - return optional_secret(self._play_context.password) + return optional_secret(self._connection_option('password')) def port(self): return self._play_context.port diff --git a/docs/changelog.rst b/docs/changelog.rst index 0b2875fa..25e3820c 100644 --- a/docs/changelog.rst +++ b/docs/changelog.rst @@ -21,6 +21,8 @@ To avail of fixes in an unreleased version, please download a ZIP file Unreleased ---------- +* :gh:issue:`1106` :mod:`ansible_mitogen`: Support for `ansible_ssh_password` + connection variable, and templated SSH connection password. v0.3.11 (2024-10-30) diff --git a/tests/ansible/hosts/default.hosts b/tests/ansible/hosts/default.hosts index adc271e2..8ed80787 100644 --- a/tests/ansible/hosts/default.hosts +++ b/tests/ansible/hosts/default.hosts @@ -19,3 +19,17 @@ ssh-common-args ansible_host=localhost ansible_user="{{ lookup('pipe', 'whoami') [issue905:vars] ansible_ssh_common_args=-o PermitLocalCommand=yes -o LocalCommand="touch {{ ssh_args_canary_file }}" ssh_args_canary_file=/tmp/ssh_args_{{ inventory_hostname }} + +[tt_targets_bare] +tt-bare + +[tt_targets_bare:vars] +ansible_host=localhost +ansible_user=mitogen__has_sudo_nopw + +[tt_targets_inventory] +tt-password ansible_password="{{ 'has_sudo_nopw_password' | trim }}" + +[tt_targets_inventory:vars] +ansible_host=localhost +ansible_user=mitogen__has_sudo_nopw diff --git a/tests/ansible/integration/ssh/all.yml b/tests/ansible/integration/ssh/all.yml index 5c16f187..ab400051 100644 --- a/tests/ansible/integration/ssh/all.yml +++ b/tests/ansible/integration/ssh/all.yml @@ -2,4 +2,6 @@ - import_playbook: config.yml - import_playbook: password.yml - import_playbook: timeouts.yml +- import_playbook: templated_by_inv.yml +- import_playbook: templated_by_play_taskvar.yml - import_playbook: variables.yml diff --git a/tests/ansible/integration/ssh/templated_by_inv.yml b/tests/ansible/integration/ssh/templated_by_inv.yml new file mode 100644 index 00000000..686518fd --- /dev/null +++ b/tests/ansible/integration/ssh/templated_by_inv.yml @@ -0,0 +1,7 @@ +- name: integration/ssh/templated_by_inv.yml + hosts: tt_targets_inventory + gather_facts: false + tasks: + - meta: reset_connection + - name: Templated variables in inventory + ping: diff --git a/tests/ansible/integration/ssh/templated_by_play_taskvar.yml b/tests/ansible/integration/ssh/templated_by_play_taskvar.yml new file mode 100644 index 00000000..bc4ef1d8 --- /dev/null +++ b/tests/ansible/integration/ssh/templated_by_play_taskvar.yml @@ -0,0 +1,10 @@ +- name: integration/ssh/templated_by_play_taskvar.yml + hosts: tt_targets_bare + gather_facts: false + vars: + ansible_password: "{{ 'has_sudo_nopw_password' | trim }}" + + tasks: + - meta: reset_connection + - name: Templated variables in play + ping: diff --git a/tests/ansible/templates/test-targets.j2 b/tests/ansible/templates/test-targets.j2 index e2708192..37a0725a 100644 --- a/tests/ansible/templates/test-targets.j2 +++ b/tests/ansible/templates/test-targets.j2 @@ -37,3 +37,22 @@ ansible_user=mitogen__has_sudo_nopw ansible_password=has_sudo_nopw_password ansible_ssh_common_args=-o PermitLocalCommand=yes -o LocalCommand="touch {{ '{{' }} ssh_args_canary_file {{ '}}' }}" ssh_args_canary_file=/tmp/ssh_args_{{ '{{' }} inventory_hostname {{ '}}' }} + +{% set tt = containers[0] %} + +[tt_targets_bare] +tt-bare + +[tt_targets_bare:vars] +ansible_host={{ tt.hostname }} +ansible_port={{ tt.port }} +ansible_python_interpreter={{ tt.python_path }} +ansible_user=mitogen__has_sudo_nopw + +[tt_targets_inventory] +tt-password ansible_password="{{ '{{' }} 'has_sudo_nopw_password' | trim {{ '}}' }}" ansible_port={{ tt.port }} + +[tt_targets_inventory:vars] +ansible_host={{ tt.hostname }} +ansible_python_interpreter={{ tt.python_path }} +ansible_user=mitogen__has_sudo_nopw