こんにちは、CI部技術5課の村上です。
今回はS3にあるオブジェクトを異なるアカウントと共有する方法part2です。前回の記事ではバケットのレプリケーションによって共有する方法を紹介しました。この記事では残り2つの方法を紹介します。
↓前回の記事はこちらからご覧ください。
S3にあるオブジェクトを異なるアカウントと共有する3つの方法 part1
やりたいこと
前回の記事でも記載しましたが、やりたいことを図にすると、以下のような感じです。

前提として、アカウントAのIAMユーザーであるuser-aがS3にオブジェクトを保存しているとします。このオブジェクトをアカウントBのIAMユーザーであるuser-bが参照または取得する方法を3つ検証してみましたので、その方法を紹介します。
今回検証した3つの方法
- バケットのレプリケーションで実現する(前回記事に掲載済み)
- バケットポリシーとIAMポリシーで実現する
- IAMロールで実現する(スイッチロール)
この記事では2と3の方法を紹介します。
2.バケットポリシーとIAMポリシーで実現する

【手順】
①user-aが、user-bによるアクセスを許可するバケットポリシーを作成し、bucket-aに適用する。
②bucket-aに対するアクセスを許可するIAMポリシーを作成し、user-bにアタッチする。
③user-bがbucket-aにアクセスする。
【特徴】
- CLIなどのプログラムによるアクセス専用(コンソール画面によるアクセスは不可)
- オブジェクトレベルでの権限設定が可能
2-1.まず理解すべきこと~アクセス権の決定ロジックについて~
少しおカタい見出しですが、ここで言いたいことは、「今回のケースでは以下の両方の条件を満たす必要がありますよ」ということです。
- バケットポリシーでuser-bによるアクセスが許可されていること
- IAMポリシーでuser-aへのアクセスが許可されていること
「言われなくても知ってるよ」という方は読み飛ばしていただいてOKです。「ん??」と思った方は以下を読んでください。
ポリシーのタイプには、アイデンティティベースのポリシーやリソースベースのポリシーなど、複数の種類があります。一例として、アイデンティティベースのポリシーではアクセス権があるけど、リソースベースのポリシーでは何も書かれていない(明示的な許可・拒否がされていない)、など様々なケースが想定されます。
では、AWSはユーザーの権限の有無をどのように評価しているのでしょうか。特に今回は異なるアカウント間でのアクセスです。公式ドキュメントのクロスアカウントポリシー評価論理には以下のように書かれています。
クロスアカウントリクエストを行うと、AWS は 2 つの評価を実行します。AWS は、信頼するアカウントのリクエストと信頼されるアカウントを評価します。リクエストは、両方の評価が Allowの決定を返す場合にのみ許可されます。
よって、今回のケースを実現するためには、上記2点を満たす必要があるということです。
2-2.バケットポリシーの設定(アカウントA側の設定)
それでは具体的な手順に入ります。ここでは、user-bによるbucket-aへのアクセスを許可するバケットポリシーを設定します。
S3のアクセス権限タブのバケットポリシー作成画面で、user-bによるアクセスを許可するポリシーを適用します。

バケットポリシーは以下のとおりです。Principal要素のアカウントIDのみ変更していますので、作成の際は適宜、設定してください。
保存するとアカウントA側の設定は完了です。
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::アカウントBのアカウントid:user/user-b"
},
"Action": [
"s3:Get*",
"s3:List*"
],
"Resource": [
"arn:aws:s3:::bucket-a",
"arn:aws:s3:::bucket-a/*"
]
}
]
}
今回、Action要素には、取得権限のGet、参照権限のListを設定しました。その他の権限については公式ドキュメントをご参照ください。
Amazon S3 のアクション、リソース、および条件キー
https://docs.aws.amazon.com/ja_jp/IAM/latest/UserGuide/list_amazons3.html
2-3.IAMポリシーの設定(アカウントB側の設定)
bucket-aに対するアクセスを許可するIAMポリシーを作成し、user-bにアタッチします。
まずはIAMポリシーを作成します。

