Terraformコードのテストに役立つオープンソースツール
Stephane Jourdan
2020年5月14日
0 分で読めます編集者注: この記事は当初 CloudSkiff.comに掲載されました。 CloudSkiffは 2021年10月にSnykに加わりました。
Terraformコードのテストは、繰り返し話題に上るテーマです。インフラストラクチャコードのテストについて多くの人が疑問を持っていますが、実際にテストが広く採用されているとは言えません。そもそもコードをテストすべきなのでしょうか。また、テストを自動化する方法にはどのようなものがあり、そのために使える最適なオープンソースツールは何でしょうか。
Terraformコードのテストは重要です。ぜひテストしてください。方法はいくつもあります。一般的なソフトウェアエンジニアリングのプロセスとよく似ています。同じ文化に根差しているので、特に驚くことではありません。
Terraformコードのテスト:まずはリンターを使う
リンターは、ノートパソコンやCI/CDシステム上で直接実行できるツールです。ほかのメンバーが一定のコーディング規約や標準に従っていることを確認するために使います。
Terraform向けのリンターで特に気に入っているのがTFLintです。オープンソースで、Githubから入手できます。インフラストラクチャ向けのリンターで、terraform validateとは異なる方法でコードを検査します。terraform validateはTerraformのサブコマンドです。基本的には構造が有効かどうかを確認するだけで、内容の妥当性はチェックしません。たとえば、存在しないタイプのAWSマシンを指定しても、terraform validateでは誤りを検出できませんが、TFLintなら検出できます。
誤ったコミットは次のようになります。

そして、次のように検出され、ログに表示されます。


