Skip to content

Commit 0ce9ffc

Browse files
authored
Merge pull request #1067 from philfry/host_key_checking
Fix add_hosts when ansible_host_key_checking is passed to the new host
2 parents 0f34e25 + 60f8682 commit 0ce9ffc

12 files changed

+215
-7
lines changed

.ci/localhost_ansible_tests.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -93,5 +93,5 @@
9393
with ci_lib.Fold('ansible'):
9494
os.chdir(TESTS_DIR)
9595
playbook = os.environ.get('PLAYBOOK', 'all.yml')
96-
ci_lib.run('./run_ansible_playbook.py %s -l target %s',
96+
ci_lib.run('./run_ansible_playbook.py %s %s',
9797
playbook, ' '.join(sys.argv[1:]))

ansible_mitogen/connection.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -119,7 +119,7 @@ def _connect_ssh(spec):
119119
"""
120120
Return ContextService arguments for an SSH connection.
121121
"""
122-
if C.HOST_KEY_CHECKING:
122+
if spec.host_key_checking():
123123
check_host_keys = 'enforce'
124124
else:
125125
check_host_keys = 'ignore'

ansible_mitogen/transport_config.py

+23
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@
6767
import ansible.constants as C
6868

6969
from ansible.module_utils.six import with_metaclass
70+
from ansible.module_utils.parsing.convert_bool import boolean
7071

7172
# this was added in Ansible >= 2.8.0; fallback to the default interpreter if necessary
7273
try:
@@ -245,6 +246,12 @@ def python_path(self):
245246
Path to the Python interpreter on the target machine.
246247
"""
247248

249+
@abc.abstractmethod
250+
def host_key_checking(self):
251+
"""
252+
Whether or not to check the keys of the target machine
253+
"""
254+
248255
@abc.abstractmethod
249256
def private_key_file(self):
250257
"""
@@ -466,6 +473,14 @@ def python_path(self, rediscover_python=False):
466473
action=self._action,
467474
rediscover_python=rediscover_python)
468475

476+
def host_key_checking(self):
477+
def candidates():
478+
yield self._connection.get_task_var('ansible_ssh_host_key_checking')
479+
yield self._connection.get_task_var('ansible_host_key_checking')
480+
yield C.HOST_KEY_CHECKING
481+
val = next((v for v in candidates() if v is not None), True)
482+
return boolean(val)
483+
469484
def private_key_file(self):
470485
return self._play_context.private_key_file
471486

@@ -692,6 +707,14 @@ def python_path(self, rediscover_python=False):
692707
action=self._action,
693708
rediscover_python=rediscover_python)
694709

