How to add SSH fingerprints to known hosts in Ansible?

Viewed 830

I have the following inventory file:

[all]
192.168.1.107
192.168.1.108
192.168.1.109

I want to add fingerprints for these hosts to known_hosts file on local machine. I know that I can use the ansible.builtin.known_hosts but based on the docs:

Name parameter must match with "hostname" or "ip" present in key attribute.

it seems like I must already have keys generated and I must have three sets of keys - one set per host. I would like to have just one key for all my hosts.

Right now I can use this:

- name: accept new remote host ssh fingerprints at the local host
  shell: "ssh-keyscan -t 'ecdsa' {{item}} >> {{ssh_dir}}known_hosts"
  with_inventory_hostnames:
    - all

but the problem with this approach is that it is not idempotent - if I run it three times it will add three similar lines in the known_hosts file.

Another solution would be to check the known_hosts file for presence of a host ip and add it only if it is not present, but I could not figure out how to use variables in when condition to check for more than one host.

So the question is how can I add hosts fingerprints to local known_hosts file before generating a set of private/public keys in idempotent manner?

2 Answers

Here in my answer to "How to include all host keys from all hosts in group" I created a small Ansible look-up module host_ssh_keys to extract public SSH keys from the host inventory. Adding all hosts' public ssh keys to /etc/ssh/ssh_known_hosts is then as simple as this, thanks to Ansible's integration of loops with look-up plugins:

- name: Add public keys of all inventory hosts to known_hosts
  ansible.builtin.known_hosts:
    path: /etc/ssh/ssh_known_hosts
    name: "{{ item.host }}"
    key: "{{ item.known_hosts }}"
  with_host_ssh_keys: "{{ ansible_play_hosts }}"

For public SSH-Keys I use this one:

- hosts: localhost
  tasks:
  - set_fact:
      linuxkey: "{{ lookup('file', '~/.ssh/id_rsa.pub') }}"
    check_mode: no 

- hosts: all
  tasks: 

  - shell: 
      cmd: "sudo su - {{ application_user }}"
      stdin: "[[ ! `grep \"{{ hostvars['localhost']['linuxkey'] }}\" ~/.ssh/authorized_keys` ]] && echo '{{ hostvars['localhost']['linuxkey'] }}' >> ~/.ssh/authorized_keys"
      warn: no 
      executable: /bin/bash
    register: results
    failed_when: results.rc not in [0,1] 

I think you can easy adapt it for known_hosts file

Related