このリンターには、単純な lint の範囲を超える「ディープリンティング」機能もあります。
既存の正しいVM、たとえばT3ラージインスタンスをリクエストするとします。アカウントでこれ以上のキャパシティが許可されていない場合(たとえば、リクエスト可能なVMをすべて起動済みの場合)、リンターはAWS APIにリクエストを送り、指定内容が正しいかだけでなく、アカウントの上限内で実行可能かどうかも確認します。開発時に適切なリンターが行う品質やタブなどのチェックをすべて実行し、Terraformに用意されているバリデーターやフォーマッターの機能を超える検査も行います。
よくあるケースとして、ステージング環境ですべてのテストを行っているため、何かをテストするたびに何度もリクエストを重ね、その環境のAWS上限が非常に高くなっていることがあります。その結果、各リージョンで数百、場合によっては数千のインスタンスが許可されているかもしれません。
ところが、新しい変更を本番環境に反映しようとすると、本番環境には同じルールやAWSアカウントの上限が適用されていない場合があります。その結果、本番環境では動作しないものをリリースしてしまうことになります。
ここでディープリンターを使えば、ステージングや開発環境など、どの環境から本番環境に反映または起動しようとしている場合でも、アカウントの権限の範囲内で実際に実行できることを確認できます。
TDDでTerraformコードの単体テストを実施する
適切なアジャイル開発ワークフローは、テスト駆動開発(TDD)から始まります。
TDDを始めるときは、単体テストを書きます。たとえば、「VPCを作成したい。このVPCのアドレス空間はこの範囲であるべきだ」といった具合です。次に関数(Terraformではリソースと呼びます)を書き、実行します。後ほど説明しますが、この用途にはRSpec派生のツール(ServerspecやInSpecなど)を使います。TDDの手順は次のようになります。
まずテストを書く。テストは失敗する
リソースを書く。隔離された環境(特にそのVPC)で起動するため、テストは失敗しない
このプロセスでは、必要なものをテストした後に破棄します。CIで行うのと同じように、プルリクエストでテストをすべて実行できます。ちなみに、テストを始める際にどの程度セキュリティを重視するかは、慎重に考えるべきテーマです。私は何かをマージする前にすべてのテストを実行しますが、プルリクエストの段階ではかなり軽めにしています。コミットのたびに毎回すべてのテストを実行すると、時間がかかるからです。
インテグレーションテストを行う
QAプロセスでよく行われる方法として、変数などをランダム化することもできます。Terratestは、インテグレーションテストに使えるもう一つの優れたツールです。おそらく最も機能が充実していますが、その分、最も複雑でもあります。
もう少し詳しく見てみましょう。
TerratestはGo言語のライブラリです。使いこなすにはスキルが必要ですが(何しろGoですから)、AWS、Azure、Google Cloud、Kubernetes、Dockerイメージ、Packerビルド(PackerはHashicorpのAMI、つまり仮想マシンのディスクイメージを作成するツール)、さらにはHelmチャートなど、APIを持つあらゆるものをテストできます。
基本的には、resource_test.goというファイルを作成し、ライブラリをインポートして実行するだけです。ただし、Go言語の一定レベルのスキルと、何をテストしたいのかについての深い理解が必要です。
値をランダム化する
インテグレーションテストの段階では、リージョン名などの項目をランダム化します。通常、コードのテストは毎回同じリージョンで行います。値をランダム化すれば結果に変化が生まれ、正常に動作することを確認できます。
名前が一意で、リソース名も一意でなければならない場合もあります。たとえば、Amazon S3バケットの名前は一意である必要があります。これはエンジニアリングプロジェクトと同じプロセスです。
ツールを使う
コードをlintする
ファイルの単体テストを実行する
値をランダム化する
結果をCIに組み込む
プルリクエストに追加する
コードとリリース(masterなど)にタグを付ける
フィーチャーブランチを使い、masterにマージしてからコードのバージョンをリリースする
インフラストラクチャコードのテストにおすすめのその他のツール
先ほど、RSpec派生のツール(ServerspecやInSpecなど)を紹介しました。InSpecはChefが開発したもので、Serverspecはよりコミュニティ主導のツールだと思います。
Serverspecは単体テスト向けですが、Terraform専用ではなく、より汎用的です。インフラストラクチャからDockerイメージ、サーバー上で動作するプロセスまで、さまざまな対象をテストできます。英語に近い書き方ができ、読みやすいのも特長です。コードを直接テストしたり、インフラストラクチャリポジトリ内のTerraformコードに直接対応付けたりするものではありませんが、実際に起動したものをテストできます。たとえば、新機能としてGoogle Cloudにデータベースを追加し、ポート「5.4.3.2」が開いていることを確認したい場合、このテストを書いて実行すれば、そのポートで何かが応答していることをいつまでも確認できます。Serverspecを使えば、これをすばやく簡単に行えます。
私が気に入っているツールにGOSSがあります。オープンソースで、とても優れたツールです。YAMLベースで非常にシンプルです。Terraformコードのテストを目的としたものではなく、テスト結果の検証に特化しています。たとえば、セキュリティグループを作成し、SSH用のポート22が閉じていることを確認したい場合にテストできます。プロセス、パッケージ、DNSリゾルバー、ユーザーなどもテストできます。また、Kubernetes上のHTTPエンドポイントが応答しているかどうかといった確認にも使えます。
テスト結果をNagios互換の形式で出力することもできると思います。そのため、マイクロサービスの/healthエンドポイントとして起動し、正常に動作していることを確認することもできます。とてもシンプルで軽量なツールです。とても気に入っています。Dockerファイルなどにも非常によく使えます。
Terraformコードをテストする
GOSSは、シンプルなYAMLと単一のバイナリで手軽に行える、高レベルのテストに最適です。単体テストにはServerspecとInSpecを使いましょう。どれもオープンソースです。
そして、インテグレーションテストにはもちろんTerratestを使います。非常に高機能です。これらをCI/CDシステムに組み込むか、少なくともリリースして公開する前に実行しましょう。そうしなければ、問題が起きる可能性があります。
Terraformのセキュリティ上の脆弱性をテストするには、Snyk IaCを使って、Terraformの設定(Kubernetes、CloudFormation、ARMテンプレートも対象)をコーディング中にスキャンできます。修正方法も案内されるため、修正をマージしてすぐに次へ進めます。コードを書きながらテストし、Gitリポジトリの変更を監視し、デプロイ前にビルドパイプラインでテストを自動化できます。Freeプランなら数分で利用を始められます。一方、IaCの設定ミスによる侵害は、取り返しのつかない被害につながるおそれがあります。ぜひ登録して、以下から設定の保護を始めましょう。
ソースコードの段階からインフラを保護
Snykはワークフロー内のIaCセキュリティとコンプライアンスを自動化し、構成ドリフトや不足しているリソースを検出します。



