【GitHub Actions】Trivyのダウンロード->スキャン->結果をIssueにあげるActionを作ってみた

今回は[Trivy](https://github.com/aquasecurity/trivy)を使ってコンテナイメージのスキャンを継続的に行い、脆弱性が発見されたらGitHubのIssueを作成するGitHub ActionsのActionを作成したお話です。このActionをGitHub Actionsのschedule機能(cron)を使って動かせば自動的に脆弱性が発見できます。Issueを自動生成するので運用フローに組み込むことができます。GitHubを使っていればかなりお手軽に導入できますので試してみてください。

それでは本題の自作したActionの中身について説明していきます :muscle:

# 言語
- TypeScript

# 実装機能
ソースコードは[homoluctus/gitrivy](https://github.com/homoluctus/gitrivy)にあります。

## Trivyのダウンロード
ユーザーは予めTrivyをダウンロードする必要はありません。
TrivyはGitHubのアセットにバイナリを置いているので、そこからユーザーが指定したバージョンが一致するものを自動的にダウンロードします。何も指定しなければlatest、つまり最新のTrivyをダウンロードします。
この時プラットフォーム(OS)は内部で判別します。GitHub ActionsではUbuntu、MacOS、Windowsをサポートしていますが、TrivyはUNIX系のみサポートしているのでWindows上でGitHub Actionsを動かしているとTrivyをダウンロードできません。このActionを動かす際はUbuntuかMacOSでお願いします:pray:

## Trivyによるスキャン
内部的にTrivyのバイナリを動かしてコンテナイメージのスキャンを行います。
ユーザーが指定できるオプションは`severity`、`vuln-type`、`ignore-unfixed`です。他にもTrivy本体には指定可能はオプションはありますが、今回の用途に限っていえば3つのオプションだけを可変にするべきと判断しました。

## Issueの作成
Trivyによって脆弱性が発見されたら結果をパースしてGitHubへIssueをあげます。
この際ユーザーはissue自体をあげるかどうかをフラグで指定できます。Trivyによるスキャンだけ行いたいというユーザーの希望も実現しました。あと指定できるのはIssueのタイトル、ラベル、アサインナーです。デフォルト値も設定してありますので特にこだわりがなければ指定しなくてもOKです。

Issueの例:

<img width="1019" alt="screenshot 2019-12-07 7.31.22.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/173064/5b9cf4cb-5aa3-7057-efc8-538a66b8be10.png">

# 使用例
## Trivyによるスキャンのみ

```yaml
name: Vulnerability Scan

on:
  schedule:
    - cron: '0 9 * * *'

jobs:
  scan:
    name: Daily Vulnerability Scan
    runs-on: ubuntu-18.04
    steps:
      - name: Pull docker image
        run: docker pull sample

      - uses: homoluctus/gitrivy@v1.0.0
        with:
          token: ${{ secrets.GITHUB_TOKEN }}
          image: sample
          issue: 'false'
```

## TrivyによるスキャンとIssue作成

```yaml
name: Vulnerability Scan

on:
  schedule:
    - cron: '0 9 * * *'

jobs:
  scan:
    name: Daily Vulnerability Scan
    runs-on: ubuntu-18.04
    steps:
      - name: Pull docker image
        run: docker pull sample

      - uses: homoluctus/gitrivy@v1.0.0
        with:
          token: ${{ secrets.GITHUB_TOKEN }}
          image: sample
          issue: 'true'
          # Issueを作成するのにGITHUB_TOKENが必要です
          # ${{ secrets.GITHUB_TOKEN }}はGITHUBによって
          # 自動生成されるので特に何もしなくていいです
          token: ${{ secrets.GITHUB_TOKEN }}
```

# 指定可能なパラメーター
`with`以下で指定できるパラメーターの説明をします。

|Parameter|Required|Default Value|Description|
|:--:|:--:|:--:|:--|
|trivy_version|False|latest|Trivyのバージョン|
|image|True|N/A|スキャン対象のイメージ名<br>`IMAGE_NAME`をキーとした環境変数にイメージ名を指定してもOK|
|severity|False|HIGH,CRITICAL|Sevirities of vulunerabilities (separeted by commma)|
|vuln_type|False|os,library|Scan target are os and / or library (separeted by commma)|
|ignore_unfixed|False|false|Ignore unfixed vulnerabilities<br>Please specify `true` or `false`|
|issue|False|true|Decide whether creating issue when vulnerabilities are found by trivy.<br>Please specify `true` or `false`|
|token|True if issue parameter is true else False|N/A|GitHub Access Token.<br>${{ secrets.GITHUB_TOKEN }} is recommended.|
|issue_title|False|Security Alert|Issue title|
|issue_label|False|trivy,vulnerability|Issue label (separeted by commma)|
|issue_assignee|False|N/A|Issue assignee (separeted by commma)|


# 参考資料
- [aquasecurity/trivy](https://github.com/aquasecurity/trivy)
- [Creating a JavaScript action](https://help.github.com/en/actions/automating-your-workflow-with-github-actions/creating-a-javascript-action)