0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

クロスアカウントでスイッチロールしてECRからlatestイメージをpullするツール

0
Last updated at Posted at 2025-08-06

スクリプト

#!/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イメージ自動更新ツールです。

処理概要

  1. アカウントAでMFA認証 - TOTPトークンを使用してセッショントークンを取得
  2. アカウントBのロールにスイッチ - クロスアカウントでAssumeRole実行
  3. ECRにログイン - アカウントBのECRレジストリにログイン
  4. 新しいイメージをpull - 最新のlatestタグをpull
  5. 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ユーザー作成

  1. IAMコンソール → ユーザー → ユーザーを追加
  2. ユーザー名: ecr-mfa-user
  3. MFAデバイスを割り当て
  4. 以下のポリシーをアタッチ:
{
    "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ロール作成

  1. IAMコンソール → ロール → ロールを作成
  2. 「別のAWSアカウント」を選択
  3. アカウントAのIDを入力
  4. ロール名: ECRAccessRole
  5. ECRアクセス権限をアタッチ:
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "ecr:GetAuthorizationToken",
                "ecr:BatchCheckLayerAvailability",
                "ecr:GetDownloadUrlForLayer",
                "ecr:BatchGetImage"
            ],
            "Resource": "*"
        }
    ]
}
  1. 信頼関係を編集して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リポジトリ情報を保存

トラブルシューティング

よくあるエラー

  1. MFA認証失敗

    • MFA_SECRETが正しいか確認
    • 時刻同期を確認: sudo ntpdate -s time.nist.gov
  2. ロール引き受け失敗

    • CROSS_ACCOUNT_ROLE_ARNが正しいか確認
    • 信頼関係でMFA条件が設定されているか確認
  3. 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リポジトリの存在確認
0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?