AWS SSO環境でクロスアカウントS3 syncがAccessDeniedになる原因と解決策

AWS SSO環境でクロスアカウントS3 syncがAccessDeniedになる原因と解決策

2026.01.27

スクリーンショット 2026-01-27 170846

想定読者

  • AWS IAM Identity Center(旧AWS SSO)でマルチアカウント運用している
  • aws s3 sync をクロスアカウントで実行しようとして AccessDenied に遭遇した

先に結論

宛先バケット側にバケットポリシーで明示的な許可が必要

  1. aws s3 sync は宛先バケットに対して s3:ListBuckets3:PutObject が必須
    • s3:ListBucket: 差分判定のために宛先のオブジェクト一覧を取得するため
    • s3:PutObject: オブジェクトを宛先にコピーするため
  2. SSO環境でのPrincipal指定はパス付きIAMロールARNを使う
    • ❌ 「一時的なセッション」を指すARN:arn:aws:sts::...:assumed-role/...
    • ✅ 「IAMロール自体」を指すARNarn:aws:iam::...:role/aws-reserved/sso.amazonaws.com/<region>/AWSReservedSSO_...

やりたいこと

ソース側のSSO認証情報(AdministratorAccess)を使って、別アカウントのS3バケットへ同期する。

項目
ソース(アカウントA) s3://dev-cm-aaaaaaaaaaaa
宛先(アカウントB) s3://dev-cm-bbbbbbbbbbbb

実行コマンド

aws s3 sync s3://dev-cm-aaaaaaaaaaaa s3://dev-cm-bbbbbbbbbbbb --only-show-errors

遭遇したエラー

fatal error: An error occurred (AccessDenied) when calling the ListObjectsV2 operation:
User: arn:aws:sts::aaaaaaaaaaaa:assumed-role/AWSReservedSSO_AdministratorAccess_.../...
is not authorized to perform: s3:ListBucket on resource: arn:aws:s3:::dev-cm-bbbbbbbbbbbb
because no resource-based policy allows the s3:ListBucket action

ハマりポイントと解決策

ハマりポイント1: 宛先側にバケットポリシーが必要だと気づかない

誤解

SSOでAdministratorAccessを取得している = どのバケットも操作できるはず

実際
AdministratorAccessはあくまでそのアカウント内の権限です。クロスアカウントでは、宛先側のリソースポリシー(バケットポリシー)で許可しない限りアクセスできません。

ハマりポイント2: PrincipalにSTSセッションARNを指定してしまう

エラーメッセージに表示されるARNをそのままコピペしたくなりますが、これでは動きません。

❌ 動かない例(STSセッションARN)

{
    "Principal": {
        "AWS": "arn:aws:sts::111111111111:assumed-role/AWSReservedSSO_AdministratorAccess_.../username"
    }
}

❌ 動かない例(パスなしIAMロールARN)

{
    "Principal": {
        "AWS": "arn:aws:iam::111111111111:role/AWSReservedSSO_AdministratorAccess_..."
    }
}

✅ 正しい例(パス付きIAMロールARN)

{
    "Principal": {
        "AWS": "arn:aws:iam::111111111111:role/aws-reserved/sso.amazonaws.com/ap-northeast-1/AWSReservedSSO_AdministratorAccess_..."
    }
}

SSO経由で作成されるIAMロールは /aws-reserved/sso.amazonaws.com/<region>/ というパスを持っています。このパスを含めた完全なARNを指定する必要があります。

正しいロールARNの取得方法

ソース側のSSO認証情報を環境変数に設定した状態で、以下を実行します。

ロール名を取得

ROLE_NAME=$(
    aws sts get-caller-identity --query Arn --output text \
    | sed -n 's#.*:assumed-role/\([^/]*\)/.*#\1#p'
)
echo "Role Name: $ROLE_NAME"

# パス付きロールARNを取得
ROLE_ARN=$(
    aws iam get-role --role-name "$ROLE_NAME" --query 'Role.Arn' --output text
)
echo "Role ARN: $ROLE_ARN"

出力例:

Role Name: AWSReservedSSO_AdministratorAccess_1234567890abcdef
Role ARN: arn:aws:iam::111111111111:role/aws-reserved/sso.amazonaws.com/ap-northeast-1/AWSReservedSSO_AdministratorAccess_1234567890abcdef

最終的なバケットポリシー

宛先バケット(アカウントB)に以下のポリシーを設定します。

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "AllowCrossAccountSync",
            "Effect": "Allow",
            "Principal": {
                "AWS": "<パス付きロールARN>"
            },
            "Action": [
                "s3:ListBucket",
                "s3:PutObject"
            ],
            "Resource": [
                "arn:aws:s3:::<宛先側のバケット名>",
                "arn:aws:s3:::<宛先側のバケット名>/*"
            ]
        }
    ]
}

まとめ

項目 内容
エラー原因 s3 sync は宛先に s3:ListBucket が必要
解決策 宛先バケットにバケットポリシーを追加
Principal指定 パス付きIAMロールARNを使用

この記事をシェアする

FacebookHatena blogX

関連記事