🎶

【GitHub Actions】golang-govulncheck-actionでGoの脆弱性診断、Issue作成、slack通知

2024/09/19に公開

こんにちは、Suuです。
今回は初めてCI/CD系をインターン先で触らせていただいたので、備忘録です。

はじめに

与えていただいたタスクは、golang-govulncheck-actionでGoの脆弱性診断を定期実行し、脆弱性に問題があればIssueを作成してslackに通知でした!
このインターンを始めた数ヶ月前はCIって何?って感じだったので成長を感じますね(自画自賛)
とか言ってますが、やってくれる人〜って言われてあまりわかってないまま新しい分野!!やりたい!って感じで手を挙げたので、ぶっちゃけ頂いてから調べました、汗
最後までやらせてくれたインターン先に感謝です!

golang-govulncheck-actionとは

golang-govulncheck-actionでは、Goのgovulncheckツールを利用して、依存ライブラリや自分のコードに含まれる脆弱性(=攻撃された時に致命傷になる可能性)を検出することができます。
GitHub Actionなので定期実行することや、今回のケースのように仮に脆弱性に問題があった場合にはIssueを立てたりすることも可能です。

実装

まず、GitHub Actionはルート直下の.github/workflows配下におきます。
今回の場合は、以下のような感じです。

root
├── .github
│   └─ workflows
│       └─ govulncheck.yml

まず一番上に、ワークフローの名前とどのタイミングで動作するのかを記述します。

name: Go Vulncheck

on:
  workflow_dispatch: #手動での作動もできるということです
  schedule:
    - cron: "0 0 * * 0" # 毎週日曜日の午前0時(UTC)に実行

次に、jobsの中に、実行したい動作を一つずつ記述していきます。今回は、「脆弱性のチェック」「issueの作成」「slackへの通知」の三つのjobを書きました。

1.go-vulncheck: # Goの脆弱性をチェックするjob

jobs:
  go-vulncheck: 
    runs-on: ubuntu-latest
    outputs: # 最終的に、check_vulnsの部分で出力されたものをVULNERABILITIES_FOUNDとするということかなと思っています
      VULNERABILITIES_FOUND: ${{ steps.check_vulns.outputs.vulnerabilities_found }}
    permissions:
      contents: read
    steps:
      - name: Checkout code
        uses: actions/checkout@v4

      - name: Setup Go #実行環境の用意
        uses: actions/setup-go@v5
        with:
          go-version-file: backend/go.mod
    
      - name: Install govulncheck
        run: go install golang.org/x/vuln/cmd/govulncheck@latest

      - name: Run govulncheck #診断開始
        working-directory: backend
        run: govulncheck ./... > result.log 2>&1 || true

     省略

      - name: Check for vulnerabilities #結果を"$GITHUB_OUTPUT"に出力
        id: check_vulns
        working-directory: ./backend
        run: |
          if grep -q "Vulnerability" result.log; then
            echo "VULNERABILITIES_FOUND=true" >> "$GITHUB_OUTPUT"
          else
            echo "VULNERABILITIES_FOUND=false" >> "$GITHUB_OUTPUT"
          fi

2.create-issue: # issueを作成することに関するjob

create-issue: 
    runs-on: ubuntu-latest
    needs: go-vulncheck
    if: needs.go-vulncheck.outputs.vulnerabilities_found == 'true'
    outputs:
      ISSUE_URL: ${{ steps.create.outputs.issue_url }}
    permissions:
      contents: read
      issues: write
    steps:
      省略
      - name: Get current date # issueのタイトルに日付を入れたかったので実装
        id: date
        run: echo "date=$(date +'%Y-%m-%d')" >> "$GITHUB_OUTPUT"

      - name: Create GitHub Issue if vulnerabilities found
        id: create
        env:
          GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
        run: |
          if [[ -f result.log && -s result.log ]]; then
            ISSUE_BODY=$(cat result.log)
            ISSUE_URL=$(gh issue create \
              --title "[${{ steps.date.outputs.date }}] Goに脆弱性が見つかりました" \
              --body "$ISSUE_BODY" \
              --label "vulnerability") # 必要であれば
            echo "ISSUE_URL=$ISSUE_URL" >> "$GITHUB_OUTPUT"
          else
            echo "Error: result.log is missing or empty." >&2
            exit 1
          fi

3.notify-slack: #slackへの通知に関するjob

  notify-slack: 
    runs-on: ubuntu-latest
    needs: [go-vulncheck, create-issue] #create-issueで作ったISSUE_URLをslackの通知に入れ込むので、needs部分に記載します
    if: "${{ needs.go-vulncheck.outputs.vulnerabilities_found }}"
    steps:
      - name: Set Slack message
        id: set-message
        run: |
          echo "message=Goに脆弱性が見つかりました。Issue: ${{ needs.create-issue.outputs.issue_url }}" >> "$GITHUB_OUTPUT"

      - name: Send Slack notification
        uses: rtCamp/action-slack-notify@v2.1.2
        env:
          SLACK_CHANNEL: "#チャンネル名"
          SLACK_MESSAGE: ${{ steps.set-message.outputs.message }}
          SLACK_COLOR: "danger"
          SLACK_WEBHOOK: ${{ secrets.SLACK_WEBHOOK }}
          SLACK_USERNAME: 好きなものをつけます
          MSG_MINIMAL: true

この実装によって、Goの脆弱性の調査を定期実行し、問題があればissuを立ててslackに通知することができるようになりました!

終わりに

コードの中に説明を書き込むのが個人的に好きなので本記事でもそうしたのですが、少し見にくくなってしまったかもしれません。
今回の実装を通して、他のCI/CD、GitHub Actionについても関心が出てきました!

Discussion