ECRのイメージスキャン結果をCodeBuild内で取得する
初めに
Zenn初投稿です。
現在プロジェクトでAWS Codepipelineを活用してビルド・デプロイの自動化を行なっています。そのCodepipeline内ではAWS CodeBuildを使用してECRへのDockerイメージプッシュと、ECSタスク定義の更新を行なっています。
今回やりたいこと
ECRにはイメージスキャンというイメージの脆弱性を特定してくれる機能があります。
(手動またはプッシュ時に自動で行う方法の2種類がありますが、今回は自動で行うようECRリポジトリに設定しています。)
今回CodeBuildからイメージをプッシュした後、もしそのスキャン結果に深刻な脆弱性が見つかった場合は処理を中止し、もし問題が無ければ次の処理を行う(タスク定義を更新する)ように処理を分岐させたいです。
やったこと
イメージプッシュ後にaws ecr describe-image-scan-findings
を実行しイメージに対してスキャン結果の問い合わせを行います。
ただしプッシュした直後はスキャン中で結果が返却されない為、CodeBuild内でポーリングする(定期的に問い合わせる)必要があります。
またスキャン結果はCritical
Low
のように脆弱性の重要度によってランク毎に出力されるのですが、今回特に重要度が高い脆弱性に絞って対応する要件があったため、取得した結果の中身を見て処理を分ける必要がありました。
これらの処理をシェルスクリプトにまとめて実行するようにしました。
スクリプト
今回作成したスクリプトは以下です。
#!/bin/bash
ALERT_SEVERITY_ARRAY=("CRITICAL" "HIGH" "MEDIUM")
JQ=$(which jq) ||:
if [ -z "$JQ" ]
then
# install jq
sudo yum -y update
sudo yum -y install jq
fi
echo "ECRイメージスキャン結果の取得処理を開始します"
while : ;
do
SCAN_FINDINGS=$(aws ecr describe-image-scan-findings --repository-name $ECR_REPOSITORY_NAME --image-id imageTag=$IMAGE_TAG)
SCAN_STATUS=$(echo $SCAN_FINDINGS | $JQ -r '.imageScanStatus.status')
if [ "$SCAN_STATUS" == "COMPLETE" ];then
break
else
echo "スキャン結果の取得中です..."
sleep 3
CNT=$(( CNT+1 ))
if [ $CNT -gt 20 ];then
echo "スキャン結果の取得に失敗したため、処理を中止します"
exit 1
fi
fi
done
echo "スキャンが完了しました。結果は以下です"
echo $SCAN_FINDINGS
echo "スキャン結果の確認を開始します"
SEVERITIES=$(echo $SCAN_FINDINGS | $JQ -r '.imageScanFindings.findings[].severity')
for s in $SEVERITIES;do
if [[ " ${ALERT_SEVERITY_ARRAY[*]} " =~ " ${s} " ]]; then
echo "「 ${s} 」レベルの脆弱性が確認されたため、処理を中止します"
exit 1
fi
done
echo "ECRイメージスキャン結果の取得処理を終了します"
exit 0
説明
-
ALERT_SEVERITY_ARRAY
で見つかった場合処理を中止する脆弱性の一覧を指定します。今回はMIDDLE
以上の脆弱性を対象としました。 -
while
のところで3秒毎に最大20回スキャン結果の問い合わせを行なっています。- 万が一取得できなかったら処理を中止します。
- 実際に何度か実行していますが、大体4~5回目の問い合わせで取得できており、これまで取得に失敗したことはないです。
-
for
のところで取得できた脆弱性の一覧から、ALERT_SEVERITY_ARRAY
で指定した脆弱性がないか確認しています。もし見つかった場合は処理を中止します。 - 以下の値はCodeBuildの環境変数で指定、または
buildspec.yaml
内で出力してください。-
ECR_REPOSITORY_NAME
ECRリポジトリ名 -
IMAGE_TAG
イメージタグ名
-
スクリプトをCodeBuild内で実行する
実行させる場合はbuildspec.yaml
内で以下のように設定します。
post_build:
commands:
- bash <今回作成したスクリプト>.sh
CodeBuildの環境設定についてですが、aws ecr describe-image-scan-findings
はAWS CLI v2から使えるコマンドなのでAWSが管理するDockerイメージを使用する場合は新しいものでないと動きません。
このスクリプトはaws/codebuild/standard:6.0
で動くことを確認しています。
参考:CodeBuild に用意されている Docker イメージ
Discussion