AWS からリソースにアクセスする

このドキュメントでは、ID 連携を使用して Amazon Web Services(AWS)から Google Cloud リソースにアクセスする方法について説明します。

従来、Google Cloud の外部で実行されているアプリケーションは、サービス アカウント キーを使用して Google Cloud リソースにアクセスしていました。ID 連携を使用すると、AWS のユーザーまたはロールでサービス アカウントになり代わることができます。これにより、ワークロードは短期間だけ有効なアクセス トークンを使用して Google Cloud リソースに直接アクセスでき、サービス アカウント キーに関連するメンテナンスとセキュリティの負担が軽減されます。

始める前に

  1. IAM, Resource Manager, Service Account Credentials, and Security Token Service (STS) API を有効にします。

    API を有効にする

  2. Workload Identity プール管理者ロール(roles/iam.workloadIdentityPoolAdmin)があることを確認します。

    また、IAM オーナー(roles/owner)の基本ロールには ID 連携を構成する権限も含まれています。本番環境で基本ロールを付与することはできませんが、開発環境またはテスト環境ではこれらのロールを付与できます。

  3. 組織により AWS からの連携が許可されるように、組織のポリシーを更新します。

    必要に応じて、Google Cloud リソースへのアクセスが許可されている AWS アカウント ID を指定することもできます。

  4. AWS ロールを作成し、Amazon Resource Name(ARN)をメモします。

  5. Google Cloud サービス アカウントを作成します。

  6. サービス アカウントにアクセス権を付与して、ワークロードに必要な Google Cloud APIs を呼び出します。

Workload Identity プールの作成

Workload Identity プールを使用して、外部 ID を編成および管理できます。Workload Identity プールは相互に分離されていますが、1 つのプールは任意の数のサービス アカウントになり代わることができます。一般に、開発、ステージング、本番環境など、環境ごとに新しいプールを作成することをおすすめします。つまり、通常は AWS アカウントごとに 1 つのプールとなります。

新しい Workload Identity プールを作成するには、ID を指定する必要があります。オプションの説明と表示名を指定することもできます。

gcloud

gcloud iam workload-identity-pools create コマンドを実行して Workload Identity プールを作成します。

gcloud iam workload-identity-pools create pool-id \
    --location="global" \
    --description="description" \
    --display-name="display-name"

レスポンスは次のようになります。

Created workload identity pool [pool-id].

REST

projects.locations.workloadIdentityPools.create メソッドにより、Workload Identity プールが作成されます。

HTTP メソッドと URL:

POST https://iam.googleapis.com/v1/projects/project-id/locations/global/workloadIdentityPools?workloadIdentityPoolId=pool-id

JSON 本文のリクエスト:

{
  "description": "description",
  "display-name": "display-name"
}

リクエストを送信するには、次のいずれかのオプションを展開します。

このメソッドは、次のような長時間実行 Operation を返します。

{
  "name": "projects/project-number/locations/global/workloadIdentityPools/pool-id/operations/operation-id"
}

ID プロバイダとして AWS を追加する

AWS を Workload Identity プールの ID プロバイダとして構成するには、少なくとも次の情報を指定します。

  • プロバイダの ID。

  • このドキュメントの前のセクションの Workload Identity プール ID。

  • AWS アカウント ID

