このドキュメントでは、ID 連携を使用して Amazon Web Services(AWS)から Google Cloud リソースにアクセスする方法について説明します。
従来、Google Cloud の外部で実行されているアプリケーションは、サービス アカウント キーを使用して Google Cloud リソースにアクセスしていました。ID 連携を使用すると、AWS のユーザーまたはロールでサービス アカウントになり代わることができます。これにより、ワークロードは短期間だけ有効なアクセス トークンを使用して Google Cloud リソースに直接アクセスでき、サービス アカウント キーに関連するメンテナンスとセキュリティの負担が軽減されます。
始める前に
Workload Identity プール管理者ロール(
roles/iam.workloadIdentityPoolAdmin
)があることを確認します。また、IAM オーナー(
roles/owner
)と編集者(roles/editor
)の基本ロールには ID 連携を構成する権限も含まれています。本番環境で基本ロールを付与することはできませんが、開発環境またはテスト環境ではこれらのロールを付与できます。組織により AWS からの連携が許可されるように、組織のポリシーを更新します。
AWS ロールを作成し、Amazon Resource Name(ARN)をメモします。
サービス アカウントにアクセス権を付与して、ワークロードに必要な Google Cloud APIs を呼び出します。
Workload Identity プールの作成
Workload Identity プールは、外部 ID のコレクション用のコンテナです。Workload Identity プールは相互に分離されていますが、1 つのプールは任意の数のサービス アカウントになり代わることができます。一般に、開発、ステージング、本番環境など、環境ごとに新しいプールを作成することをおすすめします。つまり、通常は AWS アカウントごとに 1 つのプールとなります。
新しい Workload Identity プールを作成するには、ID を指定する必要があります。オプションの説明と表示名を指定することもできます。
gcloud
gcloud beta iam workload-identity-pools create
コマンドを実行して Workload Identity プールを作成します。
gcloud beta 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/v1beta/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 トークンの属性を 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_account
がassertion.account
にマッピングされています。google.subject=assertion.arn, attribute.aws_account=assertion.account
参照できる AWS トークンの属性のリストについては、
GetCallerIdentity()
のドキュメントをご覧ください。AWS のドキュメントでは、属性にキャメルケースが使用されるのに対して、属性のマッピングには小文字が使用されます。たとえば、Account
はassertion.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"
条件の一般的なユースケースの詳細については、Workload Identity 連携の概要をご覧ください。
次の例では、AWS を ID プロバイダとして追加する方法を説明します。
gcloud
gcloud beta iam workload-identity-pools providers create-aws
コマンドを実行して AWS を ID プロバイダとして追加します。
gcloud beta 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/v1beta/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-binding
を remove-iam-policy-binding
に置き換えます。
REST API またはクライアント ライブラリを使用して、バインディングの追加または削除を行うこともできます。詳細については、リソースへのアクセス権の付与、変更、取り消しをご覧ください。
GetCallerIdentity トークンを Google トークンと交換する
AWS のロールまたはユーザーがサービス アカウントになり代わることができる状態になると、AWS 認証情報を Google 認証情報と交換できます。
交換プロセスの一環として、GetCallerIdentity
トークンをセキュリティ トークン サービスに渡します。GetCallerIdentity
トークンには、通常は AWS GetCallerIdentity()
メソッドへのリクエストに含める情報と、通常はリクエスト用に生成する署名が含まれます。Google Cloud は、GetCallerIdentity
トークンを使用して AWS プリンシパルの ID を検証し、そのプリンシパルがサービス アカウントに成り代わる権限があることを確認します。
認証情報を交換するには:
GetCallerIdentity
トークンを作成します。このトークンには、AWSGetCallerIdentity()
メソッドへのリクエスト用の情報と、リクエスト情報用の AWS の署名が含まれています。バージョン 4 の署名を使用します。リクエストには次のフィールドが含まれます。
url
:GetCallerIdentity()
の AWS STS エンドポイントの URL(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=" } ] }
連携アクセス トークンの 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/v1beta/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" }
リクエストを送信するには、次のいずれかのオプションを展開します。
このメソッドは連携トークンを返します。
連携トークンをサービス アカウントのアクセス トークンと交換するには、
generateAccessToken()
メソッドを呼び出します。連携トークンは一部の Google Cloud APIs でサポートされています。対して、すべての Google Cloud APIs はサービス アカウントのアクセス トークンをサポートしています。REST
Service Account Credentials API の
serviceAccounts.generateAccessToken
メソッドによって、サービス アカウントの OAuth 2.0 アクセス トークンが生成されます。後述のリクエストのデータを使用する前に、次のように置き換えます。
project-id
: Google Cloud プロジェクト ID。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
リクエストはサービス アカウントとして承認されます。
次のステップ
- ID 連携を使用して、Microsoft Azure からリソースにアクセスするか、OIDC プロバイダからリソースにアクセスする。
- ワークロード ID 連携について詳細を確認する。