gosecをGithub Actionsを用いて導入した話

gosecをGithub Actionsを用いて導入した話

The Gopher character is based on the Go mascot designed by Renée French.

はじめに

 こんにちは!入社してもうすぐ半年が経とうとしております、こまです。
日々悩みつつも楽しく過ごしていたら、あっという間ですね。

 さて、今回はgosecを導入したお話を書いてみようと思います。
私は普段golangを使って実装しているのですが、「セキュアなコードを書くことができているか?」という観点をもってコードを書くことは非常に大切ですよね。

問題は、「常にセキュアな実装ができているか?」ということです。

  • 公式でアップデートされるセキュア実装を見逃す可能性がある
  • チーム開発の場合、自分がセキュアな書き方を知っていても他の人が知らない可能性がある
  • 知っていても、うっかり書き漏れる可能性がある

こういった問題を解決してくれるセキュリティツール、それが「gosec」です。

gosecの特徴

 gosecはSAST(Static application security testing)の一種で、セキュリティ上の欠陥について、golangの静的コード分析を実行します。

gosecのメリット

  • 導入が非常に容易でハードルが低い
  • 一般的なセキュリティ要件を満たしている
  • レポート出力に対応
  • カスタムセキュリティ要件の設定も可能(ただし、go-regulatedの方がチームで使用する上での汎用性は高そうです)

完成形

 今回はgosecを使用して、プルリクエスト発行時に以下が自動で行われるよう実装を行いました。(※以降に記載している手順はgosec v2.9.5時点のREADMEを参照しております。)

  1. reviewdog経由でgosecのレビュー結果を表示させる
  2. Github Actionsを用いて、gosecのレビュー結果をhtmlレポートで出力する

導入

1. reviewdog経由でgosecのレビュー結果を表示させる

 gosecをGithub Actionsへ導入するにあたり、次の2点の懸念事項がありました。

  • gosecはコード全体に対してアラートを発出するため、特にgosec導入初期に大量のアラートが発出される
  • プルリクエストの差分と関係のないコードのアラートも発出される

こうなると、確認や対応が大変になり、アラートが形骸化してしまうリスクが発生します。

 そこで今回は、プルリクエストにて差分があった箇所にのみコメントを投稿してくれるreviewdogとgosecをコラボレーションさせることにしました。もちろん最終的には全リスクを解消剃る必要はありますが、差分に関わるアラートは取り急ぎreviewdogから確認可能です。

reviewdogへのgosecの組み込み

golangci-lintのActionを利用して簡単に実装することができます。

name: reviewdog
on: [pull_request]
jobs:
  reviewdog:
    runs-on: ubuntu-latest
    env:
      GO111MODULE: on
    steps:
      - name: Checkout Source
        uses: actions/checkout@v2

      - name: Run golangci-lint
        uses: reviewdog/action-golangci-lint@v2
        with:
          github_token: ${{ secrets.GITHUB_TOKEN }}
          level: info
          golangci_lint_flags: "--config=.github/.golangci.yml"
          # 差分以外のアラートをActionsの"Annotations"より確認可能にする
          filter_mode: nofilter
          reporter: github-pr-review

さらに.github/.golangci.ymlにてlinterにgosecを指定すれば、完了です。(参考:https://golangci-lint.run/usage/configuration/

linters:
  disable-all: true
  enable:
    - gosec

issues:
  exclude-use-default: false

gosec:
  exclude-generated: true
  severity: "low"
  confidence: "low"

組み込み結果

プルリクエスト上で、G404エラーが表示されました。

Annotationsのアラートは以下の様に出力されました。差分にかからないものを確認できます。

2. Github Actionsを用いて、gosecのレビュー結果をhtmlレポートで出力する

 gosecは、公式にてGitHub Actionsの設定コードが公開されています。レポートを出力しない場合、以下を.github/workflows内のyamlファイルに記載することでgosecの実行が可能です。

name: Run Gosec
on:
  push:
    branches:
      - master
  pull_request:
    branches:
      - master
jobs:
  tests:
    runs-on: ubuntu-latest
    env:
      GO111MODULE: on
    steps:
      - name: Checkout Source
        uses: actions/checkout@v2
      - name: Run Gosec Security Scanner
        uses: securego/gosec@master
        with:
          args: ./...

 ただし、上記の実装ではActionsにてスキャン結果を確認できるものの、レポートを出力することはできません。今回はレポートを出力させたいので、直接コマンドを叩くよう設定しました。
レポート形式は text, json, yaml, csv, sonarqube, JUnit XML, html, golintから選択可能であり、-fmt=で指定しています。

name: Run Gosec
on: [pull_request]
jobs:
  gosec:
    runs-on: ubuntu-latest
    env:
      GO111MODULE: on
    steps:
      - name: Checkout Source
        uses: actions/checkout@v2

      - name: Run gosec and Report results
        run: |
        #任意のバージョン(vX.Y.Z)を指定してインストール
          curl -sfL https://raw.githubusercontent.com/securego/gosec/master/install.sh | sh -s vX.Y.Z
        #gosecの実行、html形式でのレポート出力
          ./bin/gosec -fmt=html -out=results.html ./...
        #エラー(修正点)がある場合、以下の作業がキャンセルされるためオプションを追加
        continue-on-error: true

      - name: Move report
        run: |
          mkdir -p /tmp/artifacts
          mv results.html /tmp/artifacts

        #Github ActionのUpload a Build Artifactを使用
      - name: Upload gosec report
        if: ${{ always() }}
        uses: actions/upload-artifact@v2
        with:
          name: gosec results
          path: /tmp/artifacts

プルリクエストを行うとActionsの"Artifacts"にレポートが表示され、ファイル名をクリックするとzipに入ったhtmlファイルがダウンロードされます。

レポートを開くと、抵触したgosecルール、ファイル名やコード、各指摘の重要度等が確認できました。

おわりに

 以上が、gosecを用いたセキュリティーツール導入のご紹介となります。
reviewdogを使用すれば段階的なコードの修正が可能になりますし、レポートでは重要度などに応じてソートもできるので非常に便利です。

比較的導入も容易ですので、ぜひ導入を検討いただければと思います。
これから導入されるどなたかの一助になりましたら幸いです。

ありがとうございました!