Ansibleでのパスワードの取り扱い

# Ansibleでのパスワードの取り扱い

## 概要
Ansibleを使っていて、

* sambaのユーザパスワード
* BASIC認証のパスワード

など、パスワードを管理して使いたい場合が時たまあると思います。

そんな時にいつも使っている方法を紹介します。

## パスワード管理方法

### 1. Ansible Vaultで暗号化する
基本的にパスワードの類はAnsible Vaultで暗号化して使用します。
`ansible_sudo_pass:` として SUDOパスワードを入れておくと、SUDOパスワードの省略ができて便利です。

**private.ymlにパスワード類を記載し、Ansible Vaultで暗号化する**

```zsh
### sudoパスワードとsambaのパスワードを記載
% vim private.yml
+ ---
+ ansible_sudo_pass: sudo_password
+ samba_user: samba
+ samba_pass: smb_password

### private.ymlを暗号化 (暗号化用パスワードを入力)
% ansible-vault encrypt private.yml
Vault password:
Confirm Vault password:
Encryption successful
```

暗号化してるとはいえ、パスワードをgitに上げるわけにはいかないので、`.gitignore`に記載しておきます。

**private.ymlはgitで管理しない**

```zsh
### .gitignoreで除外
% vim .gitignore
...
+ private.yml
...
```

### 2. 外部変数として読み込む
`private.yml`に定義した変数を、実行時に `--extra-vars` で読み込みます。

`--ask-vault-pass`オプションを付けて実行するとVaultのパスワードを聞かれるので、先程暗号化時に設定したパスワードを入力します。

**private.ymlをextra_varsとして読み込む**

```zsh
### --extra-varsで private.yml 内の変数を渡す
% ansible-playbook -i hosts setup-smb.yml --extra-vars="@private.yml" --ask-vault-pass
Vault password:
```

playbook内では通常のように変数として記入しておきます。

**playbook内で変数の使用**

```yaml:setup-smb.yml
...
  - name: sambaユーザの追加
    shell: echo -e "{{ samba_pass }}\n{{ samba_pass }}\n" | pdbedit -t -a {{ samba_user }}
...
```

### 3. private.ymlが存在しない場合の処理を記載
このままでも個人で使うには十分ですが、`private.yml`を配置せずにplaybookを使用するとエラーが発生してしまいます。

これを避けるためには2通りの方法が考えられます。

**role内のdefaults/main.ymlにデフォルトパスワードを定義する**
roleを使用している場合、`defaults`内にデフォルトパスワードを定義しておくことで、`private.yml`が与えられなかった場合でもplaybookを実行することが可能になります。

```zsh
### パスワードのデフォルト値を設定
% cat /role/samba/defaults/main.yml
..
samba_user: samba
smb_pass: default_password
...
```
(※ `defaults`は優先順位が最も低い、`--extra-vars`は一番強い)
参考: [Variable Precedence: Where Should I Put A Variable?](http://docs.ansible.com/ansible/playbooks_variables.html#variable-precedence-where-should-i-put-a-variable)

デフォルトパスワードでインストールすることはそうそう無いのと、弱いパスワードでインストールされるのを防ぐという観点でいうとこの方法はあまり良くないかも知れません。

**プロンプトでの入力**
Ansibleには、ユーザの入力をプロンプトで受け付ける機能があります。

ここでは、パスワードとして使用する変数が`null`の場合にプロンプトで入力するように設定しておきます。

```zsh
### プロンプトを使用したplaybook
% cat setup-smb.yml
---
- hosts smb
  vars_prompt:
    - name: samba_pass            # 変数名
      prompt: Samba password      # プロンプト時に表示されるテキスト
      private: yes                # 入力値を画面に表示しない
      confirm: yes                # 2回入力で打ち間違いを防止する
      when: samba_pass == null    # nullの場合に尋ねる
  roles:
    - { role: samba, sudo: yes }
```

```zsh
### extra-varsを渡さない場合
% ansible-playbook -i hosts setup-smb.yml -K
SUDO password:
Samba password:
confirm Samba password: 
...
```

```zsh
### extra-varsを渡した場合
% ansible-playbook -i hosts setup-smb.yml --extra-vars="@private.yml" --ask-vault-pass
Vault password:
...
```

パスワードとして使用する変数が多い場合、実行時のプロンプトが多すぎて入力が面倒くさいという欠点があります。

とりあえず、これによって`private.yml`を作成していない場合でもplaybookを実行することができます。

### 4. その他

この方法を使っているとパスワードの初期セットアップや、実行時のオプションがややこしくなってくるので、`README`にちゃんと記載するか、実行用のシェルスクリプトを用意するようにしています。

また、構築用のスクリプトと設定アップデート用のスクリプトを分けて

```zsh
% tree samba -L 1
samba
├── README.md
├── private.yml
├── roles
├── hosts
├── update-smb.yml   # 設定アップデート用のplaybook, パスワードを必要としない
└── setup-smb.yml    # 構築用のplaybook, パスワードを必要とする
```

こんな感じにするのもありです。
構築はそんなに使用頻度高くない(はず‥)なので

## まとめ

まとめると、

* Ansible Vaultでファイルを暗号化
* `--extra-vars`で実行時に渡す
* (※ オプション) デフォルトパスワードか、プロンプトを仕掛ける

という感じです。

個人的には

* **デフォルトパスワードをアップロードしなくて済む**
* **デフォルトパスワードでインストールされることを防げる**
* **プロンプトがめんどくさい場合はprivate.ymlを設定する**

という理由でプロンプトを設定して使っています。

--

この記事は、以前に書いた下記のブログ二つをまとめたものになります。
http://jimaoka.hatenablog.jp/entry/ansible-vault
http://jimaoka.hatenablog.jp/entry/ansible-passwd