LoginSignup
9
3

More than 5 years have passed since last update.

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

Last updated at Posted at 2016-12-13

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 で書き直したい。

9
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
9
3