boto3 でAmazon ECR イメージスキャンを自動実行する

ECR ベーシックイメージスキャンを自動実行するためにECSクラスタ内で起動中のタスクで使用しているイメージのスキャンの開始をboto3で自動化してみました。
2022.11.30

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

はじめに

前回の記事でAmazon ECRイメージスキャンの結果を通知することができたので、今回はスキャンの定期的な実行を自動化してみます。

やること

指定したECSクラスタで実行中のタスクで使用しているイメージのスキャン開始を自動化します。Lambda関数で定期実行するのを想定しています。

詳しくは以下のようになります。

  1. クラスタ内で起動しているタスクの一覧から使用しているイメージを抽出する
  2. 当該イメージのスキャンを行う

コード

コードは下記の通りです。

import boto3
import botocore

class Tasks:
    def __init__(self):
        self.client = boto3.client('ecs')

    """
    clusterで実行中のタスクで使用されているイメージのリストを取得する
    :param cluster クラスタ名
    """

    def list_task_images(self, cluster):
        res = self.client.list_tasks(cluster=cluster)
        task_arns = res['taskArns']
        res = self.client.describe_tasks(tasks=task_arns, cluster=cluster)
        images = []
        for task in res['tasks']:
            for c in task['containers']:
                image = c['image']
                if "dkr.ecr" in image and task['lastStatus'] == 'RUNNING':
                    images.append(c['image'])
        return images

class Image:

    def __init__(self, image):
        r, t = image.split('/')[1].split(':')
        self.repository = r
        self.tag = t

class ECRScan:
    def __init__(self) -> None:
        self.client = boto3.client('ecr')

    """
    指定するImageのECR Scanを開始する
    :param image 対象のイメージ
    """

    def start(self, image):
        try:
            self.client.start_image_scan(
                imageId={
                    'imageTag': image.tag
                },
                repositoryName=image.repository
            )
            print(f'Scan started for {image.repository}:{image.tag}')
        except botocore.exceptions.ClientError as error:
            if error.response['Error']['Code'] == 'LimitExceededException':
                print(f'Scan quota exceed for{image.repository}:{image.tag}.')

CLUSTER = 'your_cluster_name_here'

scan = ECRScan()
tasks = Tasks().list_task_images(CLUSTER)
for image in tasks:
    scan.start(Image(image))

実行結果

情報は少ないですが実行結果は以下のようになります。

> python ecs-ecr-scan.py
Scan started for example-image:5bedf4c

# 1日1回の制限を超えた場合
> python ecs-ecr-scan.py
Scan quota exceed for example-image:5bedf4c .

まとめ

対象のタグの取得とスキャンの開始はもう少し手順が必要かと思ったのですがどちらもAPI1つで実行できたので思ったより簡単でした。