Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Hosts added by add_host module don't respect ansible_host_key_checking variable #1066

Closed
philfry opened this issue Apr 19, 2024 · 5 comments · Fixed by #1067
Closed

Hosts added by add_host module don't respect ansible_host_key_checking variable #1066

philfry opened this issue Apr 19, 2024 · 5 comments · Fixed by #1067
Labels
affects-0.3 Issues related to 0.3.X Mitogen releases bug Code feature that hinders desired execution outcome

Comments

@philfry
Copy link
Contributor

philfry commented Apr 19, 2024

When adding a managed node to the current inventory using add_host the variable ansible_host_key_checking is not honoured. Let's say we have a vanilla machine ansible-test-100 and this playbook:

---
- hosts: localhost
  gather_facts: no
  tasks:
    - add_host:
        name: ansible-test-100
        ansible_host: 192.168.122.100
        ansible_ssh_private_key_file: /tmp/ansibletest-leases/100/id_ed25519

- hosts: ansible-test-100
  remote_user: ansible
  become: no
  tasks:
    - copy: content="Hello world" dest=/tmp/blah
    - file: path=/tmp/blah state=absent

As ssh doesn't know about the ssh host key yet, the playbook will prompt for a fingerprint confirmation:

$ ANSIBLE_STRATEGY=linear ansible-playbook foo.yml 

PLAY [localhost] ******************************************************************************************************

TASK [add_host] *******************************************************************************************************
changed: [localhost]

PLAY [ansible-test-100] ***********************************************************************************************
The authenticity of host '192.168.122.100 (192.168.122.100)' can't be established.
ED25519 key fingerprint is SHA256:JzKOGkgn5xX67/IAksbd/S/cof9Vzn1FD25a+pQfgXQ.
This key is not known by any other names.
Are you sure you want to continue connecting (yes/no/[fingerprint])?

To circumvent this, we can add ansible_host_key_checking: no to the add_host task:

    - add_host:
        name: ansible-test-100
        ansible_host: 192.168.122.100
        ansible_ssh_private_key_file: /tmp/ansibletest-leases/100/id_ed25519
        ansible_host_key_checking: no

Now the playbook runs fine:

$ ANSIBLE_STRATEGY=linear ansible-playbook foo.yml 

PLAY [localhost] ******************************************************************************************************

TASK [add_host] *******************************************************************************************************
changed: [localhost]

PLAY [ansible-test-100] ***********************************************************************************************

TASK [copy] ***********************************************************************************************************
--- before
+++ after: /tmp/blah
@@ -0,0 +1 @@
+Hello world
\ No newline at end of file

changed: [ansible-test-100]

TASK [file] ***********************************************************************************************************
--- before
+++ after
@@ -1,4 +1,4 @@
 {
     "path": "/tmp/blah",
-    "state": "file"
+    "state": "absent"
 }

changed: [ansible-test-100]

PLAY RECAP ************************************************************************************************************
ansible-test-100           : ok=2    changed=2    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
localhost                  : ok=1    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0

Yet this doesn't work with mitogen:

$ ANSIBLE_STRATEGY=mitogen_linear ansible-playbook foo.yml 

PLAY [localhost] ******************************************************************************************************

TASK [add_host] *******************************************************************************************************
changed: [localhost]

PLAY [ansible-test-100] ***********************************************************************************************

TASK [copy] ***********************************************************************************************************
fatal: [ansible-test-100]: UNREACHABLE! => {"changed": false, "msg": "Host key checking is enabled, and SSH reported an unrecognized or mismatching host key.", "unreachable": true}

PLAY RECAP ************************************************************************************************************
ansible-test-100           : ok=0    changed=0    unreachable=1    failed=0    skipped=0    rescued=0    ignored=0   
localhost                  : ok=1    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0

I suggest to add mitogen_ssh_host_key_checking which accepts accept, enforce or ignore to mimic this behaviour:

    - add_host:
        name: ansible-test-100
        ansible_host: 192.168.122.100
        ansible_ssh_private_key_file: /tmp/ansibletest-leases/100/id_ed25519
        ansible_host_key_checking: no
        mitogen_ssh_host_key_checking: ignore

