Andible のパスワード/パスフレーズ自動入力

Ansible で使用するパスワードの指定(利用方法)に関するまとめ。

# サマリ

## ssh 接続のパスワード

* ssh のパスワードを自動入力するためには、sshpass が必要。
* sshpass は ansible のモジュールではないため、別途インストールが必要。
* sshpass は、"assword" という文字列 (プロンプト) が表示されるのを待って、パスワードを入力。
* ansible から呼び出す sshpass へ引数を渡す方法が用意されていないため、秘密鍵のパスフレーズ入力には(そのままでは)使用不可。
* 秘密鍵のパスフレーズは外さずに ssh-agent/ssh-add を使用。
* やむを得ずパスワード/パスフレーズを設定ファイル等に記載する場合には、ansible-vault で暗号化。
* ログインパスワードは一般的に sudo 権限昇格のパスワードと同じため、公開鍵暗号等に速やかに移行。

## become (sudo) パスワード

* パスワードを記載する必要がある場合には、ansible-vault で暗号化。

## 公開鍵暗号の秘密鍵のファイル名の tips

* sshpass プログラムはデフォルトで "`assword`" を含むプロンプトを期待している。
* ssh のパスフレーズ入力プロンプトは "`Enter passphrase for key '...id_rsa':`" となっており、"assword" を含まない。(そのため、sshpass がプロントを待ち続けて、そのままでは自動化できない)
* 秘密鍵のファイル名に "`assword`" を含めると、プロンプトに "`assword`" を含むことになり、sshpass がデフォルトのまま利用可能。

ということで、秘密鍵のファイル名に "`assword`" を含めれば、ansible でもパスフレーズを自動入力できるようになります。 

## ansible-valut: vault-id の tips

* 暗号化された文字列のヘッダに *label* がついていても、vault-id-list に設定された ID のパスワードファイルを頭から順に試している模様。
* つまり、現バージョンでは、*label* は人間が識別するためのもので、ansible-vault プログラムにとっては、ほとんど意味をなしていない。(と思われる)

---

# 前提環境

## OS 環境
コントロールホスト OS: Ubuntu 18.04
対象ホスト OS: Ubuntu 18.04 (docker) × 2

```text:/etc/os-release
NAME="Ubuntu"
VERSION="18.04.3 LTS (Bionic Beaver)"
ID=ubuntu
ID_LIKE=debian
PRETTY_NAME="Ubuntu 18.04.3 LTS"
VERSION_ID="18.04"
HOME_URL="https://www.ubuntu.com/"
SUPPORT_URL="https://help.ubuntu.com/"
BUG_REPORT_URL="https://bugs.launchpad.net/ubuntu/"
PRIVACY_POLICY_URL="https://www.ubuntu.com/legal/terms-and-policies/privacy-policy"
VERSION_CODENAME=bionic
UBUNTU_CODENAME=bionic
```

## Python 環境
```shell_session:Python仮想環境
(ansible) $ pip freeze
ansible==2.9.2
cffi==1.13.2
cryptography==2.8
Jinja2==2.10.3
MarkupSafe==1.1.1
passlib==1.7.2
pkg-resources==0.0.0
pycparser==2.19
PyYAML==5.2
six==1.13.0
(ansible) $
```

## 接続先とパスフレーズ等接続環境

| 接続先 IP address| ssh 接続 |秘密鍵パスフレーズ| ユーザ名&sudo 利用|
|:--|:-:|:--|:-:|
|172.17.0.2|公開鍵方式|"`privkey_passphrase`"| pubkeyuser |
||||パスワード: "`pubkeyuser_password`"|
|172.17.0.3|パスワード入力|-| pwduser |
||||パスワード: "`pwduser_password`"|

## Ansible 環境

### Ansible バージョン
```shell_session:コントロールホストのansibleバージョン
(ansible) $ ansible --version
ansible 2.9.2
  config file = /home/luser/work/ansible.cfg
  configured module search path = ['/home/luser/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules']
  ansible python module location = /home/luser/work/Python.d/envs/ansible/lib/python3.6/site-packages/ansible
  executable location = /home/luser/work/Python.d/envs/ansible/bin/ansible
  python version = 3.6.9 (default, Nov  7 2019, 10:44:02) [GCC 8.3.0]
(ansible) $
```

### Ansible hosts ファイル
```ini:./hosts
[hostgroup]
172.17.0.2
172.17.0.3
```
## Ansible の DEPRECATION WARNING の抑制
接続先で python2  ではなく、明示的に python3 を使うようにし、`DEPRECATION WARNING` を抑制するため、以下のような ansible.cfg をカレントディレクトリに置きます。
(`deprecation_warnings=False` を設定してもよいのですが、他の警告まで消えてしまわないように)

