この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。
はじめに
おはようございます、加藤です。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リポジトリに対してもスクリプトを書いてあげれば実行が可能ですね!