サービス アカウントを使用して Google Cloud APIs に対するワークロードの認証を行う


このページでは、サービス アカウントを使用して、仮想マシン(VM)インスタンス上で動作するアプリで Google Cloud APIs に対する認証を行い、リソースへのアクセスを承認できるようにする方法について説明します。

認証にサービス アカウントを使用するには、まず、サービス アカウントを使用するように VM が構成されていることを確認する必要があります。これを行うには、次のいずれかの手順に沿って操作します。

準備

  • サービス アカウントの概要を確認します。
  • まだ設定していない場合は、認証を設定します。認証とは、Google Cloud サービスと API にアクセスするために ID を確認するプロセスです。ローカル開発環境からコードまたはサンプルを実行するには、次のように Compute Engine に対する認証を行います。

    ローカル開発環境でこのページの Python サンプルを使用するには、gcloud CLI をインストールして初期化し、ユーザー認証情報を使用してアプリケーションのデフォルト認証情報を設定します。

    1. Install the Google Cloud CLI.
    2. To initialize the gcloud CLI, run the following command:

      gcloud init
    3. If you're using a local shell, then create local authentication credentials for your user account:

      gcloud auth application-default login

      You don't need to do this if you're using Cloud Shell.

    詳細については Set up authentication for a local development environment をご覧ください。

概要

サービス アカウントを使用して実行するように VM インスタンスを設定後、VM インスタンスで実行されるアプリケーションは、次のいずれかの認証方法を使用できます。

サービス アカウントの認証情報を使用したアプリケーションの認証

サービス アカウントとして実行するようにインスタンスを設定した後で、サービス アカウントの認証情報を使用してインスタンス上で実行するアプリケーションを承認できます。

クライアント ライブラリを使用したアプリケーションの認証

クライアント ライブラリは、Google API で認証するために、アプリケーションのデフォルト認証情報を使用し、それらの API にリクエストを送信できます。アプリケーションは、アプリケーションのデフォルト認証情報により、複数のソースから認証情報を自動で取得できるため、アプリケーションをローカルでテストできます。テスト後は、アプリケーション コードを変更することなく、Compute Engine インスタンスにデプロイできます。

アプリケーションのデフォルト認証情報の設定については、アプリケーションのデフォルト認証情報に認証情報を用意するをご覧ください。

この例では、Python クライアント ライブラリを使用して認証を行い、プロジェクト内のバケットの一覧表示を行う Cloud Storage API にリクエストを行います。これは、次の手順により行います。

  1. Cloud Storage API に必要な認証情報を取得し、build() メソッドと認証情報を使用して Cloud Storage サービスを初期化します。
  2. Cloud Storage 内のバケットを一覧表示します。

このサンプルは、Cloud Storage 内のバケットを管理するためのアクセス権を持つインスタンスで実行できます。

import argparse
from typing import List

from google.cloud import storage


def create_client() -> storage.Client:
    """
    Construct a client object for the Storage API using the
    application default credentials.

    Returns:
        Storage API client object.
    """
    # Construct the service object for interacting with the Cloud Storage API -
    # the 'storage' service, at version 'v1'.
    # Authentication is provided by application default credentials.
    # When running locally, these are available after running
    # `gcloud auth application-default login`. When running on Compute
    # Engine, these are available from the environment.
    return storage.Client()


def list_buckets(client: storage.Client, project_id: str) -> List[storage.Bucket]:
    """
    Retrieve bucket list of a project using provided client object.


    Args:
        client: Storage API client object.
        project_id: name of the project to list buckets from.

    Returns:
        List of Buckets found in the project.
    """
    buckets = client.list_buckets()
    return list(buckets)


def main(project_id: str) -> None:
    client = create_client()
    buckets = list_buckets(client, project_id)
    print(buckets)


if __name__ == "__main__":
    parser = argparse.ArgumentParser(
        description=__doc__, formatter_class=argparse.RawDescriptionHelpFormatter
    )
    parser.add_argument("project_id", help="Your Google Cloud Project ID.")

    args = parser.parse_args()

    main(args.project_id)

アクセス トークンを使用したアプリケーションの直接認証

ほとんどのアプリケーションでは、アプリケーションのデフォルト認証情報を使用して認証を行えます。これは、認証情報を手に入れてトークンを管理します。ただし、アプリケーションで OAuth2 アクセス トークンを指定する必要がある場合は、Compute Engine でメタデータ サーバーからアクセス トークンを取得してアプリケーションで使用できます。

アプリケーションを認証するために、これらのアクセス トークンを取得して使用する方法は複数あります。たとえば、curl を使用してシンプルなリクエストを作成することや、Python などのプログラミング言語を使用して柔軟性を高めることが可能です。

cURL

