Ansibleを使っていて、個人的にハマって調べたことをTipとしてまとめていきたいと思います。Tipsが溜まったらその3もやります!
今回紹介するTips
- OSユーザのパスワードは事前にハッシュ化しなくてもいい!
- role内変数を、role内のみで使うプライベート変数にする
- Ansibleモジュール内で*(アスタリスク)を使用する
- RPMパッケージをインストールさせたい
- become使用時にsudoパスワードを自動入力したい
- ansible-vault使用時にパスワードを環境変数で渡したい
- 何回も書く必要のあるパラメーターをまとめる!
- Ansibleでevalチックな変数の中に変数がある場合
OSユーザのパスワードは事前にハッシュ化しなくてもいい!
password_hashを使う
以前お伝えしたテクニックでは事前に暗号化しておく手順でしたが、
リファレンスをよくよく見ると暗号化してくれる書き方がありました。
以下に対応しています。
- sha256
- sha512
使い方
- name: ユーザー作成
user:
name: test
#SHA256の時はこちら
password: "{{ 'password' |password_hash('sha256', 'mysecretsalt') }}"
#SHA512の時はこちら
password: "{{ 'password' |password_hash('sha512', 'mysecretsalt') }}"
home: /home/test
ただし注意点として、以下のように変数をリスト化しループを回した場合、実行結果にパスワードが平文で流れてしまいます。
vars:
test:
- name: test1
password: password
home: /home/test1
- name: test2
password: password
home: /home/test2
tasks:
- user:
name: "{{ item.name }}"
password: "{{ item.password |password_hash('sha256', 'mysecretsalt') }}"
home: "{{ item.home }}"
with_items:
- "{{ test }}"
passwordが平文で見える!
PLAY ***************************************************************************
TASK [user] ********************************************************************
changed: [rhel6_d] => (item={u'home': u'/home/test1', u'password': u'password', u'name': u'test1'})
changed: [rhel6_d] => (item={u'home': u'/home/test2', u'password': u'password', u'name': u'test2'})
なので、リスト化する場合はno_log: True
をつけ、出力しないようにします。
vars:
test:
- name: test1
password: password
home: /home/test1
- name: test2
password: password
home: /home/test2
tasks:
- user:
name: "{{ item.name }}"
password: "{{ item.password |password_hash('sha256', 'mysecretsalt') }}"
home: "{{ item.home }}"
with_items:
- "{{ test }}"
no_log: True
こうなります
TASK [user] ********************************************************************
changed: [rhel6_d] => (item=(censored due to no_log))
changed: [rhel6_d] => (item=(censored due to no_log))
role内変数を、role内のみで使うプライベート変数にする
private_role_vars = yesを使う
roleで呼び出された・定義された変数は、別のroleに処理が移っても引き継がれます。Ansibleの変数命名ルールにて、先頭にrole名をつけろと記載されているのもそのためです。
しかし、そうもできない場合はroleの中で変数を閉じる必要がありますのでansible.cfgに以下の記載を追記します。
private_role_vars = yes
Ansibleモジュール内で*(アスタリスク)を使用する
with_fileglobを使う
- copy:
src: {{ item }}
dest: /path
with_fileglob:
- "/etcsysconfig/network-scripts/ifcfg-*"
ちなみにfetchモジュールで、with_fileglobを使用すると出力はOKとでるのにファイルが取得されないケースがあります。これは、with_fileglobの解決がローカルホストで行われるのに対し、fetchはターゲットマシン(構成管理対象サーバー)で実施されるためです。
そのため、*指定をしたい場合には、shellモジュールでfind検索を実施し、registerで登録した値をwith_itemsに入れるやり方となります。
※他のうまいやり方あったら教えて下さい。
RPMパッケージをインストールさせたい
yum モジュールを使う
yumモジュールでは、nameアトリビュートにてフルパスでの指定ができるため、ローカル上のRPMファイルを指定することでインストールが可能です。
yum:
name: xxxxx.rpm
state: present
become使用時にsudoパスワードを自動入力したい
ansible_become_passを使う
自動入力ができない!ということで、sudo時のパスワードをNOPASSWDにしている皆さん朗報です。
以前はsudo_passwordとかありましたが、becomeが推奨されてからはansible.cfg内では指定できなくなりました。じゃあどうするのか!というと、ansible_become_passが用意されています。
こいつの使い方は2通りあります。
- インベントリファイルで指定
- 変数ファイルで指定(変数として作成する)
[target]
hostname1 ansible_become_pass=xxxx
ansible_become_pass: xxxx
発展ケース(環境変数渡し)
ansible_become_pass: "{{ lookup('env','SUDO_PASSWD') }}"
ansible-vault使用時にパスワードを環境変数で渡したい
JenkinsなどのCIツールを使用している場合や、vaultのパスワードファイルを残しておきたくない場合に使えるテクニックです。
--vault-password-file
を使います。
--vault-password-file
は引数にファイルだけではなく、実行権限の付与されたスクリプトを取ることができ、その標準出力をパスワードとして利用することができます。
つまり、環境変数をスクリプトで解析し標準出力させることで、vaultパスワードをローカルに残す必要がなくなります。ダイナミックインベントリ的な使い方ですね。
#!/bin/bash
echo $VAULT_PASS
export VAULT_PASS=xxx
ansible-playbook site.yml --vault-password-file vault.sh
メモ
プロセス置換を利用して、シェルすら作りたくない!という場合はMacのみプロセス置換にて以下が可能です。(CentOSではできなかった)
ansible-playbook site.yml --vault-password-file <(echo $VAULT_PASS)
Centos系のLinuxではプロセス置換時に一時ファイルを以下のようにpipe:[xxxxxxxx]
で管理しています。
[server ]# ll <(date)
lr-x------ 1 root root 64 4月 8 11:01 /dev/fd/63 -> pipe:[24349835]
ansible-vaultコマンド実行時に読み込まれる以下のファイルでは、os.path.realpath
(実際のファイルのパスを参照する)とかかれているためにpipe:[xxxxxxxx]
が読まれてしまいうまく動作しないようです。(realpathを取り除くとうまくいった)
this_path = os.path.realpath(to_bytes(os.path.expanduser(vault_password_file), errors='strict'))
if not os.path.exists(to_bytes(this_path, errors='strict')):
raise AnsibleFileNotFound("The vault password file %s was not found" % this_path)
MacではCentosとプロセス管理の仕組み(proc周辺)が異なるため、プロセス置換でもうまくいくようです。
何回も書く必要のあるパラメーターをまとめる!
YAMLのマージ記法を使う。
参考:ansible-playbook内でもYAMLのマージ記法が使えます!
- file:
path: /tmp/a
<< : &DEF
owner: ansible
group: ansible
mode: 0755
state: directory
- file:
path: /tmp/b
<< : *DEF
DEF変数にowner/group/mode/stateの設定をいれ、それを使いまわしています。これにより次回以降のパーミッション周りの設定をすっきりさせています。(変数名はなんでもよいです<< : &
と<< : *
が大事)
これ色々と使えそうですね!
Ansibleでevalチックな変数の中に変数がある場合
{{ somvar_{{other_var}} }}
こういうことしたいときは、以下のようにします。
{{['somevar_' + other_var] }}
host_varsを使ってる時はこっちらしい
{{ hostvars[inventory_hostname]['somevar_' + other_var] }}