Repository: ansible/ansible
Pull request: Ensure -k is set to delegated hosts without a pass
##### SUMMARY
The change in https://github.com/ansible/ansible/pull/69244 stopped combining the original vars with the delegated host vars. This meant certain variables set by the play context on the host was not transferred to the delegated host, like `ansible_password`. This change reimplements the combining of connection vars to replicate the original behaviour.

Fixes https://github.com/ansible/ansible/issues/71103

##### ISSUE TYPE
- Bugfix Pull Request

##### COMPONENT NAME
task_executor

Problem statement:
winrm Kerberos automatic ticket management doesn't work
<!--- Verify first that your issue is not already reported on GitHub -->
<!--- Also test if the latest release and devel branch are affected too -->
<!--- Complete *all* sections as described, this form is processed automatically -->

##### SUMMARY
<!--- Explain the problem briefly below -->
WinRM kerberos tickets are not getting generated for the playbook tasks, the issue fails in 2.9.10 and 2.9.11 version, while it works with no code change in 2.9.9

In affected Ansible version (2.9.10 and 2.9.11), if I generate a Kerberos ticket (via kinit) in awx_task docker before running the playm the play works, in Ansible 2.9.9 the play will run with no manual ticket creation.

Beside realms configuration (which I am sure they are right as the code works for Ansible 2.9.9), below are other krb5 configuration and I had always default_ccache_name disabled.

```
bash-4.4# cat /etc/krb5.conf
[logging]
 default = FILE:/var/log/krb5libs.log
 kdc = FILE:/var/log/krb5kdc.log
 admin_server = FILE:/var/log/kadmind.log

[libdefaults]
 default_realm = <DOMAIN NAME>
 dns_lookup_realm = false
 dns_lookup_kdc = false
 ticket_lifetime = 24h
 renew_lifetime = 7d
 forwardable = true
 rdns = false
# default_ccache_name = KEYRING:persistent:%{uid}
```

Although if fails in AWX, in awx_docker command line, below works:

```
bash-4.4# cat sam_inven
[windows]
<HOST FQDN>

[windows:vars]
ansible_user=<AD ACCOUNT>@<DOMAIN NAME>
ansible_password=<AD ACCOUNT Password>
ansible_connection=winrm
ansible_port=5986
ansible_winrm_transport=kerberos
ansible_winrm_server_cert_validation=ignore
ansible_winrm_kerberos_delegation=true
become_method=runas
```

```
bash-4.4# cat test-play.yml
---
- name: PROXY TEST
  hosts: <HOST FQDN>
  gather_facts: no
  collections:
    - community.vmware

  tasks:
    - name: Wait for system connection via WinRM
      wait_for_connection:
        timeout: 20
      register: result_wait

    - name: Show WinRM result
      debug:
        var: result_wait
```


```
bash-4.4# ansible-playbook -i sam_inven test-play.yml

PLAY [PROXY TEST] **************************************************************************************************************************************************


TASK [Wait for system connection via WinRM] ************************************************************************************************************************

ok: [<HOST FQDN>]

TASK [Show WinRM result] *******************************************************************************************************************************************

ok: [<HOST FQDN>] => {
    "result_wait": {
        "changed": false,
        "elapsed": 1,
        "failed": false
    }
}

PLAY RECAP *********************************************************************************************************************************************************

<HOST FQDN> : ok=2    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0

bash-4.4#
```


##### ISSUE TYPE
- Bug Report

##### COMPONENT NAME
<!--- Write the short name of the module, plugin, task or feature below, use your best guess if unsure -->
WINRM Kerberos

##### ANSIBLE VERSION
<!--- Paste verbatim output from "ansible --version" between quotes -->
```paste below
ansible 2.9.11
  config file = /etc/ansible/ansible.cfg
  configured module search path = ['/var/lib/awx/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules']
  ansible python module location = /usr/local/lib/python3.6/site-packages/ansible
  executable location = /usr/local/bin/ansible
  python version = 3.6.8 (default, Nov 21 2019, 19:31:34) [GCC 8.3.1 20190507 (Red Hat 8.3.1-4)]
```

##### CONFIGURATION
<!--- Paste verbatim output from "ansible-config dump --only-changed" between quotes -->
```paste below

bash-4.4# ansible-config dump --only-changed
bash-4.4#

```

##### OS / ENVIRONMENT
<!--- Provide all relevant information below, e.g. target OS versions, network device firmware, etc. -->
Ansible running as AWX docker images (official) based on CentOS Linux release 8.1.1911 (Core)
Target hosts are Windows machines running Windows Server 2016

