Google Workspace

Google ドライブでの認証

DriveGCPAuthHeader

※この投稿は米国時間 2021 年 2 月 10 日に、Google Cloud blog に投稿されたものの抄訳です。

GCP 上でアプリケーションを開発していて、通常使用する Cloud SQL や Bigtable などのデータストアを使用したくない場合もあります。たとえば現在、技術系以外のスタッフでもビルドシステムに簡単にアイコンを追加できるアプリケーションを開発しているとします。ゼロからフロントエンドを記述したくありませんし、ソース コントロールは重要ではありますが、その方法を技術系以外のスタッフに教えるという方法も避けたいです。そういった場合、手軽なソリューションとして Google ドライブを利用できます。Google ドライブをデータストアとして使用するとは思いもよらなかったでしょうか。少しご説明させてください。Google ドライブは、非常にシンプルなインターフェースと基本的なソース コントロール機能を備えています。API も用意されているため、Google ドライブから適切なソース コントロール機能およびビルドシステムにアイコンを pull する処理を自動化して、誰もがアイコンを扱えるようにすることができます。

ただし、1 つ問題があります。Google ドライブの API を使用するには OAuth を使用する必要があるように見えますが、OAuth を使いたくないのです。「使いたくない」と言うと語弊があるでしょうか。OAuth は素晴らしい仕組みであり、非常に重要な認証機能を提供していることは認めています。ただ、仕組みが複雑で、気軽に使えないと感じるのです。どのトークンをどこから取得すればよいのか、ヘッダーにトークンを組み込むのか、ヘッダーの名前は何か。OAuth を実装するときは、常にこうしたことを考えなければなりません。

実際、日常的に気軽に使える認証の仕組みは存在します。GCP のサービス アカウントと IAM を使う方法です。GCP サービスをすでに使用しているアプリケーションに Google ドライブの機能を統合する場合は、IAM サービス アカウントを使用して認証を行うことができます。

IAM サービス アカウントがユーザーでもある点がポイントです。ユーザーはメールアドレスを持っています。コンソールのアクセスページのリストには、サービス アカウントが次のように表示されます。

in_the_console

このメールアドレスがポイントです。ドライブのフォルダを他のユーザーと共有することと同様に、ドライブのフォルダを IAM サービス アカウントと共有することができます。フォルダ以外にも、スプレッドシートやドキュメントなど、さまざまな要素を GCP アプリケーションに統合できます。

先ほどご紹介した例では、マーケティング部門のスタッフがアイコンを置くドライブ フォルダを共有することになります。それではその実装手順について説明していきます。こちらのコンソールでサービス アカウントを作成します。上部の [サービス アカウントを作成] ボタンをクリックします。作成したアカウントに名前を付け、使用する GCP サービスに対してアプリケーションが必要とするロールのアクセス権を付与します。ドライブ自体には、権限のロールを付与する必要はありません。たとえば、アプリケーションでドライブのコンテンツにアクセスすることに加えて Cloud SQL データベースにエントリを書き込む必要もあれば、Cloud SQL クライアントのロールを割り当てる必要があります。必要な権限のみを追加し、包括的な「オーナー」権限は付与しないようにしてください。

終わったら、リストでサービス アカウントをクリックして詳細を表示し、[鍵を追加] をクリックします。

keys

JSON のタイプを選択すると、このサービス アカウントの署名なしトークンがダウンロードされます。ここで注意が必要です。このトークンは署名なしトークンなので、トークンを手にしたユーザーは誰でも、サービス アカウントに付与した権限に基づいて任意の操作をプロジェクトで行うことができます。たとえば、Cloud SQL クライアントのロールを付与していたら、データベースに対して読み書きを実行できます。そのためオーナーレベルの権限ではなく、必要なロールのみを付与する必要があります。

Python のコードは次のようになります。

Language: Python

  from googleapiclient.discovery import build
from google.oauth2 import service_account
from googleapiclient.errors import HttpError as HTTPError

SCOPES = ['https://www.googleapis.com/auth/drive']

sa_creds = service_account.Credentials.from_service_account_file('drive_icons_sa.json')
scoped_creds = sa_creds.with_scopes(SCOPES)
drive_service = build('drive', 'v3', credentials=scoped_creds)

discovery API は、Python などの言語でネイティブに使用できる、REST API のラッパーです。この API を使用するとさまざまなことができます。詳しくない場合は、フォルダやファイルの作成、ダウンロード、検索など、Drive API の基礎をこちらでご確認いただけます。たとえば、ドライブのフォルダにあるすべてのフォルダを取得するには、次のように記述します。

  children = drive_service.files().list(q=f"mimeType = 'application/vnd.google-apps.folder' and '{marketing_icon_folder_id}' in parents", fields='files(name, id)').execute()

このコードでは、marketing_icon_folder_id 内の最初の 100 個のフォルダを取得し(pageSize はデフォルトで 100 です。list の呼び出しにパラメータ pageSize=n を追加すればこの数を変更できます)、これらのフォルダの名前とドライブ ID を返します。

以上で終了です。Google ドライブは、GCP に統合されたアプリケーション向けに、シンプルな UI、基本的なバージョニング、さまざまな機能を備えた API を備えるデータストアとして、OAuth の細かい実装方法に悩まされることなく簡単に使用することができます。最後までお読みいただきありがとうございました。お役に立てば幸いです。

開発のアイデアが必要な場合は、Codelab をご参照ください。クリエイティブなひらめきを得られるアイデアが満載です。ご質問や、ドライブと GCP を活用して開発している魅力的なアプリケーションについて情報を共有したいなど、何かありましたら Twitter までご連絡ください。DM はどなたでも送れる設定になっています。

-デベロッパー アドボケイト Gabe Weiss