=>

$ ANSIBLE_STRATEGY=mitogen_linear ansible-playbook foo.yml 

PLAY [localhost] ******************************************************************************************************

TASK [add_host] *******************************************************************************************************
changed: [localhost]

PLAY [ansible-test-100] ***********************************************************************************************

TASK [copy] ***********************************************************************************************************
--- before
+++ after: /tmp/blah
@@ -0,0 +1 @@
+Hello world
\ No newline at end of file

changed: [ansible-test-100]

TASK [file] ***********************************************************************************************************
--- before
+++ after
@@ -1,4 +1,4 @@
 {
     "path": "/tmp/blah",
-    "state": "file"
+    "state": "absent"
 }

changed: [ansible-test-100]

PLAY RECAP ************************************************************************************************************
ansible-test-100           : ok=2    changed=2    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
localhost                  : ok=1    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0

I'll open a draft pr for this, it'd be nice if you could have a look. Or maybe I'm just reinventing the wheel and such a feature already exists somehow 😄

@philfry philfry added affects-0.3 Issues related to 0.3.X Mitogen releases bug Code feature that hinders desired execution outcome labels Apr 19, 2024
@moreati
Copy link
Member

moreati commented Apr 22, 2024

If vanilla respects ansible_host_key_checking and Ansible+Mitogen doesn't, then I think we should fix that rather than add another variable. Did you have other reason(s) for adding mitogen_ssh_host_key_checking?

@philfry
Copy link
Contributor Author

philfry commented Apr 22, 2024

The reason I used a dedicated variable was because the skeleton for check_host_keys accepting 'accept', 'enforce' and 'ignore' was already there. Vanilla ansible only takes a bool as argument (which translate to 'enforce' or 'ignore' in mitogen) but I did not want to break any possible features regarding 'accept'. Also it was easier for me to test 😇

But I'm totally fine with hooking to ansible_host_key_checking and ansible_ssh_host_key_checking.

@philfry
Copy link
Contributor Author

philfry commented Apr 22, 2024

I changed the pr to use ansible_host_key_checking and ansible_ssh_host_key_checking. For now it's an extra commit but I'd squash them if you like the general idea of this pr.

@moreati moreati changed the title introduce mitogen_ssh_check_host_keys for dynamically added hosts Hosts added by add_host module don't respect ansible_host_key_checking variable Apr 24, 2024
@moreati
Copy link
Member

moreati commented Apr 24, 2024

I confirm the issue when add_hosts is passed ansible_host_key_checking.
It doesn't occur using env var ANSIBLE_HOST_KEY_CHECKING=no instead.

There are other differences I was unaware of. These may also qualify as bugs.
Fixing/amending them is probably outside scope of this issue.

Related differences

  • Ansible prompts user to accept an unknown host key, Mitogen does not
  • Ansible adds an accepted key to known_hosts, Mitogen+Ansible does not

Notes to self

Reproduction

# issue1066_repro.yml 
- hosts: localhost
  gather_facts: false
  tasks:
    - known_hosts:  {name: "192.168.1.112", state: absent}
    - add_host:     {name: ansible-test-100, ansible_host: "192.168.1.112"}

- hosts: ansible-test-100
  gather_facts: false
  tasks:
    - ping:
# issue1066_repro2.yml
- hosts: localhost
  gather_facts: false
  tasks:
    - known_hosts:  {name: "192.168.1.112", state: absent}
    - add_host:     {name: ansible-test-100, ansible_host: "192.168.1.112", ansible_host_key_checking: false}

- hosts: ansible-test-100
  gather_facts: false
  tasks:
    - ping:
Playbook runs

Vanilla Ansible, add_hosts

$ ANSIBLE_STRATEGY=linear ansible-playbook issue1066_repro.yml            
[WARNING]: No inventory was parsed, only implicit localhost is available
[WARNING]: provided hosts list is empty, only localhost is available. Note that the implicit localhost does not match 'all'

PLAY [localhost] *************************

TASK [known_hosts] ***********************
ok: [localhost]

TASK [add_host] **************************
changed: [localhost]

PLAY [ansible-test-100] ******************

