LoginSignup
0
1

More than 3 years have passed since last update.

checkovをreviewdogに対応させた話

Last updated at Posted at 2021-03-31

タイトルの通りですがcheckovは出力結果がreviewdogの入力形式に対応していないので、そのままだと組み合わせて使うことができません。そこで以下のようにスクリプトを書いて対応しました。

やりたい事

terraformを管理するGithubのリポジトリでPRを作成した際にterraformコードの静的解析を行い、問題があればPRにコメントを投稿してくれる、という形を目指します。

ここではcheckovで静的解析の結果を標準出力しreviewdogがパイプで結果を受け取ってPRにコメントします。

実際には以下のような表示になります。

スクリーンショット 2021-03-31 20.37.46.png

各ツールについて

実装

まずreviewdogが受け取り可能な形式については以下に記載があります。

そのなかで今回はerrorformatという形式に合わせていこうと思います。errorformatは行単位で指定した形式の標準出力を受け取ることができます。

例えば標準出力が{file}:{line number}:{column number}: {message}のような形式だとすると、errorformat%f:%l:%c: %mとなります。

$ golint ./...
comment_iowriter.go:11:6: exported type CommentWriter should have comment or be unexported
$ golint ./... | reviewdog -efm="%f:%l:%c: %m" -diff="git diff FETCH_HEAD"

出力形式の変換

reviewdogでどのように受け取るかが分かったので次はcheckovの出力を調整します。

checkovの出力形式は以下に記されている通りです。

これらの出力形式からどれかを選びreviewdogの受け取り形式に合うよう変更していきます。選択可能なかで形式変更が最も容易なのはJSONなので、一旦JSON形式で出力した結果をパイプで受け取り、自作のスクリプトを通してerrorformatに変換していきます。

コマンドとしては以下のようになります。

$ checkov -d . -o json | python3 parse.py

ここではpythonを利用していますが言語は何でも構いません。

pythonのコードは以下のようになります。
(結構雑に書いているので細かいバグがありそうですが...)

parse.py

import json, sys

def main():
    data = json.load(sys.stdin)
    failed_checks = data["results"].get("failed_checks")
    if failed_checks is None:
        exit(0)

    for failed_check in failed_checks:
        file_name = failed_check["file_path"].replace('/', '')
        line_number = failed_check["file_line_range"][0]
        error_message = failed_check["check_name"]
        print('{}:{}: {}'.format(file_name, line_number, error_message))

    exit(1)


if __name__ == "__main__":
    main()

テスト実行

ここまで出来たらローカル環境で実際にtfファイルを作成してテストしてみます。

gke.tf

resource "google_service_account" "default" {
  account_id   = "service-account-id"
  display_name = "Service Account"
  project      = var.project_id
}

resource "google_container_cluster" "primary" {
  name     = "my-gke-cluster"
  location = var.region

  # We can't create a cluster with no node pool defined, but we want to only use
  # separately managed node pools. So we create the smallest possible default
  # node pool and immediately delete it.
  remove_default_node_pool = true
  initial_node_count       = 1
}

resource "google_container_node_pool" "primary_preemptible_nodes" {
  name       = "my-node-pool"
  location   = var.region
  cluster    = google_container_cluster.primary.name
  node_count = 1

  node_config {
    preemptible  = true
    machine_type = "e2-medium"

    # Google recommends custom service accounts that have cloud-platform scope and permissions granted via IAM Roles.
    service_account = google_service_account.default.email
    oauth_scopes = [
      "https://www.googleapis.com/auth/cloud-platform"
    ]
  }
}

ローカルでテスト実行すると以下のような表示になります。

$ checkov -d . -o json | python3 parse.py | reviewdog -efm="%f:%l: %m" -name="checkov" -reporter=local -filter-mode=nofilter
gke.tf:7: Ensure PodSecurityPolicy controller is enabled on the Kubernetes Engine Clusters
gke.tf:7: Ensure Kubernetes Cluster is created with Private cluster enabled
gke.tf:7: Ensure Kubernetes Cluster is created with Alias IP ranges enabled
gke.tf:7: Ensure master authorized networks is set to enabled in GKE clusters
gke.tf:7: Ensure Kubernetes Clusters are configured with Labels
gke.tf:7: Ensure a client certificate is used by clients to authenticate to Kubernetes Engine Clusters
gke.tf:7: Ensure GKE basic auth is disabled
gke.tf:7: Ensure Network Policy is enabled on Kubernetes Engine Clusters
gke.tf:18: Ensure 'Automatic node upgrade' is enabled for Kubernetes Clusters
gke.tf:18: Ensure Container-Optimized OS (cos) is used for Kubernetes Engine Clusters Node image
gke.tf:18: Ensure 'Automatic node repair' is enabled for Kubernetes Clusters

後はGithub Actionsのyamlに設定ファイルとして書いてあげればCIとして利用することが出来ます。

以上、「checkovをreviewdogに対応させた話」でした。

0
1
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
0
1