スクリプト
#!/bin/bash
# ECR Refresh Script
# MFA対応のクロスアカウントECRイメージpull & 削除ツール
set -euo pipefail
# 必須の環境変数
ECR_REPOSITORY_NAME=${ECR_REPOSITORY_NAME:-""}
AWS_REGION=${AWS_REGION:-"ap-northeast-1"}
ACCOUNT_A_ACCESS_KEY_ID=${ACCOUNT_A_ACCESS_KEY_ID:-""}
ACCOUNT_A_SECRET_ACCESS_KEY=${ACCOUNT_A_SECRET_ACCESS_KEY:-""}
ACCOUNT_B_ID=${ACCOUNT_B_ID:-""}
CROSS_ACCOUNT_ROLE_ARN=${CROSS_ACCOUNT_ROLE_ARN:-""}
MFA_SERIAL_NUMBER=${MFA_SERIAL_NUMBER:-""}
MFA_TOKEN_CODE=${MFA_TOKEN_CODE:-""}
# カラー出力
GREEN='\033[0;32m'
RED='\033[0;31m'
BLUE='\033[0;34m'
YELLOW='\033[1;33m'
NC='\033[0m'
timestamp() { date '+%Y-%m-%d %H:%M:%S'; }
info() { echo -e "$(timestamp) ${BLUE}[INFO]${NC} $1"; }
success() { echo -e "$(timestamp) ${GREEN}[OK]${NC} $1"; }
warning() { echo -e "$(timestamp) ${YELLOW}[WARN]${NC} $1"; }
error() { echo -e "$(timestamp) ${RED}[ERROR]${NC} $1"; exit 1; }
# 必須項目チェック
info "設定値をチェック中..."
[[ -z "$ECR_REPOSITORY_NAME" ]] && error "ECR_REPOSITORY_NAME が設定されていません"
[[ -z "$ACCOUNT_A_ACCESS_KEY_ID" ]] && error "ACCOUNT_A_ACCESS_KEY_ID が設定されていません"
[[ -z "$ACCOUNT_A_SECRET_ACCESS_KEY" ]] && error "ACCOUNT_A_SECRET_ACCESS_KEY が設定されていません"
[[ -z "$ACCOUNT_B_ID" ]] && error "ACCOUNT_B_ID が設定されていません"
[[ -z "$CROSS_ACCOUNT_ROLE_ARN" ]] && error "CROSS_ACCOUNT_ROLE_ARN が設定されていません"
[[ -z "$MFA_SERIAL_NUMBER" ]] && error "MFA_SERIAL_NUMBER が設定されていません"
[[ -z "$MFA_TOKEN_CODE" ]] && error "MFA_TOKEN_CODE が設定されていません"
success "設定値OK"
# 既存のAWS設定をクリア
unset AWS_PROFILE
unset AWS_DEFAULT_PROFILE
# ステップ1: アカウントAでMFA認証
info "アカウントAでMFA認証中..."
export AWS_ACCESS_KEY_ID="$ACCOUNT_A_ACCESS_KEY_ID"
export AWS_SECRET_ACCESS_KEY="$ACCOUNT_A_SECRET_ACCESS_KEY"
export AWS_DEFAULT_REGION="$AWS_REGION"
unset AWS_SESSION_TOKEN
# MFA認証でセッショントークンを取得
info "MFAトークンでセッション取得中..."
MFA_CREDENTIALS=$(aws sts get-session-token \
--serial-number "$MFA_SERIAL_NUMBER" \
--token-code "$MFA_TOKEN_CODE" \
--duration-seconds 3600 \
--output json 2>/dev/null) || error "MFA認証に失敗しました。MFAシリアル番号とトークンコードを確認してください。"
# MFAセッション認証情報を設定
export AWS_ACCESS_KEY_ID=$(echo "$MFA_CREDENTIALS" | jq -r '.Credentials.AccessKeyId')
export AWS_SECRET_ACCESS_KEY=$(echo "$MFA_CREDENTIALS" | jq -r '.Credentials.SecretAccessKey')
export AWS_SESSION_TOKEN=$(echo "$MFA_CREDENTIALS" | jq -r '.Credentials.SessionToken')
success "MFA認証成功"
# 認証テスト
if ! aws sts get-caller-identity >/dev/null 2>&1; then
error "MFA認証後の認証確認に失敗しました。"
fi
success "アカウントAで認証成功(MFA有効)"
# ステップ2: アカウントBのロールにスイッチ
info "アカウントBのロールにスイッチ中..."
CROSS_ACCOUNT_CREDENTIALS=$(aws sts assume-role \
--role-arn "$CROSS_ACCOUNT_ROLE_ARN" \
--role-session-name "ecr-refresh-$(date +%s)" \
--output json 2>/dev/null) || error "ロールの引き受けに失敗しました。ロールARNと信頼関係を確認してください。"
# クロスアカウント認証情報を設定
export AWS_ACCESS_KEY_ID=$(echo "$CROSS_ACCOUNT_CREDENTIALS" | jq -r '.Credentials.AccessKeyId')
export AWS_SECRET_ACCESS_KEY=$(echo "$CROSS_ACCOUNT_CREDENTIALS" | jq -r '.Credentials.SecretAccessKey')
export AWS_SESSION_TOKEN=$(echo "$CROSS_ACCOUNT_CREDENTIALS" | jq -r '.Credentials.SessionToken')
success "アカウントBのロールにスイッチ成功"
# ステップ3: ECRにログイン
info "ECRにログイン中..."
ECR_REGISTRY="${ACCOUNT_B_ID}.dkr.ecr.${AWS_REGION}.amazonaws.com"
IMAGE_URI="${ECR_REGISTRY}/${ECR_REPOSITORY_NAME}:latest"
aws ecr get-login-password --region "$AWS_REGION" | \
docker login --username AWS --password-stdin "$ECR_REGISTRY" || \
error "ECRログインに失敗しました。"
success "ECRログイン成功"
# ステップ4: 新しいイメージをpull
info "新しいイメージをpull中..."
docker pull "$IMAGE_URI" || error "イメージpullに失敗しました。リポジトリ名を確認してください。"
NEW_IMAGE_ID=$(docker images --format "{{.ID}}" "$IMAGE_URI")
success "新しいイメージpull完了: $IMAGE_URI"
info "新しいイメージID: $NEW_IMAGE_ID"
# ステップ5: pullしたイメージを削除
info "pullしたイメージを削除中..."
# pullしたイメージを削除
if docker rmi "$IMAGE_URI" >/dev/null 2>&1; then
success "pullしたイメージを削除しました: $IMAGE_URI"
else
warning "pullしたイメージの削除に失敗しました: $IMAGE_URI"
fi
# 不要なイメージをクリーンアップ(dangling images等)
DANGLING_IMAGES=$(docker images -f "dangling=true" -q 2>/dev/null || true)
if [[ -n "$DANGLING_IMAGES" ]]; then
info "不要なイメージ(dangling)を削除中..."
echo "$DANGLING_IMAGES" | xargs -r docker rmi >/dev/null 2>&1 || true
success "不要なイメージを削除しました"
fi
success "イメージ削除処理完了"
# 認証情報をクリア
unset AWS_ACCESS_KEY_ID AWS_SECRET_ACCESS_KEY AWS_SESSION_TOKEN
# 最終結果の表示
echo ""
success "=== ECR Refresh 完了 ==="
success "リポジトリ: $ECR_REPOSITORY_NAME"
success "処理したイメージ: $IMAGE_URI"
success "処理内容: pullしたイメージを削除しました"
echo ""
success "すべて完了しました!"
ECR Refresh Tool
MFA対応のクロスアカウントECRイメージ自動更新ツールです。
処理概要
- アカウントAでMFA認証 - TOTPトークンを使用してセッショントークンを取得
- アカウントBのロールにスイッチ - クロスアカウントでAssumeRole実行
- ECRにログイン - アカウントBのECRレジストリにログイン
- 新しいイメージをpull - 最新のlatestタグをpull
- pullしたイメージを削除 - ローカルディスク容量節約のため即座に削除
目的: ECRの最新イメージ存在確認とネットワーク接続テスト(ローカルにイメージは残さない)
前提条件
- AWS CLI, Docker, jq, oathtool がインストール済み
- アカウントAのMFA必須IAMユーザーが設定済み
- アカウントBのクロスアカウントIAMロールが設定済み
初期構築手順
1. 必要パッケージのインストール
# Ubuntu/Debian
sudo apt-get update
sudo apt-get install -y awscli docker.io jq oathtool
# CentOS/RHEL
sudo yum install -y awscli docker jq oathtool
# macOS
brew install awscli docker jq oath-toolkit
2. ディレクトリ作成とファイル配置
# ディレクトリ作成
sudo mkdir -p /usr/local/ecr_refresh_tool
cd /usr/local/ecr_refresh_tool
# ファイルをダウンロード(または作成)
sudo curl -o ecr_refresh.sh https://path-to-your-script/ecr_refresh.sh
sudo curl -o run_ecr_refresh.sh https://path-to-your-script/run_ecr_refresh.sh
# または手動で作成
sudo vim ecr_refresh.sh # メインスクリプト
sudo vim run_ecr_refresh.sh # 実行用ラッパースクリプト
sudo vim .env # 環境変数設定
# 実行権限付与
sudo chmod +x ecr_refresh.sh run_ecr_refresh.sh
3. 環境変数ファイル(.env)の作成
sudo vim /usr/local/ecr_refresh_tool/.env
# 基本設定
ECR_REPOSITORY_NAME=my-app
AWS_REGION=ap-northeast-1
# アカウントA(MFA必須ユーザー)
ACCOUNT_A_ACCESS_KEY_ID=AKIA...
ACCOUNT_A_SECRET_ACCESS_KEY=xxxx...
# アカウントB(ECRがある)
ACCOUNT_B_ID=222222222222
CROSS_ACCOUNT_ROLE_ARN=arn:aws:iam::222222222222:role/ECRAccessRole
# MFA設定
MFA_SERIAL_NUMBER=arn:aws:iam::111111111111:mfa/ecr-mfa-user
MFA_SECRET=YOUR_MFA_SECRET_KEY_HERE
4. 実行用ラッパースクリプト(run_ecr_refresh.sh)の作成
sudo vim /usr/local/ecr_refresh_tool/run_ecr_refresh.sh
#!/bin/bash
# ECR Refresh実行用ラッパースクリプト
cd /usr/local/ecr_refresh_tool
# 環境変数を読み込み
source .env
# MFAトークンを生成
export MFA_TOKEN_CODE=$(oathtool --totp --base32 "$MFA_SECRET")
# メインスクリプト実行
./ecr_refresh.sh
5. AWS側の設定
アカウントA: MFA必須IAMユーザー作成
- IAMコンソール → ユーザー → ユーザーを追加
- ユーザー名:
ecr-mfa-user - MFAデバイスを割り当て
- 以下のポリシーをアタッチ:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": "sts:GetSessionToken",
"Resource": "*"
},
{
"Effect": "Allow",
"Action": "sts:AssumeRole",
"Resource": "arn:aws:iam::ACCOUNT_B_ID:role/ECRAccessRole"
}
]
}
アカウントB: クロスアカウントIAMロール作成
- IAMコンソール → ロール → ロールを作成
- 「別のAWSアカウント」を選択
- アカウントAのIDを入力
- ロール名:
ECRAccessRole - ECRアクセス権限をアタッチ:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"ecr:GetAuthorizationToken",
"ecr:BatchCheckLayerAvailability",
"ecr:GetDownloadUrlForLayer",
"ecr:BatchGetImage"
],
"Resource": "*"
}
]
}
- 信頼関係を編集してMFA条件を追加:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::ACCOUNT_A_ID:user/ecr-mfa-user"
},
"Action": "sts:AssumeRole",
"Condition": {
"Bool": {
"aws:MultiFactorAuthPresent": "true"
}
}
}
]
}
cron設定
1. cronエントリの追加
# rootユーザーのcrontabを編集
sudo crontab -e
# 以下を追加(毎日午前3時に実行)
0 3 * * * cd /usr/local/ecr_refresh_tool && ./run_ecr_refresh.sh >> /var/log/ecr_refresh.log 2>&1
2. ログローテーション設定(オプション)
# logrotateの設定
sudo vim /etc/logrotate.d/ecr_refresh
/var/log/ecr_refresh.log {
daily
rotate 7
compress
delaycompress
missingok
notifempty
}
実行方法
テスト実行
# 手動実行(テスト用)
cd /usr/local/ecr_refresh_tool
sudo ./run_ecr_refresh.sh
成功時の出力例
[INFO] 設定値をチェック中...
[OK] 設定値OK
[INFO] アカウントAでMFA認証中...
[INFO] MFAトークンでセッション取得中...
[OK] MFA認証成功
[OK] アカウントAで認証成功(MFA有効)
[INFO] アカウントBのロールにスイッチ中...
[OK] アカウントBのロールにスイッチ成功
[INFO] ECRにログイン中...
[OK] ECRログイン成功
[INFO] 新しいイメージをpull中...
[OK] 新しいイメージpull完了: 222222222222.dkr.ecr.ap-northeast-1.amazonaws.com/my-app:latest
[INFO] pullしたイメージを削除中...
[OK] pullしたイメージを削除しました: 222222222222.dkr.ecr.ap-northeast-1.amazonaws.com/my-app:latest
[OK] イメージ削除処理完了
[OK] === ECR Refresh 完了 ===
[INFO] リポジトリ: my-app
[INFO] 処理したイメージ: 222222222222.dkr.ecr.ap-northeast-1.amazonaws.com/my-app:latest
[INFO] 処理内容: pullしたイメージを削除しました
[OK] すべて完了しました!
ログ確認
# 実行ログの確認
sudo tail -f /var/log/ecr_refresh.log
# 最近の実行結果を確認
sudo tail -n 50 /var/log/ecr_refresh.log
ファイル構成
/usr/local/ecr_refresh_tool/
├── ecr_refresh.sh # メインスクリプト(MFA認証→ECR pull→削除)
├── run_ecr_refresh.sh # 実行用ラッパー(環境変数読み込み→MFA生成)
└── .env # 環境変数設定ファイル
/var/log/
└── ecr_refresh.log # 実行ログファイル
各ファイルの役割
-
ecr_refresh.sh: メイン処理スクリプト
- MFA認証、クロスアカウントロール引き受け、ECRログイン、pull、削除を実行
-
run_ecr_refresh.sh: 実行用ラッパースクリプト
- 環境変数読み込み、MFAトークン生成、メインスクリプト実行
-
.env: 環境変数設定ファイル
- アカウント情報、MFA設定、ECRリポジトリ情報を保存
トラブルシューティング
よくあるエラー
-
MFA認証失敗
- MFA_SECRETが正しいか確認
- 時刻同期を確認:
sudo ntpdate -s time.nist.gov
-
ロール引き受け失敗
- CROSS_ACCOUNT_ROLE_ARNが正しいか確認
- 信頼関係でMFA条件が設定されているか確認
-
ECRログイン失敗
- ACCOUNT_B_IDが正しいか確認
- IAMロールにECR権限があるか確認
デバッグ方法
# 設定値確認
cd /usr/local/ecr_refresh_tool
source .env
echo "Repository: $ECR_REPOSITORY_NAME"
echo "Account B: $ACCOUNT_B_ID"
echo "Role ARN: $CROSS_ACCOUNT_ROLE_ARN"
# MFAトークン生成テスト
oathtool --totp --base32 "$MFA_SECRET"
# AWSコマンド個別テスト
AWS_ACCESS_KEY_ID="$ACCOUNT_A_ACCESS_KEY_ID" AWS_SECRET_ACCESS_KEY="$ACCOUNT_A_SECRET_ACCESS_KEY" aws sts get-caller-identity
セキュリティ注意事項
-
.envファイルは適切な権限設定(600)にしてください - MFAシークレットは安全に保管してください
- 定期的なアクセスキーローテーションを実施してください
- ログファイルに機密情報が含まれないよう注意してください
メンテナンス
定期メンテナンス項目
- アクセスキーのローテーション(3-6ヶ月)
- MFAデバイスの更新確認
- ログファイルのサイズ監視
- ECRリポジトリの存在確認