次の複数のオプション パラメータを指定することもできます。

  • 表示名と説明。

  • AWS トークンの属性を Google トークンの属性にマッピングする属性マッピングのリスト。デフォルトでは、各プールは次の属性マッピングを使用します。これらは最も一般的なシナリオに対応しています。

    Google AWS 説明
    google.subject assertion.arn IAM が認証するプリンシパル。これは、Cloud Logging ログエントリに表示される件名でもあります。このマッピングには、自動的に arn:aws:sts::account-id:assumed-role/aws-role/aws-session-name の形式で ARN が入力されます。
    attribute.aws_role AWS のロール AWS のロールです。arn:aws:sts::account-id:assumed-role/aws-role の形式を使用します。

    IAM ロール バインディングで参照できるカスタム マッピングを指定することもできます。assertion を使用して AWS 認証情報を参照します。Google 属性の場合は google、カスタム属性の場合は attribute を使用します。たとえば、次の例では、google.subject のデフォルトのマッピングに加えて、attribute.aws_accountassertion.account にマッピングされています。

    google.subject=assertion.arn,
    attribute.aws_account=assertion.account
    

    参照できる AWS トークンの属性のリストについては、GetCallerIdentity() のドキュメントをご覧ください。AWS のドキュメントでは、属性にキャメルケースが使用されるのに対して、属性のマッピングには小文字が使用されます。たとえば、Accountassertion.account になります。

    より複雑なアサーションの場合は、Common Expression Language を使用できます。例:

    attribute.environment=assertion.arn.contains(":instance-profile/Production") ? "prod" : "test"
    

    式で使用されている属性の特定の部分を参照するには、CEL の extract() 関数を使用します。この関数は、指定したテンプレートに基づいて属性から値を抽出します。extract() の詳細については、リソース名からの値の抽出をご覧ください。

    認証情報に属性が含まれているかどうかを確認するには、has() 関数を使用します。

  • プリンシパルが提示する必要がある属性を指定する属性条件。この属性は、外部の認証情報と Google の認証情報に適用できます。属性の条件を満たしていないリクエストは拒否されます。

    属性条件は、ブール値を返す CEL 式の形式になります。たとえば下記では、特定の AWS ロールを持たない ID からのリクエストは拒否されます。

    attribute.aws_role == "role-mapping"
    

    一般的なユースケースの詳細については、属性の条件をご覧ください。

次の例では、AWS を ID プロバイダとして追加する方法を説明します。

gcloud

gcloud iam workload-identity-pools providers create-aws コマンドを実行して AWS を ID プロバイダとして追加します。

gcloud iam workload-identity-pools providers create-aws provider-id \
    --workload-identity-pool="pool-id" \
    --account-id="aws-account-id" \
    --location="global"

レスポンスは次のようになります。

Created workload identity pool provider [provider-id].

REST

projects.locations.workloadIdentityPools.providers.create メソッドにより、AWS がプロバイダとして追加されます。

HTTP メソッドと URL:

POST https://iam.googleapis.com/v1/projects/project-id/locations/global/workloadIdentityPools/pool-id/providers?workloadIdentityPoolProviderId=provider-id

JSON 本文のリクエスト:

{
  "aws": {
    "accountId": "aws-account-id"
  }
}

リクエストを送信するには、次のいずれかのオプションを展開します。

このメソッドは、次のような長時間実行 Operation を返します。

{
  "name": "projects/project-number/locations/global/workloadIdentityPools/pool-id/providers/provider-id/operations/operation-id"
}

サービス アカウントの権限借用を許可する

外部 ID は、ほとんどの Google Cloud リソースに直接アクセスできません。代わりに、Workload Identity ユーザーロール(roles/iam.workloadIdentityUser)をサービス アカウントに付与することで、サービス アカウントの権限を借用できます。

このバインディングを AWS ロールに追加するには、次の形式を使用します。

attribute.aws_role/arn:aws:sts::aws-account-id:assumed-role/aws-role-name

例:

gcloud iam service-accounts add-iam-policy-binding service-account-email \
    --role roles/iam.workloadIdentityUser \
    --member "principalSet://iam.googleapis.com/projects/project-number/locations/global/workloadIdentityPools/pool-id/attribute.aws_role/arn:aws:sts::aws-account-id:assumed-role/aws-role-name"

AWS ユーザー用にこのバインディングを追加するには、次の形式を使用します。

subject/arn:aws:sts::aws-account-id:assumed-role/aws-role-name/aws-session-name

AWS ARN から AWS ロール セッションを抽出する方法については、IAM 識別子の AWS ドキュメントをご覧ください。

次の例では、AWS ユーザー用にバインディングを追加する方法を示しています。

