お久しぶりです。4月に就職して以来、約8ヶ月ぶりの投稿です。
今は田町でRuby、Ansible、Jenkins辺りと戯れつつクラウドを作っています。
学生時代は、研究室用にhico-horiuchi/ansible-playbooksを書いていました。
今見ると、roleで整理されていなかったり、tagやvarを使えていないなど、中々酷いものですね…。
そこで、5月の研修中に暇だったので、Ansible 2.0対応も兼ねて、自鯖用のPlaybookを書いてみました。
内容は「ConoHa + DokkuでプライベートPaaS構築」の環境を構築するものです。
今回は、ansible-vaultで暗号化した情報を、Serverspecで使うために工夫した内容を紹介します。
これにより、「設定ファイルにトークンが記述されているか」「パスワードを使ってログインできるか」などが確認できるようになります。
ansible_specの紹介
Ansible + Serverspecでテストをするために、volanja/ansible_specを使っています。
ansible_specの詳細は、開発した方が書かれている下記の記事をご覧下さい。
今回は、ansible_specが生成した spec/spec_helper.rb
に改造を施していきます。
Rubyでansible-vaultの情報を読み込む
ansible-vaultは、Ansibleのvars(変数)を暗号化するためのツールです。
パスワードやトークンを記述したYAMLファイルを、暗号化・複合化することができます。
今回は、ansible-vaultの暗号化ファイルをRubyで読み込むために、tpickett66/ansible-vault-rbを使用します。
使い方は簡単で、下記のように暗号化ファイルのパスとパスワードを渡すだけで複合化してくれます。
ただし、 Ansible::Vault.read
の返り値はStringなので、 YAML.load
でハッシュ化する必要があります。
require 'ansible/vault'
require 'yaml'
contents = Ansible::Vault.read(path: '/path/to/file', password: 'foobar')
vars = YAML.load(contents)
Serverspecでansible-vaultの情報を使う
前置きが長くなりましたが、ここからが本題です。
Serverspecでansible-vault-rbを使うために、 spec/spec_helper.rb
の末尾に下記の内容を追加します。
ソースコード全体は、hico-horiuchi/hiconyan-com-ansible/spec/spec_helper.rbをご覧下さい。
vars = AnsibleSpec.get_variables(host, group_idx, hosts)
property = AnsibleSpec.get_properties[group_idx]
ansible_cfg = File.expand_path('../ansible.cfg', File.dirname(__FILE__))
vault_password_file = ''
vault_password = ''
# ansible.cfgからvault_password_fileのパスを抽出
File.open(ansible_cfg, 'r') do |f|
vault_password_file = f.read.match(/^vault_password_file = (.+)$/)[1]
end
# vault_password_fileからパスワードを読込
File.open(File.expand_path(vault_password_file), 'r') do |f|
vault_password = f.read.chomp
end
# 必要なroles/*/vars/secret.ymlをハッシュとして読込
property['roles'].each do |role|
secret = "roles/#{role}/vars/secret.yml"
if File.exist?(secret)
vars.merge! YAML.load(Ansible::Vault.read(path: secret, password: vault_password))
end
end
set_property vars
コメントでも補足していますが、処理手順は下記のようになっています。
- ansible.cfgからvault_password_fileのパスを抽出
- ansible-playbook時にパスワードを入力しなくて良いように、設定ファイルにパスを記述している。
- 私の場合は~/.vault_password
にパスワードを書き出して保存している。
- 詳細は「Configuration file — Ansible Documentation」をご覧下さい。 - vault_password_fileからパスワードを読込
- 単純なRubyのファイル操作で、vault_password_fileの中身を読み込む。
-~
などを展開するためにFile.expand_path
で絶対パスを取得する。 - 必要な
roles/*/vars/secret.yml
をハッシュとして読込
- 今回は暗号化ファイル(secret.yml
)をrole毎に分けてvars
ディレクトリに格納した。
-property['roles']
で対象ホストのroleが分かるので、secret.yml
が存在する場合は読み込む。
また、 set_property vars
をすることで、Serverspecの中で property
ハッシュで利用できるようになります。
実際のServerspecで利用している箇所は下記の2つです、参考にして下さい。
- hico-horiuchi/hiconyan-com-ansible/roles/mackerel/spec/config_spec.rb
- hico-horiuchi/hiconyan-com-ansible/roles/redis/spec/config_spec.rb
おわりに
実は、この方式は8月中旬には確立していたのですが、仕事でバタバタしていて記事にするのが遅くなりました…。
社会人になると、趣味もそうですが、技術的に遊べる時間が少なくなって、中々大変です。
今回は secret.yml
を roles/*/vars
に配置しました。
別の方法として、groupで分けるために group_vars/*/secret.yml
に配置する方法もありますね。
両方を実現しようとすると、Ansibleの変数読み込み順序も考慮する必要があるので、大変そうです。