AnsibleのSSH接続エラーの回避設定

# AnsibleのSSH接続エラーの回避設定

## 概要
Managed NodeにSSHで一度も接続をしたことが無い時や、fingerprintが変わった時、OpenSSHのチェック機能により警告が表示され、ansibleの実行ができないことがあります。これを回避するための設定を記載します。

## 動作環境
CentOS 6
Ansible 2.1

## 警告メッセージが表示される状況
以下のような状況で警告メッセージが表示されます。

- Managed NodeにSSHで接続したことがなく、~/.ssh/known_hostsにfingerprintが無いとき。
  - sshでの接続時、以下のようなメッセージが表示されます。

```
The authenticity of host 'XXX.XXX.XXX.XXX (XXX.XXX.XXX.XXX)' 
can't be established.
RSA key fingerprint is XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX.
Are you sure you want to continue connecting (yes/no)?
```
  - ansibleやansible-playbookを実行時、以下のようなメッセージが表示されます。

```
Using a SSH password instead of a key is not possible 
because Host Key checking is enabled and sshpass does not support this.  
Please add this host's fingerprint to your known_hosts file to manage this host.
```

- Managed Nodeのサーバ更改後、初めてSSHで接続した時。
  （＝IPアドレスの変更はないが物理やＯＳが変更された）
  （＝fingerprintが変わり~/.ssh/known_hostsと値が一致しなくなった）
  - sshでの接続時、以下のようなメッセージが表示されます。

```
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@    WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED!     @
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
```

  - ansibleやansible-playbookを実行時、以下のようなメッセージが表示されます。

```
SSH encountered an unknown error during the connection. 
We recommend you re-run the command using -vvvv, 
which will enable SSH debugging output to help diagnose the issue
```

## 回避方法
- ansible.cfgのssh_argsの設定
/etc/ansible/ansible.cfgの[ssh_connection]のブロックに以下の設定を記載する。

```
[ssh_connection]
ssh_args = -o ControlMaster=auto -o ControlPersist=60s -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null
```

- 設定の意味
  - デフォルト設定  
    ControlMaster,ControlPersistはデフォルトの設定のままなので割愛。
  - StrictHostKeyChecking=no  
    ホストのデータベースファイル（デフォルトでは~/.ssh/known_hosts）に存在しないときに確認なしに接続する。  
    fingerprintは確認なしにホストのデータベースファイルに記録されていく。  
  - UserKnownHostsFile=/dev/null  
    ホストのデータベースファイル。（デフォルトでは~/.ssh/known_hosts）  
    データベースファイルを常に空(/dev/null)にすることで、Managed Nodeのサーバ更改時など、fingerprintが変わった時に、データベースファイルを整合性が取れずエラーとなってしまうのを回避する。

- 問題点
  - インベントリファイルに記載されているサーバは、すべて信頼できることが前提となる。

## 他の回避方法
1. 手動でSSHで接続  
   全ての対象サーバ・ユーザに対してSSHで接続を行う。
   - 問題点  
     対象が多いと手間である。  
     fingerprintが変わった時に対処（~/.ssh/known_hostsの修正）が必要になる。  
2. ansibleを実行するユーザのSSH設定
   ansibleを実行するControl MachineのユーザのSSH設定で、fingerprintのチェックを行わないようにする。
   - 設定（例）

```
$ vi ~/.ssh/config
Host 192.168.0.*
StrictHostKeyChecking no
UserKnownHostsFile=/dev/null
```
   - 問題点  
     Hostで記載した対象・範囲がすべて信頼できることが前提となる。  
     ansibleの実行時以外の通常のSSH接続時もこの設定が効いてくる。
3. ansible.cfgのhost_key_checkingの設定
   ansible.cfgに、host_key_checkingというStrictHostKeyCheckingに相当する設定項目がある。
   Anible公式のドキュメント（Docs>>Getting Started>>Host Key Checking）にはこれが掲載されている。
   - 設定（例）　[defaults]のブロックにhost_key_checking = Falseを設定

```
$ vi /etc/ansible/ansible.cfg
[defaults]
host_key_checking = False
```
   - 問題点  
     ~/.ssh/known_hostsに登録されている値のチェックは有効なので、fingerprintが変わった時にエラーになるので、その対処（~/.ssh/known_hostsの修正）が必要になる。

## おわりに
セキュリティ的には回避するのではなく、事前にSSHで接続してknown_hostsを作っていおいた方がよい。
ただ、fingerprintが変わるタイミングは、サーバ更改やハード交換といったときになるので、そこでknown_hostsの更新が必要と気づく人がどれだけいるだろか。かなりの割合でエラーになって調べて気づくのではないだろうか。

最終的には、セキュリティ・運用等の要件によって設定方法を選択する必要がある。

以上