【AWS ECS】ECRイメージスキャンをPythonで自動化する

container

こんにちは、エンジニアの田代です。
ECS+Fargateに関する記事も第4弾となりました。
今回は、前回の記事で推奨事項として挙げた定期的にイメージのスキャンを行うについて、boto3を使って自動化するPythonスクリプトを実装したのでサンプルとして紹介したいと思います。
blog.tech-monex.com

ECRイメージスキャンを自動化するコード

import boto3

class EcrImageScanner:
    def __init__(self, registry_id: str, repository_name: str, image_tag: str) -> None:
        self.ecr_client = boto3.client('ecr')
        self.waiter = self.ecr_client.get_waiter('image_scan_complete')
        self.registry_id = registry_id
        self.repository_name = repository_name
        self.image_tag = image_tag
        return
    
    def start_image_scan(self) -> None:
        # イメージスキャンを開始する.
        response = self.ecr_client.start_image_scan(
            registryId=self.registry_id,
            repositoryName=self.repository_name,
            imageId={
                'imageTag': self.image_tag,
            },
        )
        print(response)
        # イメージスキャンが完了するまで待つ.
        self.waiter.wait(
            registryId=self.registry_id,
            repositoryName=self.repository_name,
            imageId={
                'imageTag': self.image_tag,
            },
            WaiterConfig={
                'Delay': 5,
                'MaxAttempts': 60,
            },
        )
        return
    
    def get_scan_findings(self) -> None:
        # イメージの情報を取得する.
        response = self.ecr_client.describe_images(
            registryId=self.registry_id,
            repositoryName=self.repository_name,
            imageIds=[
                {
                    'imageTag': self.image_tag,
                },
            ],
        )
        print(response)
        image_detail = response['imageDetails'][0]
        finding_severity_counts = image_detail['imageScanFindingsSummary']['findingSeverityCounts']

        # 重大な脆弱性が見付かった場合, 例外を送出.
        if 'CRITICAL' in finding_severity_counts and finding_severity_counts['CRITICAL'] > 0:
            raise Exception('CRITICAL vulnerability found (Count: {})'.format(finding_severity_counts['CRITICAL']))
        return


def main():
    registry_id = 'AWSのアカウントID'
    repository_name = 'ECRのリポジトリ名'
    image_tag = 'イメージタグ'

    ecr_image_scanner = EcrImageScanner(registry_id=registry_id, repository_name=repository_name, image_tag=image_tag)
    ecr_image_scanner.start_image_scan()
    ecr_image_scanner.get_scan_findings()


if __name__ == '__main__':
    main()

解説とまとめ

AWSアカウントID、ECRリポジトリ名及びイメージタグをそれぞれ変数に設定して上記のスクリプトを実行するだけで、脆弱性を検知出来ます。
今回のサンプルでは単一のイメージタグで重大な脆弱性が見付かった場合に単純にExceptionを送出していますが、
リポジトリ内の全てのイメージタグに対してスキャンを実行したり、結果をSlackに配信する等色々な事が出来ると思うので、
用途に応じて作り替えてみて下さい。
参考になれば嬉しいです。

田代 侑大システム開発部 マネックス・ラボ