##### STEPS TO REPRODUCE
<!--- Describe exactly how to reproduce the problem, using a minimal test-case -->

<!--- Paste example playbooks or commands between quotes below -->
In AWX inventory host var:

ansible_connection: winrm
ansible_winrm_transport: kerberos
ansible_winrm_server_cert_validation: ignore 
ansible_winrm_kerberos_delegation: true
become_method: runas
ansible_port: 5986

```yaml
---
- name: TEST
  hosts: localhost
  gather_facts: no
  tasks:
    - name: Wait for system connection via WinRM
      wait_for_connection:
        timeout: 60
      register: result_wait
      delegate_to: <host FQDN>
      ignore_errors: yes
    
    - name: Show WinRM result
      debug:
        var: result_wait

```

<!--- HINT: You can paste gist.github.com links for larger files -->

##### EXPECTED RESULTS
<!--- Describe what you expected to happen when running the steps above -->

```
{
    "elapsed": 1,
    "_ansible_no_log": false,
    "changed": false,
    "_ansible_delegated_vars": {
        "ansible_host": "<HOST FQDN>"
    }
}
```

##### ACTUAL RESULTS
<!--- Describe what actually happened. If possible run with extra verbosity (-vvvv) -->

<!--- Paste verbatim command output between quotes -->
```paste below
{
    "msg": "timed out waiting for ping module test success: kerberos: authGSSClientInit() failed: (('Unspecified GSS failure.  Minor code may provide more information', 851968), (\"Can't find client principal <ACCOUNT NAME>@<DOMAIN NAME> in cache collection\", -1765328243))",
    "elapsed": 60,
    "_ansible_no_log": false,
    "changed": false,
    "_ansible_delegated_vars": {
        "ansible_host": "<HOST FQDN>",
        "ansible_port": 5986,
        "ansible_user": "<acount name>@<DOMAIN NAME>"
    }
}
```

Hints from issue discussion:
Files identified in the description:
None

If these files are incorrect, please update the `component name` section of the description or use the `!component` bot command.

