Fix local connection interaction with become plugins (#86473) (#86509)

The local connection plugin is incorrectly passing a bytearray to methods of become plugins that expect bytes. A recent change to the su plugin exposed this by breaking the become plugin for different locale settings (the bytearray was not properly converted to a str for comparison operations). This changes the local connection plugin to send bytes.

(cherry picked from commit 90595736ed)
This commit is contained in:
David Shrewsbury 2026-02-11 12:48:04 -05:00 committed by GitHub
parent b1270aa897
commit 966db65ea2
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
6 changed files with 50 additions and 4 deletions

View file

@ -0,0 +1,2 @@
bugfixes:
- local connection - Pass correct type to become plugins when checking password (https://github.com/ansible/ansible/issues/86458)

View file

@ -105,7 +105,7 @@ class BecomeBase(AnsiblePlugin):
b_success = to_bytes(self.success)
return any(b_success in l.rstrip() for l in b_output.splitlines(True))
def check_password_prompt(self, b_output):
def check_password_prompt(self, b_output: bytes) -> bool:
""" checks if the expected password prompt exists in b_output """
if self.prompt:
b_prompt = to_bytes(self.prompt).strip()

View file

@ -201,8 +201,8 @@ class Connection(ConnectionBase):
raise AnsibleError(become_error_msg('Premature end of stream'))
if expect_password_prompt and (
self.become.check_password_prompt(become_stdout[last_stdout_prompt_offset:]) or
self.become.check_password_prompt(become_stderr[last_stderr_prompt_offset:])
self.become.check_password_prompt(bytes(become_stdout[last_stdout_prompt_offset:])) or
self.become.check_password_prompt(bytes(become_stderr[last_stderr_prompt_offset:]))
):
if sent_password:
raise AnsibleError(become_error_msg('Duplicate become password prompt encountered'))

View file

@ -5,6 +5,7 @@ gather_facts/no
needs/root
needs/target/setup_become_user_pair
needs/target/setup_test_user
needs/target/setup_pexpect
setup/always/setup_passlib_controller # required for setup_test_user
skip/macos # requires a TTY
skip/freebsd # appears to require a TTY (ignores password input from stdin)

View file

@ -61,3 +61,46 @@
- wrong_su_prompt is unreachable
- ansible_connection != "local" or wrong_su_prompt.msg is contains "Timed out waiting for become success or become password prompt"
- ansible_connection != "ssh" or wrong_su_prompt.msg is contains "waiting for privilege escalation prompt"
# The bug from issue https://github.com/ansible/ansible/issues/86458 presents itself only on local connections
# and only when the password is entered interactively using -K/--ask-become-pass.
- name: Test different locale
when: ansible_os_family == 'RedHat' and ansible_connection == 'local'
block:
- import_role:
name: setup_pexpect
- name: install language pack and pexpect
dnf:
name:
- langpacks-uk
- glibc-langpack-uk
state: present
- name: verify language pack is enabled
command: locale -a
register: installed_languages
- assert:
that: "'uk_UA.utf8' in installed_languages.stdout"
- name: test su prompt basic success with alternate language on local connection
expect:
command: "ansible -m command -a whoami localhost -b --become-method su -K"
responses:
BECOME password:
- "{{ target_user_password }}"
environment:
LC_ALL: uk_UA.utf8
ANSIBLE_BECOME_USER: "{{ target_user_name }}"
ANSIBLE_BECOME_EXE: /tmp/sushim.sh
ANSIBLE_BECOME_FLAGS: --intermediate-user {{ intermediate_user_name | quote }}
# protect our target user password
no_log: true
always:
- name: remove language pack
dnf:
name:
- langpacks-uk
- glibc-langpack-uk
state: absent

View file

@ -70,4 +70,4 @@ def test_check_password_prompt_escaping(mocker) -> None:
mocker.patch.object(become, 'get_option', return_value=['(invalid regex'])
assert become.check_password_prompt('(invalid regex:') is True
assert become.check_password_prompt(b'(invalid regex:') is True