Access key等を使用せず、Assume Role使用でStorage Transfer Serviceを使ってS3→GCSへデータ転送

## これは一体…？

Assumerole使用で転送できるとのことで、やってみました。
途中、S3のLocationが取れなくてエラーになったり、subjectidが取れなかったりと、いろいろありましたが、権限あたりを見回したところ、うまくいきました。
なお、今回プロジェクトやアカウントにいろいろ権限が必要になったので、会社の検証PJで権限が設定されている場合は、あらかじめ社内で権限を持っている方に確認取るとスムースに行くかもしれません。

## やってみた

下記開き、右側に出てくるTry APIで、accountEmailとSubject idを取得。
https://cloud.google.com/storage-transfer/docs/reference/rest/v1/googleServiceAccounts/get

```json
#IAM ロール設定
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "s3:List*",
                "s3:Get*",
                "s3:DeleteObject"
            ],
            "Resource": [
                "arn:aws:s3:::バケット名前",
                "arn:aws:s3:::バケット名前/*"
            ]
        }
    ]
}
```

```json
#信頼関係のポリシー
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "Federated": "accounts.google.com"
      },
      "Action": "sts:AssumeRoleWithWebIdentity",
      "Condition": {
        "StringEquals": {
          "accounts.google.com:sub": "SAのsubject id"
        }
      }
    }
  ]
}
```

```
/// GCPコンソールのCloud shell開き、.pyを実行
vi 適当な名前.py
以下ファイル貼り付け
python3 適当な名前.py
```

```python
/// 実行した.pyファイル
from pprint import pprint

from googleapiclient import discovery
from oauth2client.client import GoogleCredentials

credentials = GoogleCredentials.get_application_default()

service = discovery.build('storagetransfer', 'v1', credentials=credentials)

transfer_job_body ={
  "name": "transferJobs/ジョブの名前",
  "projectId": "GCPプロジェクトの名前",
  "status": "ENABLED",
  "transferSpec": {
    "awsS3DataSource": {
        "bucketName": "バケットの名前",
        "path": "任意",
      "roleArn": "設定したAWS IAM ロールのARN"
    },
    "gcsDataSink": {
      "bucketName": "GCSバケットの名前",
      "path": "任意のパスを設定"
      },
    "transferOptions": {
#転送後にソース削除
      "deleteObjectsFromSourceAfterTransfer": "true"
  }
  },
    "schedule": {
#任意
        "scheduleStartDate": {
            "year": "2021",
            "month": "10",
            "day": "13"
  },
#定期的な転送は、scheduleEndDateを通じて、毎日指定された時間に実行されます。
    "scheduleEndDate": {
  "year": "2021",
  "month": "10",
  "day": "13"
},
#startTimeOfDayが指定されていない場合：1回限りの転送がすぐに実行されます。JTC-9する。
  "startTimeOfDay": {
  "hours": "9",
  "minutes": "0",
  "seconds": "0",
  "nanos": "0"
  },
#endTimeOfDayが設定されておらず、scheduleEndDateが設定されている場合、デフォルト値の23:59:59が endTimeOfDayになる。
  "endTimeOfDay": {
  "hours": "9",
  "minutes": "5",
  "seconds": "0",
  "nanos": "0"
  },
    }
}
request = service.transferJobs().create(body=transfer_job_body)
response = request.execute()

# TODO: Change code below to process the `response` dict:
pprint(response)
```

## 注意点

転送にあたっての注意点をまとめていたので、一応貼っておきます。
お役に立てたら幸いです。

```
S3送信元削除
可能。
時間指定で実行
可能。
Prefix指定
sourceのPath指定なしで実行すると、sourceバケットの全てのオブジェクトが転送される。
sourceを2021/で指定した場合、転送されるのは2021配下の01/のみ。2021/フォルダは転送できない。
なので、2021/も含めて転送する方法は、以下２つだと考える。
destinationのpathをlogs/2021にして、sourceのpathは"2021/"にする。
sourceに2021/しか置かず、sourceのpath指定なしで全て転送させる。
```

## 総括
Pythonに慣れていなかったのと、API叩くところがよくわかっておらず、苦戦しましたが、チームの方に助けてもらい、なんとかなりました。
GCさんには、公式に早く手順載せてもらえるとありがたいです。

## 参考

```
https://cloud.google.com/storage-transfer/docs/reference/rest/v1/googleServiceAccounts/get
https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_create_for-idp_oidc.html
https://cloud.google.com/storage-transfer/docs/reference/rest/v1/transferJobs/create
https://ksksksks2.hatenadiary.jp/entry/20211005/1633391108
```

参考にさせていただきました。ありがとうございます。