Glueの使い方的な㉝(別のAWSアカウントのS3バケットに出力時の権限のアレ)

# Glueの出力を別アカウントのS3にして、別アカウントから読めなくて困った場合

他のアカウントのS3バケットにファイルを書き込むと、所有者は自分のままで、書き込んだ先のアカウントからはそのファイルを読むことができません。

### ジョブの内容

<b>"S3の指定した場所に配置したcsvデータを、別のAWSアカウントのS3バケットににparquetとして出力する"<b>

S3のデータを入力にGlueジョブ実行(アカウントA) ==> S3(アカウントB) ==> S3 Selectでクエリ(アカウントB)

利用するジョブは以下のジョブと同じ内容です。ジョブの詳細はリンクをみてください
https://qiita.com/pioho07/items/c9ce1d0677777f974ffe

### ジョブ名
se2_job17(AWSアカウントA)

### クローラー名
se2_in0(AWSアカウントA)
se2_out0(AWSアカウントB)

# 全体の流れ

* 前準備
* アカウントB側でバケット作成と権限設定
* アカウントA側でGlueジョブ実行
* アカウントB側で確認

# 前準備

### 今回使うサンプルログファイル(19件)

```csv:csvlog.csv
deviceid,uuid,appid,country,year,month,day,hour
iphone,11111,001,JP,2017,12,14,12
android,11112,001,FR,2017,12,14,14
iphone,11113,009,FR,2017,12,16,21
iphone,11114,007,AUS,2017,12,17,18
other,11115,005,JP,2017,12,29,15
iphone,11116,001,JP,2017,12,15,11
pc,11118,001,FR,2017,12,01,01
pc,11117,009,FR,2017,12,02,18
iphone,11119,007,AUS,2017,11,21,14
other,11110,005,JP,2017,11,29,15
iphone,11121,001,JP,2017,11,11,12
android,11122,001,FR,2017,11,30,20
iphone,11123,009,FR,2017,11,14,14
iphone,11124,007,AUS,2017,12,17,14
iphone,11125,005,JP,2017,11,29,15
iphone,11126,001,JP,2017,12,19,08
android,11127,001,FR,2017,12,19,14
iphone,11128,009,FR,2017,12,09,04
iphone,11129,007,AUS,2017,11,30,14
```

### 入力ファイルをS3に配置(AWSアカウントA)

```shell:
$ aws s3 ls s3://test-glue00/se2/in0/
2018-01-02 15:13:27          0 
2018-01-02 15:13:44        691 cvlog.csv
```

### ①のPySparkスクリプトを修正

##### 以下の1行を追加

```
glueContext._jsc.hadoopConfiguration().set("fs.s3.canned.acl", "BucketOwnerFullControl")
```

- fs.s3.canned.acl： S3 へのファイル書き込み時に既定 ACL を使用するようにする設定オプション。AuthenticatedRead、BucketOwnerFullControl、BucketOwnerReadなどがある

- BucketOwnerFullControl： バケットの所有者に Permission.FullControl が与えられるように指定します。バケットの所有者は、オブジェクトの所有者と同じであるとは限りません

##### 出力S3バケットを、これから作る以下のアカウントBのバケットに修正

test-glue01/se2/out0

