S3バケットポリシーで別組織IDを許可してアップロードできるか試してみた

バケットポリシーで組織IDを制御しているS3バケットに対して、別組織からの許可を与えられるのか試してみたよ。
2023.06.14

はじめに

マルチアカウント運用が一般的になっている中、クロスアカウントでのS3アップロードは頻繁におこなっている環境も多いと思います。 よくあるパターンで言えば、Control Towerなどでセットアップしたログアーカイブ用のアカウントにログを出力するケースなどが思いつきますね。

この時、S3バケット側のバケットポリシーの制御方法としては組織IDをConditionで縛ることが多いですよね。こうすることで、今後組織内に払い出されるアカウントが増えても、バケットポリシー側には手を加えずに済むのがメリットです。

今回は、アカウントが所属している組織ID以外についても制御ができるのか? と疑問に思ったのでやってみました。やりたいイメージはこんな感じです。

バケットポリシーに組織2(o-yyyyyyyyyy)の組織IDを追加して、メンバーBアカウントからファイルをアップロードしてみます。

やってみる

以下3アカウントでやっていきます。アカウントを行き来するので、間違えないように注意してください。

  • ログアーカイブ(組織1)
  • メンバーA(組織1)
  • メンバーB(組織2)

S3バケットの作成

ログアーカイブアカウントに保存先のS3バケットを作成します。

バケットポリシーに以下を設定して、他はデフォルトにします。 S3バケット名と組織IDは適宜置き換えてください。

{
    "Version": "2008-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Principal": {
                "AWS": "*"
            },
            "Action": [
                "s3:AbortMultipartUpload",
                "s3:GetBucketLocation",
                "s3:ListBucket",
                "s3:ListBucketMultipartUploads",
                "s3:PutObject",
                "s3:PutObjectAcl"
            ],
            "Resource": [
                "arn:aws:s3:::${S3バケット名}",
                "arn:aws:s3:::${S3バケット名}/*"
            ],
            "Condition": {
                "ForAnyValue:StringLike": {
                    "aws:PrincipalOrgPaths": "o-xxxxxxxxxx/*"
                }
            }
        }
    ]
}

組織内からのアップロード

確認のため、メンバーAのアカウントから同じ組織内のログアーカイブアカウントに対して、ファイルをアップロードしてみます。

CloudShellで適当なテストファイルを作成して、以下コマンドを実行します。

$ touch testA.txt
$ aws s3 cp testA.txt s3://{S3バケット名}
upload: ./testA.txt to s3://{S3バケット名}/testA.txt

ログアーカイブアカウントでS3バケットを確認すると、問題なくアップロードができています。

組織外からのアップロード

それでは組織2(o-yyyyyyyyyy)から同じ手順でアップロードしてみます。

メンバーBにログインし、以下コマンドをCloudShellから実行します。

$ touch testB.txt
$ aws s3 cp testB.txt s3://{S3バケット名}
upload failed: ./testB.txt to {S3バケット名}/testB.txt An error occurred (AccessDenied) when calling the PutObject operation: Access Denied

バケットポリシーを変更していないので、Access Deniedのエラーとなりました。

このままではアップロードできないことが確認できたので、次に組織1のログアーカイブアカウントのバケットポリシーを変更します。

組織2(o-yyyyyyyyyy)を許可したいので、aws:PrincipalOrgPathsに組織IDを追加しました。

{
    "Version": "2008-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Principal": {
                "AWS": "*"
            },
            "Action": [
                "s3:AbortMultipartUpload",
                "s3:GetBucketLocation",
                "s3:ListBucket",
                "s3:ListBucketMultipartUploads",
                "s3:PutObject",
                "s3:PutObjectAcl"
            ],
            "Resource": [
                "arn:aws:s3:::${S3バケット名}",
                "arn:aws:s3:::${S3バケット名}/*"
            ],
            "Condition": {
                "ForAnyValue:StringLike": {
                    "aws:PrincipalOrgPaths": [
                        "o-xxxxxxxxxx/*",
                        "o-yyyyyyyyyy/*"
                    ]
                }
            }
        }
    ]
}

おさらいですが、これで以下の図の状態になりました。

それではメンバーBから再度アップロードを試してみます。

$ aws s3 cp testB.txt s3://{S3バケット名}
upload: ./testB.txt to s3://{S3バケット名}/testB.txt

今度はAccess Deniedのエラーが発生しませんでしたね。 無事アップロードできたようなので、ログアーカイブアカウントでもS3バケットを確認してみます。

問題なくS3バケット側でもアップロードしたtestB.txtが確認できました。

まとめ

組織をまたがったS3アップロードについて試してみました。 バケットポリシーに設定したaws:PrincipalOrgPathsが所属している組織ID以外を認識してくれるのか?という疑問があったのですが、問題なく設定できるようで安心しました。

ユースケースですがアカウントを移行する際など、ログの出力先を移行前に変更したいケースなどで活用できるかと思います。

このブログが少しでも参考になれば幸いです。

参考