Microsoft Defender for DevOps の始め方2 - GitHub Actions 上でのコンテナーイメージの脆弱性スキャン

:::note warn
2023年10月時点で、Microsoft Defender for DevOps は Microsoft Defender CSPM の一部として、DevOps セキュリティを担う形に製品体系が変更されています。詳細については、公式ドキュメントをご参照ください。
:::

# 本記事について

本記事では、Microsoft Defender for DevOps の始め方2として、GitHub Actions のワークフロー上でビルドされた Docker イメージの脆弱性スキャンを行う方法を見ていきます。

GitHub Actions で Microsoft Defender for DevOps そのものを利用する方法については、[Microsoft Security Advent Calendar 2022 Advent Calendar 2022](https://qiita.com/advent-calendar/2022/microsoft-security)でリリースした、[Microsoft Defender for DevOps の始め方 - for GitHub -](https://qiita.com/YoshiakiOi/items/c18419e5d1c514148042) をご参照ください。

# コンテナーイメージの脆弱性スキャンについて

アプリケーションをコンテナー化して実行する場合、ミドルウェアや言語、ライブラリやアプリケーションはコンテナー側に含まれます。そのため、たとえばマイクロソフト社の Defender for Endpoint のような脆弱性スキャナーでは実行中のコンテナーの内部を見ることはできず、イメージ側でそれぞれの脆弱性を確認する必要があります。そのため、使っているミドルウェアやライブラリのバージョンに CVE 化された脆弱性があるかどうかなどは、コンテナーイメージのスキャナーを使って調査を行います。

そういった背景から、たとえば、Microsoft Azure の Kubernetes クラスターマネージドサービスである [Azure Kubernetes Service (AKS) のセキュリティベストプラクティス](https://learn.microsoft.com/ja-jp/azure/aks/concepts-security)でも、ビルドのセキュリティやイメージのセキュリティとして、イメージの脆弱性スキャナーの利用を推奨しています。

# Azure を利用する際のイメージスキャンの種類について

Azure では、イメージの脆弱性管理は Microsoft Defender for Cloud が担っています。特に、下記の2種類のサービスで脆弱性スキャンを行います。

## Microsoft Defender for Containers

[Microsoft Defender for Containers](https://learn.microsoft.com/ja-jp/azure/defender-for-cloud/defender-for-containers-vulnerability-assessment-azure) では、Azure Container Registry (ACR) にプッシュされたイメージに対して、Push 時や7日間に一度という周期で、イメージのスキャンがなされます。スキャナーは Qualys 社のスキャナーが用いられます。

## Microsoft Defender for DevOps

一方、本記事のテーマである、Microsoft Defender for DevOps では、GitHub Actions のランナー上でビルドされたイメージのスキャンを行います。スキャナーは Trivy になります。

## Defender for Containers vs Defender for DevOps - 比較と使い分け

脆弱性スキャナーの種類や動作環境が異なる両者は、それぞれ特徴や利用できるシーンが異なります。下記の表に簡単にポイントをまとめています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/276225/1a91e852-e3aa-3e39-e824-baf0509a681e.png)


# Defender for DevOps でコンテナーイメージの脆弱性スキャンを行う時の全体像

システムの全体像としては下記の絵のようになります。GitHub Repository にプッシュされたコードや Dockerfile を使って、GitHub Actions でビルドやリリース (レジストリへの Push) を行います。その際に、Advanced Security の機能を使ってセキュリティ解析を行う形です。セキュリティ解析のツールとして、Defender for DevOps から提供される Microsoft Security DevOps のツールを使います。特に今回はコンテナーイメージスキャンを行える Trivy を用います。

セキュリティ解析の結果は Advaned Security に送られ、GitHub 上のセキュリティの画面で見られます。また、Defender for Cloud にも連携されるので、Azure の画面からも確認できます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/276225/5454dad6-32ee-257e-74e4-ac93ac47dda0.png)

# 実際に Defender for DevOps の Trivy スキャナーで Docker イメージをスキャンする

## 前提条件

Defender for DevOps を Azure サブスクリプションで有効にし、今回利用する GitHub レポジトリと接続してください。手順は、[Microsoft Defender for DevOps の始め方 - for GitHub -](https://qiita.com/YoshiakiOi/items/c18419e5d1c514148042) にもまとめています。

## Docker イメージをスキャンする

GitHub Actions で以下のようなワークフローの YAML ファイルを作成し、実行します。Microsoft Security DevOps ツール実行以外の場所については、任意のステップを追加してください。

```YAML: ワークフロー
name: <ワークフロー名>

on: 
  workflow_dispatch:

jobs:
  Job1:
    runs-on: ubuntu-latest
    steps:
    
      # checkout the repo
      - name: Checkout GitHub Action
        uses: actions/checkout@v3
              
      # たとえば Docker イメージをビルドするジョブをスキャン前に実行
      - name: Docker Build
        run: docker build . <必要な引数など>

      # Microsoft Security DevOps ツールの実行
      # Run analyzers
      - name: Run Microsoft Security DevOps Analysis
        uses: microsoft/security-devops-action@latest
        id: msdo
        env:
          GDN_TRIVY_ACTION: image
          GDN_TRIVY_TARGET: <Docker コンテナーのイメージ名>
        with:
          categories: "containers"
          tools: "Trivy"

    # Upload alerts to the Security tab
      - name: Upload alerts to Security tab
        uses: github/codeql-action/upload-sarif@v2
        with:
          sarif_file: ${{ steps.msdo.outputs.sarifFile }}

    # Upload alerts file as a workflow artifact
      - name: Upload alerts file as a workflow artifact
        uses: actions/upload-artifact@v3
        with:  
          name: alerts
          path: ${{ steps.msdo.outputs.sarifFile }}

```

上記のワークフローを実行すると、脆弱性情報が取得されます。GitHub Actions の Runner 上では下記のようなコマンドが実際に実行されています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/276225/a10ccc6f-673f-cd29-8ba5-b2e28c3543c0.png)

そして、生成された SARIF ファイルのデータを GitHub レポジトリのセキュリティタブにアップロードし、下記のように確認できます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/276225/b85ce9f7-06e1-e10f-a0ab-aec2c9c7dcf2.png)

