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


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

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

準備

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

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

    1. Google Cloud CLI をインストールします。
    2. gcloud CLI を初期化するには:

      gcloud init
    3. Google アカウントのローカル認証情報を作成します。

      gcloud auth application-default login

    詳細については、 ローカル開発環境の認証の設定 をご覧ください。

概要

サービス アカウントを使用して実行するように 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 ツールや gsutil ツールのコマンドが使用されることがあります。これらのツールは、インスタンスのサービス アカウントとそのアカウントに付与されている関連の権限を自動的に認識します。特に、サービス アカウントに正しいロールを付与すると、gcloud auth login を使用せずに、インスタンスから gcloudgsutil ツールを使用できます。

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

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

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

次のステップ

使ってみる

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

Compute Engine の無料トライアル