### ansible.cfg ファイル
```ini:./ansible.cfg(初期設定)
[defaults]
interpreter_python      = /usr/bin/python3
```

## 秘密鍵
動作確認用の秘密鍵をカレントディレクトリに置きます。

### pubkeyuser_id_rsa ファイル
```shell-session:秘密鍵のパーミッション
(ansible) $ ls -l pubkeyuser_id_rsa
-rw------- 1 luser luser 1766 Jan 11 02:19 pubkeyuser_id_rsa
```

## ファイル構成

```shell_session:初期ファイル構成
(ansible) $ tree -a ./
./
|-- ansible.cfg
|-- host_vars
|   |-- 172.17.0.2.yml
|   `-- 172.17.0.3.yml
|-- hosts
|-- pubkeyuser_id_rsa
`-- pubkeyuser_id_rsa_assword -> pubkeyuser_id_rsa

1 directory, 6 files
(ansible) $
```

前提ここまで。

---

# Ansible で使用するパスワード(パスフレーズ)の種類

1. ssh 接続時のパスワード/パスフレーズ
2. sudo (become) 時のパスワード


## ssh 接続のパスワード/パスフレーズ設定
参照: [ssh – connect via ssh client binary — Ansible Documentation](https://docs.ansible.com/ansible/latest/plugins/connection/ssh.html)

ssh 接続は主に以下の2つの方法で行われます。

1. 公開鍵暗号を用いた接続
2. PAM パスワードによる接続

## 公開鍵暗号を用いた接続

```shell-session:公開鍵によるssh接続確認
(ansible) $ ssh -i ./pubkeyuser_id_rsa pubkeyuser@172.17.0.2
Enter passphrase for key './pubkeyuser_id_rsa':  ← ここで秘密鍵のパスフレーズを入力
Last login: Tue Jan  7 08:00:57 2020 from 172.17.0.1
$ id -a
uid=1001(pubkeyuser) gid=1001(pubkeyuser) groups=1001(pubkeyuser),27(sudo)
$ exit
Connection to 172.17.0.2 closed.
(ansible) $
```

ansible での接続は以下のようになります。

```shell-session:公開鍵によるansible動作確認
(ansible) $ ansible -i hosts -u pubkeyuser --private-key pubkeyuser_id_rsa 172.17.0.2 -m ping
Enter passphrase for key 'pubkeyuser_id_rsa':  ← ここで秘密鍵のパスフレーズを入力
172.17.0.2 | SUCCESS => {
    "changed": false,
    "ping": "pong"
}
(ansible) $
```

### ssh-agent/ssh-add の利用
sh-agent/ssh-add を利用して、パスフレーズの入力を避けることができます。

> * Ansible does not expose a channel to allow communication between the user and the ssh process to accept a password manually to decrypt an ssh key when using this connection plugin (which is the default). The use of ssh-agent is highly recommended.

Ansible のドキュメントでも、ssh-agent の利用を強く推奨しています。

```shell_session:ssh-agentとssh-addを用いた接続確認
(ansible) $ eval `ssh-agent`
Agent pid 3256
(ansible) $ echo $SSH_AUTH_SOCK
/tmp/ssh-dcXxsNEXR7zu/agent.3254
(ansible) $ ssh-add pubkeyuser_id_rsa
Enter passphrase for pubkeyuser_id_rsa:
Identity added: pubkeyuser_id_rsa (pubkeyuser_id_rsa)
(ansible) $ ssh-add -l
2048 SHA256:Skhwkjn4nNRdRzWxNZBRGSPamcZikVkeBVpPhtFzgXw pubkeyuser_id_rsa (RSA)
(ansible) $ ansible -i hosts -u pubkeyuser --private-key pubkeyuser_id_rsa 172.17.0.2 -m ping
172.17.0.2 | SUCCESS => {
    "changed": false,
    "ping": "pong"
}
(ansible) $
```

csh 系を使用している場合には、``eval `ssh-agent -c` `` というように、`-c` オプションを付けます。

### バッチ処理におけるパスフレーズの設定
インタラクティブ(会話型)ではなく、バッチ処理のように、無人で起動するような場合には、設定が必要になります。

#### ssh-agent/ssh-add の利用
* ssh-agent は、(通常)ログアウトしてもプロセスが残り、ソケットが利用可能です。
* これを利用すると、非インタラクティブな処理でもパスワードの入力を省略できます。

以下のようなシェルスクリプトを ~/.bashrc から呼び出す (あるいは、.bashrc に直接記述する) と、既存のプロセスを再利用できます。

```shell:setup-ssh-agent.sh
#!/bin/sh

[ $(id -u) -eq 0 ] && exit 255

LANG=C
SSH_AGENT=ssh-agent
SSH_AGENT_SAVED=${SSH_AGENT_SAVED:-"${HOME}/.ssh/.${SSH_AGENT}"}

AGENT_ENV=""

if [ -f ${SSH_AGENT_SAVED} ]
then
        eval $(tail -1 ${SSH_AGENT_SAVED}) > /dev/null

        if (ps -fp ${SSH_AGENT_PID} | sed -e 's/  */ /g' | cut -d' ' -f 8 | grep '^ssh-agent$' > /dev/null)
        then
                AGENT_ENV=$(tail -1 ${SSH_AGENT_SAVED})
        else
                AGENT_ENV=$(${SSH_AGENT})
        fi
else
        AGENT_ENV=$(${SSH_AGENT})
fi

echo ${AGENT_ENV} | tee ${SSH_AGENT_SAVED}
chmod 0600 ${SSH_AGENT_SAVED}
```

ssh-agent の環境変数設定を読み込んで、ansible コマンドを利用するようにするとよいでしょう。

非インタラクティブな実行でも、前処理として、実行済み ssh-agent/ssh-add に関する環境変数の読み込みなどを行う必要があります。
パスワード自体をファイルなどで保存しておく必要がない、という点で、推奨されます。


#### sshpass の利用

sshpass を利用すると、パスフレーズ記載したファイルを指定して実行できます。

sshpass は ansible の一部ではないので、別途インストールする必要があります。

```shell_session:sshpassのインストールと動作確認
(ansible) $ sudo apt install sshpass
Reading package lists... Done
Building dependency tree
Reading state information... Done
The following NEW packages will be installed:
  sshpass
0 upgraded, 1 newly installed, 0 to remove and 0 not upgraded.
:
Processing triggers for man-db (2.8.3-2ubuntu0.1) ...
(ansible) $ ls -l ~/.ansible_rings/.pubkeyuser_passphrase
-rw------- 1 luser luser 19 Jan 12 21:00 /home/luser/.ansible_rings/.pubkeyuser_passphrase
(ansible) $ cat ~/.ansible_rings/.pubkeyuser_passphrase
privkey_passphrase
(ansible) $ sshpass -P "pubkeyuser_id_rsa':" -f ~/.ansible_rings/.pubkeyuser_passphrase ansible -i hosts -u pubkeyuser --private-key pubkeyuser_id_rsa 172.17.0.2 -m ping
172.17.0.2 | SUCCESS => {
    "changed": false,
    "ping": "pong"
}
(ansible) $ cat ~/.ansible_rings/.pubkeyuser_passphrase | sshpass -P "pubkeyuser_id_rsa':" -d 0 ansible -i hosts -u pubkeyuser --private-key pubkeyuser_id_rsa 172.17.0.2 -m ping
172.17.0.2 | SUCCESS => {
    "changed": false,
    "ping": "pong"
}
(ansible) $
```

sshpass を非インタラクティブに使用する場合には、どこかに平文でパスフレーズを保存しておく必要があることに注意してください。
sshpass は、パスワード入力のプロンプトとして "`assword`" を期待しているので、秘密鍵のパスフレーズを入力する際のプロンプトを `-P` オプションで指定する必要があります。

ところが、ansible から sshpass へ引数を渡す方法が用意されていません。
そこで、"`assword`" がプロンプトに現れるように、プライベートキーのファイル名に "`assword`" を含めます。

```shell_session:秘密鍵のファイル名設定
(ansible) $ ln -s pubkeyuser_id_rsa pubkeyuser_id_rsa_assword
(ansible) $ ls -l pubkeyuser_id_rsa pubkeyuser_id_rsa_assword
-rw------- 1 luser luser 1766 Jan 11 02:19 pubkeyuser_id_rsa
lrwxrwxrwx 1 luser luser   17 Jan 12 21:12 pubkeyuser_id_rsa_assword -> pubkeyuser_id_rsa
(ansible) $
```

[ssh – connect via ssh client binary — Ansible Documentation](https://docs.ansible.com/ansible/latest/plugins/connection/ssh.html) の "password" の行を見ると、変数(var)として

> var: ansible_password
> var: ansible_ssh_pass
> var: ansible_ssh_password

が使えることが記載されています。
そこで、172.17.0.2 のホストにパスワードを設定します。
(tips として後述しますが、"`ansible_ssh_password`" は使用しないほうが無難です)

```yaml:./host_vars/172.17.0.2.yml
---
# Remote User
ansible_ssh_user: pubkeyuser
# 秘密鍵
ansible_private_key_file: ./pubkeyuser_id_rsa_assword
# SSH 共通引数
ansible_ssh_common_args: "-o PubkeyAuthentication=yes -o PasswordAuthentication=no -o StrictHostKeyChecking=no"
# SSH 秘密鍵パスフレーズ
ansible_ssh_pass: 'privkey_passphrase'
```

```shell_session:動作確認
(ansible) $ ansible 172.17.0.2 -m ping
172.17.0.2 | SUCCESS => {
    "changed": false,
    "ping": "pong"
}
(ansible) $
```

パスフレーズの入力をせずに実行することができました。

## PAM パスワードによる接続
ログインパスワードを用いた接続は避けたいところ[^脚注1] ですが、何らかの事情でユーザのパスワードで ssh 接続を行わなければならないことがあります。
例えば、初期状態で、public キーがまだコピーできていないようなケースです。(可能であれば、ansible 実行前に公開鍵の登録を行いたいところです)

[^脚注1]: 一般に、ログインパスワードを用いた接続で入力するパスワードと、sudo によって管理者権限へ昇格する場合のパスワードは同じため、ログインパスワードが漏れると、対象サーバ上の管理者権限が奪われるリスクが高くなります。ログインのためのパスワード/パスフレーズと、権限昇格のための sudo で用いるパスワードは、分けておく(つまり、ログインはできるだけログインパスワード以外で利用する)ことをお勧めします。

```shell-session:sshの接続確認
(ansible) $ ssh -o PubkeyAuthentication=no -o PasswordAuthentication=yes -o StrictHostKeyChecking=no pwduser@172.17.0.3 id -a
pwduser@172.17.0.3's password: ← "pwduser" のログインパスワードを入力
uid=1001(pwduser) gid=1001(pwduser) groups=1001(pwduser),27(sudo)
(ansible) $
```

このようなケースでは、SSH のパスワードを入力する必要があります。

```shell_session:パスワードでのansibleの試み
(ansible) $ ansible --ssh-common-args="-o PubkeyAuthentication=no -o PasswordAuthentication=yes -o StrictHostKeyChecking=no" -i hosts -u pwduser 172.17.0.3 -m ping
172.17.0.3 | UNREACHABLE! => {
    "changed": false,
    "msg": "Failed to connect to the host via ssh: Permission denied (publickey,password).",
    "unreachable": true
}
(ansible) $
```

ansible では、`-k` オプションを指定することで、SSH のパスワードを訊いてきますが、このオプションを付けないと、上のようにエラーになります。

```shell_session:-kオプションを指定したansible実行
(ansible) $ ansible --ssh-common-args="-o PubkeyAuthentication=no -o PasswordAuthentication=yes -o StrictHostKeyChecking=" -i hosts -u pwduser 172.17.0.3 -m ping -k
SSH password:
172.17.0.3 | FAILED! => {
    "msg": "to use the 'ssh' connection type with passwords, you must install the sshpass program"
}
(ansible) $
```

`-k` オプションをつけることで、パスワード入力のプロンプトが出ましたが、こんどは、「sshpass プログラムをインストールしろ(`"to use the 'ssh' connection type with passwords, you must install the sshpass program"`)」と言ってきます。公開鍵での接続の際にも利用しましたが、sshpass は ansible の一部ではありませんので、別途インストールする必要があります。

```shell_session:sshpassのインストール
(ansible) $ sudo apt install sshpass
Reading package lists... Done
Building dependency tree
Reading state information... Done
The following NEW packages will be installed:
  sshpass
0 upgraded, 1 newly installed, 0 to remove and 0 not upgraded.
:
Processing triggers for man-db (2.8.3-2ubuntu0.1) ...
(ansible) $
```

sshpass をインストールすると、動作するようになります。

```shell_session:sshpassインストール後の接続確認
(ansible) $ ansible --ssh-common-args="-o PubkeyAuthentication=no -o PasswordAuthentication=yes -o StrictHostKeyChecking=no" -i hosts -u pwduser 172.17.0.3 -m ping -k
SSH password:
172.17.0.3 | SUCCESS => {
    "changed": false,
    "ping": "pong"
}
(ansible) $
```

### バッチ処理におけるパスフレーズの設定

公開鍵の場合と同様に、172.17.0.3.yml で変数を設定します。

```yaml:./host_vars/172.17.0.3.yml
---
# Remote User
ansible_ssh_user: pwduser
# パスワード認証の指定
ansible_ssh_common_args: '-o PreferredAuthentications=password -o PubkeyAuthentication=no -o PasswordAuthentication=yes -o StrictHostKeyChecking=no'
# 認証パスワード
ansible_ssh_pass: 'pwduser_password'
```

```shell_session: 
(ansible) $ ansible 172.17.0.3 -m ping
172.17.0.3 | SUCCESS => {
    "changed": false,
    "ping": "pong"
}
(ansible) $
```

パスワードの入力をせずに実行することができました。


# sudo (become) 時のパスワード
参照: [sudo – Substitute User DO — Ansible Documentation](https://docs.ansible.com/ansible/latest/plugins/become/sudo.html)

[sudo – Substitute User DO — Ansible Documentation](https://docs.ansible.com/ansible/latest/plugins/become/sudo.html) を参照すると、パスワードの設定は以下のように記載されています。

> ini entries:
> [sudo_become_plugin]
> password = VALUE
> 
> env:ANSIBLE_BECOME_PASS
> env:ANSIBLE_SUDO_PASS
> var: ansible_become_password
> var: ansible_become_pass
> var: ansible_sudo_pass

変数(var) `ansible_become_pass` を使って、`172.17.0.2.yml` と `172.17.0.3.yml` に設定します。

```yaml:./host_vars/172.17.0.2.yml
---
# Remote User
ansible_ssh_user: pubkeyuser
# 秘密鍵
ansible_private_key_file: ./pubkeyuser_id_rsa_assword
# SSH 共通引数
ansible_ssh_common_args: "-o PubkeyAuthentication=yes -o PasswordAuthentication=no -o StrictHostKeyChecking=no"
# SSH 秘密鍵パスフレーズ
ansible_ssh_pass: 'privkey_passphrase'

# become (sudo) パスワード
ansible_sudo_pass: 'pubkeyuser_password'
```

```yaml:./host_vars/172.17.0.3.yml
---
# Remote User
ansible_ssh_user: pwduser
# パスワード認証の指定
ansible_ssh_common_args: '-o PreferredAuthentications=password -o PubkeyAuthentication=no -o PasswordAuthentication=yes -o StrictHostKeyChecking=no'
# 認証パスワード
ansible_ssh_pass: 'pwduser_password'

# become (sudo) パスワード
ansible_sudo_pass: 'pwduser_password'
```

パスワードを入力せずに(非インタラクティブで) become が実行できるようになります。

```shell_session:非インタラクティブなbecomeの動作確認
(ansible) $ ( set -x; for h in 172.17.0.2 172.17.0.3 hostgroup; do ansible $h -m command -a 'id -a'; ansible $h -m command -a 'id -a' -b; done )
+ for h in 172.17.0.2 172.17.0.3 hostgroup
+ ansible 172.17.0.2 -m command -a 'id -a'
172.17.0.2 | CHANGED | rc=0 >>
uid=1001(pubkeyuser) gid=1001(pubkeyuser) groups=1001(pubkeyuser),27(sudo)

+ ansible 172.17.0.2 -m command -a 'id -a' -b
172.17.0.2 | CHANGED | rc=0 >>
uid=0(root) gid=0(root) groups=0(root)

+ for h in 172.17.0.2 172.17.0.3 hostgroup
+ ansible 172.17.0.3 -m command -a 'id -a'
172.17.0.3 | CHANGED | rc=0 >>
uid=1001(pwduser) gid=1001(pwduser) groups=1001(pwduser),27(sudo)

+ ansible 172.17.0.3 -m command -a 'id -a' -b
172.17.0.3 | CHANGED | rc=0 >>
uid=0(root) gid=0(root) groups=0(root)

+ for h in 172.17.0.2 172.17.0.3 hostgroup
+ ansible hostgroup -m command -a 'id -a'
172.17.0.3 | CHANGED | rc=0 >>
uid=1001(pwduser) gid=1001(pwduser) groups=1001(pwduser),27(sudo)

172.17.0.2 | CHANGED | rc=0 >>
uid=1001(pubkeyuser) gid=1001(pubkeyuser) groups=1001(pubkeyuser),27(sudo)

+ ansible hostgroup -m command -a 'id -a' -b
172.17.0.3 | CHANGED | rc=0 >>
uid=0(root) gid=0(root) groups=0(root)

172.17.0.2 | CHANGED | rc=0 >>
uid=0(root) gid=0(root) groups=0(root)

(ansible) $
```

# ansible-vault を利用した暗号化
参照: [Ansible Vault — Ansible Documentation](https://docs.ansible.com/ansible/latest/user_guide/vault.html)

パスワード/パスフレーズを各変数に設定することで、入力せずに実行できるようになりましたが、パスワード/パスフレーズが平文で残っているのは好ましくありません。

そこで、ansible-vault を利用して、暗号化します。
ansible-vault で、以下のようなことができます。

* ファイル全体を暗号化する
* key=value を暗号化する
* value 部分を暗号化する

詳しいことは参照先の "[Ansible Vault — Ansible Documentation](https://docs.ansible.com/ansible/latest/user_guide/vault.html)" を見ていただくとして、ここでは、3番目の value 部分を暗号化した実例を示します。

ansible-vault には、vault-id というものがありますが、これがドキュメントではわかりにくくなっています。

* `--vault-id` オプションで、ID **リスト** (カンマ区切りで複数指定可) を提示し、`--encrypt-vault-id` オプションで、暗号化時の ID (*label*) を指定します。
* vault-id の形式は、"*label*@*パスワードファイル名*" という形で、*label* とパスワードの記載されたファイル名の組み合わせになります。

ansible-vault の暗号化/復号パスワードを以下のようなファイルに設定することにします。

```shell_session
(ansible) $ tree -a ~/.ansible_rings/
/home/luser/.ansible_rings/
|-- .vault_pass_sample.txt
|-- .vault_pass_sample1.txt
|-- .vault_pass_sample2.txt
|-- .vault_pass_sample3.txt
|-- .vault_pass_sample4.txt
`-- .vault_pass_sample_default.txt

0 directories, 6 files
(ansible) $
```

```text:~/.ansible_rings/.vault_pass_sample.txt
samplepassword
```

```text:~/.ansible_rings/.vault_pass_sample1.txt
sample1password
```

```text:~/.ansible_rings/.vault_pass_sample2.txt
sample2password
```

```text:~/.ansible_rings/.vault_pass_sample3.txt
sample3password
```

```text:~/.ansible_rings/.vault_pass_sample4.txt
sample4password
```

```text:~/.ansible_rings/.vault_pass_sample_default.txt
defaultPassword
```


次に、ansible.cfg に ansible-vault の設定を行います。


```ini:./ansible.cfg
[defaults]
interpreter_python      = /usr/bin/python3
# インベントリ
inventory               = hosts
# ansible-vault 関連
vault_identity          = sample
vault_encrypt_identity  = sample
vault_identity_list     = sample@~/.ansible_rings/.vault_pass_sample.txt,sample1@~/.ansible_rings/.vault_pass_sample1.txt,sample2@~/.ansible_rings/.vault_pass_sample2.txt,sample3@~/.ansible_rings/.vault_pass_sample3.txt,sample4@~/.ansible_rings/.vault_pass_sample4.txt,@~/.ansible_rings/.vault_pass_sample_default.txt

#[privilege_escalation]
## become (sudo)
#become                 = True
```

ansible.cfg の設定が終わったら、パスワード/パスフレーズの暗号化を行います。

```shell_session:ansible-vaultによる暗号化
(ansible) $ ( set -x; ( while read n p s; do ansible-vault encrypt_string -v --encrypt-vault-id $s -n $n $p; done ) << EOT
ansible_ssh_pass privkey_passphrase sample1
ansible_sudo_pass pubkeyuser_password sample2
ansible_ssh_pass pwduser_password sample3
ansible_sudo_pass pwduser_password sample4
EOT
)
+ cat
+ read n p s
+ ansible-vault encrypt_string -v --encrypt-vault-id sample1 -n ansible_ssh_pass privkey_passphrase
Using /home/luser/work/Ansible.d/passwordtest.withVault/ansible.cfg as config file
ansible_ssh_pass: !vault |
          $ANSIBLE_VAULT;1.2;AES256;sample1
          31386662393263333631396165646631616139323064346631633931363563323330643035393366
          3132633136633734383665373135343833353835396461640a633132663862633130653735633436
          61613535333964383162373135383966643438303661326333303337656263626262303232333961
          3436656633316232310a636336323737323761346535613761623038623362636565633934656437
          30633462363565383035626165393832626465636161313932333866306266666638
Encryption successful
+ read n p s
+ ansible-vault encrypt_string -v --encrypt-vault-id sample2 -n ansible_sudo_pass pubkeyuser_password
Using /home/luser/work/Ansible.d/passwordtest.withVault/ansible.cfg as config file
ansible_sudo_pass: !vault |
          $ANSIBLE_VAULT;1.2;AES256;sample2
          34646236623634393565333836346238333662313466323762316462636637633735326330393261
          6335373233666334386362626661653363373563393763360a633161336663303737376535393638
          65333033333330326534643233336466363931336633643464373862653663316665373331616566
          3333343232306266350a656464363232376661626135613063333032353037376333323830363538
          35333362353534376664613736343765373862333631346338656634383262373935
Encryption successful
+ read n p s
+ ansible-vault encrypt_string -v --encrypt-vault-id sample3 -n ansible_ssh_pass pwduser_password
Using /home/luser/work/Ansible.d/passwordtest.withVault/ansible.cfg as config file
ansible_ssh_pass: !vault |
          $ANSIBLE_VAULT;1.2;AES256;sample3
          39623031313762626535383264623838613435306233323863363466363231663265363230653666
          3739666333396133313332613563626238323665636638300a653433303139373734326562633735
          36303536366533323665623436633939393138393064633435383063366531373662343339643631
          6263386465663838630a623365383336373536343039343663393662396162613433646132373438
          61326165326566373761613831663961363237376563653863666330336330396139
Encryption successful
+ read n p s
+ ansible-vault encrypt_string -v --encrypt-vault-id sample4 -n ansible_sudo_pass pwduser_password
Using /home/luser/work/Ansible.d/passwordtest.withVault/ansible.cfg as config file
ansible_sudo_pass: !vault |
          $ANSIBLE_VAULT;1.2;AES256;sample4
          62346235306363343334653464653235373632386165383735343038313765633133376462663737
          3532323962316536663333363366666432383832323531340a336132376130326430633765333566
          66336238653038366233323834383862303262336435623039316135613139303862306133646562
          3162393332343931370a366365666564326462396365376434353234353661353763626465383734
          65383938383535356137313531613631646366363231393737656266383134353239
Encryption successful
+ read n p s
(ansible) $
```

上では、標準出力に表示させていますが、ファイルに書き込む場合には --output オプションが使用できます。

それぞれの出力を、変数として設定します。

```yaml:host_vars/172.17.0.2.yml
---
# Remote User
ansible_ssh_user: pubkeyuser
# 秘密鍵
ansible_private_key_file: ./pubkeyuser_id_rsa_assword
# SSH 共通引数
ansible_ssh_common_args: "-o PubkeyAuthentication=yes -o PasswordAuthentication=no -o StrictHostKeyChecking=no"
# SSH 秘密鍵パスフレーズ
#ansible_ssh_pass: 'privkey_passphrase'
ansible_ssh_pass: !vault |
                  $ANSIBLE_VAULT;1.2;AES256;sample1
                  31386662393263333631396165646631616139323064346631633931363563323330643035393366
                  3132633136633734383665373135343833353835396461640a633132663862633130653735633436
                  61613535333964383162373135383966643438303661326333303337656263626262303232333961
                  3436656633316232310a636336323737323761346535613761623038623362636565633934656437
                  30633462363565383035626165393832626465636161313932333866306266666638

# become (sudo) パスワード
#ansible_sudo_pass: 'pubkeyuser_password'
ansible_sudo_pass: !vault |
                   $ANSIBLE_VAULT;1.2;AES256;sample2
                   34646236623634393565333836346238333662313466323762316462636637633735326330393261
                   6335373233666334386362626661653363373563393763360a633161336663303737376535393638
                   65333033333330326534643233336466363931336633643464373862653663316665373331616566
                   3333343232306266350a656464363232376661626135613063333032353037376333323830363538
                   35333362353534376664613736343765373862333631346338656634383262373935
```

```yaml:host_vars/172.17.0.3.yml
---
# Remote User
ansible_ssh_user: pwduser
# パスワード認証の指定
ansible_ssh_common_args: '-o PreferredAuthentications=password -o PubkeyAuthentication=no -o PasswordAuthentication=yes -o StrictHostKeyChecking=no'
# 認証パスワード
#ansible_ssh_pass: 'pwduser_password'
ansible_ssh_pass: !vault |
                  $ANSIBLE_VAULT;1.2;AES256;sample3
                  39623031313762626535383264623838613435306233323863363466363231663265363230653666
                  3739666333396133313332613563626238323665636638300a653433303139373734326562633735
                  36303536366533323665623436633939393138393064633435383063366531373662343339643631
                  6263386465663838630a623365383336373536343039343663393662396162613433646132373438
                  61326165326566373761613831663961363237376563653863666330336330396139

# become (sudo) パスワード
#ansible_sudo_pass: 'pwduser_password'
ansible_sudo_pass: !vault |
                   $ANSIBLE_VAULT;1.2;AES256;sample4
                   62346235306363343334653464653235373632386165383735343038313765633133376462663737
                   3532323962316536663333363366666432383832323531340a336132376130326430633765333566
                   66336238653038366233323834383862303262336435623039316135613139303862306133646562
                   3162393332343931370a366365666564326462396365376434353234353661353763626465383734
                   65383938383535356137313531613631646366363231393737656266383134353239
```

```
(ansible) $ ( set -x; for h in 172.17.0.2 172.17.0.3 hostgroup; do ansible $h -m command -a 'id -a'; ansible $h -m command -a 'id -a' -b; done )
+ for h in 172.17.0.2 172.17.0.3 hostgroup
+ ansible 172.17.0.2 -m command -a 'id -a'
172.17.0.2 | CHANGED | rc=0 >>
uid=1001(pubkeyuser) gid=1001(pubkeyuser) groups=1001(pubkeyuser),27(sudo)

+ ansible 172.17.0.2 -m command -a 'id -a' -b
172.17.0.2 | CHANGED | rc=0 >>
uid=0(root) gid=0(root) groups=0(root)

+ for h in 172.17.0.2 172.17.0.3 hostgroup
+ ansible 172.17.0.3 -m command -a 'id -a'
172.17.0.3 | CHANGED | rc=0 >>
uid=1001(pwduser) gid=1001(pwduser) groups=1001(pwduser),27(sudo)

+ ansible 172.17.0.3 -m command -a 'id -a' -b
172.17.0.3 | CHANGED | rc=0 >>
uid=0(root) gid=0(root) groups=0(root)

+ for h in 172.17.0.2 172.17.0.3 hostgroup
+ ansible hostgroup -m command -a 'id -a'
172.17.0.2 | CHANGED | rc=0 >>
uid=1001(pubkeyuser) gid=1001(pubkeyuser) groups=1001(pubkeyuser),27(sudo)

172.17.0.3 | CHANGED | rc=0 >>
uid=1001(pwduser) gid=1001(pwduser) groups=1001(pwduser),27(sudo)

+ ansible hostgroup -m command -a 'id -a' -b
172.17.0.2 | CHANGED | rc=0 >>
uid=0(root) gid=0(root) groups=0(root)

172.17.0.3 | CHANGED | rc=0 >>
uid=0(root) gid=0(root) groups=0(root)

(ansible) $
```

ssh のパスフレーズは、ssh-agent/ssh-add を使うことが推奨されていますし、become(sudo)のパスワードは、ansible-vault で暗号化し、復号パスワードが記載されたファイルは、厳重に管理しましょう。


# ssh のパスワード設定の tips

* [ssh – connect via ssh client binary — Ansible Documentation](https://docs.ansible.com/ansible/latest/plugins/connection/ssh.html) の password の説明では、変数名として `ansible_ssh_password` が使えるように記載されているが、`ansible_ssh_pass` と `ansible_password` のみが実装されており、`ansible_ssh_password` は実装されていない。

> var: ansible_password
> var: ansible_ssh_pass
> var: ansible_ssh_password

* 以下の修正を加えれば使用できるようになるが、回避策(`ansible_ssh_pass` か `ansible_password` を使用する)があるのと、まとめようという issue もあるで、修正されるかどうかは不明。

```diff:ansible-constants.py.patch
*** constants.py.orig   2019-12-04 23:10:58.000000000 +0000
--- constants.py        2020-01-10 05:16:07.520928899 +0000
***************
*** 140,146 ****
      # connection common
      remote_addr=('ansible_ssh_host', 'ansible_host'),
      remote_user=('ansible_ssh_user', 'ansible_user'),
!     password=('ansible_ssh_pass', 'ansible_password'),
      port=('ansible_ssh_port', 'ansible_port'),
      pipelining=('ansible_ssh_pipelining', 'ansible_pipelining'),
      timeout=('ansible_ssh_timeout', 'ansible_timeout'),
--- 140,146 ----
      # connection common
      remote_addr=('ansible_ssh_host', 'ansible_host'),
      remote_user=('ansible_ssh_user', 'ansible_user'),
!     password=('ansible_ssh_password', 'ansible_ssh_pass', 'ansible_password'),
      port=('ansible_ssh_port', 'ansible_port'),
      pipelining=('ansible_ssh_pipelining', 'ansible_pipelining'),
      timeout=('ansible_ssh_timeout', 'ansible_timeout'),
```