Ansible/ubuntu/fix-ssh-host-keys.yaml

71 lines
2.5 KiB
YAML
Executable File

---
# fix-ssh-host-keys.yaml
#
# Detects cloned VMs that share the same SSH host key and regenerates a
# unique key set on each one, then refreshes the controller's known_hosts.
#
# Run with host key checking disabled for this one remediation pass,
# since known_hosts is currently in a conflicted state:
#
# ANSIBLE_HOST_KEY_CHECKING=False ansible-playbook fix-ssh-host-keys.yaml
#
# The `duplicate_fingerprint` guard means only hosts presenting the shared
# key get touched. Hosts with an already-unique key are left alone.
- name: Regenerate shared SSH host keys on cloned guests
hosts: all
become: true
gather_facts: false
vars:
# The shared key every clone is currently presenting.
duplicate_fingerprint: "SHA256:AZekUU+Wwn6S6sCjGD0SdkhVgj3WVqVdiVYa1AXYW8A"
tasks:
- name: Read current ED25519 host key fingerprint
ansible.builtin.command:
cmd: ssh-keygen -lf /etc/ssh/ssh_host_ed25519_key.pub
register: hostkey_fp
changed_when: false
failed_when: false
- name: Regenerate host keys if this host shares the duplicate key
when: duplicate_fingerprint in (hostkey_fp.stdout | default(''))
block:
- name: Remove existing host keys
ansible.builtin.shell:
cmd: rm -f /etc/ssh/ssh_host_*
# rm on a glob isn't idempotent-reportable; treat as changed.
changed_when: true
- name: Generate a fresh unique set of host keys
ansible.builtin.command:
cmd: ssh-keygen -A
changed_when: true
- name: Restart SSH so the new key is served
ansible.builtin.service:
name: ssh
state: restarted
- name: Note that this host was remediated
ansible.builtin.debug:
msg: "{{ inventory_hostname }} had the shared key and was regenerated."
- name: Refresh known_hosts on the Ansible controller
hosts: localhost
gather_facts: false
vars:
known_hosts_path: "{{ lookup('env', 'HOME') }}/.ssh/known_hosts"
target_hosts: "{{ groups['all'] | difference(['localhost']) }}"
tasks:
- name: Remove stale entries for every managed host
ansible.builtin.command:
cmd: "ssh-keygen -f {{ known_hosts_path }} -R {{ item }}"
loop: "{{ target_hosts }}"
changed_when: false
- name: Rescan and add current keys
ansible.builtin.shell:
cmd: "ssh-keyscan -t ed25519,rsa,ecdsa {{ item }} >> {{ known_hosts_path }}"
loop: "{{ target_hosts }}"
changed_when: true