gcloud iam service-accounts add-iam-policy-binding service-account-email \
    --role roles/iam.workloadIdentityUser \
    --member "principal://iam.googleapis.com/projects/project-number/locations/global/workloadIdentityPools/pool-id/subject/arn:aws:sts::aws-account-id:assumed-role/aws-role-name/aws-session-name"

カスタム属性に基づいてアクセス権を付与することもできます。例:

gcloud iam service-accounts add-iam-policy-binding service-account-email \
    --role="roles/iam.workloadIdentityUser" \
    --member="principalSet://iam.googleapis.com/projects/project-number/locations/global/workloadIdentityPools/pool-id/attribute.custom-attribute/arn:aws:sts::aws-account-id:aws-role-name"

アクセス権を取り消すには、add-iam-policy-bindingremove-iam-policy-binding に置き換えます。

REST API またはクライアント ライブラリを使用して、バインディングの追加または削除を行うこともできます。詳細については、リソースへのアクセス権の付与、変更、取り消しをご覧ください。

Google 認証情報を生成する

サポートされているクライアント ライブラリを使用する場合は、Google 認証情報が自動的に生成されるようにクライアント ライブラリを構成できます。あるいは、AWS 認証情報を手動で生成し、Google 認証情報と交換することもできます。

可能であれば、トークン交換プロセスを自身で実装しなくても済むように、認証情報を自動的に生成することをおすすめします。

認証情報の自動生成

次のいずれかの言語のクライアント ライブラリを使用して Google Cloud にアクセスする場合は、ID 連携を使用して認証情報を自動的に生成するようにクライアント ライブラリを構成できます。

C++

C++ 用 Google Cloud クライアント ライブラリのほとんどは、grpc::GoogleDefaultCredentials() を呼び出して作成される ChannelCredentials オブジェクトを使用して ID 連携をサポートしています。この認証情報を初期化するには、バージョン 1.36.0 以降の gRPC でクライアント ライブラリを構築する必要があります。

C++ 用 Cloud Storage クライアント ライブラリは、gRPC ではなく REST API を使用するため、ID 連携をサポートしていません。

Go

Go 用クライアント ライブラリは、golang.org/x/oauth2 モジュールのバージョン v0.0.0-20210218202405-ba52d332ba99 以降を使用している場合、ID 連携をサポートします。

クライアント ライブラリが使用しているこのモジュールのバージョンを確認するには、次のコマンドを実行します。

cd $GOPATH/src/cloud.google.com/go
go list -m golang.org/x/oauth2

Java

Java 用クライアント ライブラリは、com.google.auth:google-auth-library-oauth2-http アーティファクトのバージョン 0.24.0 以降を使用している場合、ID 連携をサポートします。

クライアント ライブラリで使用しているこのアーティファクトのバージョンを確認するには、アプリケーション ディレクトリで次の Maven コマンドを実行します。

mvn dependency:list -DincludeArtifactIds=google-auth-library-oauth2-http

Node.js

Node.js 用クライアント ライブラリは、google-auth-library パッケージのバージョン 7.0.2 以降を使用している場合、ID 連携をサポートします。

クライアント ライブラリで使用されているこのパッケージのバージョンを確認するには、アプリケーション ディレクトリで次のコマンドを実行します。

npm list google-auth-library

GoogleAuth オブジェクトを作成するときに、プロジェクト ID を指定できます。また、GoogleAuth で自動的にプロジェクト ID を検出することもできます。プロジェクト ID を自動的に検出するには、構成ファイルのサービス アカウントに、プロジェクト上でブラウザのロール(roles/browser)または同等の権限を持つロールが付与されている必要があります。詳細については、google-auth-library パッケージの README をご覧ください。

Python

Python 用クライアント ライブラリは、google-auth パッケージのバージョン 1.27.0 以降を使用している場合、ID 連携をサポートします。

クライアント ライブラリで使用されているこのパッケージのバージョンを確認するには、パッケージがインストールされている環境で次のコマンドを実行します。

pip show google-auth

