FutureVuls で ECRのコンテナイメージを脆弱性スキャンしてみた
はじめに
おはようございます、加藤です。FutureVulsを使ってAmazon EC2 Container Registry(以降、ECR)にアップロードされているコンテナイメージを脆弱性スキャンしてみました。
やってみた
スキャン用EC2インスタンス
スキャン用のEC2インスタンスをが必要です。
OSはAmazon Linux 2を使用し、ECRにアクセスする為のIAMロールを作成・関連付けします。
IAMロールの条件はAWS管理ポリシーAmazonEC2ContainerRegistryReadOnly
が関連付けされている事です。
インスタンスが作成できたら、FutureVulsのスキャナをインストールします。インストールコマンドはFutureVulsにログインして下記の操作を行うことで取得できます。
- 右上の人のアイコンをクリック
- グループ設定をクリック
- 左メニューのスキャナをクリック
VULS_SCAN_MODE
をFAST
に変更- 表示されるコマンドをコピー
EC2インスタンスにログインしてコンテナスキャン用としてセットアップします。
# rootにスイッチユーザー sudo su - # パッケージの最新化 yum -y update # FutureVulsスキャナのインストール curl -s http://installer.vuls.biz/vuls-installer.sh | VULS_SAAS_GROUPID="XXX" VULS_SAAS_TOKEN="XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" VULS_SCAN_MODE="fast" bash -s inst # Dockerとjq(後述のスクリプト内で使用)のインストール yum -y install docker jq # Dockerの起動 systemctl enable docker && systemctl start docker # 初回スキャンの実行 /opt/vuls-saas/vuls-saas.sh
コンテナスキャンの設定
こちらのスクリプトを使ってやってみます。
https://gist.github.com/usiusi360/8704fbbd1e9e8931db65aea53535c411
#!/bin/bash BASE_URL="XXXXXXXXX.dkr.ecr.ap-northeast-1.amazonaws.com" IGNORE="dev-,stg-" SUFFIX="image" export AWS_DEFAULT_REGION="ap-northeast-1" export AWS_DEFAULT_OUTPUT="json" ########## function progress() { logger -i -s -p user.$1 "$2" } function get_repolist() { local arr=( `echo ${IGNORE} | tr -s ',' ' '`) local ignores="" for ignore_str in ${arr[@]}; do ignores="${ignores}|${ignore_str}" done ignores=`echo ${ignores} | sed 's/^|//g'` aws ecr describe-repositories \ | jq -r ".repositories[].repositoryName" \ | sort \ | egrep -v "${ignores}" } function get_latest_tag() { local taglist=() for line in `get_repolist` do local repository_name=${line} local tag=`aws ecr describe-images \ --repository-name ${repository_name} \ --filter '{"tagStatus": "TAGGED"}' \ | jq -r ".imageDetails[] | [.imagePushedAt, .repositoryName, .imageTags[] ] | @csv" \ | sort | sed 's/"//g' | tail -1` taglist+=(${tag}) done echo ${taglist[@]} } function login_ecr() { progress notice "login ecr" login_str=`aws ecr get-login --no-include-email --region ${AWS_DEFAULT_REGION}` if [ $? -ne 0 ]; then progress err "fail login ECR" exit fi ${login_str} if [ $? -ne 0 ]; then progress err "fail login ECR" exit fi } function start_container() { login_ecr progress notice "docker pull & docker run" for line in `get_latest_tag` do repository_name=`echo ${line} | cut -d "," -f2` image_tag=`echo ${line} | cut -d "," -f3` progress notice "docker pull [${repository_name}: ${image_tag}]" docker pull ${BASE_URL}/${repository_name}:${image_tag} if [ $? -ne 0 ]; then progress err "fail docker pull" exit fi docker run --detach --rm --name ${SUFFIX}-${repository_name} --entrypoint="" ${BASE_URL}/${repository_name}:${image_tag} tail -f /dev/null if [ $? -ne 0 ]; then progress err "fail docker run" exit fi done } function vuls_scan() { progress notice "start vuls scan" ./vuls-saas.sh if [ $? -ne 0 ]; then progress err "fail vuls scan" fi } function stop_container() { progress notice "stop container" docker kill $(docker ps -q -f name=${SUFFIX}-) if [ $? -ne 0 ]; then progress err "fail stop container" fi } function delete_image() { progress notice "delete old container images" duplicate_images=`docker images | cut -d " " -f1 | sort | uniq -d` for line in ${duplicate_images} do docker rmi -f `docker images | grep $line | tail -n +2 | awk '{print $3}'` done } ##### MAIN cd $(dirname $0) start_container vuls_scan stop_container delete_image
内容を確認してみると
- ECRからイメージのダウンロードしコンテナを起動
- Vuls Scan
- コンテナを停止
- イメージを削除
というステップで実行されています。これをBASE_URL
を自分のAWS環境に合わせて変更してください。
# FutureVulsのディレクトリに移動 cd /opt/vuls-saas/ # スクリプトのダウンロード curl -O https://gist.githubusercontent.com/usiusi360/8704fbbd1e9e8931db65aea53535c411/raw/3d13b7f37ded810c1f6f614e2d9d5f42e559af30/vuls-ecr-scan.sh # スクリプトに実行権限を付与 chmod +x ./vuls-ecr-scan.sh # BASE_URLの変更 vi ./vuls-ecr-scan.sh
デフォルトではFutureVulsは起動中のコンテナをスキャン対象に含めてくれません。config.toml
を変更します。scanMode = ["fast"]
の次行にcontainersIncluded = ["${running}"]
を追加します。
--- config.toml.bak 2018-11-18 14:31:53.432606612 +0000 +++ config.toml 2018-11-18 14:31:22.044601085 +0000 @@ -29,5 +29,6 @@ host = "localhost" port = "local" scanMode = ["fast"] + containersIncluded = ["${running}"] [servers.ip-XXX-XXX-XXX-XXX_ap-northeast-1_compute_internal.uuids] ip-XXX-XXX-XXX-XXX_ap-northeast-1_compute_internal = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
準備ができました!ECRにあるイメージをスキャンしてみましょう。
/opt/vuls-saas/vuls-ecr-scan.sh
ECRにはあらかじめ、Nginxのコンテナを用意しておきました。イメージのスキャンが無事に完了しています!
Cronの修正
FutureVulsスキャナはデフォルトでは、毎日スキャンを行うように設定されています。下記の様に実行するスクリプトをvuls-saas.sh
からvuls-ecr-scan.sh
に変更してください。(実行時間は環境のよって異なります)
#/etc/cron.d/vuls-saas-scan 59 00 * * * vuls-saas /opt/vuls-saas/vuls-ecr-scan.sh >/dev/null 2>&1
あとがき
コンテナをスキャンする際はscanMode
をFast-Root
ではなくFast
にする必要があることに気づいておらずハマってしまいました...(触っていて気づいただけでソースにたどり着いて居ないので知っている方はコメントくれると嬉しいです)
今回はECRのイメージに対してスキャンしましたが、要は実行中のコンテナであればスキャンが可能なのでPrivateなDockerリポジトリに対してもスクリプトを書いてあげれば実行が可能ですね!