8
6

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

Serverspecでansible-vaultの情報を使う

Last updated at Posted at 2016-09-24

お久しぶりです。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をご覧下さい。

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

コメントでも補足していますが、処理手順は下記のようになっています。

  1. ansible.cfgからvault_password_fileのパスを抽出
    - ansible-playbook時にパスワードを入力しなくて良いように、設定ファイルにパスを記述している。
    - 私の場合は ~/.vault_password にパスワードを書き出して保存している。
    - 詳細は「Configuration file — Ansible Documentation」をご覧下さい。
  2. vault_password_fileからパスワードを読込
    - 単純なRubyのファイル操作で、vault_password_fileの中身を読み込む。
    - ~ などを展開するために File.expand_path で絶対パスを取得する。
  3. 必要な roles/*/vars/secret.yml をハッシュとして読込
    - 今回は暗号化ファイル( secret.yml )をrole毎に分けて vars ディレクトリに格納した。
    - property['roles'] で対象ホストのroleが分かるので、 secret.yml が存在する場合は読み込む。

また、 set_property vars をすることで、Serverspecの中で property ハッシュで利用できるようになります。
実際のServerspecで利用している箇所は下記の2つです、参考にして下さい。

おわりに

実は、この方式は8月中旬には確立していたのですが、仕事でバタバタしていて記事にするのが遅くなりました…。
社会人になると、趣味もそうですが、技術的に遊べる時間が少なくなって、中々大変です。

今回は secret.ymlroles/*/vars に配置しました。
別の方法として、groupで分けるために group_vars/*/secret.yml に配置する方法もありますね。
両方を実現しようとすると、Ansibleの変数読み込み順序も考慮する必要があるので、大変そうです。

8
6
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
8
6

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?