TASK [ping] ******************************
The authenticity of host '192.168.1.112 (192.168.1.112)' can't be established.
ED25519 key fingerprint is SHA256:AXEqIPmNmX02Nqs4H0fsIV286vmXvYhZXfPTO373c10.
This key is not known by any other names.
Are you sure you want to continue connecting (yes/no/[fingerprint])? ^C [ERROR]: User interrupted execution

Vanilla Ansible, add_hosts, ANSIBLE_HOST_KEY_CHECKING=no

Result: Playbook completes, key is added to known_hosts

$ ANSIBLE_STRATEGY=linear ANSIBLE_HOST_KEY_CHECKING=no ansible-playbook issue1066_repro.yml
[WARNING]: No inventory was parsed, only implicit localhost is available
[WARNING]: provided hosts list is empty, only localhost is available. Note that the implicit localhost does not match 'all'

PLAY [localhost] *************************

TASK [known_hosts] ***********************
ok: [localhost]

TASK [add_host] **************************
changed: [localhost]

PLAY [ansible-test-100] ******************

TASK [ping] ******************************
ok: [ansible-test-100]

PLAY RECAP *******************************
ansible-test-100           : ok=1    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
localhost                  : ok=2    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   

Mitogen + Ansible, add_hosts

Result: No prompt, playbook fails

$ ANSIBLE_STRATEGY=mitogen_linear ansible-playbook issue1066_repro.yml                     
[WARNING]: No inventory was parsed, only implicit localhost is available
[WARNING]: provided hosts list is empty, only localhost is available. Note that the implicit localhost does not match 'all'

PLAY [localhost] *************************

TASK [known_hosts] ***********************
changed: [localhost]

TASK [add_host] **************************
changed: [localhost]

PLAY [ansible-test-100] ******************

TASK [ping] ******************************
[WARNING]: Unhandled error in Python interpreter discovery for host ansible-test-100: Host key checking is enabled, and SSH reported an unrecognized or mismatching host key.
fatal: [ansible-test-100]: UNREACHABLE! => {"changed": false, "msg": "Host key checking is enabled, and SSH reported an unrecognized or mismatching host key.", "unreachable": true}

PLAY RECAP *******************************
ansible-test-100           : ok=0    changed=0    unreachable=1    failed=0    skipped=0    rescued=0    ignored=0   
localhost                  : ok=2    changed=2    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   

Mitogen + Ansible, add_hosts, ANSIBLE_HOST_KEY_CHECKING=no

Result: Playbook succeeds, key is not added to known hosts

$ ANSIBLE_STRATEGY=mitogen_linear ANSIBLE_HOST_KEY_CHECKING=no ansible-playbook issue1066_repro.yml
[WARNING]: No inventory was parsed, only implicit localhost is available
[WARNING]: provided hosts list is empty, only localhost is available. Note that the implicit localhost does not match 'all'

PLAY [localhost] *************************

TASK [known_hosts] ***********************
ok: [localhost]

TASK [add_host] **************************
changed: [localhost]

PLAY [ansible-test-100] ******************

TASK [ping] ******************************
ok: [ansible-test-100]

PLAY RECAP *******************************
ansible-test-100           : ok=1    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
localhost                  : ok=2    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   

Mitogen + Ansible, add_hosts with ansible_host_key_checking=false

Result: Playbook fails, no prompt

$ ANSIBLE_STRATEGY=mitogen_linear ansible-playbook issue1066_repro2.yml 
[WARNING]: No inventory was parsed, only implicit localhost is available
[WARNING]: provided hosts list is empty, only localhost is available. Note that the implicit localhost does not match 'all'

PLAY [localhost] *************************************************

TASK [known_hosts] ***********************************************
ok: [localhost]

TASK [add_host] **************************************************
changed: [localhost]

PLAY [ansible-test-100] ******************************************

TASK [ping] ******************************************************
[WARNING]: Unhandled error in Python interpreter discovery for host ansible-test-100: Host key checking is enabled, and SSH reported an unrecognized or mismatching host key.
fatal: [ansible-test-100]: UNREACHABLE! => {"changed": false, "msg": "Host key checking is enabled, and SSH reported an unrecognized or mismatching host key.", "unreachable": true}

