3回目でやった例を、もう一度見てみたい。
Unix OSでユーザーのグループを作る。以下の様なタスクを作ると、hogeグループをID=7777で作ることが出来る。
tasks: - name: Make groups group: name: hoge gid: 7777
複数のユーザーを作りたかったら、こう書けと入門書には書いてある。
vars: - usergroups: - name: hoge gid: 7777 - name: fuga gid: 8888 tasks: - name: Make groups group: name: "{{ item.name }}" gid: "{{ item.gid }}" loop: "{{ usergroups }}"
しかし、これはどう見ても冗長だ。
vars: - usergroups: - name: hoge gid: 7777 - name: fuga gid: 8888 tasks: - name: Make groups group: "{{ item }}" loop: "{{ usergroups }}"
これで良くないか?
というわけで試してみる。
TASK [usergroup : Make groups] ************************************************* [WARNING]: Using a variable for a task's 'args' is unsafe in some situations (see https://docs.ansible.com/ansible/devel/reference_appendices/faq.html#argsplat- unsafe) changed: [inst] => (item={'name': 'hoge', 'gid': 7777}) changed: [inst] => (item={'name': 'fuga', 'gid': 8888})
ちゃんと動作するが、怒られる。「安全じゃ無い」らしい。「argsを使ったら、危ないよ」としてるのは、つまり、
group: dict_value
は
group: args: dict_value
と扱われるということらしい。
詳しくはこちら・・・と書いているので、そのFAQを見てみよう。
ただし、
usermod_args
に渡されるパラメーターや値が、 ウイルスなどに感染したターゲットマシンのhost facts
に含まれる悪意のある値で上書きされる可能性があるため、 このようなタスクの構築にはリスクがあります。
AnsibleのFactはあんまりよく理解できていない概念の1つなんだけども、つまり、操作対象システムの情報、例えばOSが何かとかバージョンが何かといういうものを変数と同じように参照できる仕組みのことだ。そして、それはまさに変数(Var)と同じスコープの中で同じように扱われる。
しかし、Ansibleというプログラムのことを考えたら、Factはシステムの外部から与えられたものなので信用できない情報が含まれることがある。例えば、Rubyにはtaintという仕組みが(あるが、有効に使うのが難しいので風前の灯火で)ある。コマンドライン引数などの文字列オブジェクトなどに汚染されてますよマークが付いて、そのマークが付いたオブジェクトで一部の動作が禁止されるというような仕組みだ。Ansibleはパラメータとして与えられた情報を元にroot権限でコマンドが実行されるような仕組みなので、コマンドの引数が汚染された情報でうっかり書き換えられると大変にマズい。それはなんとなく理解できる。
しかし、そもそも自分で定義したVarがFactで塗り替えられるかも知れないというのは、何かが間違っている。そもそも、AnsibleのVarは定義できる場所が多すぎてスコープがよくわからないんだけども。というわけで、Factは別の名前空間に押し込められることになった。Ansible 2.5でのこと。しかしながら、まだ移行期間なのでFactがVarを塗り替える状況は変わらない。現状は、INJECT_FACTS_AS_VARS
をFalseに設定する(例えばANSIBLE_INJECT_FACT_VARSという環境変数をFalseに設定する)と将来的に予告されているとおりにVarの名前空間にFactは入ってこない動作になり、この警告の表示も消える。
しかし、タスクへのパラメータをdictを渡そうとすると、Factで上書きされる可能性が生じるのはなぜなのかは、やっぱりよくわからない。