curl を使用してアクセス トークンをリクエストして、API にリクエストを送信するには:

  1. アプリケーションが実行するインスタンス上で、次のコマンドによってアクセス トークンのメタデータ サーバーをクエリします。

    $ curl "http://metadata.google.internal/computeMetadata/v1/instance/service-accounts/default/token" \
    -H "Metadata-Flavor: Google"

    その結果、次のようなレスポンスが得られます。

    {
          "access_token":"ya29.AHES6ZRN3-HlhAPya30GnW_bHSb_QtAS08i85nHq39HE3C2LTrCARA",
          "expires_in":3599,
          "token_type":"Bearer"
     }

    API リクエストでは、レスポンス全体ではなく access_token 値を含める必要があります。jq コマンドライン JSON プロセッサをインストールしている場合は、次のコマンドを使用して、レスポンスからアクセス トークンの値を抽出できます。

    $ ACCESS_TOKEN=`curl \
    "http://metadata.google.internal/computeMetadata/v1/instance/service-accounts/default/token" \
    -H "Metadata-Flavor: Google" | jq -r '.access_token'`
    
  2. レスポンスから access_token プロパティの値をコピーし、その値を使用して API にリクエストを送信します。たとえば、次のリクエストでは、特定のゾーンからプロジェクト内のインスタンスのリストが出力されます。

    $ curl https://compute.googleapis.com/compute/v1/projects/PROJECT_ID/zones/ZONE/instances \
    -H "Authorization":"Bearer ACCESS_TOKEN"
    

    次のように置き換えます。

    • PROJECT_ID: このリクエストのプロジェクト ID。
    • ZONE: VM を一覧表示するゾーン。
    • ACCESS_TOKEN: 前のステップで取得したアクセス トークンの値。

    リクエストに設定可能なパラメータの詳細については、システム パラメータのドキュメントを参照してください。

Python

この例では、Python アプリケーションで Cloud Storage API にアクセスするためにトークンをリクエストする方法を示します。これは、次の手順により行います。

  1. メタデータ サーバーのアクセス トークンをリクエストします。
  2. サーバーのレスポンスからアクセス トークンを取り出します。
  3. アクセス トークンを使用して Cloud Storage にリクエストを行います。
  4. リクエストが成功した場合、スクリプトによってレスポンスが出力されます。

import argparse

import requests


METADATA_URL = "http://metadata.google.internal/computeMetadata/v1/"
METADATA_HEADERS = {"Metadata-Flavor": "Google"}
SERVICE_ACCOUNT = "default"


def get_access_token() -> str:
    """
    Retrieves access token from the metadata server.

    Returns:
        The access token.
    """
    url = f"{METADATA_URL}instance/service-accounts/{SERVICE_ACCOUNT}/token"

    # Request an access token from the metadata server.
    r = requests.get(url, headers=METADATA_HEADERS)
    r.raise_for_status()

    # Extract the access token from the response.
    access_token = r.json()["access_token"]

    return access_token


def list_buckets(project_id: str, access_token: str) -> dict:
    """
    Calls Storage API to retrieve a list of buckets.

    Args:
        project_id: name of the project to list buckets from.
        access_token: access token to authenticate with.

    Returns:
        Response from the API.
    """
    url = "https://www.googleapis.com/storage/v1/b"
    params = {"project": project_id}
    headers = {"Authorization": f"Bearer {access_token}"}

    r = requests.get(url, params=params, headers=headers)
    r.raise_for_status()

    return r.json()


def main(project_id: str) -> None:
    """
    Retrieves access token from metadata server and uses it to list
    buckets in a project.

    Args:
        project_id: name of the project to list buckets from.
    """
    access_token = get_access_token()
    buckets = list_buckets(project_id, access_token)
    print(buckets)


if __name__ == "__main__":
    parser = argparse.ArgumentParser(
        description=__doc__, formatter_class=argparse.RawDescriptionHelpFormatter
    )
    parser.add_argument("project_id", help="Your Google Cloud project ID.")

    args = parser.parse_args()

    main(args.project_id)

アクセス トークンは短期間で失効します。メタデータ サーバーは、失効までの残り時間が 5 分になるまでアクセス トークンをキャッシュに保存します。トークンをキャッシュに保存できない場合、1 秒あたり 50 クエリを超えるリクエストにはレート制限が適用される可能性があります。API 呼び出しを成功させるには、アプリケーションに有効なアクセス トークンが必要です。

サービス アカウントを使用してインスタンス上のツールを承認する

一部のアプリケーションでは、Compute Engine の大部分のイメージにデフォルトで含まれている gcloud CLI のコマンドが使用されることがあります。gcloud CLI は、インスタンスのサービス アカウントと、そのアカウントに付与されている関連の権限を自動的に認識します。特に、サービス アカウントに正しいロールを付与すると、gcloud auth login を使用せずに、インスタンスから gcloud CLI を使用できます。

サービス アカウントの認識は自動的に行われ、インスタンスに含まれている gcloud CLI にのみ適用されます。新しいツールを作成する場合や、カスタムツールを追加する場合は、クライアント ライブラリを使用するか、アプリケーション内で直接アクセス トークンを使用して、アプリケーションを承認する必要があります。

サービス アカウントの自動認識を利用するには、サービス アカウントに適切な IAM のロールを付与し、サービス アカウントをインスタンスに接続します。たとえば、サービス アカウントに roles/storage.objectAdmin ロールを付与すると、gcloud CLI で、Cloud Storage のオブジェクトを自動的に管理してアクセスできます。

同様に、サービス アカウントに対して roles/compute.instanceAdmin.v1 を有効にすると、gcloud compute ツールでインスタンスを自動管理できます。

次のステップ

使ってみる

Google Cloud を初めて使用する場合は、アカウントを作成して、実際のシナリオで Compute Engine のパフォーマンスを評価してください。新規のお客様には、ワークロードの実行、テスト、デプロイができる無料クレジット $300 分を差し上げます。

Compute Engine の無料トライアル