[2.12] Add accept_newhostkey option to git module (#73819)

* Add integration test for accept_newhostkey option

* Add changelog
pull/74317/head
Amin Vakil 4 years ago committed by GitHub
parent 019452dda7
commit a7c8093ce4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -0,0 +1,3 @@
---
minor_changes:
- git - Add ``accept_newhostkey`` option (https://github.com/ansible/ansible/issues/69846).

@ -48,6 +48,15 @@ options:
type: bool type: bool
default: 'no' default: 'no'
version_added: "1.5" version_added: "1.5"
accept_newhostkey:
description:
- As of OpenSSH 7.5, "-o StrictHostKeyChecking=accept-new" can be
used which is safer and will only accepts host keys which are
not present or are the same. if C(yes), ensure that
"-o StrictHostKeyChecking=accept-new" is present as an ssh option.
type: bool
default: 'no'
version_added: "2.12"
ssh_opts: ssh_opts:
description: description:
- Creates a wrapper script and exports the path as GIT_SSH - Creates a wrapper script and exports the path as GIT_SSH
@ -317,6 +326,7 @@ from distutils.version import LooseVersion
from ansible.module_utils.basic import AnsibleModule from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils.six import b, string_types from ansible.module_utils.six import b, string_types
from ansible.module_utils._text import to_native, to_text from ansible.module_utils._text import to_native, to_text
from ansible.module_utils.common.process import get_bin_path
def relocate_repo(module, result, repo_dir, old_repo_dir, worktree_dir): def relocate_repo(module, result, repo_dir, old_repo_dir, worktree_dir):
@ -462,6 +472,21 @@ def get_version(module, git_path, dest, ref="HEAD"):
return sha return sha
def ssh_supports_acceptnewhostkey(module):
try:
ssh_path = get_bin_path('ssh')
except ValueError as err:
module.fail_json(
msg='Remote host is missing ssh command, so you cannot '
'use acceptnewhostkey option.', details=to_text(err))
supports_acceptnewhostkey = True
cmd = [ssh_path, '-o', 'StrictHostKeyChecking=accept-new', '-V']
rc, stdout, stderr = module.run_command(cmd)
if rc != 0:
supports_acceptnewhostkey = False
return supports_acceptnewhostkey
def get_submodule_versions(git_path, module, dest, version='HEAD'): def get_submodule_versions(git_path, module, dest, version='HEAD'):
cmd = [git_path, 'submodule', 'foreach', git_path, 'rev-parse', version] cmd = [git_path, 'submodule', 'foreach', git_path, 'rev-parse', version]
(rc, out, err) = module.run_command(cmd, cwd=dest) (rc, out, err) = module.run_command(cmd, cwd=dest)
@ -1107,6 +1132,7 @@ def main():
verify_commit=dict(default='no', type='bool'), verify_commit=dict(default='no', type='bool'),
gpg_whitelist=dict(default=[], type='list', elements='str'), gpg_whitelist=dict(default=[], type='list', elements='str'),
accept_hostkey=dict(default='no', type='bool'), accept_hostkey=dict(default='no', type='bool'),
accept_newhostkey=dict(default='no', type='bool'),
key_file=dict(default=None, type='path', required=False), key_file=dict(default=None, type='path', required=False),
ssh_opts=dict(default=None, required=False), ssh_opts=dict(default=None, required=False),
executable=dict(default=None, type='path'), executable=dict(default=None, type='path'),
@ -1119,7 +1145,7 @@ def main():
archive_prefix=dict(), archive_prefix=dict(),
separate_git_dir=dict(type='path'), separate_git_dir=dict(type='path'),
), ),
mutually_exclusive=[('separate_git_dir', 'bare')], mutually_exclusive=[('separate_git_dir', 'bare'), ('accept_hostkey', 'accept_newhostkey')],
required_by={'archive_prefix': ['archive']}, required_by={'archive_prefix': ['archive']},
supports_check_mode=True supports_check_mode=True
) )
@ -1150,11 +1176,21 @@ def main():
if module.params['accept_hostkey']: if module.params['accept_hostkey']:
if ssh_opts is not None: if ssh_opts is not None:
if "-o StrictHostKeyChecking=no" not in ssh_opts: if ("-o StrictHostKeyChecking=no" not in ssh_opts) and ("-o StrictHostKeyChecking=accept-new" not in ssh_opts):
ssh_opts += " -o StrictHostKeyChecking=no" ssh_opts += " -o StrictHostKeyChecking=no"
else: else:
ssh_opts = "-o StrictHostKeyChecking=no" ssh_opts = "-o StrictHostKeyChecking=no"
if module.params['accept_newhostkey']:
if not ssh_supports_acceptnewhostkey(module):
module.warn("Your ssh client does not support accept_newhostkey option, therefore it cannot be used.")
else:
if ssh_opts is not None:
if ("-o StrictHostKeyChecking=no" not in ssh_opts) and ("-o StrictHostKeyChecking=accept-new" not in ssh_opts):
ssh_opts += " -o StrictHostKeyChecking=accept-new"
else:
ssh_opts = "-o StrictHostKeyChecking=accept-new"
# evaluate and set the umask before doing anything else # evaluate and set the umask before doing anything else
if umask is not None: if umask is not None:
if not isinstance(umask, string_types): if not isinstance(umask, string_types):

