CodebuildでSnyk CLIを使用し、OSSの脆弱性をスキャンする

DevOps

はじめに

本記事では、AWSのCodeBuildを使って、プルリクエストが作成された際にSnykを利用してOSSの脆弱性をスキャンする方法をご紹介します。
Snykは、開発者がソフトウェアのセキュリティ問題を特定し、修正するためのツールです。今回はAWS CDKを用いてCodeBuildを作成し、その中でSnyk CLIを利用します。

CodeBuildを作成する

まずはAWS CDKを用いてCodeBuildのプロジェクトを作成します。ここではTypeScriptを使用します。

  • CodeBuildの設定: GitHubのリポジトリと連携し、PRの作成をトリガーにCodeBuildが動作するように設定しています。
  • Snykの設定: buildSpecにて、Snykのインストールから認証、スキャンまでの処理を定義しています。Snykの組織IDと認証トークンは、前述のSSM Parameter Storeから取得します。
  • IAMの設定: Snykの設定情報をSSM Parameter Storeから取得するため、CodeBuildのロールに対してssm:GetParametersの権限を付与しています。
import { StackProps } from 'aws-cdk-lib';
import { Construct } from 'constructs';
import * as codeBuild from 'aws-cdk-lib/aws-codebuild';
import * as iam from 'aws-cdk-lib/aws-iam';
import { ScopedAws } from 'aws-cdk-lib';


export interface CiProps extends StackProps {
    repositoryName: string;
    githubOwnerName: string;
}

export class Ci extends Construct {
    constructor(
        scope: Construct,
        id: string,
        props: CiProps
    ) {
        super(scope, id);

        const {
            repositoryName,
            githubOwnerName,
        } = props;
        const { accountId, region } = new ScopedAws(this);

        // codeBuild
        const gitHubSource = codeBuild.Source.gitHub({
            owner: githubOwnerName,
            repo: repositoryName,
            webhook: true,
            webhookFilters: [
                codeBuild.FilterGroup
                    .inEventOf(codeBuild.EventAction.PULL_REQUEST_CREATED, codeBuild.EventAction.PULL_REQUEST_REOPENED)
            ],
        });

        let snyk_build_project = new codeBuild.Project(this, 'snykBuild', {
            source: gitHubSource,
            buildSpec: codeBuild.BuildSpec.fromObject({
                "version": "0.2",
                "env": {
                    "parameter-store": {
                        "SNYK_ORG": "snyk-org-id",
                        "SNYK_TOKEN": "snyk-auth-code",
                    }
                },
                "phases": {
                    "install": {
                        "commands": [
                            "echo 'installing Snyk'",
                            "npm install -g snyk"
                        ]
                    },
                    "pre_build": {
                        "commands": [
                            "echo 'authorizing Snyk'",
                            "snyk config set api=$SNYK_TOKEN"
                        ]
                    },
                    "build": {
                        "commands": [
                            "echo 'starting scan'",
                            "pip install -r ./cdk/scraping-lambda/lambda/requirements.txt",
                            "snyk config set org=$SNYK_ORG",
                            `snyk test --file=./cdk/scraping-lambda/lambda/requirements.txt --project-name=${repositoryName} --package-manager=pip`
                        ]
                    },
                    "post_build": {
                        "commands": [
                            "echo ***build complete****"
                        ]
                    }
                }
            }),
            environment: {
                buildImage: codeBuild.LinuxBuildImage.STANDARD_5_0,
                computeType: codeBuild.ComputeType.SMALL
            }
        });

        snyk_build_project.addToRolePolicy(new iam.PolicyStatement({
            actions: ['ssm:GetParameters'],
            effect: iam.Effect.ALLOW,
            resources: [
                `arn:aws:ssm:${region}:${accountId}:parameter/snyk-org-id`,
                `arn:aws:ssm:${region}:${accountId}:parameter/snyk-auth-code`
            ]
        }));
    }
}

