LoginSignup
12

More than 5 years have passed since last update.

InSpec でデプロイを自動テスト化する

Posted at

InSpec とは

InSpec は環境構築が正しく行われているかどうかをテストするためのフレームワークです。 Ruby で記述されており環境構築ツールで有名な Chef が開発しています。

serverspec との違い

InSpec と同系のツールに serverspec というフレームワークがあります。もともと InSpec は serverspec の拡張として作られていたため、テストコードの記述の仕方もよく似ています。しかし InSpec の方がセキュリティやコンプライアンスのテストなど serverspec よりも幅広いテストが可能となっています。

InSpec と serverspec の書き方の違いは マイグレーションガイド にまとまっていますので、 serverspec から InSpec に乗り換える際にはご活用下さい。

試した環境

  • CentOS 7
  • InSpec 3.0.52

インストール

$ gem install inspec

使い方

Apache がインストールされているかどうかをテストしたいときは次のようなコードを書きます。

httpd.rb

describe package('httpd') do
  it { should be_installed }
end

テストを実行するにはターミナルで次のコマンドを叩きます。下記は httpd が入っていない場合の結果です。

$ inspec exec httpd.rb

Profile: tests from tests (tests from tests)
Version: (not specified)
Target:  local://

  System Package httpd
     ×  should be installed
     expected that `System Package httpd` is installed

Test Summary: 0 successful, 1 failure, 0 skipped

テストを実行する対象はローカルマシンではなくリモートマシンを指定することもできます。リモートマシン上でテストを実行するには次のように ssh でログインするときのユーザ名とパスワードを指定して実行します。

$ inspec exec httpd.rb -t ssh://<user>:<pass>@<host>:<port>

httpd.rb 内の package() というのはリソースといって各種情報源へアクセスするためのオブジェクトになります。リソースには次のようなものがあります。

リソース 説明
package yum/apt などのパッケージの情報
file ファイルの情報
http HTTP に関する情報
port ポートに関する情報
command コマンドの実行に関する情報

公式サイトに リソース一覧 がまとまっていますのでご活用下さい。

ある観点でテストを作成するときには複数のリソースを使用するケースがあります。そのような場合には control というブロックを使って複数のリソースをまとめることができます。

control 'command' do
  title 'コマンドに関するテスト'

  describe command('/bin/sh').exist? do
    it { should eq true }  # /bin/sh が存在するかの確認
  end

  describe command('echo hello') do
    its('stdout') { shuld eq "hello\n" }  # 標準出力の内容を確認
    its('stderr') { should eq '' }        # 標準エラー出力を確認
    its('exits_status') { should eq 0 }   # 終了コードが 0 であることの確認
  end
end

リソースで提供されていない情報源を参照したい場合は command() を使ってコマンドの実行結果をパースすることになりますが、場合によっては複数のコマンドを組み合わせる必要があったり複雑なパースが必要になることもあります。そのような場合には osquery というコマンドラインツールを使うと情報源の取得を SQL で記述し結果を JSON で受け取れるので記述がシンプルになります。

require 'json'

# osquery で httpd のプロセス情報を JSON で取得
result = command('osqueryi --json "SELECT * FROM processes WHERE name = \'httpd\';"')

JSON.parse(result.stdout).each do |item|
  # httpd はポートをリッスンしているか?
  describe port(item['port']) do
    it { should be_listening }
  end
end

まとめ

ナビタイムではデプロイ時のテストとして InSpec を活用しています。InSpec を使うことで安全なデプロイができるだけでなく、デプロイに対する心理的負担が下がる効果もあるのでぜひご活用下さい。

参考

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
12