ansible-collections/ansible.windows

Using Machine credentials from AAP passed to playbook with ansible.windows.win_copy fails

rbukovansky opened this issue · 3 comments

SUMMARY

Using ansible_become_user and ansible_become_password with ansible.windows.win_copy module with credentials passed from Machine credentials defined in Ansible Automation Platform returns error

ISSUE TYPE
  • Bug Report
COMPONENT NAME

ansible.windows.win_copy module

ANSIBLE VERSION
ansible-playbook [core 2.15.8]
  config file = /runner/project/ansible.cfg
  configured module search path = ['/home/runner/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules']
  ansible python module location = /usr/lib/python3.9/site-packages/ansible
  ansible collection location = /runner/requirements_collections:/home/runner/.ansible/collections:/usr/share/ansible/collections
  executable location = /usr/bin/ansible-playbook
  python version = 3.9.18 (main, Sep 22 2023, 17:58:34) [GCC 8.5.0 20210514 (Red Hat 8.5.0-20)] (/usr/bin/python3.9)
  jinja version = 3.1.2
  libyaml = True
COLLECTION VERSION
ansible.windows 2.2.0
CONFIGURATION
Unable to gather, restricted access to Ansible Automation Platform.
OS / ENVIRONMENT

RH Ansible Automation Platform

STEPS TO REPRODUCE

1] Add Machine credentials in AAP (just username and password)
2] Add these credentials to Job Template
3] Try to use "ansible_user" and "ansible_password" facts (where the credentials are passed) with ansible.windows.win_copy module

- name: "Debug ansible_user"
  ansible.builtin.debug:
    msg: "{{ ansible_user }}"

- name: "Copy result file to windows share"
  ansible.windows.win_copy:
    src: "{{ results_pathname }}"
    dest: "{{ win_share_target_path }}\\"
  vars:
    ansible_become_user: "{{ ansible_user }}"
    ansible_become_password: "{{ ansible_password }}"
    ansible_remote_tmp: 'c:\tmp'
EXPECTED RESULTS

File is copied to target share

ACTUAL RESULTS

File is not copied over, instead I'm getting this error:

TASK [Debug ansible_user] ******************************************************
task path: /runner/project/include/transfer_to_share.yml:6
ok: [localhost] => {
    "msg": "ta2nabb"
}

TASK [Copy result file to windows share] ************************************
task path: /runner/project/include/transfer_to_share.yml:19
fatal: [localhost]: FAILED! => {
    "msg": "The field 'become_user' has an invalid value, which includes an undefined variable. The error was: {{ ansible_user }}: 'ansible_user' is undefined. 'ansible_user' is undefined. {{ ansible_user }}: 'ansible_user' is undefined. 'ansible_user' is undefined. {{ ansible_user }}: 'ansible_user' is undefined. 'ansible_user' is undefined. {{ ansible_user }}: 'ansible_user' is undefined. 'ansible_user' is undefined"
}

So, setting facts with the same name "ansible_user" and "ansible_password" solves this issue:

- name: "Set ansible_user and ansible_password facts"
  ansible.builtin.set_fact:
    ansible_user: "{{ ansible_user }}"
    ansible_password: "{{ ansible_password }}"

But why?

The error would seem to indicate that the value has some sort of recursive template happening. I'm not sure how Controller sets those connection vars but I believe there are a few other possible options available to use here

  • Use the lookup('config') plugin to lookup the vars based on the connection plugin

This will go through the same config system as the connection plugin used to get the value requested. In this case you would want something like

- ansible.windows.win_ping:
  become: true
  become_method: runas
  vars:
    ansible_become_user: '{{ lookup("config", "remote_user", plugin_type="connection", plugin_name=ansible_connection) }}'
    ansible_become_pass: '{{ lookup("config", "remote_password", plugin_type="connection", plugin_name=ansible_connection) }}'

The config option is derived from the documented options under the connection plugin, for example with winrm you can see these options under its documentation. The downside of this approach is that it's a lot more verbose.

  • Use the become machine credential in Controller

This is done through a machine credential where you can configure the relevant privilege escalation sections to set the required variables https://docs.ansible.com/automation-controller/4.0.0/html/userguide/credentials.html#machine. This would be my recommended approach when using Controller/Tower/AWX here.