Help us understand the problem. What is going on with this article?

CloudFront+S3(OAI)設定時に外部アカウントからPutObjectしたファイルを開こうとすると403になる

More than 1 year has passed since last update.

これはなんですか

  • 別アカウントからS3バケットにオブジェクトを投入し、CloudFrontで読む設定をした時に失敗したのでメモとして残しておきます。
  • クロスアカウントアクセスの際にはAssumeRoleを使いましょう、という話です。
  • 失敗の内容と解決策を書きます。

ざっくり構成

  • アカウントAとアカウントBがあり、アカウントA側でCloudFront + S3(OAI)を設定する。
    • CloudFrontの署名つきURLを発行してバケット内のオブジェクトを読み込むアプリケーションを作成していた。
  • アプリケーションの要件で、アカウントBからS3バケットにオブジェクトをおく必要があり、次の設定を行った
    • アカウントB側でS3バケットへのPutObjectを許可するポリシーを書き、ロールに当てる
    • アカウントAのS3バケットポリシーに上記ロールからのPutObjectを許可する設定を書く

おきたことと解決策

事象1. アカウントAがオブジェクトを操作できない

上記設定でアカウントBからアカウントAにオブジェクトを配置したところ、アカウントAのユーザー、ロールからオブジェクトの操作ができなくなっていた。CloudFront経由でアクセスしても403 (AccessDenied) が返ってくる。

原因

オブジェクトのACLを確認したところ、アカウントBがオーナーとなっており、アカウントAへのアクセス権限が設定されていなかった。

解決策

原因は、アカウントBがオブジェクトへのアクセス権をアカウントAに付与しなかったこと。以下リンク (AWSのKnowledge Center) がまさにこの件を扱っている。

https://aws.amazon.com/jp/premiumsupport/knowledge-center/s3-bucket-owner-access/

ざっくり言うと、「PutObjectの際にACL設定に bucket-owner-full-control を指定すればOK」と言う内容。

事象2. CloudFrontで403エラー(AccessDenied)が返ってくる

上記問題を解決したものの、依然としてCloudFront経由のアクセスでは403となる。

原因

オブジェクトのオーナーについて調べたところ、以下の記事を見つけた。

https://qiita.com/h-imaoka/items/f1cfa242fd7c953bef5f

曰く、

オブジェクトのオーナーがバケットのオーナーと異なる場合、そのオブジェクトにはバケットポリシーによるアクセス制御が効かない

とのこと。CloudfrontのOAI設定は以下のようなS3のバケットポリシーで行うため、今の構成ではCloudFront経由のアクセスは実現できない。

{
    "Version": "2012-10-17",
    "Id": "PolicyForCloudFrontPrivateContent",
    "Statement": [
        {
            "Sid": "1",
            "Effect": "Allow",
            "Principal": {
                "AWS": "arn:aws:iam::cloudfront:user/CloudFront Origin Access Identity Exxxxxxxxxxxxxxxx"
            },
            "Action": "s3:GetObject",
            "Resource": "arn:aws:s3:::my-bucket/*"
        },
        ...  ...
    ]
}

解決策

クロスアカウントアクセスの方法を変えることで解決した。

  • アカウントAにIAMロールを作成し、アカウントBとの信頼関係を設定する
  • 作成したIAMロールにS3バケットへのPutObject権限を付与する
  • アカウントBはアカウントAのロールに対して sts:AssumeRole を許可するポリシーをロールに当て、アプリ側で AssumeRole を行いS3バケットにオブジェクトを配置する

こうすることでアカウントBはアカウントAの権限を委任されることになり、オブジェクトのオーナーがアカウントAとなる。この設定により無事にCloudFront経由のアクセスができるようになった。 (そもそも初めからこうしておけば事象1も発生しなかった)

まとめ

  • CloudFront + S3 構成で別アカウントからS3バケットにオブジェクトを投入しようとして失敗しまくった
  • 素直にAssumeRole設定を書くことで解決した

感想

  • すごく勉強になった。
  • 横着はよくない。
Hikosaburou
AWSとGCPの話題が多いです。
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした