22
14

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

Google Cloud Platform その2Advent Calendar 2018

Day 3

PythonでGoogle Cloud Storageの署名付きURLを作成する

Last updated at Posted at 2018-12-02

Google Cloud Platform その2 Advent Calendar 2018の3日目の投稿となります。

Google App Engine(GAE)でアプリ開発をしていたのですが、ファイルアップロード機能を実装していると、アップロードできるファイルサイズに制限があったため、Google Cloud Storage(GCS)の署名付きURLを作成して直接アップロードすることにしました。

署名付きURLを作成するのに1日ほどハマったので、まとめておきます。

環境構築

仮想環境を作成して環境を構築します。

ソースはGitHubにアップしていますので、よければご参考ください。
https://github.com/kai-kou/create-cloud-storage-signed-url

> python --version
Python 3.6.6

> python -m venv venv
>. venv/bin/activate

> touch requirements.txt
> touch main.py

Google Cloud Platform(GCP)のサービスアカウントを利用してURLを生成するのに、oauth2clientを利用します。

requirements.txt
oauth2client

実装は下記を参考にさせてもらいました。

authentication - Cloud storage and secure download strategy on app engine. GCS acl or blobstore - Stack Overflow
https://stackoverflow.com/questions/29847759/cloud-storage-and-secure-download-strategy-on-app-engine-gcs-acl-or-blobstore

署名付きURLの作成方法については公式ドキュメントが詳しかったです。

Generating Signed URLs with Your Own Program  |  Cloud Storage  |  Google Cloud
https://cloud.google.com/storage/docs/access-control/signing-urls-manually

main.py
import time

import urllib

from datetime import datetime, timedelta

import os

import base64

from oauth2client.service_account import ServiceAccountCredentials

API_ACCESS_ENDPOINT = 'https://storage.googleapis.com'


def sign_url(bucket, bucket_object, method, expires_after_seconds=60):
    gcs_filename = '/%s/%s' % (bucket, bucket_object)
    content_md5, content_type = None, None

    credentials = ServiceAccountCredentials.from_json_keyfile_name('[サービスアカウントキーのファイルパス]')
    google_access_id = credentials.service_account_email

    expiration = datetime.now() + timedelta(seconds=expires_after_seconds)
    expiration = int(time.mktime(expiration.timetuple()))

    signature_string = '\n'.join([
        method,
        content_md5 or '',
        content_type or '',
        str(expiration),
        gcs_filename])
    _, signature_bytes = credentials.sign_blob(signature_string)
    signature = base64.b64encode(signature_bytes)

    query_params = {'GoogleAccessId': google_access_id,
                    'Expires': str(expiration),
                    'Signature': signature}

    return '{endpoint}{resource}?{querystring}'.format(
        endpoint=API_ACCESS_ENDPOINT,
        resource=gcs_filename,
        querystring=urllib.parse.urlencode(query_params))


if __name__ == '__main__':
    url = sign_url('[バケット名]', '[オブジェクト名(ファイル名)]', 'GET')
    print(url)

上記で指定する[サービスアカウントキーのファイルパス]はGCPのサービスアカウントを作成すると取得できるjsonファイルとなります。サービスアカウントには必要なGCSの役割を付与します。

サービスアカウントの作成方法は下記が詳しかったです。

Google Cloud Platform のサービスアカウントキーを作成する | MAGELLAN BLOCKS
https://www.magellanic-clouds.com/blocks/guide/create-gcp-service-account-key/

実行する

実行するとURLが生成されます。URLにアクセスする、指定したGCSのバケットにあるオブジェクトが取得できることが確認できます。

> python main.py

https://storage.googleapis.com/[バケット名]/[オブジェクト名]?GoogleAccessId=xxxxx%40xxxxx.iam.gserviceaccount.com&Expires=1542687588&Signature=xxxxxxxxxx

ハマりポイント

GCPサービス上でGoogleCredentials.get_application_default() が使えない

Google App Engine(GAE)やGoogle Cloud Functions(GCF)だと、実行に利用しているサービスアカウントの情報が取得できるので、GoogleCredentials.get_application_default()Credentials を利用しようとしたのですが、service_account_email が空で、sign_blob メソッドも利用できませんでした。

まとめ

AWSだと署名付きURLの作成はもう少し簡単だった記憶があったので、GCPでも同じ感覚でいたら、~~ひどい目にあいました。~~自前でURLを組み立てる必要があったので、手間がかかりましたが、作成方法さえわかれば、あとは、GAEやGCFでの利用も簡単そうです。

参考

authentication - Cloud storage and secure download strategy on app engine. GCS acl or blobstore - Stack Overflow
https://stackoverflow.com/questions/29847759/cloud-storage-and-secure-download-strategy-on-app-engine-gcs-acl-or-blobstore

Generating Signed URLs with Your Own Program  |  Cloud Storage  |  Google Cloud
https://cloud.google.com/storage/docs/access-control/signing-urls-manually

Google Cloud Platform のサービスアカウントキーを作成する | MAGELLAN BLOCKS
https://www.magellanic-clouds.com/blocks/guide/create-gcp-service-account-key/

22
14
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
22
14

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?