PLAY RECAP *******************************************************
ansible-test-100           : ok=0    changed=0    unreachable=1    failed=0    skipped=0    rescued=0    ignored=0   
localhost                  : ok=2    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   

Characterisation

# inv.ini 
mitogen     ansible_host=192.168.1.112
# issue1066_ping.yml 
- hosts: mitogen
  gather_facts: false
  tasks:
    - ping:
Playbook runs

Vanilla Ansible, host from inventory.

Result: prompts on an unknown key.

$ ansible -i inv.ini -o localhost -mknown_hosts -a"name={{ hostvars.mitogen.ansible_host }} state=absent"
localhost | SUCCESS => {"changed": false,"gid": 20,"group": "staff","hash_host": false,"key": null,"mode": "0600","name": "192.168.1.112","owner": "alex","path": "/Users/alex/.ssh/known_hosts","size": 13196,"state": "file","uid": 501}
$ ANSIBLE_STRATEGY=linear ansible-playbook -i inv.ini issue1066_ping.yml 

PLAY [mitogen] *********************

TASK [ping] ************************
The authenticity of host '192.168.1.112 (192.168.1.112)' can't be established.
ED25519 key fingerprint is SHA256:AXEqIPmNmX02Nqs4H0fsIV286vmXvYhZXfPTO373c10.
This key is not known by any other names.
Are you sure you want to continue connecting (yes/no/[fingerprint])? ^C [ERROR]: User interrupted execution

Vanilla Ansible, host from inventory, ANSIBLE_HOST_KEY_CHECKING=no

Resut: Completes, key is added to known_hosts

$ ANSIBLE_STRATEGY=linear ANSIBLE_HOST_KEY_CHECKING=no ansible-playbook -i inv.ini issue1066_ping.yml

PLAY [mitogen] *********************

TASK [ping] ************************
ok: [mitogen]

PLAY RECAP *************************
mitogen                    : ok=1    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   

Mitogen + Ansible, host form inventory

Result: doesn't prompt, playbook fails

$ ansible -i inv.ini -o localhost -mknown_hosts -a"name={{ hostvars.mitogen.ansible_host }} state=absent"
localhost | CHANGED => {"changed": true,"gid": 20,"group": "staff","hash_host": false,"key": null,"mode": "0600","name": "192.168.1.112","owner": "alex","path": "/Users/alex/.ssh/known_hosts","size": 13196,"state": "file","uid": 501}
$ ANSIBLE_STRATEGY=mitogen_linear ansible-playbook -i ~/ansible_inventory.yml issue1066_ping.yml                             

PLAY [mitogen] *********************

TASK [ping] ************************
[WARNING]: Unhandled error in Python interpreter discovery for host mitogen: Host key checking is enabled, and SSH reported an unrecognized or mismatching host key.
fatal: [mitogen]: UNREACHABLE! => {"changed": false, "msg": "Host key checking is enabled, and SSH reported an unrecognized or mismatching host key.", "unreachable": true}

PLAY RECAP *************************
mitogen                    : ok=0    changed=0    unreachable=1    failed=0    skipped=0    rescued=0    ignored=0   

Mitogen + Ansible, host form inventory, ANSIBLE_HOST_KEY_CHECKING=no

Result: Playbook completes, key is not added to known hosts

$ ANSIBLE_STRATEGY=mitogen_linear ANSIBLE_HOST_KEY_CHECKING=no ansible-playbook -i ~/ansible_inventory.yml issue1066_ping.yml

PLAY [mitogen] *********************

TASK [ping] ************************
ok: [mitogen]

PLAY RECAP *************************
mitogen                    : ok=1    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   

@moreati
Copy link
Member

moreati commented Apr 24, 2024