```python:se2_job17.py
import sys
from awsglue.transforms import *
from awsglue.utils import getResolvedOptions
from pyspark.context import SparkContext
from awsglue.context import GlueContext
from awsglue.job import Job

## @params: [JOB_NAME]
args = getResolvedOptions(sys.argv, ['JOB_NAME'])
sc = SparkContext()
glueContext = GlueContext(sc)
spark = glueContext.spark_session
glueContext._jsc.hadoopConfiguration().set("fs.s3.canned.acl", "BucketOwnerFullControl")
job = Job(glueContext)
job.init(args['JOB_NAME'], args)
## @type: DataSource
## @args: [database = "se2", table_name = "se2_in0", transformation_ctx = "datasource0"]
## @return: datasource0
## @inputs: []
datasource0 = glueContext.create_dynamic_frame.from_catalog(database = "se2", table_name = "se2_in0", transformation_ctx = "datasource0")
## @type: ApplyMapping
## @args: [mapping = [("deviceid", "string", "deviceid", "string"), ("uuid", "long", "uuid", "long"), ("appid", "long", "appid", "long"), ("country", "string", "country", "string"), ("year", "long", "year", "long"), ("month", "long", "month", "long"), ("day", "long", "day", "long"), ("hour", "long", "hour", "long")], transformation_ctx = "applymapping1"]
## @return: applymapping1
## @inputs: [frame = datasource0]
applymapping1 = ApplyMapping.apply(frame = datasource0, mappings = [("deviceid", "string", "deviceid", "string"), ("uuid", "long", "uuid", "long"), ("appid", "long", "appid", "long"), ("country", "string", "country", "string"), ("year", "long", "year", "long"), ("month", "long", "month", "long"), ("day", "long", "day", "long"), ("hour", "long", "hour", "long")], transformation_ctx = "applymapping1")
## @type: ResolveChoice
## @args: [choice = "make_struct", transformation_ctx = "resolvechoice2"]
## @return: resolvechoice2
## @inputs: [frame = applymapping1]
resolvechoice2 = ResolveChoice.apply(frame = applymapping1, choice = "make_struct", transformation_ctx = "resolvechoice2")
## @type: DropNullFields
## @args: [transformation_ctx = "dropnullfields3"]
## @return: dropnullfields3
## @inputs: [frame = resolvechoice2]
dropnullfields3 = DropNullFields.apply(frame = resolvechoice2, transformation_ctx = "dropnullfields3")
## @type: DataSink
## @args: [connection_type = "s3", connection_options = {"path": "s3://test-glue01/se2/out0"}, format = "parquet", transformation_ctx = "datasink4"]
## @return: datasink4
## @inputs: [frame = dropnullfields3]
datasink4 = glueContext.write_dynamic_frame.from_options(frame = dropnullfields3, connection_type = "s3", connection_options = {"path": "s3://test-glue01/se2/out0"}, format = "parquet", transformation_ctx = "datasink4")
job.commit()
```

# アカウントB側でバケット作成と権限設定

### アカウントB側で、S3バケットとディレクトリを作成

test-glue01/se2/out0

<img width="565" alt="スクリーンショット 0031-01-11 10.01.10.png" src="https://qiita-image-store.s3.amazonaws.com/0/27932/77116448-4193-4fda-383e-80c73062d9e9.png">

### 権限設定

対象バケットtest-glue01にチェックを入れ、"アクセス権限"をクリックする

![スクリーンショット 0031-01-11 10.03.05.png](https://qiita-image-store.s3.amazonaws.com/0/27932/05aa5896-f759-a73c-be8b-a7fa0114883b.png)

[バケットポリシー]をクリックし、以下のJSONを入力し、[保存]をクリックする

![スクリーンショット 0031-01-11 10.08.39.png](https://qiita-image-store.s3.amazonaws.com/0/27932/2499807c-6b4a-f7f6-a1cf-f60c687b56d2.png)


```json:
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "Example",
            "Effect": "Allow",
            "Principal": {
                "AWS": "arn:aws:iam::xxxxxxxxxxxa:role/test-glue"
            },
            "Action": "s3:*",
            "Resource": [
                "arn:aws:s3:::test-glue01/*",
                "arn:aws:s3:::test-glue01"
            ]
        }
    ]
}
```

# アカウントA側でGlueジョブ実行

Glueジョブ実行

# アカウントB側で確認

アカウントB側のバケットにparquetファイルが出力されている
モザイク入れてるけどparquetファイルの所有者がアカウントBになっている
parquetファイルをS3 Slectする

![スクリーンショット 0031-01-11 10.21.39.png](https://qiita-image-store.s3.amazonaws.com/0/27932/6f97473f-ceeb-b963-a100-2e44fa350e8a.png)

S3 Select できた

![スクリーンショット 0031-01-11 10.22.19.png](https://qiita-image-store.s3.amazonaws.com/0/27932/d234ce1f-9e3f-28e0-b7bb-77329669ec6f.png)

## こちらも是非

別アカウントのS3に書き込み
http://blog.serverworks.co.jp/tech/2016/10/27/s3-crossaccount/

EMRで別のAWSアカウントのS3に出力
https://docs.aws.amazon.com/ja_jp/emr/latest/ManagementGuide/emr-s3-acls.html

Glueの使い方まとめ
https://qiita.com/pioho07/items/32f76a16cbf49f9f712f