S3のデータを別アカウントの別バケットにコピーする際の権限設定

こんにちは。データサイエンティスト兼、データ基盤エンジニアのshobyです。

TVISION INSIGHTSでは、本番環境と開発環境でAWSのアカウントを分けて運用しており、 時折本番ログデータを開発用S3バケットにコピーする必要が生じています。

別アカウントの別バケットにデータをコピーする際に一番の詰まるポイントは権限周りです。 今回は、異なるアカウント間でデータをコピーする際に、問題を起こしづらい権限設定の方法をご紹介します。

概要

  • S3の権限の仕組みについて
  • 他人のはReadのみ、自分のにWrite作戦
  • TVISION INSIGHTSでの活用事例

S3の権限の仕組みについて

異なるアカウント間でデータをコピーする際で、一番詰まるポイントが権限周りです。

S3の権限管理は複雑でバケットACL、オブジェクトACL、バケットポリシー、IAMという4レイヤーの権限を考慮する必要があり、異なるアカウント間でデータを移動するのは混乱を招きます。

dev.classmethod.jp

4レイヤー全てを適切に運用するのは難易度が高く、一時的なコピー作業のために権限管理で消耗するのは本質的ではありません。

そのため、今回は強いIAM権限をもつユーザーを一時的に作成し、バケットポリシーのみに注意を払えば良いという方法をご紹介します。

他人のはReadのみ、自分のにWrite作戦

異なるアカウント間での権限管理を容易にするのが、他人のはReadのみ、自分のにWrite作戦です。*1

他人のバケットはReadのみにすることで設定すべき権限を最小限にし、 自分のバケットにWriteすることでオブジェクトの所有権に関わる問題発生を防ぐことができます。

具体的な天順は以下の通りです。

  1. コピー先アカウントBにコピー先バケットsnapshotを作成
  2. コピー先アカウントBに一時ユーザーtemp_migratorを作成
  3. 一時ユーザーtemp_migratorにAmazonS3FullAccess権限を付与
  4. コピー元アカウントAのバケットoriginalに、temp_migratorのReadを許可するバケットポリシーを設定
  5. コピーが終わったら、temp_migratorを削除し、バケットポリシーを戻す

イメージを図示すると以下のような形です。

f:id:shoby:20180830191912p:plain

以下、詳細を解説します。

コピー先アカウントBにコピー先バケットsnapshotを作成

まず、コピー先のアカウント側に、バケットを作成します。

コピー専用のバケットを作成し、AmazonS3FullAccessでWriteを行うことで、 コピー先バケットの権限設定で悩む必要がなくなります。

コピー先アカウントBに一時ユーザーtemp_migratorを作成

コピー先 のアカウント側で、コピー作業に使う一時ユーザーを作成します。 この一時ユーザーは作業完了後に削除します。

他人のバケットはReadだけ、自分のバケットにWrite、という形にすることで、オブジェクトに関わる権限を気にせずに済むようになります。

バケットとオブジェクトには所有者という概念があり、誰が所有しているかによってACLの権限設定に影響を与えます。 他人のアカウントにWriteしてしまうと、オブジェクトの所有者がバケットの所有者とずれる可能性があり、気にしなければならないことが増えてしまいます。

自分のバケットに自分のアカウントでWriteすることで、バケットACL、オブジェクトACLに関わる問題の発生を防ぐことができます。

一時ユーザーtemp_migratorにAmazonS3FullAccess権限を付与

一時的にAmazonS3FullAccessという強力な権限を付与することで、権限に関して考慮しなければならないことを減らすことができます。

具体的には、4レイヤーの権限制御のうち、IAMレイヤーの権限問題を無視することができ、アクセス拒否された場合の原因調査を他の3レイヤーに絞ることができるようになります。

コピー元アカウントAのバケットoriginalに、temp_migratorのReadを許可するバケットポリシーを設定

コピー元 のバケットに、コピー先アカウントの一時ユーザーに対して、Readを許可するバケットポリシーを設定します。

バケットポリシーは、バケットACLやオブジェクトACLよりも優先されるため、 簡単にバケット内の全オブジェクトに対してReadの権限を付与することができます。

ただし、現状のバケットACLやオブジェクトACLでは許可しているアカウントに対して、 バケットポリシーでは拒否してしまうと、問題が生じる可能性があるのでご注意ください。

これにより、IAM、バケットACL、オブジェクトACLのレイヤーの権限設定は実質的に無視することができ、 バケットポリシーの権限のみを正しく設定することのみに集中できるようになります。

設定するバケットポリシーは以下の通りです。

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "s3_data_migration",
            "Effect": "Allow",
            "Principal": {"AWS": "arn:aws:iam::222222222222:user/temp_migrator"},
            "Action": ["s3:ListBucket","s3:GetObject"],
            "Resource": [
                "arn:aws:s3:::original/*",
                "arn:aws:s3:::original"
            ]
        }
    ]
}

Principalには一時ユーザーを表すARN、ActionにはListBucketとGetObjectの設定が必要です。

TVISION INSIGHTSでの活用例

TVISION INSIGHTSでは、本番環境と開発環境でAWSのアカウントを分けて運用しており、 開発環境で本番のログデータを用いて動作検証する際に別アカウントの別バケットにコピーする作業が発生しています。

本番環境と開発環境のアカウント自体を分けることで、 オペレーションミスによるデータの削除を防ぐことができるというメリットがありますが、 権限管理が複雑になってしまうため、可能な限りシンプルにできるよう考えながら運用しています。

まとめ

S3で別アカウントの別バケットにデータをコピーする際には、権限設定が複雑になりがちです。

他人のはReadのみ、自分のにWrite作戦を取ることで、バケットACL、オブジェクトACL、バケットポリシー、IAMという4レイヤーの権限設定のうち、バケットポリシーのみに集中して権限設定をするだけで良くなります。

*1:こちらのドキュメントを参考にしています。 https://aws.amazon.com/jp/premiumsupport/knowledge-center/account-transfer-s3/