CodeBuildのbuildspec.yml

CodeBuildの実行内容を定義したbuildspec.ymlについて説明します。
ここでは、Snykをインストールし、認証情報を設定した後、特定のパスにあるrequirements.txtを対象にSnykのスキャンを実行します。
コマンドのオプションについては、Test – Snyk User Docsを参照ください。
スキャンが完了したら、ビルドが終了したことを示すメッセージを表示します。

{
  "version": "0.2",
  "env": {
    "parameter-store": {
      "SNYK_ORG": "snyk-org-id",
      "SNYK_TOKEN": "snyk-auth-code"
    }
  },
  "phases": {
    "install": {
      "commands": [
        "echo 'installing Snyk'",
        "npm install -g snyk"
      ]
    },
    "pre_build": {
      "commands": [
        "echo 'authorizing Snyk'",
        "snyk config set api=$SNYK_TOKEN"
      ]
    },
    "build": {
      "commands": [
        "echo 'starting scan'",
        "pip install -r ./cdk/scraping-lambda/lambda/requirements.txt",
        "snyk config set org=$SNYK_ORG",
        "snyk test --file=./cdk/scraping-lambda/lambda/requirements.txt --project-name=jumble --package-manager=pip"
      ]
    },
    "post_build": {
      "commands": [
        "echo ***build complete****"
      ]
    }
  }
}

動作確認

設定が完了したら、実際にCodeBuildが動作することを確認します。
プルリクエストを作成すると、CodeBuildが起動しSnykによるスキャンが開始されます。下記は実際にSnykが脆弱性を検出し、その結果がCodeBuildのログに表示されている例です。

(省略)

[Container] 2023/07/28 04:35:47 Running command snyk test --file=./cdk/scraping-lambda/lambda/requirements.txt --project-name=jumble --package-manager=pip

Testing /codebuild/output/src1714918155/src/github.com/masawai/jumble...

Tested 13 dependencies for known issues, found 1 issue, 1 vulnerable path.


Issues to fix by upgrading dependencies:

  Pin certifi@2023.5.7 to certifi@2023.7.22 to fix
  ✗ Improper Following of a Certificate's Chain of Trust (new) [Low Severity]
Snyk Vulnerability Database | Snyk
Critical severity (9.8) Improper Following of a Certificate's Chain of Trust in certifi | CVE-2023-37920
in certifi@2023.5.7 introduced by selenium@4.10.0 > certifi@2023.5.7 Organization: masawai Package manager: pip Target file: ./cdk/scraping-lambda/lambda/requirements.txt Project name: jumble Open source: no Project path: /codebuild/output/src1714918155/src/github.com/masawai/jumble Licenses: enabled Tip: Try `snyk fix` to address these issues.`snyk fix` is a new CLI command in that aims to automatically apply the recommended updates for supported ecosystems. See documentation on how to enable this beta feature: https://docs.snyk.io/snyk-cli/fix-vulnerabilities-from-the-cli/automatic-remediation-with-snyk-fix#enabling-snyk-fix Tip: Detected multiple supported manifests (7), use --all-projects to scan all of them at once. [Container] 2023/07/28 04:35:53 Command did not exit successfully snyk test --file=./cdk/scraping-lambda/lambda/requirements.txt --project-name=jumble --package-manager=pip exit status 1 [Container] 2023/07/28 04:35:53 Phase complete: BUILD State: FAILED [Container] 2023/07/28 04:35:53 Phase context status code: COMMAND_EXECUTION_ERROR Message: Error while executing command: snyk test --file=./cdk/scraping-lambda/lambda/requirements.txt --project-name=jumble --package-manager=pip. Reason: exit status 1

終わりに

本記事では、Snyk CLIとCodeBuildを用いてOSSの脆弱性スキャンを実行する方法を解説しました。これにより開発のスピードを落とすことなくセキュリティを確保することができます。
この記事がどなたかの参考になれば幸いです。

参考

コメント