Notes to self, these aren't things to address within this issue/PR

  • Ansible SSH option is "host_key_checking"

  • ansible-core 2.16.6 ansible.plugins.connection.ssh.Connection._build_command() adds -o StrictHostKeyChecking=no if the option evaluates False (default True)

  • OpenSSH 9.6 StrictHostKeyChecking accepts any of true, false, yes, no, ask, off, accept-new https://github.com/openssh/openssh-portable/blob/V_9_6_P1/readconf.c#L913-L922

  • Mitogen <= 0.3.7 maps Ansible's host_key_checking -> kwarg check_host_keys

    host_key_checking check_host_keys
    False ignore
    True enforce

    check_host_keys accepts any of accept, enforce, ignore

    • enforce -> StrictHostKeyChecking yes
    • accept -> StrictHostKeyChecking ask and Mitogen answers
      any host key prompts with yes.
    • ignore -> StrictHostKeyChecking no, UserKnownHostsFile /dev/null, GlobalKnownHostsFile /dev/null
  • ansible_mitogen.transport_config contains a mishmash of naming conventions.

    • no prefix (e.g. Spec.port, Spec.become_exe)
    • prefix (e.g. Spec.mitogen_kind)
    • prefix & plugin name (e.g. Spec.ansible_ssh_timeout, Spec.ansible_doas_exe, Spec.mitogen_lxc_path)
  • ansible_mitogen.connection.convert_bool() possibly duplicates ansible.module_utils.parsing.convert_bool.boolean(), and/or it should be somewhere more generic.

moreati added a commit to moreati/mitogen that referenced this issue May 2, 2024
moreati added a commit to moreati/mitogen that referenced this issue May 3, 2024
moreati added a commit to moreati/mitogen that referenced this issue May 6, 2024
moreati added a commit to moreati/mitogen that referenced this issue May 6, 2024
moreati added a commit to moreati/mitogen that referenced this issue May 6, 2024
Some tests were being incorrectly excluded. Including those that use
`add_host`.
refs mitogen-hq#1066, mitogen-hq#1069
moreati added a commit to moreati/mitogen that referenced this issue May 6, 2024
Some tests were being incorrectly excluded. Including those that use
`add_host`.
refs mitogen-hq#1066, mitogen-hq#1069
philfry pushed a commit to philfry/mitogen that referenced this issue May 7, 2024
Some tests were being incorrectly excluded. Including those that use
`add_host`.
refs mitogen-hq#1066, mitogen-hq#1069
moreati added a commit to moreati/mitogen that referenced this issue May 7, 2024
moreati added a commit to moreati/mitogen that referenced this issue May 7, 2024
Some tests were being incorrectly excluded. Including those that use
`add_host`.
refs mitogen-hq#1066, mitogen-hq#1069
moreati added a commit to moreati/mitogen that referenced this issue May 7, 2024
moreati added a commit to moreati/mitogen that referenced this issue May 8, 2024
moreati added a commit to moreati/mitogen that referenced this issue May 8, 2024
Some tests were being incorrectly excluded. Including those that use
`add_host`.
refs mitogen-hq#1066, mitogen-hq#1069
moreati added a commit to moreati/mitogen that referenced this issue May 8, 2024
philfry pushed a commit to philfry/mitogen that referenced this issue May 9, 2024
philfry pushed a commit to philfry/mitogen that referenced this issue May 9, 2024
Some tests were being incorrectly excluded. Including those that use
`add_host`.
refs mitogen-hq#1066, mitogen-hq#1069
philfry pushed a commit to philfry/mitogen that referenced this issue May 10, 2024
philfry pushed a commit to philfry/mitogen that referenced this issue May 10, 2024
Some tests were being incorrectly excluded. Including those that use
`add_host`.
refs mitogen-hq#1066, mitogen-hq#1069
moreati added a commit to moreati/mitogen that referenced this issue May 21, 2024
moreati added a commit to moreati/mitogen that referenced this issue May 21, 2024
Some tests were being incorrectly excluded. Including those that use
`add_host`.
refs mitogen-hq#1066, mitogen-hq#1069
rjhesketh pushed a commit to bbc/mitogen that referenced this issue Jul 10, 2024
Some tests were being incorrectly excluded. Including those that use
`add_host`.
refs mitogen-hq#1066, mitogen-hq#1069
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
affects-0.3 Issues related to 0.3.X Mitogen releases bug Code feature that hinders desired execution outcome
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants