Network Automation Cookbook
上QQ阅读APP看书,第一时间看更新

There's more...

If we need to verify the identity of the SSH hosts that we will connect to, and thereby enable host_key_checking, we can automate the addition of the SSH public key of the remote managed hosts to the ~/.SSH/known_hosts file using Ansible. We create a new Ansible playbook that will run on the Ansible control machine to connect to the remote devices using the ssk-keyscan command. We then collect the SSH public keys for the remote machines and add them to the ~/.SSH/known_hosts file. The method is outlined here:

  1. Create a new playbook pb_gather_SSH_keys.yml file and add the following play:
- name: "Play2: Record Keys in Known Hosts file"
hosts: localhost
vars:
- hosts_file: "~/.SSH/known_hosts"
tasks:
- name: create know hosts file
file:
path: "{{ hosts_file }}"
state: file
changed_when: false
  1. Update the playbook and add another play within the same playbook to save and store the SSH public keys for the remote managed nodes:
- name: "Play2: Record Keys in Known Hosts file"
hosts: localhost
vars:
- hosts_file: "~/.SSH/known_hosts"
tasks:
- name: create know hosts file
file:
path: "{{ hosts_file }}"
state: file
changed_when: false
- name: Populate the known_hosts file
blockinfile:
block: |
{% for host in groups['all'] if hostvars[host].SSH_keys.stdout != ''
%}
{{ hostvars[host].SSH_keys.stdout}}
{% endfor %}
path: "{{ hosts_file }}"
create: yes

In our new playbook, we have a play that targets all our managed devices by setting the hosts parameter to all. In this play, we have a single task, which we run on the Ansible control node (using the delegate_to localhost) to issue the SSH-keyscan command, which returns the SSH public key for the remote device, as shown in the following code:

$ SSH-keyscan 172.20.1.22

# 172.20.1.22:22 SSH-2.0-Cisco-1.25
172.20.1.22 SSH-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDTwrH4phzRnW/RsC8eXMh/accIErRfkgffDWBGSdEX0r9EwAa6p2uFMWj8dq6kvrREuhqpgFyMoWmpgdx5Cr+10kEonr8So5yHhOhqG1SJO9RyzAb93H0P0ro5DXFK8A/Ww+m++avyZ9dShuWGxKj9CDM6dxFLg9ZU/9vlzkwtyKF/+mdWNGoSiCbcBg7LrOgZ7Id7oxnhEhkrVIa+IxxGa5Pwc73eR45Uf7QyYZXPC0RTOm6aH2f9+8oj+vQMsAzXmeudpRgAu151qUH3nEG9HIgUxwhvmi4MaTC+psmsGg2x26PKTOeX9eLs4RHquVS3nySwv4arqVzDqWf6aruJ
In this task, we are using delegate_to as being equal to localhost, as Ansible will try to connect to the remote devices and issue the command on the remote device by default. In our case, this is not what we need; we need to issue this command from the Ansible control node. So, we use delegate_to as being equal to localhost in order to enforce this behavior.

We run the second play on the Ansible control host by setting hosts to localhost, and we execute tasks to create the known hosts file (if not already present) and to populate this file with the data that we captured in the first play using the SSH_keys variable. We run this playbook on the Ansible control machine to store the SSH keys from the remotely managed nodes prior to running any of our playbooks.