認証クライアントのプロジェクト ID を指定するには、GOOGLE_CLOUD_PROJECT 環境変数を設定するか、クライアントがプロジェクト ID を自動的に検出するようにします。プロジェクト ID を自動的に検出するには、構成ファイルのサービス アカウントに、プロジェクト上でブラウザのロール(roles/browser)または同等の権限を持つロールが付与されている必要があります。詳細については、google-auth パッケージのユーザーガイドをご覧ください。

認証情報が自動的に生成されるようにクライアント ライブラリを構成するには、gcloud iam workload-identity-pools create-cred-config コマンドを実行して JSON 構成ファイルを生成します。

gcloud iam workload-identity-pools create-cred-config \
    projects/project-number/locations/global/workloadIdentityPools/pool-id/providers/provider-id \
    --service-account=service-account-email \
    --output-file=filepath \
    --aws

次の値を置き換えます。

  • project-number: プロジェクトの数値 ID。
  • pool-id: Workload Identity プールの ID。
  • provider-id: Workload Identity プール プロバイダの ID。
  • service-account-email: なり代わるサービス アカウントのメールアドレス。
  • filepath: 構成ファイルのファイルパス。

構成ファイルを生成したら、環境変数 GOOGLE_APPLICATION_CREDENTIALS を構成ファイルのファイルパスに設定します。この環境変数は、クライアント ライブラリに対し、アプリケーションのデフォルト認証情報を使用して認証するように指示します。詳細については、認証情報の自動検出をご覧ください。

認証情報を手動で交換する

AWS ロールまたはユーザーが、サービス アカウントになり代わることができると、AWS 認証情報を Google 認証情報と手動で交換できます。

この交換プロセスで、GetCallerIdentity トークンをセキュリティ トークン サービスに渡します。GetCallerIdentity トークンには、AWS GetCallerIdentity() メソッドへのリクエストに含める情報と、リクエストに生成する署名が含まれます。Google Cloud は、GetCallerIdentity トークンを使用して AWS プリンシパルの ID を確認し、そのプリンシパルがサービス アカウントの権限を借用できることを確認します。