710+
def host_key_checking(self):
711+
def candidates():
712+
yield self._host_vars.get('ansible_ssh_host_key_checking')
713+
yield self._host_vars.get('ansible_host_key_checking')
714+
yield C.HOST_KEY_CHECKING
715+
val = next((v for v in candidates() if v is not None), True)
716+
return boolean(val)
717+
695718
def private_key_file(self):
696719
# TODO: must come from PlayContext too.
697720
return (

docs/changelog.rst

+1
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ Unreleased
2424
* :gh:issue:`952` Fix Ansible `--ask-become-pass`, add test coverage
2525
* :gh:issue:`957` Fix Ansible exception when executing against 10s of hosts
2626
"ValueError: filedescriptor out of range in select()"
27+
* :gh:issue:`1066` Support Ansible `ansible_host_key_checking` & `ansible_ssh_host_key_checking`
2728

2829

2930
v0.3.7 (2024-04-08)

tests/ansible/ansible.cfg

+8-3
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,12 @@
11
[defaults]
22
any_errors_fatal = true
3-
# callback_whitelist naming will be deprecated in ansible-core >= 2.15.
4-
# callbacks_enabled naming was added in ansible-core 2.11
3+
# callbacks_enabled was added in Ansible 4 (ansible-core 2.11).
54
# profile_tasks: Displays timing for each task and summary table of top N tasks
65
# timer: Displays "Playbook run took 0 days, 0 hours, ..."
6+
callbacks_enabled =
7+
profile_tasks,
8+
timer
9+
# callback_whitelist was deprecated in Ansible >= 8 (ansible-core >= 2.15).
710
callback_whitelist =
811
profile_tasks,
912
timer
@@ -37,7 +40,9 @@ no_target_syslog = True
3740
# Required by integration/ssh/timeouts.yml
3841
timeout = 30
3942

40-
# On Travis, paramiko check fails due to host key checking enabled.
43+
# Ideally this would be true here and and overridden for hosts/groups. However
44+
# ansible_host_key_checking don't work on Vanilla Ansible 2.10, even for
45+
# static inventory hosts (ansible/ansible#49254, ansible/ansible#73708)
4146
host_key_checking = False
4247

4348
[inventory]

tests/ansible/hosts/transport_config.hosts

+6
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ tc_become
1313
tc_become_method
1414
tc_become_pass
1515
tc_become_user
16+
tc_host_key_checking
1617
tc_password
1718
tc_port
1819
tc_remote_addr
@@ -74,6 +75,11 @@ tc-become-pass-password ansible_become_password=apassword
7475
tc-become-pass-pass ansible_become_pass=apass
7576
tc-become-pass-both ansible_become_pass=bpass ansible_become_password=bpassword
7677

78+
[tc_host_key_checking]
79+
tc-hkc-unset
80+
tc-hkc-host-key-checking ansible_host_key_checking=true
81+
tc-hkc-ssh-host-key-checking ansible_ssh_host_key_checking=true
82+
7783
[tc_port]
7884
tc-port-unset
7985
tc-port-explicit-port ansible_port=1234

tests/ansible/integration/transport_config/all.yml

+1
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
- import_playbook: become_pass.yml
33
- import_playbook: become_user.yml
44
- import_playbook: become.yml
5+
- import_playbook: host_key_checking.yml
56
- import_playbook: password.yml
67
- import_playbook: port.yml
78
- import_playbook: python_path.yml
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
# Each case is followed by mitogen_via= case to test hostvars method.
2+
3+
- name: integration/transport_config/host_key_checking.yml
4+
hosts: tc-hkc-unset
5+
tasks:
6+
- include_tasks: ../_mitogen_only.yml
7+
- {mitogen_get_stack: {}, register: out}
8+
- assert:
9+
that:
10+
- out.result | length == 1
11+
- out.result[0].method == "ssh"
12+
- out.result[0].kwargs.check_host_keys == "ignore"
13+
fail_msg: out={{ out }}
14+
tags:
15+
- mitogen_only
16+
17+
- hosts: tc-hkc-unset
18+
vars:
19+
mitogen_via: tc-hkc-host-key-checking
20+
tasks:
21+
- include_tasks: ../_mitogen_only.yml
22+
- {mitogen_get_stack: {}, register: out}
23+
- assert:
24+
that:
25+
- out.result | length == 2
26+
- out.result[0].method == "ssh"
27+
- out.result[0].kwargs.check_host_keys == "enforce"
28+
- out.result[1].method == "ssh"
29+
- out.result[1].kwargs.check_host_keys == "ignore"
30+
fail_msg: out={{ out }}
31+
tags:
32+
- mitogen_only
33+
34+
35+
- hosts: tc-hkc-host-key-checking
36+
tasks:
37+
- include_tasks: ../_mitogen_only.yml
38+
- {mitogen_get_stack: {}, register: out}
39+
- assert:
40+
that:
41+
- out.result | length == 1
42+
- out.result[0].method == "ssh"
43+
- out.result[0].kwargs.check_host_keys == "enforce"
44+
fail_msg: out={{ out }}
45+
tags:
46+
- mitogen_only
47+
48+
- hosts: tc-hkc-host-key-checking
49+
vars:
50+
mitogen_via: tc-hkc-unset
51+
tasks:
52+
- include_tasks: ../_mitogen_only.yml
53+
- {mitogen_get_stack: {}, register: out}
54+
- assert:
55+
that:
56+
- out.result | length == 2
57+
- out.result[0].method == "ssh"
58+
- out.result[0].kwargs.check_host_keys == "ignore"
59+
- out.result[1].method == "ssh"
60+
- out.result[1].kwargs.check_host_keys == "enforce"
61+
fail_msg: out={{ out }}
62+
tags:
63+
- mitogen_only
64+
65+
66+
- hosts: tc-hkc-ssh-host-key-checking
67+
tasks:
68+
- include_tasks: ../_mitogen_only.yml
69+
- {mitogen_get_stack: {}, register: out}
70+
- assert:
71+
that:
72+
- out.result | length == 1
73+
- out.result[0].method == "ssh"
74+
- out.result[0].kwargs.check_host_keys == "enforce"
75+
fail_msg: out={{ out }}
76+
tags:
77+
- mitogen_only
78+
79+
- hosts: tc-hkc-ssh-host-key-checking
80+
vars:
81+
mitogen_via: tc-hkc-unset
82+
tasks:
83+
- include_tasks: ../_mitogen_only.yml
84+
- {mitogen_get_stack: {}, register: out}
85+
- assert:
86+
that:
87+
- out.result | length == 2
88+
- out.result[0].method == "ssh"
89+
- out.result[0].kwargs.check_host_keys == "ignore"
90+
- out.result[1].method == "ssh"
91+
- out.result[1].kwargs.check_host_keys == "enforce"
92+
fail_msg: out={{ out }}
93+
tags:
94+
- mitogen_only

tests/ansible/regression/all.yml

+1
Original file line numberDiff line numberDiff line change
@@ -15,3 +15,4 @@
1515
- import_playbook: issue_655__wait_for_connection_error.yml
1616
- import_playbook: issue_776__load_plugins_called_twice.yml
1717
- import_playbook: issue_952__ask_become_pass.yml
18+
- import_playbook: issue_1066__add_host__host_key_checking.yml
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
- name: regression/issue_1066__add_host__host_key_checking.yml
2+
hosts: test-targets[0]
3+
gather_facts: false
4+
become: false
5+
tasks:
6+
- name: Add hosts dynamically
7+
add_host:
8+
name: "{{ item.name }}"
9+
ansible_host_key_checking: "{{ item.host_key_checking | default(omit) }}"
10+
ansible_ssh_host_key_checking: "{{ item.host_ssh_key_checking | default(omit) }}"
11+
ansible_host: "{{ hostvars[inventory_hostname].ansible_host | default(omit) }}"
12+
ansible_password: "{{ hostvars[inventory_hostname].ansible_password | default(omit) }}"
13+
ansible_port: "{{ hostvars[inventory_hostname].ansible_port | default(omit) }}"
14+
ansible_python_interpreter: "{{ hostvars[inventory_hostname].ansible_python_interpreter | default(omit) }}"
15+
ansible_user: "{{ hostvars[inventory_hostname].ansible_user | default(omit) }}"
16+
loop:
17+
- {name: issue-1066-host-hkc-false, host_key_checking: false}
18+
- {name: issue-1066-host-hkc-true, host_key_checking: true}
19+
- {name: issue-1066-host-hskc-false, host_ssh_key_checking: false}
20+
- {name: issue-1066-host-hskc-true, host_ssh_key_checking: true}
21+
delegate_to: localhost
22+
tags:
23+
- issue_1066
24+
25+
- name: regression/issue_1066__add_host__host_key_checking.yml
26+
hosts: issue-1066-host-*
27+
gather_facts: false
28+
become: false
29+
serial: 1
30+
tasks:
31+
- meta: reset_connection
32+
33+
# The host key might be in ~/.ssh/known_hosts. If it's removed then no
34+
# problem - test-targets hosts have host_key_checking=false.
35+
- name: Remove existing host keys
36+
known_hosts:
37+
name: "{{ ansible_host }}"
38+
state: absent
39+
delegate_to: localhost
40+
41+
- name: Ping dynamically added hosts
42+
ping:
43+
ignore_errors: true
44+
ignore_unreachable: true
45+
register: issue_1066_ping
46+
47+
- debug:
48+
var: issue_1066_ping
49+
50+
- name: Confirm dynamically added hosts are/are not reachable
51+
vars:
52+
expected:
53+
issue-1066-host-hkc-false: {}
54+
issue-1066-host-hkc-true: {unreachable: true}
55+
issue-1066-host-hskc-false: {}
56+
issue-1066-host-hskc-true: {unreachable: true}
57+
assert:
58+
that:
59+
- issue_1066_ping.unreachable is defined == expected[inventory_hostname].unreachable is defined
60+
- issue_1066_ping.unreachable | default(42) == expected[inventory_hostname].unreachable | default(42)
61+
# ansible_host_key_checking don't work on Vanilla Ansible 2.10, even for
62+
# static inventory hosts (ansible/ansible#49254, ansible/ansible#73708).
63+
when:
64+
- ansible_version.full is version('2.11', '>=', strict=True)
65+
or is_mitogen
66+
tags:
67+
- issue_1066

tests/ansible/regression/issue_655__wait_for_connection_error.yml

+9-1
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,19 @@
44
# since things are ran on localhost; Azure DevOps loses connection and fails
55
# TODO: do we want to install docker a different way to be able to do this for other tests too
66
---
7-
- name: regression/issue_655_wait_for_connection_error.yml
7+
- name: regression/issue_655__wait_for_connection_error.yml
88
hosts: localhost
99
gather_facts: yes
1010
become: no
1111
tasks:
12+
- meta: end_play
13+
when:
14+
# TODO CI currently runs on macOS 11 images in Azure DevOps. MacOS 11
15+
# is no longer supported by homebrew, so the following install
16+
# task fails.
17+
- ansible_facts.system == 'Darwin'
18+
- ansible_facts.distribution_major_version == '11'
19+
1220
- name: set up test container and run tests inside it
1321
block:
1422
- name: install deps

tests/ansible/setup/report_controller.yml

+3-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
- name: Report controller parameters
2-
hosts: localhost
2+
hosts: test-targets[0]
33
gather_facts: false
44
tasks:
55
- debug:
@@ -9,9 +9,11 @@
99
- $(groups): "{{ lookup('pipe', 'groups') }}"
1010
- $(pwd): "{{ lookup('pipe', 'pwd') }}"
1111
- $(whoami): "{{ lookup('pipe', 'whoami') }}"
12+
- ansible_inventory_sources: "{{ ansible_inventory_sources | default('<unset>') }}"
1213
- ansible_run_tags: "{{ ansible_run_tags | default('<unset>') }}"
1314
- ansible_playbook_python: "{{ ansible_playbook_python | default('<unset>') }}"
1415
- ansible_skip_tags: "{{ ansible_skip_tags | default('<unset>') }}"
1516
- ansible_version.full: "{{ ansible_version.full | default('<unset>') }}"
1617
- is_mitogen: "{{ is_mitogen | default('<unset>') }}"
1718
- playbook_dir: "{{ playbook_dir | default('<unset>') }}"
19+
delegate_to: localhost

0 commit comments

Comments
 (0)