「Dockle」を使用して、AWS CDKレイヤーでコンテナイメージのスキャン(セキュリティ診断)を行うConstructライブラリをConstruct Hubに公開しました。
目次
概要
AWS CDKで、Dockleを使用して、ECRにアップロードするコンテナイメージのセキュリティ・脆弱性検査を行うConstructを、Construct Hubに公開しました。
Dockle
Dockleとは、コンテナイメージの脆弱性検査・診断ツールであり、Dockerfileをビルドしたイメージ内の脆弱性に対して警告・対処法などを提案してくれるツールになります。
使い所
AWS CDKレイヤー(cdk deploy
)内で、Dockerのコンテナイメージのビルド・デプロイをしているケースも多いかと思います。
CDKとコンテナのビルド・デプロイを分離しているケースも多いかと思いますが、シンプルにCDKだけでビルド・デプロイが行えるのが利点です。
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レイヤーでイメージのビルド・デプロイをしていると、そのイメージの検査をする暇がなかったりしますよね。
また、CI/CDパイプラインでイメージの検査をするとしても、そこでシェルなどでビルドをしてさらにCDKでもビルドをしていると、無駄に2回ビルドをしてしまって余計な時間がかかってしまうことがあります(キャッシュを有効活用しているケースを除く)。
さらにデプロイフェーズでイメージスキャンを入れない場合、もし脆弱性を検出してもそのままアプリケーションのECRにpushされてしまいます (CDの前のCIでイメージスキャンをして止めているケースももちろんあると思いますがそうではないケースも込みで)。これは避けたいですよね。
本Constructは
- CI/CDパイプラインでなく、CDKレイヤー(deploy内)で、Dockleによるイメージスキャン(セキュリティ診断)を行う
- 無駄なビルドを避け、CDKデプロイでビルドしたイメージのアセットを使い回す
- 脆弱性を検知した際に、アプリケーションのECRへのイメージpushを止める
ということが可能なConstructになります。
image-scanner-with-dockle
今回作ったConstructは、「image-scanner-with-dockle」という名前でConstruct Hubに公開しています。
また、Construct Hub公開のためには事前にnpmにpublishしている必要があり、npmパッケージとしてのページは以下になります。
ついでにGitHubもよければご覧ください。
Constructの使い方
インストール
まず、CDKリポジトリでインストールします。
npm install image-scanner-with-dockle
宣言
new ImageScannerWithDockle
が該当Constructになります。
this.repository = new Repository(this, "ImageRepository", { removalPolicy: RemovalPolicy.DESTROY, autoDeleteImages: true, }); const image = new DockerImageAsset(this, "DockerImage", { directory: resolve(__dirname, "../../.."), }); const imageScannerWithDockle = new ImageScannerWithDockle(this, "ImageScannerWithDockle", { imageUri: image.imageUri, repository: image.repository, ignore: ["CIS-DI-0009"], }); // By adding addDependency, if the vulnerabilities are detected by ImageScannerWithDockle, the following ECRDeployment will not be executed, deployment will fail. const ecrDeployment = new ECRDeployment(this, "DeployImage", { src: new DockerImageName(image.imageUri), dest: new DockerImageName(`${this.repository.repositoryUri}:${props.ecrTag}`), }); ecrDeployment.node.addDependency(imageScannerWithDockle);
脆弱性検出時にイメージプッシュを止める
上記例のようにecrDeployment.node.addDependency(imageScannerWithDockle)
というようにして、ECRDeployment
がImageScannerWithDockle
に依存するようにすることで先にImageScannerWithDockle
が実行されるようになり、ImageScannerWithDockle
によって脆弱性を検出してエラーになった際にアプリケーションのECRへのイメージpushを止めることができます。
ignore
無視したいルールはignore
パラメータに指定可能です。何も無視しない場合はignore
パラメータを省略することができます。
const imageScannerWithDockle = new ImageScannerWithDockle(this, "ImageScannerWithDockle", { imageUri: image.imageUri, repository: image.repository, ignore: ["CIS-DI-0002", "CIS-DI-0003"], });
ignoreの種類に関しては以下をご覧ください。
SingletonFunction
CDKの話になりますが、これはカスタムリソースLambdaを使用しています。
1スタックで複数のイメージをビルドする際に何度もImageScannerWithDockle
を作成する(呼び出す)ことになりますが、毎回同じコードのLambdaを生成するのはもったいないですよね。
ここでは、何度呼び出されてもCDKの内部で同じLambdaを使い回すように、SingletonFunction
というConstructを利用して、Lambdaを1つだけ生成して使い回すようにしています。
実際の使用例として、ソースコードでいうとこの辺りです。
Trivy版
今回はDockleを使いましたが、Trivyを使用するライブラリも公開したので良かったらぜひ!
最後に
CDK好きとして、Dockle好きとして、CDKをフル活用している環境でDockleによるイメージスキャンを行いたいケースがあったので、作ってみました。
どなたかに刺されば幸いです。