理系学生日記

おまえはいつまで学生気分なのか

GitLab CI/CD で terraform ファイルに tflint をかける

Terraform のスクリプトにも lint を自動で実行できるようにします。

lint ツール

Terraform には terraform validate コマンドがあり、設定上のかなりの問題を検知してくれます。 一方で terraform は AWS に特定の問題を検知してくれない場合があったり、description を記述していない variables.tf 等に警告してくれるわけではありません。

terraform には TFlint という linter があるので、こちらを GitLab CI/CD に組み込んでみました。

TFlint

TFlint は単純に引数なしで実行するだけでも、そのディレクトリにあるルートモジュールを対象に HCL をパースしてその問題を検知してくれます。 チェック内容としては例えば以下のようなものがあります。

設定内容のチェックについては、実はデフォルトでは有効になっておらず、 --deep を指定する必要があります。 この --deep チェックは、AWS の API を呼び出しつつリソース間の関係をチェックしていくというもの(なはず)です。 API を呼び出すがゆえに、この場合はアクセスキー ID やシークレットアクセスキーも合わせて渡す必要があります。

また、TFLint は「ルートモジュールを対象」に lint をかけてくれるものであり、再帰的に利用モジュールまで lint をかけるわけではありません。 ただ「渡している値に整合性が取れているか」については Module Inspection と呼ばれる機能でチェックが可能です。 こちらは、 --module を指定することで有効化できます。

加えて、output や variable のドキュメントを書く、といったルールはデフォルトで有効になっていません。これは有効にしていく必要があります。

設定の渡し方

もちろん、このような linter 設定はもちろんコマンドラインで渡すことが可能です。 一方で都度設定するのは面倒なので、 .tflint.hcl というファイルに設定を記述し、カレントディレクトリかホームディレクトリに配置しておくことで tflint が読み込んでくれるようになります。

当該ファイルは HCL 形式なので、今回は以下のような設定としました。

config {
  module     = true
  deep_check = false
}

rule "terraform_dash_in_resource_name" {
  enabled = true
}

rule "terraform_documented_outputs" {
  enabled = true
}

rule "terraform_documented_variables" {
  enabled = true
}

rule "terraform_module_pinned_source" {
  enabled = true
}

GitLab CI/CD への組み込み

GitLab では GitHub Actions と同じように .gitlab-ci.yml をプロジェクトルートに配置しておくことで自動的に CI/CD を走らせることができます。 今回は以下のような設定としてみました。

stages:
  - lint
variables:
  TERRAFORM_VERSION: 0.12.24
  TFLINT_VERSION: 0.15.5
tflint:
  stage: lint
  image:
    name: hashicorp/terraform:${TERRAFORM_VERSION}
    entrypoint: [""]
  before_script:
    - wget https://github.com/terraform-linters/tflint/releases/download/v${TFLINT_VERSION}/tflint_linux_amd64.zip -O tflint.zip
    - unzip tflint.zip -d $HOME
    - rm tflint.zip
  script:
    - >-
      find . -type f -name "*.tf" -exec dirname {} \;
      | sort -u
      | while read line; do
          cd $line;
          echo "processing $PWD ..."
          terraform init -backend=false && $HOME/tflint --config $CI_PROJECT_DIR/.tflint.hcl;
          cd -;
        done

Module Inspection を行うためには terraform init が必要となるので、利用コンテナとしては hashicorp/terraform のイメージを使用します。そこに tflint のバイナリを組み込む形です。

実際にチェックを行っているのは tflint.script の箇所です。 TFlint は先述の通りルートモジュールを対象とする linter なので、モジュールも含めてルートモジュール扱いとするため、個々のディレクトリに移動してから lint をかけます。

実行結果は以下の通り。これは terraform validate でも検知できるレベルのエラーですが、きちんと tflint でも検知できていることがわかります。

今後

できれば --deep チェックを組み込めればと思っているのですが、複数の AWS アカウントがあることを前提とした時にどう運用するのが良いのかなという点が悩みどころになっています。