Amazon ECSのコンテナからGCP Cloud Storageへアクセスしてみた

Amazon Elastic Container Service(Amazon ECS)のコンテナからGCP Cloud Storage(GCS)へアクセスするのにどうしたらよいものか調べて試してみたのでメモ。


## ポイント

- GCPサービスアカウントのキーファイルで認証する
- Amazon ECSでGCPが提供しているgsutilのイメージが使えた
- AWS Systems Manager パラメータストア‎でキーファイルを管理する


### GCPサービスアカウントのキーファイルで認証する

こちらが参考になりました。

GCPサービスアカウントでgsutilを利用したりAPIアクセスする方法 - kikumotoのメモ帳
http://kikumoto.hatenablog.com/entry/2015/10/05/203545

サーバーサイドのアプリケーションなどからGCPのリソースへアクセスするにはサービスアカウントを利用するのが良いそうなので、サービスアカウントを作成、権限(役割)を付与します。サービスアカウントに権限を付与するにはIAM管理権限が必要になります。

GCSのバケットの参照とオブジェクトの参照・作成するには以下の権限(役割)を付与します。

- ストレージのオブジェクト作成者
- ストレージ オブジェクト閲覧者

Cloud Storage の認証  |  Cloud Storage  |  Google Cloud
https://cloud.google.com/storage/docs/authentication?hl=ja


サービスアカウントのキーファイルはJSONかP12形式が選択できますが、JSONファイルで取得します。
JSONファイルは下記のようになっていて、プライベートキーなどが含まれています。取り扱いにご注意ください。

```json
{
  "type": "service_account",
  "project_id": "<GCPプロジェクトID>",
  "private_key_id": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
  "private_key": "-----BEGIN PRIVATE KEY-----\nxxxxxx=\n-----END PRIVATE KEY-----\n",
  "client_email": "<サービスアカウント>@<GCPプロジェクトID>.iam.gserviceaccount.com",
  "client_id": "xxxxxxxxxxxxxxxxxxxxx",
  "auth_uri": "https://accounts.google.com/o/oauth2/auth",
  "token_uri": "https://oauth2.googleapis.com/token",
  "auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs",
  "client_x509_cert_url": "https://www.googleapis.com/robot/v1/metadata/x509/<サービスアカウント名>%40<GCPプロジェクト>.iam.gserviceaccount.com"
}
```

### Amazon ECSでGCPが提供しているgsutilのイメージが使えた

Amazon ECSで稼働させるコンテナ内からGCSのバケットへアクセスするのに`gsutil` コマンドが利用できれば事足りたので、利用できるイメージを探したところ、GCPが提供するDockerイメージが使えました。

cloud-builders/gsutil at master · GoogleCloudPlatform/cloud-builders
https://github.com/GoogleCloudPlatform/cloud-builders/tree/master/gsutil


本来はGCPのCloud Build用のイメージなのですが、公開されているイメージなので利用しても多分大丈夫？

Cloud Build - 継続的インテグレーションのためのビルドの自動化  |  Cloud Build  |  Google Cloud
https://cloud.google.com/cloud-build/?hl=ja

イメージは`gcr.io/cloud-builders/gsutil` で取得することができます。

```console
> docker run -it --rm \
  gcr.io/cloud-builders/gsutil \
  --version

Updates are available for some Cloud SDK components.  To install them,
please run:
  $ gcloud components update

gsutil version: 4.46
```

このイメージと作成したサービスアカウントのキーファイル(JSON)でGCSのバケットへアクセスしてみます。
キーファイルを利用するには`gcloud auth activate-service-account` コマンドが利用できます。

```console
> cd キーファイルがあるディレクトリ

> docker run -it --rm \
  --mount type=bind,source="($pwd)"/,target=/work \
  --entrypoint="bash" \
  gcr.io/cloud-builders/gsutil


# ここからコンテナ内

$ gcloud auth activate-service-account \
  --key-file /work/<JSONファイル名>

Activated service account credentials for: [<サービスアカウント名>@<GCPプロジェクト>.iam.gserviceaccount.com]

# 権限がないとバケット一覧は取得できない
$ gsutil ls
You are attempting to perform an operation that requires a project id, with none configured. Please re-run gsutil config and make sure to follow the instructions for finding and entering your default project id.

# プロジェクトIDを指定しても権限がないとダメ
$ gsutil ls -p <GCPプロジェクトID>
AccessDeniedException: 403 <サービスアカウント名>@<GCPプロジェクト>.iam.gserviceaccount.com does not have storage.buckets.list access to project xxxxxxxxxxxx.


# ファイルをアップロードする
$ echo "hoge" > hoge.txt

$ gsutil cp hoge.txt gs://<バケット名>/
Copying file://hoge.txt...
/ [1 files][    5.0 B/    5.0 B]
Operation completed over 1 objects/5.0 B.

$ gsutil ls gs://<バケット名>
gs://<バケット名>/hoge.txt

# ファイルをダウンロードする
$ gsutil cp gs://<バケット名>/hoge.txt hoge2.txt
Copying gs://<バケット名>/hoge.txt...
- [1 files][    5.0 B/    5.0 B]
Operation completed over 1 objects/5.0 B.

$ cat hoge2.txt
hoge
```


