[Ansible] 將 public key 加入 known hosts

SSH RSA key fingerprint

在使用 Ansible 部署時,常常會需要使用到 git clone 或 scp 等方式,透過 ssh 去另一台主機抓取專案程式碼或檔案,平常如果是手動在一台全新的機器第一次使用 ssh 連線,通常會跳出詢問對話:

$ git clone git@github.com:SarsTW/Learn-Git-in-30-days.git
Cloning into 'Learn-Git-in-30-days'...
The authenticity of host 'github.com (192.30.252.120)' can't be established.
RSA key fingerprint is SHA256:nThbg6kXUpJWGl7E1IGOCspRomTxdCARLviKw6E5SY8.
Are you sure you want to continue connecting (yes/no)?


在 Ansible 1.9 之前,通常會使用 Managing ssh known hosts with ansible 這篇文章提到的方式,將主機加入 known_hosts 列表中:

- name: Make sure the known hosts file exists
  file: "path={{ ssh_known_hosts_file }} state=touch"

- name: Check host name availability
  shell: "ssh-keygen -f {{ ssh_known_hosts_file }} -F {{ item }}"
  with_items: ssh_known_hosts
  register: ssh_known_host_results
  ignore_errors: yes

- name: Scan the public key
  shell: "{{ ssh_known_hosts_command}} {{ item.item }} >> {{ ssh_known_hosts_file }}"
  with_items: ssh_known_host_results.results
  when: item.stdout == ""

搭配 Ansible 變數

ssh_known_hosts_command: "ssh-keyscan -H -T 10"
ssh_known_hosts_file: "/etc/ssh/ssh_known_hosts"
ssh_known_hosts:
- foo.example.com
- bar.example.org

這篇的作法主要就是先透過 ssh-keyscan 取得主機的 RSA public key,然後加入 known_hosts 檔案中,這樣之後在使用 ssh 連線時,就不會跳出 ECDSA key fingerprint 的確認視窗。


但在 Ansible 1.9 之後,出現了 known_hosts 這個 module,用法很簡單,以 github.com 為例,先使用 ssh-keyscan github.com 指令取得 github.com 的 public key,並將結果寫入 pubkeys/github.com.pub 檔案之中:

$ ssh-keyscan github.com > pubkeys/github.com.pub
$ cat pubkeys/github.com.pub
github.com ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEAq2A7hRGmdnm9tUDbO9IDSwBK6TbQa+PXYPCPy6rbTrTtw7PHkccKrpp0yVhp5HdEIcKr6pLlVDBfOLX9QUsyCOV0wzfjIJNlGEYsdlLJizHhbn2mUjvSAHQqZETYP81eFzLQNnPHt4EVVUh7VfDESU84KezmD5QlWpXLmvU31/yMf+Se8xhHTvKSCZIFImWwoG6mbUoWf9nzpIoaSjB+weqqUUmpaaasXVal72J+UX2B+2RPW3RcT0eOzQgqlJL3RKrTJvdsjE3JEAvGq3lGHSZXy28G3skua2SmVi/w4yCE6gbODqnTWlg7+wC604ydGXA8VJiS5ap43JXiUFFAaQ==

最後再寫一個使用 known_hosts module 的 task:

- name: tell the host about our servers it might want to ssh to
  known_hosts: path='/etc/ssh/ssh_known_hosts' name='github.com' key="{{ lookup('file', 'pubkeys/github.com') }}"

這樣就大功告成了!

Leave a Reply

Your email address will not be published. Required fields are marked *