[click here for bot help](https://github.com/ansible/ansibullbot/blob/master/ISSUE_HELP.md)
<!--- boilerplate: components_banner --->
!component +windows modules


Files identified in the description:
* [`windows`](https://github.com/ansible/ansible/blob/devel/windows)

If these files are incorrect, please update the `component name` section of the description or use the `!component` bot command.

[click here for bot help](https://github.com/ansible/ansibullbot/blob/master/ISSUE_HELP.md)
<!--- boilerplate: components_banner --->
!component +winrm
!component +remote_management
Can you run with `-vvvvv` (5 v's) and share the output then. That will tell us if the winrm connection plugin is at least attempting to call `kinit` and with what principal.
Files identified in the description:
* [`remote_management`](https://github.com/ansible/ansible/blob/devel/remote_management)
* [`windows`](https://github.com/ansible/ansible/blob/devel/windows)
* [`winrm`](https://github.com/ansible/ansible/blob/devel/winrm)

If these files are incorrect, please update the `component name` section of the description or use the `!component` bot command.

[click here for bot help](https://github.com/ansible/ansibullbot/blob/master/ISSUE_HELP.md)
<!--- boilerplate: components_banner --->
My guess is that `ansible_password` is not being set on the delegated connection and without that the winrm connection plugin will not attempt to call `kinit`. This would probably be a bug but would have to investigate why it's dropping that connection var.
Thanks @jborean93 


```

bash-4.4# ansible --version
ansible 2.9.11
  config file = /etc/ansible/ansible.cfg
  configured module search path = ['/var/lib/awx/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules']
  ansible python module location = /usr/local/lib/python3.6/site-packages/ansible
  executable location = /usr/local/bin/ansible
  python version = 3.6.8 (default, Nov 21 2019, 19:31:34) [GCC 8.3.1 20190507 (Red Hat 8.3.1-4)]

bash-4.4# ansible-playbook -i sam_inven test-play.yml -vvvvv

ansible-playbook 2.9.11
  config file = /etc/ansible/ansible.cfg
  configured module search path = ['/var/lib/awx/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules']
  ansible python module location = /usr/local/lib/python3.6/site-packages/ansible
  executable location = /usr/local/bin/ansible-playbook
  python version = 3.6.8 (default, Nov 21 2019, 19:31:34) [GCC 8.3.1 20190507 (Red Hat 8.3.1-4)]
Using /etc/ansible/ansible.cfg as config file
setting up inventory plugins
host_list declined parsing /tmp/sam_inven as it did not pass its verify_file() method
script declined parsing /tmp/sam_inven as it did not pass its verify_file() method
auto declined parsing /tmp/sam_inven as it did not pass its verify_file() method
Parsed /tmp/sam_inven inventory source with ini plugin
Loading callback plugin default of type stdout, v2.0 from /usr/local/lib/python3.6/site-packages/ansible/plugins/callback/default.py

PLAYBOOK: test-play.yml ********************************************************************************************************************************************

Positional arguments: test-play.yml
verbosity: 5
connection: smart
timeout: 10
become_method: sudo
tags: ('all',)
inventory: ('/tmp/sam_inven',)
forks: 5
1 plays in test-play.yml

PLAY [PROXY TEST] **************************************************************************************************************************************************

META: ran handlers

TASK [Wait for system connection via WinRM] ************************************************************************************************************************

task path: /tmp/test-play.yml:9
wait_for_connection: attempting ping module test
<<HOSTNAME FQDN>> ESTABLISH WINRM CONNECTION FOR USER: <AD Account Name>@<Domain Name> on PORT 5986 TO <HOSTNAME FQDN>
creating Kerberos CC at /tmp/tmp16nul3ip
calling kinit with subprocess for principal <AD Account Name>@<Domain Name>
kinit succeeded for principal <AD Account Name>@<Domain Name>
<<HOSTNAME FQDN>> WINRM CONNECT: transport=kerberos endpoint=https://<HOSTNAME FQDN>:5986/wsman
<<HOSTNAME FQDN>> WINRM OPEN SHELL: 3412CD6B-8944-4206-84A5-68DABD8DCA28
Using module file /usr/local/lib/python3.6/site-packages/ansible/modules/windows/win_ping.ps1
Pipelining is enabled.
EXEC (via pipeline wrapper)
<<HOSTNAME FQDN>> WINRM EXEC 'PowerShell' ['-NoProfile', '-NonInteractive', '-ExecutionPolicy', 'Unrestricted', '-EncodedCommand', 'UABvAHcAZQByAFMAaA
BlAGwAbAAgAC0ATgBvAFAAcgBvAGYAaQBsAGUAIAAtAE4AbwBuAEkAbgB0AGUAcgBhAGMAdABpAHYAZQAgAC0ARQB4AGUAYwB1AHQAaQBvAG4AUABvAGwAaQBjAHkAIABVAG4AcgBlAHMAdAByAGkAYwB0AGUAZAAgAC
0ARQBuAGMAbwBkAGUAZABDAG8AbQBtAGEAbgBkACAASgBnAEIAagBBAEcAZwBBAFkAdwBCAHcAQQBDADQAQQBZAHcAQgB2AEEARwAwAEEASQBBAEEAMgBBAEQAVQBBAE0AQQBBAHcAQQBEAEUAQQBJAEEAQQArAEEAQw
BBAEEASgBBAEIAdQBBAEgAVQBBAGIAQQBCAHMAQQBBAG8AQQBKAEEAQgBsAEEASABnAEEAWgBRAEIAagBBAEYAOABBAGQAdwBCAHkAQQBHAEUAQQBjAEEAQgB3AEEARwBVAEEAYwBnAEIAZgBBAEgATQBBAGQAQQBCAH
kAQQBDAEEAQQBQAFEAQQBnAEEAQwBRAEEAYQBRAEIAdQBBAEgAQQBBAGQAUQBCADAAQQBDAEEAQQBmAEEAQQBnAEEARQA4AEEAZABRAEIAMABBAEMAMABBAFUAdwBCADAAQQBIAEkAQQBhAFEAQgB1AEEARwBjAEEAQw
BnAEEAawBBAEgATQBBAGMAQQBCAHMAQQBHAGsAQQBkAEEAQgBmAEEASABBAEEAWQBRAEIAeQBBAEgAUQBBAGMAdwBBAGcAQQBEADAAQQBJAEEAQQBrAEEARwBVAEEAZQBBAEIAbABBAEcATQBBAFgAdwBCADMAQQBIAE
kAQQBZAFEAQgB3AEEASABBAEEAWgBRAEIAeQBBAEYAOABBAGMAdwBCADAAQQBIAEkAQQBMAGcAQgBUAEEASABBAEEAYgBBAEIAcABBAEgAUQBBAEsAQQBCAEEAQQBDAGcAQQBJAGcAQgBnAEEARABBAEEAWQBBAEEAdw
BBAEcAQQBBAE0AQQBCAGcAQQBEAEEAQQBJAGcAQQBwAEEAQwB3AEEASQBBAEEAeQBBAEMAdwBBAEkAQQBCAGIAQQBGAE0AQQBkAEEAQgB5AEEARwBrAEEAYgBnAEIAbgBBAEYATQBBAGMAQQBCAHMAQQBHAGsAQQBkAE
EAQgBQAEEASABBAEEAZABBAEIAcABBAEcAOABBAGIAZwBCAHoAQQBGADAAQQBPAGcAQQA2AEEARgBJAEEAWgBRAEIAdABBAEcAOABBAGQAZwBCAGwAQQBFAFUAQQBiAFEAQgB3AEEASABRAEEAZQBRAEIARgBBAEcANA
BBAGQAQQBCAHkAQQBHAGsAQQBaAFEAQgB6AEEAQwBrAEEAQwBnAEIASgBBAEcAWQBBAEkAQQBBAG8AQQBDADAAQQBiAGcAQgB2AEEASABRAEEASQBBAEEAawBBAEgATQBBAGMAQQBCAHMAQQBHAGsAQQBkAEEAQgBmAE
EASABBAEEAWQBRAEIAeQBBAEgAUQBBAGMAdwBBAHUAQQBFAHcAQQBaAFEAQgB1AEEARwBjAEEAZABBAEIAbwBBAEMAQQBBAEwAUQBCAGwAQQBIAEUAQQBJAEEAQQB5AEEAQwBrAEEASQBBAEIANwBBAEMAQQBBAGQAQQ
BCAG8AQQBIAEkAQQBiAHcAQgAzAEEAQwBBAEEASQBnAEIAcABBAEcANABBAGQAZwBCAGgAQQBHAHcAQQBhAFEAQgBrAEEAQwBBAEEAYwBBAEIAaABBAEgAawBBAGIAQQBCAHYAQQBHAEUAQQBaAEEAQQBpAEEAQwBBAE
EAZgBRAEEASwBBAEYATQBBAFoAUQBCADAAQQBDADAAQQBWAGcAQgBoAEEASABJAEEAYQBRAEIAaABBAEcASQBBAGIAQQBCAGwAQQBDAEEAQQBMAFEAQgBPAEEARwBFAEEAYgBRAEIAbABBAEMAQQBBAGEAZwBCAHoAQQ
BHADgAQQBiAGcAQgBmAEEASABJAEEAWQBRAEIAMwBBAEMAQQBBAEwAUQBCAFcAQQBHAEUAQQBiAEEAQgAxAEEARwBVAEEASQBBAEEAawBBAEgATQBBAGMAQQBCAHMAQQBHAGsAQQBkAEEAQgBmAEEASABBAEEAWQBRAE
IAeQBBAEgAUQBBAGMAdwBCAGIAQQBEAEUAQQBYAFEAQQBLAEEAQwBRAEEAWgBRAEIANABBAEcAVQBBAFkAdwBCAGYAQQBIAGMAQQBjAGcAQgBoAEEASABBAEEAYwBBAEIAbABBAEgASQBBAEkAQQBBADkAQQBDAEEAQQ
BXAHcAQgBUAEEARwBNAEEAYwBnAEIAcABBAEgAQQBBAGQAQQBCAEMAQQBHAHcAQQBiAHcAQgBqAEEARwBzAEEAWABRAEEANgBBAEQAbwBBAFEAdwBCAHkAQQBHAFUAQQBZAFEAQgAwAEEARwBVAEEASwBBAEEAawBBAE
gATQBBAGMAQQBCAHMAQQBHAGsAQQBkAEEAQgBmAEEASABBAEEAWQBRAEIAeQBBAEgAUQBBAGMAdwBCAGIAQQBEAEEAQQBYAFEAQQBwAEEAQQBvAEEASgBnAEEAawBBAEcAVQBBAGUAQQBCAGwAQQBHAE0AQQBYAHcAQg
AzAEEASABJAEEAWQBRAEIAdwBBAEgAQQBBAFoAUQBCAHkAQQBBAD0APQA=']
<<HOSTNAME FQDN>> WINRM RESULT '<Response code 0, out "{"changed":false,"in", err "#< CLIXML\r\n<Objs Ver">'
<<HOSTNAME FQDN>> WINRM CLOSE SHELL: 3412CD6B-8944-4206-84A5-68DABD8DCA28
ok: [<HOSTNAME FQDN>] => {
    "changed": false,
    "elapsed": 1
}

TASK [Show WinRM result] *******************************************************************************************************************************************

task path: /tmp/test-play.yml:16
ok: [<HOSTNAME FQDN>] => {
    "result_wait": {
        "changed": false,
        "elapsed": 1,
        "failed": false
    }
}
META: ran handlers
META: ran handlers

PLAY RECAP *********************************************************************************************************************************************************

<HOSTNAME FQDN> : ok=2    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0
```
So in that example things worked fine and you can see that kinit was called

```
creating Kerberos CC at /tmp/tmp16nul3ip
calling kinit with subprocess for principal <AD Account Name>@<Domain Name>
kinit succeeded for principal <AD Account Name>@<Domain Name>
```

We would have to see if that same output is shown in your delegation scenario.

Commit message: Fix up some broken tests

Patch to review:
diff --git a/changelogs/fragments/delegation_password.yml b/changelogs/fragments/delegation_password.yml
new file mode 100644
index 00000000000000..c68191b25df86f
--- /dev/null
+++ b/changelogs/fragments/delegation_password.yml
@@ -0,0 +1,2 @@
+bugfixes:
+- Ensure password passed in by -k is used on delegated hosts that do not have ansible_password set
diff --git a/lib/ansible/executor/task_executor.py b/lib/ansible/executor/task_executor.py
index 2e64b613439c01..4b3c8265fc26dd 100644
--- a/lib/ansible/executor/task_executor.py
+++ b/lib/ansible/executor/task_executor.py
@@ -507,7 +507,8 @@ def _execute(self, variables=None):
 
         if self._task.delegate_to:
             # use vars from delegated host (which already include task vars) instead of original host
-            cvars = variables.get('ansible_delegated_vars', {}).get(self._task.delegate_to, {})
+            delegate_vars = variables.get('ansible_delegated_vars', {}).get(self._task.delegate_to, {})
+            cvars = combine_vars(variables, delegate_vars)
             orig_vars = templar.available_variables
         else:
             # just use normal host vars
diff --git a/test/integration/targets/connection_delegation/action_plugins/delegation_action.py b/test/integration/targets/connection_delegation/action_plugins/delegation_action.py
new file mode 100644
index 00000000000000..9d419e75b083d6
--- /dev/null
+++ b/test/integration/targets/connection_delegation/action_plugins/delegation_action.py
@@ -0,0 +1,12 @@
+from __future__ import (absolute_import, division, print_function)
+__metaclass__ = type
+
+from ansible.plugins.action import ActionBase
+
+
+class ActionModule(ActionBase):
+
+    def run(self, tmp=None, task_vars=None):
+        return {
+            'remote_password': self._connection.get_option('remote_password'),
+        }
diff --git a/test/integration/targets/connection_delegation/aliases b/test/integration/targets/connection_delegation/aliases
new file mode 100644
index 00000000000000..9950a08844a192
--- /dev/null
+++ b/test/integration/targets/connection_delegation/aliases
@@ -0,0 +1,4 @@
+shippable/posix/group1
+skip/freebsd  # No sshpass
+skip/osx  # No sshpass
+skip/rhel  # No sshpass
diff --git a/test/integration/targets/connection_delegation/connection_plugins/delegation_connection.py b/test/integration/targets/connection_delegation/connection_plugins/delegation_connection.py
new file mode 100644
index 00000000000000..30f739aef07f2e
--- /dev/null
+++ b/test/integration/targets/connection_delegation/connection_plugins/delegation_connection.py
@@ -0,0 +1,42 @@
+from __future__ import (absolute_import, division, print_function)
+__metaclass__ = type
+
+DOCUMENTATION = """
+author: Ansible Core Team
+connection: delegation_connection
+short_description: Test connection for delegated host check
+description:
+- Some further description that you don't care about.
+options:
+  remote_password:
+    description: The remote password
+    type: str
+    vars:
+    - name: ansible_password
+"""
+
+from ansible.plugins.connection import ConnectionBase
+
+
+class Connection(ConnectionBase):
+
+    transport = 'delegation_connection'
+    has_pipelining = True
+
+    def __init__(self, *args, **kwargs):
+        super(Connection, self).__init__(*args, **kwargs)
+
+    def _connect(self):
+        super(Connection, self)._connect()
+
+    def exec_command(self, cmd, in_data=None, sudoable=True):
+        super(Connection, self).exec_command(cmd, in_data, sudoable)
+
+    def put_file(self, in_path, out_path):
+        super(Connection, self).put_file(in_path, out_path)
+
+    def fetch_file(self, in_path, out_path):
+        super(Connection, self).fetch_file(in_path, out_path)
+
+    def close(self):
+        super(Connection, self).close()
diff --git a/test/integration/targets/connection_delegation/inventory.ini b/test/integration/targets/connection_delegation/inventory.ini
new file mode 100644
index 00000000000000..e7f846d3ee9773
--- /dev/null
+++ b/test/integration/targets/connection_delegation/inventory.ini
@@ -0,0 +1 @@
+my_host  ansible_host=127.0.0.1 ansible_connection=delegation_connection
diff --git a/test/integration/targets/connection_delegation/runme.sh b/test/integration/targets/connection_delegation/runme.sh
new file mode 100755
index 00000000000000..cf047f1334490d
--- /dev/null
+++ b/test/integration/targets/connection_delegation/runme.sh
@@ -0,0 +1,5 @@
+#!/usr/bin/env bash
+
+set -ux
+
+sshpass -p my_password ansible-playbook -i inventory.ini test.yml -k "$@"
diff --git a/test/integration/targets/connection_delegation/test.yml b/test/integration/targets/connection_delegation/test.yml
new file mode 100644
index 00000000000000..678bef518b7bb5
--- /dev/null
+++ b/test/integration/targets/connection_delegation/test.yml
@@ -0,0 +1,23 @@
+---
+- hosts: localhost
+  gather_facts: no
+  tasks:
+  - name: test connection receives -k from play_context when delegating
+    delegation_action:
+    delegate_to: my_host
+    register: result
+
+  - assert:
+      that:
+      - result.remote_password == 'my_password'
+
+  - name: ensure vars set for that host take precedence over -k
+    delegation_action:
+    delegate_to: my_host
+    vars:
+      ansible_password: other_password
+    register: result
+
+  - assert:
+      that:
+      - result.remote_password == 'other_password'


Code review comments:
diff_hunk: @@ -507,7 +507,8 @@ def _execute(self, variables=None):
 
         if self._task.delegate_to:
             # use vars from delegated host (which already include task vars) instead of original host
-            cvars = variables.get('ansible_delegated_vars', {}).get(self._task.delegate_to, {})
+            delegate_vars = variables.get('ansible_delegated_vars', {}).get(self._task.delegate_to, {})
+            cvars = combine_vars(variables, delegate_vars)
path: lib/ansible/executor/task_executor.py
text: @user1:
no, combine vars with inventory_hostname variables is specifically what we want to avoid, this does not only bring the `-k` defined password but any that where set in inventory for the inventory_hostname, then applying possibly wrong password (among other settings) to the delegated_to host.  What we do need to do is pull the play_context passwords  (in the end they should really be applied to the task, but that is future fix) and let delegated_to host override if set.

@user1:
need to x2 check, but `  self._play_context.update_vars(cvars)` shoudl do the trick here

@user1:
currently other plugins use play_context directly as a fallback ` conn_password = self.get_option('password') or self._play_context.password`

@user1:
after thinking for a bit, bets place should be to add passwords to the `set_options` calls in  task_executor, both for connection and become by merging into 'task_keys' before passing it in (at lowest priority) which will allow settings/vars to keep the right precedence and insure its always present



@user1:
https://github.com/ansible/ansible/blob/devel/lib/ansible/executor/task_executor.py#L903

@user1:
actually .. it seems we do attempt to do that .. could it be we have a bug in that code?

@user1:
ah ... winrm uses `remote_password` not `password` .. why it is not getting picked up.

@user1:
not sure how we want to fix it, add 'remote_password' as another task field or update the winrm plugin?

@user2:
may I ask please why WinRM uses remote_password and not password ?

@author:
@user2 they are just keyword names for the config options which they never really were used for anything special before. I mostly followed the same standard for `remote_user` and `remote_addr` but after this change it does have a meaning. I've added the alias for `password` and fixed the code to actually use the aliases when setting the options for keywords.

@user2:
@author thanks for explanation, should we expect this fix to be pushed in next Ansible release 2.9.12 ? or shall I do the same fix manually on my installed version 2.9.11 ?

@author:
I'll be creating a backport for this so the next 2.9 release will include it. Unfortunately it is too late for 2.10.0 so it will be in the 2.10.1 release later on.

@user2:
yes I saw them, what about 2.11 ?