今回IAMポリシーは以下のように作成しました。
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"s3:Get*",
"s3:List*"
],
"Resource": "arn:aws:s3:::bucket-a"
}
]
}
注意すべき点は、1-1.でも記載したとおり、許可するAction要素がバケットポリシーと一致している必要があることです。
次に、作成したIAMポリシーをuser-bにアタッチします。IAMユーザーからuser-bを選択し、アクセス権限の追加を選択します。

「既存のポリシーを直接アタッチ」から、先ほど作成したIAMポリシーを選択しuser-bにアタッチします。

これでアカウントB側の設定も完了です。
2-4.オブジェクトの参照または取得
あとはuser-bがbucket-aにアクセスするだけです。ただし前述のとおり、この方法はCLIなどのプログラムによるアクセス専用となります。
今回はCLIによるアクセスを検証しました。
バケット内のオブジェクトの参照
実行コマンド
aws s3 ls s3://bucket-a
実行結果
2020-04-** **:**:** object-name.txt
バケット内のオブジェクトの取得
実行コマンド
aws s3 cp s3://bucket-a/object-name.txt 取得先のパス名
実行結果
download: s3://bucket-a/object-name.txt to 取得先のパス名
2つとも無事うまくいったようです。
3.IAMロールで実現する(スイッチロール)

【手順】
① user-bを信頼されたエンティティに指定して、bucket-aへのアクセスを許可するIAMロールを作成する。
② ①で作成したIAM ロールを継承できるIAMポリシーをuser-bにアタッチする。
③ user-bがbucket-aにアクセスする(スイッチロールする)。
【特徴】
- コンソール画面からもアクセスが可能
- オブジェクトレベルでの権限設定が可能
3-1.IAMロールの作成(アカウントA側の設定)
まずIAMロールの画面から、ロールの作成を選択します。

ロールの作成画面では、別のAWSアカウントを選択し、アカウントBのIDを入力します。

次にこのIAMロールにアタッチするIAMポリシーを選択します。既存のIAMポリシーがない場合は新規作成することもできます。今回はIAMポリシーを新しく作成しました。

作成したIAMポリシーは以下のとおりです。
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"s3:ListAllMyBuckets"
],
"Resource": "arn:aws:s3:::*"
},
{
"Action": [
"s3:ListBucket",
"s3:GetBucketLocation"
],
"Effect": "Allow",
"Resource": "arn:aws:s3:::bucket-a"
},
{
"Effect": "Allow",
"Action": [
"s3:Get*"
],
"Resource": [
"arn:aws:s3:::bucket-a/*"
]
}
]
}
作成したIAMロールのロールARN"arn:aws:iam::AccountA:role/AccountARole"は次のアカウントB側の設定で使用します。
3-2.IAMポリシーの作成(アカウントB側の設定)
アカウントB側では、先ほどアカウントAが作成したIAMロールを継承できるIAMポリシーをuser-bにアタッチする必要があります。
以下のIAMポリシーを作成し、user-bにアタッチします。IAMポリシーをIAMユーザーへアタッチする方法は2-3を参照してください。
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": "sts:AssumeRole",
"Resource": "arn:aws:iam::AccountA:role/AccountARole"
}
]
}
Resource要素には3-1で先ほどアカウントAが作成したロールARNを入力する必要があります。
3-3.スイッチロールする
IAMポリシーがアタッチできたら、次は画面右上のアカウント情報のメニューを表示し、スイッチロールを選択します。

ロールの切り替えの画面に遷移しますので、アカウントIDとロール名を入力します。表示名と色は任意入力なので、お好みで入力してください。

スイッチロールが成功すると、以下のようにコンソール画面に遷移しますので、あとはbucket-aにアクセスするだけです。

まとめ
以上、2回にわたってS3にあるオブジェクトを異なるアカウントと共有する3つの方法を紹介してきました。
個人的な所感ですが、
- 手っ取り早く共有するなら、前回の記事で紹介したレプリケーションがおすすめ
- 共有する相手やオブジェクトをIAMできっちり管理するなら、今回紹介した方法がおすすめ
といったところでしょうか。ご参考になれば幸いです。
※前回の記事はこちらからご覧ください。
S3にあるオブジェクトを異なるアカウントと共有する3つの方法 part1