はじめに
本ブログに記載した内容は個人の見解であり、所属する会社、組織とは全く関係ありません。
概要
本記事では、誤って自分以外のアカウントのS3バケットにデータをPutしないように設定する方法を説明します。
背景
初学者をターゲットとしていると思われる、悪意のある「your-s3-bucket-name」というS3バケットが以前話題となるなど、意図せず他のアカウントのバケットにデータをPutすることを防ぐための対策が必要です。
参考:【注意】your-s3-bucket-nameというS3Bucketについて
IAMの設定
自身のアカウント以外のS3バケットにオブジェクトをアップロードできないようなIAMポリシーを作成し、IAMユーザーに付与します。
IAMポリシーの作成
DenyPutExternalS3というIAMポリシーを作成します。
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Deny",
            "Action": "s3:PutObject",
            "Resource": "*",
            "Condition": {
                "StringNotEquals": {
                    "s3:ResourceAccount": "${aws:PrincipalAccount}"
                }
            }
        }
    ]
}
以下の部分で、S3が所属するアカウントと自身のアカウントが等しいかを比較し、
"StringNotEquals": {
    "s3:ResourceAccount": "${aws:PrincipalAccount}"
}
自身のアカウントのバケットでない場合は、Putを拒否するようなポリシーになっています。
なお、一部の AWS サービスは AWS マネージドバケットへのアクセスに依存していることに注意してください。アクセスできるS3バケットを絞ることはこれらのリソースへのアクセスにも影響する可能性があります。
詳細は以下をご参照ください。
- 
Restrict access to buckets in a specified AWS account in the AWS PrivateLink Guide
 - 
Restrict access to buckets that Amazon ECR uses in the Amazon ECR Guide
 - 
SSM Agent communications with AWS managed S3 buckets in the AWS Systems Manager Guide
 
このIAMポリシーをIAMユーザーまたはユーザーが所属するIAMグループに付与します。
検証
前提
アカウントAに所属するIAMユーザーuser-Aから、アカウントBのS3バケットへ、オブジェクトをPutできるかを試してみます。
user-AにはAdmin権限を付与しています。
また、アカウントBのS3バケットには、以下のバケットポリシーを設定しています。
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Principal": {
                "AWS": "arn:aws:iam::{アカウントAのID}:root"
            },
            "Action": "s3:PutObject",
            "Resource": [
                "arn:aws:s3:::{アカウントBのS3バケット名}",
                "arn:aws:s3:::{アカウントBのS3バケット名}/*"
            ]
        }
    ]
}
Put拒否ポリシー無しの場合
user-Aに先ほど作成したDenyPutExternalS3が付与されていない場合、当然ですがアカウントBへのputは成功します。
$ aws s3 cp test.txt s3://{アカウントBのS3バケット名}/test/
upload: ./test.txt to s3://{アカウントBのS3バケット名}/test/test.txt
Put拒否ポリシー有りの場合
user-Aに先ほど作成したDenyPutExternalS3が付与している場合、アカウントBへのPutObjectはDenyポリシーにより失敗します。
$ aws s3 cp test.txt s3://{アカウントBのS3バケット名}/test/
upload failed: ./test.txt to s3://{アカウントBのS3バケット名}/test/test.txt An error occurred (AccessDenied) when calling the PutObject operation: Access Denied
なお、自身のアカウントのS3バケットへのPutObjectは問題なく成功します。
$ aws s3 cp test.txt s3://{アカウントAのS3バケット名}/test/
upload: ./test.txt to s3://{アカウントAのS3バケット名}/test/test.txt  
まとめ
自分以外のアカウントのS3バケットにデータをPutしないように設定するIAMポリシーを紹介しました。
生成AIの出力をコピペする等により、意図せず他アカウントへのputを行ってしまうインシデントを防ぐために、ガードレールとして設定しておくのも良いかもしれないです。
本ブログに記載した内容は個人の見解であり、所属する会社、組織とは全く関係ありません。