Workload Identity + フェデレーションIDを使用して、AWS環境からStorage Transfer Serviceの転送ジョブを作成する


# 概要
AWS環境に構築したシステムのデータを、Google Cloud環境にあるデータレイク（GCS）に格納して欲しいという依頼があり、Storage Transfer Serviceを使って、S3バケットからGCSバケットにデータ転送することにした。
また、なるべく永続的なキー情報を使用せずに対応して欲しいとの要望があり、

- Storage Transfer Serviceの環境構築するために、Workload Identityを使用すること
- Storage Transfer ServiceがS3バケットのアクセス設定でフェデレーションIDを使用すること

を提案しようと思ったが、まずはちゃんと実装できることを確認するために検証作業を行った。
その時に実施した作業内容を備忘録としてまとめる。

# 手順
## Workload Identityの設定
Workload Identityを設定して、JSONの認証情報ファイルを取得する。
手順はNRIネットコムの記事が綺麗に纏まっているので割愛。
https://tech.nri-net.com/entry/2021/07/01/111020

### サービスアカウントの権限付与
Workload Identityに関連付けたサービスアカウントに対して、Google Cloud側で許可する操作権限を付与する。
今回は、Storage Transfer Serviceの転送ジョブを作成するので、`Storage Transfer 管理者`をアタッチする。
![スクリーンショット 2021-10-30 3.03.22.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1698899/51518c70-4dad-40fa-e97e-527a02a4e328.png)

## 転送元のS3バケットの作成
転送元のS3バケットを作成する。
![スクリーンショット 2021-10-30 2.47.57.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1698899/9206dd2b-c05b-49aa-8c83-48cd5d44632c.png)

## 転送先のGCSバケットの作成
転送先のGCSバケットを作成する。
![スクリーンショット 2021-10-30 2.51.14.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1698899/6baab788-e873-bbf5-2864-7dadc838d65f.png)

## 転送元のS3バケットへのアクセス設定
データソースのS3バケットに対して、Storage Transfer Serviceがアクセスするための設定を行う。
今回は、Google Cloud側でAWSのアクセスキーとシークレットを管理したくないという要件があったので、フェデレーション IDで設定する。
手順はKSKSKSKS2さんの記事が綺麗に纏まっているので割愛。
https://ksksksks2.hatenadiary.jp/entry/20211005/1633391108

## AWS環境から転送ジョブの作成
AWSアカウント上のCloud9から、Storage Transfer Serviceの転送ジョブを作成する。
### 認証情報ファイルの配置
事前作業として、Cloud9上にWorkload Identity設定で取得した認証情報ファイルを配置する。
![スクリーンショット 2021-10-30 3.09.02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1698899/5cebc51c-6843-d403-f125-67ba4790ff0f.png)
→「clientLibraryConfig-awstogcp.json」が認証情報ファイル。

### 転送ジョブ作成スクリプトの作成
次に、転送ジョブを作成するためのpythonファイルを作成する。
基本的に以下ドキュメントに記載されているpythonスクリプトを踏襲する。
https://cloud.google.com/storage-transfer/docs/reference/rest/v1/transferJobs/create
Workload Identityを使用して、Google Cloud環境にアクセスするため、一時変更する。
変更内容としては、以下の通り。

```
from pprint import pprint

from googleapiclient import discovery

# Workload Identityを使用するため不要。
"""
from oauth2client.client import GoogleCredentials

credentials = GoogleCredentials.get_application_default()
"""

# Workload Identityを使用するため追加。
### ここから ###
import google.auth

scopes=['https://www.googleapis.com/auth/cloud-platform']
credentials, project = google.auth.default(scopes=scopes)
### ここまで ###

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

transfer_job_body = {
    # TODO: Add desired entries to the request body.
}

request = service.transferJobs().create(body=transfer_job_body)
response = request.execute()

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

### 転送ジョブ作成スクリプトの実行

まず、配置した認証情報ファイルを環境変数`GOOGLE_APPLICATION_CREDENTIALS`に設定する。

```
admin:~/environment $ export GOOGLE_APPLICATION_CREDENTIALS=~/environment/clientLibraryConfig-awstogcp.json
```

次に、Google APIを実行するためのpythonクライアントライブラリーをインストールする。

```
admin:~/environment $ pip install --upgrade google-api-python-client
```

最後に、作成したスクリプトを実行する。

```
admin:~/environment $ python create-tranferjob.py 
{'creationTime': '2021-10-29T18:34:20.709570416Z',
 'lastModificationTime': '2021-10-29T18:34:20.709570416Z',
 'name': 'transferJobs/okada-transferjob',
 'projectId': '<転送先のGoogle CloudプロジェクトID>',
 'schedule': {},
 'status': 'ENABLED',
 'transferSpec': {'awsS3DataSource': {'bucketName': 'okada-source-bucket-202110',
                                      'roleArn': '<転送元のS3バケットへのアクセス設定で作成したIAMロール>'},
                  'gcsDataSink': {'bucketName': 'okada-destination-bucket-202110'}}}
admin:~/environment $ 
```

実行結果から問題なく作成されたことが確認できる。