「Trivy」を使用して、AWS CDKレイヤーでコンテナイメージのスキャンを行うConstructライブラリをConstruct Hubに公開しました。
目次
概要
AWS CDKで、Trivyを使用して、ECRにアップロードするコンテナイメージのスキャン(セキュリティ・脆弱性検査)を行うConstructを、Construct Hubに公開しました。
Trivy
Trivyとは、コンテナイメージやファイルシステム、はたまたAWSアカウントなど幅広いターゲットに対する脆弱性検査・診断が行えるセキュリティツールです。
本記事では、Dockerfileをもとにビルドしたコンテナイメージに対するスキャンをCDKで実施する用途で使用します。
使い所
AWS CDKでは、シンプルにCDKだけで(CDKレイヤー = cdk deploy
内で)、Dockerのコンテナイメージのビルド・デプロイが行えます。
const repository = new Repository(this, "ImageRepository", { removalPolicy: RemovalPolicy.DESTROY, autoDeleteImages: true, }); const image = new DockerImageAsset(this, "DockerImage", { directory: resolve(__dirname, "../../.."), }); const ecrDeployment = new ECRDeployment(this, "DeployImage", { src: new DockerImageName(image.imageUri), dest: new DockerImageName(`${repository.repositoryUri}:${props.ecrTag}`), });
しかし簡単にビルド・プッシュはできますが、そのビルドイメージを同じCDKデプロイの中でイメージスキャンまでする方法は確立されていませんでした。
ECRのスキャン機能もありますがこれは非同期で走るものなので、脆弱性検知時にpushを止めるために使うなどは難しい現状でした(自前でカスタムリソースLambdaを作ったりなどすればできますが・・・)。
また、CI/CDパイプライン(CDK外)でイメージ検査をするにしても、そこでシェルやコマンドなどでビルドをしてさらにCDK内でもビルドをしていると、無駄に2回ビルドをしてしまって余計な時間がかかってしまうことがあります(キャッシュを有効活用しているケースを除く)。
さらにCDKでのデプロイフェーズでイメージスキャンをしない場合、もし脆弱性を検出してもそのままアプリケーションのECRにpushされてしまいます (CDの前のCIでイメージスキャンをして止めているケースももちろんあると思いますがそうではないケースも込みで)。
本Constructは
- CI/CDパイプラインでなく、CDKレイヤー(deploy内)で、Trivyによるイメージスキャンを行う
- 無駄なビルドを避け、CDKデプロイでビルドしたイメージのアセットを使い回す
- 脆弱性を検知した際に、アプリケーションのECRへのイメージpushを止める
ということが可能なConstructになります。
image-scanner-with-trivy
今回作ったConstructは、「image-scanner-with-trivy」という名前でConstruct Hubに公開しています。
また、Construct Hub公開のためには事前にnpmにpublishしている必要があり、npmパッケージとしてのページは以下になります。
ついでにGitHubもよければご覧ください。
Constructの使い方
インストール
まず、CDKリポジトリでインストールします。
npm install image-scanner-with-trivy
宣言
new ImageScannerWithTrivy
が該当Constructになります。
import { ImageScannerWithTrivy } from 'image-scanner-with-trivy'; const repository = new Repository(this, 'ImageRepository', { removalPolicy: RemovalPolicy.DESTROY, autoDeleteImages: true, }); const image = new DockerImageAsset(this, 'DockerImage', { directory: resolve(__dirname, './'), }); // Add properties you want for trivy options (ignoreUnfixed, severity, scanners, trivyIgnore, etc). const imageScanner = new ImageScannerWithTrivy(this, 'ImageScannerWithTrivy', { imageUri: image.imageUri, repository: image.repository, }); // By adding `addDependency`, if the vulnerabilities are detected by `ImageScannerWithTrivy`, the following `ECRDeployment` will not be executed, deployment will fail. const ecrDeployment = new ECRDeployment(this, 'DeployImage', { src: new DockerImageName(image.imageUri), dest: new DockerImageName(`${repository.repositoryUri}:latest`), }); ecrDeployment.node.addDependency(imageScanner);
オプション例
trivyのオプションも色々と指定が可能です。以下のAPIリファレンスをご覧ください。(scanners, severity, ignoreUnfixed, trivyIgnore, etc...と揃っています。)
※もちろん明示的に指定しなくても使えますし、「いい感じにCI/CDでのCDKデプロイで効かせたいオプション」をデフォルトで内部で指定しています。
例えば以下のような感じでオプション指定ができます。trivy自体で使うものではない、Construct特有のオプションも入っていますが、詳細は上記APIリファレンス内のdescriptionをご覧ください。
new ImageScannerWithTrivy(stack, 'ImageScannerWithTrivy', { imageUri: image.imageUri, repository: image.repository, ignoreUnfixed: true, severity: [Severity.CRITICAL], scanners: [Scanners.VULN, Scanners.SECRET], exitCode: 1, exitOnEol: 1, trivyIgnore: ['CVE-2023-37920', 'CVE-2019-14697 exp:2023-01-01', 'generic-unwanted-rule'], memorySize: 4096, platform: 'linux/arm64', });
脆弱性検出時にイメージプッシュを止める
上記CDKコード例のようにecrDeployment.node.addDependency(imageScannerWithTrivy)
とし、ECRDeployment
がImageScannerWithTrivy
に依存するようにすることで先にImageScannerWithTrivy
が実行されるようになり、ImageScannerWithTrivy
によって脆弱性を検出してエラーになった際にアプリケーションのECRへのイメージpushを止めることができます。
const imageScanner = new ImageScannerWithTrivy(this, 'ImageScannerWithTrivy', { imageUri: image.imageUri, repository: image.repository, }); // By adding `addDependency`, if the vulnerabilities are detected by `ImageScannerWithTrivy`, the following `ECRDeployment` will not be executed, deployment will fail. const ecrDeployment = new ECRDeployment(this, 'DeployImage', { src: new DockerImageName(image.imageUri), dest: new DockerImageName(`${repository.repositoryUri}:latest`), }); ecrDeployment.node.addDependency(imageScanner);
公式ドキュメントに掲載!
なんと、Trivyの公式ドキュメントのエコシステムページに本ライブラリを掲載して頂きました!
Dockle版
今回はTrivyを使いましたが、Dockleを使用するライブラリも公開しているので良かったらぜひ!
最後に
CDKで同期的なコンテナイメージスキャンをしたくて自作ライブラリを作りました。
良かったらぜひ使ってみてください。