📥

Google Cloud Storage のオブジェクトを別プロジェクトのアプリケーションからダウンロードする

2023/06/23に公開

複数の GCP (Google Cloud Platform) プロジェクトを運用している場合に、GCS (Google Cloud Storage) のオブジェクトを別のプロジェクトからダウンロードしたい!という場面があるかと思います。実際に試してみたので、今回はその方法をまとめます。

ここでは、アクセスされる側の GCP プロジェクトを projectA、アクセスする側の GCP プロジェクトを projectB と呼んで説明します。

アクセスする側 projectB の準備

1. サービスアカウントキーを作成

GCPコンソール画面の IAMと管理>サービスアカウント で、サービスアカウントを作成します。
作成完了したら、キー タブで 鍵を追加>新しい鍵を作成 をクリックします。
キーのタイプは JSON を選択すると、JSONの鍵ファイルがダウンロードされます。

2. Secret Manager にサービスアカウントキーをアップロード

後ほど作成するアプリケーション内でサービスアカウントキーを使用するため、Secret Manager に登録しておきます。
Secret Manager の +シークレットを作成 をクリックし、サービスアカウントキーのJSONファイルをアップロードしてシークレットの値を登録します。

アクセスされる側 projectA の準備

1. projectB に GCS のオブジェクト閲覧権限を与える

projectB に GCS バケットの閲覧権限を与えるために、バケットの権限を編集します。
プリンシパルを追加 をクリックし、projectB のサービスアカウントを入力し、ロールは Storageオブジェクト閲覧者 を選択します。

これで、projectB から projectA の GCS バケットにアクセスできるようになりました。

アプリケーション作成

projectA の GCS オブジェクトをダウンロードする Python コードを示します。オブジェクトの一覧取得やダウンロードは、GCS 公式ドキュメントのサンプルコードが参考になりました。

ポイントは以下の2点になります。

  • サービスアカウントキーを使用し、projectA のクレデンシャルを作成する
  • クレデンシャルを利用して、GCSのクライアントインスタンスを作成する
Pythonサンプルコード
import os
import json
from google.cloud import storage
from google.oauth2 import service_account

# 環境変数取得
# projectAのバケット名
BUCKET_NAME = os.environ.get('BUCKET_NAME')
# projectBのサービスアカウントキー
SERVICE_ACCOUNT_KEY = os.environ.get('service_account_key')
# ダウンロードファイルの保存パス
DOWNLOAD_PATH = os.environ.get('DOWNLOAD_PATH')


def create_crendentials():
    """
    サービスアカウントキーを使用してクレデンシャルを作成

    Returns:
        クレデンシャル
    """

    credentials = service_account.Credentials \
        .from_service_account_info(json.loads(SERVICE_ACCOUNT_KEY))

    scoped_credentials = credentials.with_scopes(
        [
            'https://www.googleapis.com/auth/cloud-platform',
            'https://www.googleapis.com/auth/analytics.readonly'
        ])

    return scoped_credentials


def list_blobs(credentials, bucket_name):
    """
    GCSバケットのオブジェクトを取得

    Args:
        credentials: クレデンシャル
        bucket_name (str): GCSバケット名

    Returns:
        list: オブジェクト名のリスト
    """

    # GCSのクライアントインスタンス作成
    storage_client = storage.Client(credentials=credentials)

    # 指定バケットのオブジェクト一覧を取得
    blobs = storage_client.list_blobs(bucket_name)

    return list(blobs)


def download_blob(credentials, bucket_name, blob_name, file_name):
    """
    GCSバケットの指定オブジェクトをダウンロード

    Args:
        credentials: クレデンシャル
        bucket_name (str): GCSバケット名
        blob_name (str): オブジェクト名
        file_name (str): 保存ファイル名
    """

    # GCSのクライアントインスタンス作成
    storage_client = storage.Client(credentials=credentials)

    # 指定バケットのインスタンス取得
    bucket = storage_client.bucket(bucket_name)

    # 指定オブジェクトのインスタンス取得
    blob = bucket.blob(blob_name)

    # ダウンロードして指定パスに保存する
    blob.download_to_filename(file_name)


def main(self):
    """
    別のGCPプロジェクトのGCSバケットのオブジェクトを一覧表示し、ダウンロードする
    """

    # クレデンシャル作成
    scoped_credentials = create_crendentials()

    # projectAの指定バケットのオブジェクト一覧を取得
    blobs = list(list_blobs(scoped_credentials, BUCKET_NAME))

    # オブジェクトのダウンロード
    for blob in blobs:
        file_name = DOWNLOAD_PATH + blob.name
        download_blob(scoped_credentials, BUCKET_NAME, blob.name, file_name)

    return "OK"


おわりに

今回は GCS バケットのオブジェクトを、別プロジェクトのアプリケーションからアクセスしてダウンロードする方法を紹介しました。アクセスされる側で権限を与えて、アクセスする側ではサービスアカウントキーを使用してクレデンシャルを作成することで、別プロジェクトからアクセスすることができました。ご参考になればうれしいです。

レスキューナウテックブログ

Discussion