InSpec1自体はAnsibleのRoleをTDDで作成するときにkitchen-inspecでよく利用していたものの、実環境に対するテストでは使ったことがなかったのでどう使うかを整理。
環境
- Ansible 2.7.10
- InSpec 4.3.2
InSpecの基本的な使い方
インストール
Chefと同じくパッケージが提供されているのでChef Downloadsからダウンロードするのが手っ取り早い。
gem installする場合はCLIで利用するためにinspec-binが必要なので注意。
$ yum -y localinstall /tmp/inspec-4.3.2-1.el7.x86_64.rpm
$ rbenv exec gem install inspec inspec-bin
$ rbenv rehash
$ inspec --version
4.3.2
$ inspec help
Commands:
inspec archive PATH # archive a profile to tar.gz (default) or zip
...
Profileの作成
knife
コマンドよろしくinspec
コマンドにもテンプレートの生成機能があるのでそちらを利用。
inspec init profile PROFILE_NAME
$ inspec init profile my-profile
my-profile
├── README.md
├── controls
│ └── example.rb
├── inspec.yml
└── libraries
ProfileのDirectory Layoutの概要は以下の通り。
- inspec.yml (required)
- このテストに関するメタ情報を記載する
- 実行可能なOS環境や他のテストとの依存関係などの定義が可能
- controls (required)
- テストを配置するディレクトリ
- このディレクトリ配下に配置されたrbファイルがすべて実行対象になる
- libraries (optional)
- Custom Resourcesを配置するディレクトリ
- 今のバージョンだと標準のResourcesだけで大体事足りるので使うことはあんまりないかも
- files (optional)
-
inspec init profile
では作成されない - このディレクトリ配下のファイルはテストコードの中で
inspec.profile.file('ファイル名')
とすることでアクセス可能 - テストで利用するパラメータを定義するために使うが、環境依存で変更されるファイルを置く場所ではないことに注意
-
リモートサーバへのテスト実行
サンプルで作成されるexample.rbは「/tmpというディレクトリが作成されていること」のテストになっているのでテスト対象がCentOSとかであればinspec init profile
で作成したプロファイルを使ってそのまま試せる。
Ansibleで管理しているのであれば、Ansible実行用のリモートユーザをそのまま使えばOK。
inspec exec PROFILE_PATH --target=ssh://REMOTE_USER@REMOTE_HOST
$ inspec exec my-profile --target=ssh://vagrant@192.168.33.10
Profile: InSpec Profile (my-profile)
Version: 0.1.0
Target: ssh://vagrant@192.168.33.10:22
✔ tmp-1.0: Create /tmp directory
✔ File /tmp should be directory
File /tmp
✔ should be directory
Profile Summary: 1 successful control, 0 control failures, 0 controls skipped
Test Summary: 2 successful, 0 failures, 0 skipped
Ansibleとの併用
Serverspecでもちょっと考える必要があるのがサーバ毎のパラメータを読み込む箇所。
Ansibleではansible-inventory
を利用することで実行対象で利用されるvarsをyaml形式で出力できる2。
InSpecでは--input-file
オプションを使うことで外部のyamlファイルをロードすることができるので、生成したyamlファイルをロードすることでサーバ毎のパラメータを利用したテストが実行可能となる。
Direcotry Layoutについて
ローカル検証用にochiba/inspec-exampleを用意したのでこちらで解説。
├── ansible.cfg
├── inventories
│ └── stg
│ ├── group_vars
│ ├── host_vars
│ └── nodes.yml
├── plays # playbookの配置先(roles_pathはansible.cfgで調整)
├── roles
│ └── common
│ ├── defaults
│ ├── tasks
│ ├── templates
│ └── test
│ └── integration
│ └── default # InSpec Profile
│ ├── controls
│ ├── inspec.yml
│ └── libraries
└── test
└── attributes # ansible-inventoryで出力したvarsの配置先
Alternative Directory LayoutからPlaybookの配置を少し弄った構成。
Profile自体はTDDで作成したものを使い回すのがポイント。
パラメータの呼び出し方
検証用に作成したテストは以下の通り。
# encoding: utf-8
# copyright: 2019, Hiroki KUNITAKE
title 'MyProfile section'
control 'myprofile-01' do
impact 0.7
title 'Create myprofile.txt'
desc 'Check contents'
describe file('/var/tmp/myprofile.txt') do
it { should be_file }
its('content') { should match /^My name is #{attribute('my_name')}/ }
its('content') { should match /^I'm in #{attribute('my_group')}/ }
end
end
--input-file
オプションで読んだパラメータはattribute('VARS_NAME')
で呼び出せる。
階層構造になっている場合は親を呼び出して一旦変数に格納してから利用する。
実行サンプル
ansible-inventory
を利用してAttributes File(vars情報が入ったyamlファイル)を作成し、そのファイルを--input-file
オプションで食わせてテストを実行する。
$ ansible-inventory --yaml --inventory=inventories/stg/nodes.yml --host=192.168.33.10 > test/attributes/192.168.33.10.yml
$ cat test/attributes/192.168.33.10.yml
my_group: Web
my_name: Web-01
$ inspec exec roles/common/test/integration/default --target=ssh://vagrant@192.168.33.10 --input-file=test/attributes/192.168.33.10.yml
Profile: Common baseline (common-baseline)
Version: 0.1.0
Target: ssh://vagrant@192.168.33.10:22
✔ myprofile-01: Create myprofile.txt
✔ File /var/tmp/myprofile.txt should be file
✔ File /var/tmp/myprofile.txt content should match /^My name is Web-01/
✔ File /var/tmp/myprofile.txt content should match /^I'm in Web/
Profile Summary: 1 successful control, 0 control failures, 0 controls skipped
Test Summary: 3 successful, 0 failures, 0 skipped
今のところinspec exec
そのものには並列実行の機能がなく1ホストずつしか実行できない。
グループ単位でテストを実行したい場合はProfileやAttirbutes Fileの配置パスについてルールを設けてクリプト化する必要がある。
-
Serverspecの拡張として作られているテストツール。サーバの状態をチェックするのにも利用できるが、どちらかといえばある規則に従っているかどうかをスコア付けするためのツール。 ↩
-
Factsやvars_filesはその特性上
ansible-inventory
では出力できないので別の手立てが必要。 ↩