AWSのアカウント間でS3のデータを共有する

## はじめに
業務で対応した内容を、今後でも参考にする可能性があり、メモとして残します。（この記事の内容を踏襲される場合は、自己責任でお願いします。）

要件は以下。
・あるアカウント(Aとする)でAWS上で検証環境を構築した
・別のアカウント(Bとする)にAの検証データ(そこそこのサイズ)を共有したい

検証環境の構成は以下。
・アカウントA：Private Subnet内のEC2インスタンスだが、NAT-Gateway経由でインターネット接続可能
・アカウントB：インターネット接続完全不可のPrivate Subnet内のEC2インスタンス

## 作業フロー
### 概要
概要は以下。
1. アカウントBでバケット(bucket B)を作成し、ポリシーを編集してバケットをアカウントBに共有する
2. アカウントAでEC2からバケット(bucket B)にデータを登録する
3. アカウントBでS3のEndpointを作成する
4. アカウントBでバケット(bucket B)からデータをEC2に取得する

### 詳細
#### バケットポリシーの編集（by アカウントB）
・バケットのPublic Accessの設定を行う（Public Accessを許可する必要がある）
・下記のバケットポリシーを適用する（アカウントAに権限を付与する）

```json:policy
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "Example permissions for test",
            "Effect": "Allow",
            "Principal": {
                "AWS": "arn:aws:iam::XXXXXXXXXXXX:root"
            },
            "Action": [
                "s3:GetBucketLocation",
                "s3:ListBucket"
            ],
            "Resource": "arn:aws:s3:::s3-dev-tools"
        },
        {
            "Sid": "statement1",
            "Effect": "Allow",
            "Principal": {
                "AWS": "arn:aws:iam::XXXXXXXXXXXX:root"
            },
            "Action": [
                "s3:PutObject",
                "s3:DeleteObject",
                "s3:GetObject"
            ],
            "Resource": "arn:aws:s3:::s3-dev-tools/*"
        }
    ]
}
```
#### バケットへのデータ登録（by アカウントA）
EC2からデータを登録する(put-object)
・単純なファイル登録はput-objectでできる

```cmd:
$ aws s3api put-object --bucket s3-dev-tools --key tools.tar.gz --body date --profile hanako-a
{
    "ETag": "\"cd04401d4c09a17cc36005d8973619c4\""
}
$ aws s3 ls --region ap-northeast-1 --recursive s3://s3-dev-tools --profile hanako-a
2019-07-25 06:40:06         29 tools.tar.gz
$
```
・オブジェクトの所有者はアカウントAだけど、バケットオーナーのアカウントBで取得できるようにするためには「--acl bucket-owner-full-control」が必要

```cmd:
$ aws s3api put-object-acl --bucket s3-dev-tools --key tools.tar.gz --acl bucket-owner-full-control --profile hanako-a
```


put-objectではなくsyncを使う場合も同じ。-aclオプションで[bucket-owner-full-control]を指定する必要がある。

(参考)別の AWS アカウントで自分の Amazon S3 バケットにアップロードされたオブジェクトにアクセスできないのはなぜですか?
https://aws.amazon.com/jp/premiumsupport/knowledge-center/s3-bucket-owner-access/
(参考)AWS CLI Command Reference
https://docs.aws.amazon.com/cli/latest/reference/s3/sync.html#options

**この時点で、アカウントBは、AWSマネジメントコンソール上にて、該当するバケット内のファイルを参照およびダウンロードが可能なことを確認するべし。**

#### S3のEndpointを作成する（by アカウントB）
アカウントBでS3からデータを取得したいEC2は、完全に閉じたPrivate Subnetにいるため、Endpointを作成しないと(自分で作ったS3だとしても）S3に接続できません。
…後で手順追記するかも。。

（参考）VPCエンドポイントを使ってプライベートサブネットからS3へアクセスする。
https://qiita.com/kooohei/items/794a7d6e041f43f98f5b

#### アカウントBでバケット(bucket B)からデータをEC2に取得する
バケット参照できるか？確認する。

```cmd:
$ aws s3 ls s3://s3-dev-tool --profile hanako-b
```

そしてダウンロード。

```cmd
$ mkdir -p ~/tools-data
$ cd tools-data
$ aws s3 sync s3://s3-dev-tools ~/tools-data/ --profile hanako-b
download: s3://s3-dev-tools/md5sum.txt to ./md5sum.txt
download: s3://s3-dev-tools/tools.tar.gz to ./tools.tar.gz
$ 
```

## 躓いたところ
初心者ならでは、っぽいところで躓きました。

1. bucket ownerの権限変更が必要
バケットオーナーであるアカウントBでも、「アカウントAがアップロードしたオブジェクトを参照するには明示的に権限付与が必要」というところがわからず、最初、バタバタしました。
 
2. S3 Endpointが必要
バケットオーナーが無事にマネジメントコンソールでオブジェクトを参照/ダウンロード可能になっても、EC2からは見えない状況でした。基本的にはEC2からS3へのアクセスはPublicの経路で接続するということで、完全にprivateなsubnetから接続するには、S3のEndpointの作成が必要でした。