Storage Transfer Service で AssumeRoleWithWebIdentity を使用して、キー情報なしで S3 から GCS にファイル転送してみた。

2022.09.10

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

こんにちは、みかみです。

トップシーズン(小学生の夏休み)避けて近所の川にでも遊びに行こうと思ってたら、ここのところ毎週末台風に見舞われて、とほほな今日この頃です(今年はまだ川で獲ったテナガエビ食べてないんだよなーw

やりたいこと

  • S3 から GCS に、セキュアにファイル転送したい
  • ファイル転送には Storage Transfer Service を使いたい
  • Storage Transfer Service で AssumeRoleWithWebIdentity を使用してファイル転送したい

AssumeRoleWithWebIdentity とは

AssumeRoleWithWebIdentity API オペレーションでは、パブリック ID プロバイダーを経由して認証されたフェデレーティッドユーザーの一時的なセキュリティ認証情報のセットが返ります。パブリック ID プロバイダーの例としては、Login with Amazon、Facebook、Google、または OpenID Connect (OIDC) に対応している任意の ID プロバイダーがあります。

ざっくりいうと、AWS 外のサービスからの一時的な認証方法?

AWS の AssumeRole (ざっくり、キー情報ではなく STS による認証方法)を、AWS 外からも使えるようにした認証方法です。

ほんとざっくりですみません。。 詳しくは以下をご参照ください。

何がうれしいの?

AWS のリソースにアクセスする場合、IAM ユーザーのアクセスキー ID とシークレットアクセスキーを使用することも多いかと思いますが、キーを発行すると、そのキーの管理にも気を配る必要がでてきます。

キーが漏洩してしまうと、そのキーを持つ IAM ユーザーの権限で実行できることが誰にでもできてしまうので非常に危険です。 うっかりコードに埋め込んで、誰でもアクセスできる場所に上げてしまうリスクも発生します。

リスク軽減のためにはキーローテーション必須かと思いますが、ローテーションの自動化まで考えると、手間がかかることも多いのではないかと思います。。

AWS のベストプラクティスとしても、キーではなくロールでアクセスすることが推奨されています。

Storage Transfer Service を使って AWS S3 から GCS にファイル転送を行う場合、Google Cloud から AWS へのアクセスが発生するため認証が必要になりますが、その認証をキー情報ではなくロール(AssumeRoleWithWebIdentity)で行う方が、よりセキュアになります。

前提

Google Cloud SDK(gcloud コマンド)の実行環境は準備済みであるものとします。 本エントリでは、Cloud Shell を使用ました。

サービスアカウント ID を取得

下記公式ドキュメントの記載の通り、Storage Transfer Service のサービスアカウント情報を取得します。

API レスポンスの accountEmailsubjectId は、後ほど使用するので控えておきます。

合わせて転送先バケットに対して、先ほど確認した accountEmail がファイル書き込みできるように、Storage レガシーバケット書き込みロール(roles/storage.legacyBucketWriter)を追加しました。

gsutil iam ch \
  serviceAccount:project-[プロジェクトID]@storage-transfer-service.iam.gserviceaccount.com:legacyBucketWriter \
  gs://test-mikami-sts-assumerole

※一部伏せ字に変更しています。

確認してみると、想定通り対象バケットのアクセス権限に Storage Transfer Service サービスアカウントが追加されていることが確認できました。

gsutil iam get gs://test-mikami-sts-assumerole
$ gsutil iam get gs://test-mikami-sts-assumerole
{
  "bindings": [
(省略)
    {
      "members": [
        "serviceAccount:project-[プロジェクトID]@storage-transfer-service.iam.gserviceaccount.com"
      ],
      "role": "roles/storage.legacyBucketWriter"
    },
(省略)
  ],
  "etag": "CAQ="
}

※一部伏せ字に変更しています。

なお、転送に必要な権限は以下で確認可能です。 バケットレベルではなくサービスアカウントに対して権限付与したい場合には、必要な権限をご確認ください。

AWS IAM ロールを作成

AWS 管理コンソール IAM > ロールから、「ロールを作成」します。

ロール作成画面「信頼されたエンティティタイプ」で「ウェブアイデンティティ」を選択し、「アイデンティティプロバイダー」プルダウンから「Google」を選択して、「Audience」に Storage Transfer Service サービスアカウントの subjectId を入力して「次へ」。

「許可ポリシー」で「AmazonS3ReadOnlyAccess」を選択して「次へ」。

「ロール名」に任意の名前を入力したら、「ロールの作成」をクリック。

後ほど、Storage Transfer ジョブの作成時に指定する必要があるため、作成したロールの ARN を控えておきます。

Storage Transfer ジョブを作成

以下のJSONファイルを、aws_credential.json という名前で保存しました。

{
  "roleArn": "arn:aws:iam::[AWSアカウントID]:role/test-mikami-sts-assumerole"
}

※一部伏せ字に変更しています。

以下のコマンドで、AWS S3 から GCS にファイル転送するための Storage Transfer Service のジョブを作成します。

gcloud transfer jobs create --name test-sts-assumerole \
  s3://cm-mikami-test/temp-sts/ gs://test-mikami-sts-assumerole \
  --source-creds-file=aws_credential.json \
  --do-not-run

今回はワンショットで手動で実行するためスケジュール実行などの設定はしていませんが、オプション指定で転送頻度なども指定可能です。

転送元の AWS S3 バケットの指定パスには、以下の1ファイルが配置してある状況です。

転送先の GCS バケットには、まだ何もありません。

作成したジョブを実行してみます。

gcloud transfer jobs run test-sts-assumerole

しばらく待ってから、ジョブ実行状況を確認すると

$ gcloud transfer jobs monitor test-sts-assumerole
Polling for latest operation name...done.
Operation name: transferJobs-test-sts-assumerole-3363234993587737045
Parent job: test-sts-assumerole
Start time: 2022-09-09T12:13:25.377734977Z
SUCCESS | 100% (5.0B of 5.0B) | Skipped: 0B | Errors: 0
End time: 2022-09-09T12:13:46.887591311Z

正常に実行できたようです。

転送先 GCS バケットの中身も確認してみます。

$ gsutil ls gs://test-mikami-sts-assumerole
gs://test-mikami-sts-assumerole/target.txt

無事、AWS IAM ユーザーのキー情報なしで、Storage Transfer Service でファイル転送することができました。

まとめ(所感)

AWS IAM ユーザーを払い出す場合とさほど変わらない手間で、AWS IAM ロール(AssumeRoleWithWebIdentity)を作成して、Storage Transfer Service でファイル転送することができました。

今回は Google Cloud から AWS へアクセスするケースでしたが、逆に AWS から Google Cloud にアクセスする場合には、Workload Identity 連携で、同様にキー情報(サービスアカウントキー)発行なしでアクセスすることが可能です。

AssumeRoleWithWebIdentity や Workload Identity 連携を使うとよりセキュアな運用が実現できるので、マルチクラウド環境をお使いの場合には是非ご利用をご検討いただければと思います。

参考