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

S3 のクロスアカウント書き込みにまつわる厳しい現実

More than 1 year has passed since last update.

tl;dr

AWS アカウントをまたいだ S3 バケットへの書き込みが色々とアレなので Lambda で無理矢理アレした

※1年半ぶりに追記: 解決策はあまりにも無理矢理だったが問題の知見としては有用なのでタイトルを変更しておく

背景

S3 は AWS 最古参のサービスであり、 S3 が登場した頃は IAM も存在しなかった。このため、今では AWS サービスの標準アクセス権限管理になった IAM とは異なる、独自のアクセス権限管理の仕組みが S3 にはある。

この歴史的経緯により、ある状況で非常に面倒な事態が発生する。

バケットオーナー != オブジェクトオーナー の場合に発生するつらみ

  • 凡例
    • つらくない現実
    • つらい現実
  • バケットポリシーで他アカウントへの認可を設定すると、別の AWS アカウント(と、その配下の IAM User など)がバケットへの書き込みを行えるようになる
  • バケットに PutObject されたオブジェクトのオーナーはそのオブジェクトを PUT したユーザーになる
    • ここでの ユーザーAWS アカウント と読み替えても構わない
    • これが誰なのかを調べる API は GetObjectACL である
  • 権限付与(Object ACL)を明示的に指定せず PUT されたオブジェクトへの権限は、オブジェクトオーナーのフルアクセスのみになる
    • オブジェクトオーナーのフルアクセス権限は剥がすことができるが、そのようにしても依然としてオブジェクトオーナーはそのオブジェクトへのフルアクセスが可能である
  • 自分がオーナーではなく、自分に対して明示的許可が与えられていないオブジェクトに対するGetObjectGetObjectACL はバケットオーナーであっても不可能
  • バケットオーナーは、自分に対してアクセス許可がないオブジェクトを DeleteObject できる
  • 自分がオーナーでないオブジェクトと同じキーに対して PutObject すること(上書き)は可能
  • バケットポリシーによるアクセス許可は、オーナーがバケットオーナーであるオブジェクトのみに適用される

どうしたか

アカウント A と B があるとして、アカウント A にあるバケットに対し、アカウント B から PutObject した場合に上のようなつらみが発生する。

そこで、まず s3:PutObject, s3:GetObject, s3:GetObjectAcl が可能な Role をアカウント B に作り、さらに以下のような Lambda Function をアカウント A に配置して S3 の ObjectCreated イベントで発火するようにした。

これは何をしているのか

  1. 前述の、アカウント B にある Role を sts:AssumeRole する
  2. 作成されたオブジェクトにバケットオーナー(アカウント A)に対する ACL が設定されていなければ
  3. バケットオーナー(アカウント A)に対する ACL を明示的に指定して、 PutObject しなおす

1が必要なのは、この場合2と3がそもそもアカウント A からは操作できないから。

まとめ

ここまで全部 BK 。 S3 (Simple Storage Service) は極力シンプルに使うべき。

その他

Serverless Framework で書き直したい。

y13i
冷凍うどん
https://y13i.com/
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