一方、Azure Portal の Defender for Cloud の画面でも同様の結果を取得できます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/276225/684dee67-77c9-3f6a-0c32-24d8afdf7a36.png)

### YAML の設定方法について

Defender for DevOps の Trivy オプションを利用するときの設定については、[こちらの Wiki](https://github.com/microsoft/security-devops-action/wiki#trivy-options) が参考になります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/276225/56b2d5ae-2da7-9e48-89d9-ff586e401907.png)

上記では、GDN_TRIVY_ACTION を "image" にして、デフォルト値の filesystem から変更しています。また、GDN_TRIVY_TARGET でイメージ名を指定しています。

### vulnerables/web-dvwa:latest を利用したテスト

もしくは、すでに脆弱性が含まれている既製のコンテナーイメージを使って、このツール自体を試してみることもできます。下記は、Damn Vulnerable Web Application (DVWA) を利用したサンプルです。

```YAML
name: "Trivy-Test"

on: 
  workflow_dispatch:

jobs:
  Job1:
    runs-on: ubuntu-latest
    steps:
    
      # checkout the repo
      - name: Checkout GitHub Action
        uses: actions/checkout@v3
              
      # Docker Pull
      - name: Docker pull
        run: docker pull vulnerables/web-dvwa:latest
        
      # Microsoft Security DevOps ツールの実行
      # Run analyzers
      - name: Run Microsoft Security DevOps Analysis
        uses: microsoft/security-devops-action@latest
        id: msdo
        env:
          GDN_TRIVY_ACTION: image
          GDN_TRIVY_TARGET: vulnerables/web-dvwa:latest
        with:
          categories: "containers" 
          tools: "Trivy"

    # Upload alerts to the Security tab
      - name: Upload alerts to Security tab
        uses: github/codeql-action/upload-sarif@v2
        with:
          sarif_file: ${{ steps.msdo.outputs.sarifFile }}

    # Upload alerts file as a workflow artifact
      - name: Upload alerts file as a workflow artifact
        uses: actions/upload-artifact@v3
        with:  
          name: alerts
          path: ${{ steps.msdo.outputs.sarifFile }}
```

こちらだと膨大な数の脆弱性情報が Security Tab に追加されます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/276225/da77be3e-6287-5ebd-beac-371d923cb089.png)

# 最後に

本記事では、2022年10月の Ignite にて発表された Microsoft Defender for DevOps について、特にコンテナーイメージの脆弱性スキャンに焦点を当ててご紹介しました。GitHub Advanced Security や Microsoft Defender を使い始め、より簡単にコンテナー化されたアプリケーションのセキュリティ課題を特定いただく一助となれば幸いです。

＊本稿は、個人の見解に基づいた内容であり、所属する会社の公式見解ではありません。また、いかなる保証を与えるものでもありません。正式な情報は、各製品の販売元にご確認ください。