認証情報を交換するには:

  1. 一時的な AWS 認証情報を取得します

  2. GetCallerIdentity トークンを作成します。このトークンには、AWS GetCallerIdentity() メソッドへのリクエスト用の情報と、リクエスト情報用の AWS の署名が含まれています。バージョン 4 の署名を使用します。

    リクエストには次のフィールドが含まれます。

    • url: GetCallerIdentity() の AWS STS エンドポイントの URL。標準の GetCallerIdentity() リクエストの本文がクエリ パラメータとして追加されます。例: https://sts.amazonaws.com?Action=GetCallerIdentity&Version=2011-06-15リージョン エンドポイントもサポートされます。
    • method: HTTP リクエスト メソッド: POST
    • headers: HTTP リクエスト ヘッダー。次の情報を含める必要があります。

      • Authorization: リクエストの署名。
      • host: url フィールドのホスト名。たとえば、sts.amazonaws.com
      • x-amz-date: リクエストを送信する時刻。ISO 8601 の基本文字列の形式になります。通常、この値は現在の時刻に設定され、リプレイ攻撃の防止に使用されます。
      • x-goog-cloud-target-resource: ID プロバイダの完全なリソース名。例:
      //iam.googleapis.com/projects/project-number/locations/global/workloadIdentityPools/pool-id/providers/provider-id
      
      • x-amz-security-token: 一時的なセキュリティ認証情報を使用する場合にのみ必要です。含める AWS セッション トークン

    GetCallerIdentity トークンは次のような形式になります。

    {
      "url": "https://sts.amazonaws.com?Action=GetCallerIdentity&Version=2011-06-15",
      "method": "POST",
      "headers": [
        {
          "key": "Authorization",
          "value" : "AWS4-HMAC-SHA256 Credential=AKIASOZTBDV4D7ABCDEDF/20200228/us-east-1/sts/aws4_request, SignedHeaders=host;x-amz-date,Signature=abcedefdfedfd"
        },
        {
          "key": "host",
          "value": "sts.amazonaws.com"
        },
        {
          "key": "x-amz-date",
          "value": "20200228T225005Z"
        },
        {
          "key": "x-goog-cloud-target-resource",
          "value": "//iam.googleapis.com/projects/12345678/locations/global/workloadIdentityPools/my-pool/providers/my-aws-provider"
        },
        {
          "key": "x-amz-security-token",
          "value": "GizFWJTqYX...xJ55YoJ8E9HNU="
        }
      ]
    }
    
  3. 連携アクセス トークンの AWS 認証情報を交換するには、GetCallerIdentity トークンをセキュリティ トークン サービスの token() メソッドに渡します。

    REST

    token メソッドにより、サードパーティ トークンが Google トークンに交換されます。

    後述のリクエストのデータを使用する前に、次のように置き換えます。

    • project-number: Google Cloud プロジェクト番号。
    • pool-id: このチュートリアルで前に作成した Workload Identity プールの ID。
    • provider-id: このチュートリアルで前に構成した AWS ID プロバイダの ID。
    • aws-request: URL の生成から除外された JSON 形式の GetCallerIdentity トークン。

    HTTP メソッドと URL:

    POST https://sts.googleapis.com/v1/token

    JSON 本文のリクエスト:

    {
      "audience": "//iam.googleapis.com/projects/project-number/locations/global/workloadIdentityPools/pool-id/providers/provider-id",
      "grantType": "urn:ietf:params:oauth:grant-type:token-exchange",
      "requestedTokenType": "urn:ietf:params:oauth:token-type:access_token",
      "scope": "https://www.googleapis.com/auth/cloud-platform",
      "subjectTokenType": "urn:ietf:params:aws:token-type:aws4_request",
      "subjectToken": "aws-request"
    }
    

    リクエストを送信するには、次のいずれかのオプションを展開します。

     

    このメソッドは連携トークンを返します。

  4. 連携トークンをサービス アカウントのアクセス トークンと交換するには、generateAccessToken() メソッドを呼び出します。連携トークンは一部の Google Cloud APIs でサポートされています。すべての Google Cloud APIs はサービス アカウントのアクセス トークンをサポートしています。

    REST

    Service Account Credentials API の serviceAccounts.generateAccessToken メソッドによって、サービス アカウントの OAuth 2.0 アクセス トークンが生成されます。

    後述のリクエストのデータを使用する前に、次のように置き換えます。

    • PROJECT_ID: Google Cloud プロジェクト IDプロジェクト ID は英数字からなる文字列です(例: my-project)。
    • SA_ID: サービス アカウントの ID。これは、サービス アカウントのメールアドレス(SA_NAME@PROJECT_ID.iam.gserviceaccount.com の形式)、またはサービス アカウントの一意の数値 ID のいずれかです。
    • token: 連携アクセス トークン。

    HTTP メソッドと URL:

    POST https://iamcredentials.googleapis.com/v1/projects/-/serviceAccounts/SA_NAME@PROJECT_ID.iam.gserviceaccount.com:generateAccessToken

    JSON 本文のリクエスト:

    {
      "scope": [
        "https://www.googleapis.com/auth/cloud-platform"
      ]
    }
    

    リクエストを送信するには、次のいずれかのオプションを展開します。

    generateAccessToken リクエストが成功した場合、レスポンスの本文には OAuth 2.0 アクセス トークンと有効期限が含まれます。expireTime に達するまで、サービス アカウントの代わりに accessToken をリクエストの認証に使用できます。

    {
      "accessToken": "eyJ0eXAi...NiJ9",
      "expireTime": "2020-04-07T15:01:23.045123456Z"
    }
    

サービス アカウントのアクセス トークンを取得すると、リクエストの Authorization ヘッダーにトークンを含めることで、トークンを使用して Google Cloud APIs を呼び出せます。

Authorization: Bearer access-token

リクエストはサービス アカウントとして承認されます。

次のステップ