@ -21,6 +21,7 @@
- import_tasks: formats.yml - import_tasks: formats.yml
- import_tasks: missing_hostkey.yml - import_tasks: missing_hostkey.yml
- import_tasks: missing_hostkey_acceptnew.yml
- import_tasks: no-destination.yml - import_tasks: no-destination.yml
- import_tasks: specific-revision.yml - import_tasks: specific-revision.yml
- import_tasks: submodules.yml - import_tasks: submodules.yml

@ -46,3 +46,16 @@
that: that:
- git_result is changed - git_result is changed
when: github_ssh_private_key is defined when: github_ssh_private_key is defined
- name: MISSING-HOSTEKY | Remove github.com hostkey from known_hosts
lineinfile:
dest: '{{ output_dir }}/known_hosts'
regexp: "github.com"
state: absent
when: github_ssh_private_key is defined
- name: MISSING-HOSTKEY | clear checkout_dir
file:
state: absent
path: '{{ checkout_dir }}'
when: github_ssh_private_key is defined

@ -0,0 +1,78 @@
- name: MISSING-HOSTKEY | check accept_newhostkey support
shell: ssh -o StrictHostKeyChecking=accept-new -V
register: ssh_supports_accept_newhostkey
ignore_errors: true
- block:
- name: MISSING-HOSTKEY | accept_newhostkey when ssh does not support the option
git:
repo: '{{ repo_format2 }}'
dest: '{{ checkout_dir }}'
accept_newhostkey: true
ssh_opts: '-o UserKnownHostsFile={{ output_dir }}/known_hosts'
register: git_result
ignore_errors: true
- assert:
that:
- git_result is failed
- git_result.warnings is search("does not support")
when: ssh_supports_accept_newhostkey.rc != 0
- name: MISSING-HOSTKEY | checkout ssh://git@github.com repo without accept_newhostkey (expected fail)
git:
repo: '{{ repo_format2 }}'
dest: '{{ checkout_dir }}'
ssh_opts: '-o UserKnownHostsFile={{ output_dir }}/known_hosts'
register: git_result
ignore_errors: true
- assert:
that:
- git_result is failed
- block:
- name: MISSING-HOSTKEY | checkout git@github.com repo with accept_newhostkey (expected pass)
git:
repo: '{{ repo_format2 }}'
dest: '{{ checkout_dir }}'
accept_newhostkey: true
key_file: '{{ github_ssh_private_key }}'
ssh_opts: '-o UserKnownHostsFile={{ output_dir }}/known_hosts'
register: git_result
- assert:
that:
- git_result is changed
- name: MISSING-HOSTKEY | clear checkout_dir
file:
state: absent
path: '{{ checkout_dir }}'
- name: MISSING-HOSTKEY | checkout ssh://git@github.com repo with accept_newhostkey (expected pass)
git:
repo: '{{ repo_format3 }}'
dest: '{{ checkout_dir }}'
version: 'master'
accept_newhostkey: false # should already have been accepted
key_file: '{{ github_ssh_private_key }}'
ssh_opts: '-o UserKnownHostsFile={{ output_dir }}/known_hosts'
register: git_result
- assert:
that:
- git_result is changed
- name: MISSING-HOSTEKY | Remove github.com hostkey from known_hosts
lineinfile:
dest: '{{ output_dir }}/known_hosts'
regexp: "github.com"
state: absent
- name: MISSING-HOSTKEY | clear checkout_dir
file:
state: absent
path: '{{ checkout_dir }}'
when: github_ssh_private_key is defined and ssh_supports_accept_newhostkey.rc == 0
Loading…
Cancel
Save