### AWS Systems Manager パラメータストア‎でキーファイルを管理する

Amazon ECSのコンテナで認証情報を取り扱うのにはAWS Systems Manager(AWS SSM) パラメータストアを利用するのが良いみたいです。


機密データの指定 - Amazon Elastic Container Service
https://docs.aws.amazon.com/ja_jp/AmazonECS/latest/developerguide/specifying-sensitive-data.html

AWS Systems Manager パラメータストア - AWS Systems Manager
https://docs.aws.amazon.com/ja_jp/systems-manager/latest/userguide/systems-manager-parameter-store.html


ファイルをアップロードすることはできませんが、ファイル内容を文字列として登録することで利用できます。

AWS Systems Manager(SSM) パラメータストアに改行コードを含むデータを保存するときの方法 - Qiita
https://qiita.com/pdsyun/items/ca31834e864a09cd828f

```console
> aws ssm put-parameter \
  --name "<パラメータ名>" \
  --value fileb://<キーファイルのパス> \
  --description "GCPサービスアカウントのキーファイル" \
  --type String
```

Amazon ECSでAWS SSM パラメータストアのキーを参照するにはAmazon ECSのタスク実行ロールにポリシーを追加する必要があります。設定方法は下記が参考になりました。

ECSでごっつ簡単に機密情報を環境変数に展開できるようになりました！ ｜ Developers.IO
https://dev.classmethod.jp/cloud/aws/ecs-secrets/

ECS(Fargate)で動かすコンテナにSSMからクレデンシャル情報を渡す - Software engineering from east direction
https://khigashigashi.hatenablog.com/entry/2018/08/28/214417


Amazon ECSのタスク定義で以下のようなコンテナを追加します。
環境変数に設定された復号化済みのファイル内容をファイルに出力して`gcloud auth activate-service-account` コマンドで指定して認証します。

- イメージ: `gcr.io/cloud-builders/gsutil`
- 環境変数
  - Key: `GCLOUD_KEY`
  - ValueForm: `<AWS SSM パラメータストアに登録したパラメータ名>`
- エンドポイント: `bash,-c`
- コマンド:

```
echo $GCLOUD_KEY > gcloud_key.json
gcloud auth activate-service-account --key-file gcloud_key.json
gsutil --version
gsutil ls gs://<バケット名>/
gsutil cp gs://<バケット名>/hoge.txt .
echo hoge > hoge3.txt
gsutil cp hoge3.txt gs://<バケット名>/
```

Amazon ECSでAWS SSM パラメータストアを利用すると、パラメータの復号化を自動で行ってくれるのでコンテナで行う処理を減らすことができて素敵でした。


## 参考

GCPサービスアカウントでgsutilを利用したりAPIアクセスする方法 - kikumotoのメモ帳
http://kikumoto.hatenablog.com/entry/2015/10/05/203545

Cloud Storage の認証  |  Cloud Storage  |  Google Cloud
https://cloud.google.com/storage/docs/authentication?hl=ja

cloud-builders/gsutil at master · GoogleCloudPlatform/cloud-builders
https://github.com/GoogleCloudPlatform/cloud-builders/tree/master/gsutil

Cloud Build - 継続的インテグレーションのためのビルドの自動化  |  Cloud Build  |  Google Cloud
https://cloud.google.com/cloud-build/?hl=ja

機密データの指定 - Amazon Elastic Container Service
https://docs.aws.amazon.com/ja_jp/AmazonECS/latest/developerguide/specifying-sensitive-data.html

AWS Systems Manager パラメータストア - AWS Systems Manager
https://docs.aws.amazon.com/ja_jp/systems-manager/latest/userguide/systems-manager-parameter-store.html

ECSでごっつ簡単に機密情報を環境変数に展開できるようになりました！ ｜ Developers.IO
https://dev.classmethod.jp/cloud/aws/ecs-secrets/

ECS(Fargate)で動かすコンテナにSSMからクレデンシャル情報を渡す - Software engineering from east direction
https://khigashigashi.hatenablog.com/entry/2018/08/28/214417