アーキテクチャで複数のサービスを使用している場合、これらのサービスは同期または非同期で相互に通信する必要があります。これらのサービスの多くは非公開で、アクセスには認証情報が必要です。
非同期通信では、次の Google Cloud サービスを使用できます。
- Cloud Tasks(1 対 1 の非同期通信を行う場合)。
- Pub/Sub(1 対多、1 対 1、多対 1 の非同期通信を行う場合)
- Cloud Scheduler(定期的にスケジュール設定された非同期通信を行う場合)
- Eventarc(イベントベースの通信を行う場合)
いずれの場合も、使用中のサービスが、設定した構成に基づいて受信側のサービスとの通信を管理します。
ただし、同期通信の場合は、サービスがエンドポイント URL を使用して HTTP 経由で別のサービスを直接呼び出します。このユースケースでは、各サービスが特定のサービスに対してのみリクエストを送信できるようにします。たとえば、login
サービスの場合、user-profiles
サービスにはアクセスできますが、search
サービスにはアクセスできません。
この場合は、IAM と、その作業に必要な権限の最小セットが付与されたサービスごとのユーザー管理サービス アカウントに基づいてサービス ID を使用することをおすすめします。
さらに、リクエストで呼び出し側サービス ID の証明を提示する必要があります。これを行うには、Google 署名付き OpenID Connect ID トークンをリクエストの一部として追加するように呼び出し側サービスを構成します。
サービス アカウントを設定する
サービス アカウントを設定するには、呼び出し元のサービス アカウントを受信側サービスのプリンシパルにすることで、呼び出し側サービスからのリクエストを受け入れるように受信側サービスを構成します。そのサービス アカウントに Cloud Run 起動元(roles/run.invoker
)のロールを付与します。該当するタブの手順に沿って、これらの作業を行います。
コンソール UI
Google Cloud コンソールに移動します。
受信側のサービスを選択します。
右上隅にある [情報パネルを表示] をクリックして、[権限] タブを表示します。
[プリンシパルを追加] をクリックします。
呼び出し側のサービスの ID を入力します。これは通常、デフォルトでメールアドレス
PROJECT_NUMBER-compute@developer.gserviceaccount.com
です。[ロールの選択] プルダウン メニューから、
Cloud Run Invoker
ロールを選択します。[保存] をクリックします。
gcloud
gcloud run services add-iam-policy-binding
コマンドを使用します。
gcloud run services add-iam-policy-binding RECEIVING_SERVICE \ --member='serviceAccount:CALLING_SERVICE_IDENTITY' \ --role='roles/run.invoker'
ここでは、RECEIVING_SERVICE
は受信側サービスの名前で、CALLING_SERVICE_IDENTITY
はサービス アカウントのメールアドレス(デフォルトでは PROJECT_NUMBER-compute@developer.gserviceaccount.com
)です。
Terraform
Terraform 構成を適用または削除する方法については、基本的な Terraform コマンドをご覧ください。
次の Terraform コードは、一般公開となる最初の Cloud Run サービスを作成します。
us-docker.pkg.dev/cloudrun/container/hello
は、コンテナ イメージへの参照に置き換えます。
次の Terraform コードを使用すると、最初のサービスが公開されます。
次の Terraform コードは、非公開となる 2 つ目の Cloud Run サービスを作成します。
us-docker.pkg.dev/cloudrun/container/hello
は、コンテナ イメージへの参照に置き換えます。
次の Terraform コードを使用すると、2 番目のサービスが非公開になります。
次の Terraform コードは、サービス アカウントを作成します。
次の Terraform コードを使用すると、サービス アカウントに関連付けられたサービスが、最初の非公開 Cloud Run サービスを呼び出すことができます。
ID トークンの取得と構成
呼び出し元のサービス アカウントに適切なロールを付与したら、次の操作を行います。
次のセクションで説明するいずれかの方法で、Google によって署名された ID トークンを取得します。オーディエンス クレーム(
aud
)を、受信側のサービスまたは構成されたカスタム オーディエンスの URL に設定します。カスタム オーディエンスを使用しない場合は、特定のトラフィック タグにリクエストを送信する場合でも、aud
値をサービスの URL として残す必要があります。前のステップで取得した ID トークンを、受信側のサービスに対するリクエストの次のいずれかのヘッダーに追加します。
Authorization: Bearer ID_TOKEN
ヘッダー。X-Serverless-Authorization: Bearer ID_TOKEN
ヘッダー。アプリケーションがすでにカスタム承認にAuthorization
ヘッダーを使用している場合は、このヘッダーを使用できます。これにより、トークンがユーザー コンテナに渡される前に署名が削除されます。
このページで説明されていない ID トークンを取得するその他の方法については、ID トークンの取得方法をご覧ください。
認証ライブラリを使用する
ID トークン プロセスを取得して構成する最も簡単かつ信頼性の高い方法は、認証ライブラリを使用することです。このコードは、ライブラリによってサービス アカウントの認証情報が取得される Google Cloud 外のあらゆる環境で機能します(ローカル アプリケーションのデフォルト認証情報をサポートする環境を含む)。アプリケーションのデフォルト認証情報を設定するには、サービス アカウント キー ファイルをダウンロードし、環境変数 GOOGLE_APPLICATION_CREDENTIALS
をサービス アカウント キー ファイルのパスに設定します。詳細については、アプリケーションのデフォルト認証情報の仕組みをご覧ください。
このコードは、ユーザー アカウントの認証情報を取得できません。
Node.js
Python
Go
Java
メタデータ サーバーを使用する
なんらかの理由で認証ライブラリを使用できない場合は、コンテナが Cloud Run で実行されている間、コンピューティング メタデータ サーバーから ID トークンを取得できます。この方法は、ローカルマシンからなど、Google Cloud の外部では機能しないことに注意してください。
curl "http://metadata.google.internal/computeMetadata/v1/instance/service-accounts/default/identity?audience=[AUDIENCE]" \
-H "Metadata-Flavor: Google"
「オーディエンス」は、起動しているサービスの URL または構成済みのカスタム オーディエンスです。
次の表に、メタデータ クエリ リクエストの主要部分を示します。
コンポーネント | 説明 |
---|---|
ルート URL | すべてのメタデータ値は、次のルート URL のサブパスとして定義されます。 http://metadata.google.internal/computeMetadata/v1 |
リクエスト ヘッダー | 次のヘッダーは各リクエストに含める必要があります。 Metadata-Flavor: Google このヘッダーにより、そのリクエストがメタデータ値を取得する目的で送信されたものであり、安全でないソースから意図せず送信されたものではないことが示されるため、リクエストしたデータがメタデータ サーバーから返されるようになります。このヘッダーが含まれていないリクエストはメタデータ サーバーで拒否されます。 |
このサービス間の認証方式を使用するアプリケーションのエンドツーエンドのチュートリアルは、安全な Cloud Run サービスのチュートリアルをご覧ください。
Google Cloud の外部から Workload Identity 連携を使用する
Workload Identity 連携でサポートされている ID プロバイダを環境で使用している場合は、次の方法で Google Cloud の外部から Cloud Run サービスへの認証を安全に行うことができます。
このページのサービス アカウントの設定の説明に従ってサービス アカウントを設定します。
Workload Identity 連携の構成の説明に従って ID プロバイダの Workload Identity 連携を構成します。
外部 ID にサービス アカウントの権限借用を許可するの手順を行います。
REST API を使用して有効期間の短いトークンを取得します。ただし、
generateAccessToken
を呼び出してアクセス トークンを取得する代わりに、generateIdToken
を呼び出して ID トークンを取得します。cURL の使用例を次に示します。
ID_TOKEN=$(curl -0 -X POST https://iamcredentials.googleapis.com/v1/projects/-/serviceAccounts/SERVICE_ACCOUNT:generateIdToken \ -H "Content-Type: text/json; charset=utf-8" \ -H "Authorization: Bearer $STS_TOKEN" \ -d @- <<EOF | jq -r .token { "audience": "SERVICE_URL" } EOF ) echo $ID_TOKEN
ここで、
SERVICE_ACCOUNT
は Workload Identity プールがアクセスするように構成されているサービス アカウントのメールアドレスです。SERVICE_URL
は、呼び出す Cloud Run サービスの URL です。この値は、特定のトラフィック タグにリクエストを送信する場合でも、サービスの URL として残す必要があります。$STS_TOKEN
は、Workload Identity 連携の前の手順で受信したセキュリティ トークン サービス トークンです。
Authorization: Bearer ID_TOKEN
ヘッダーまたは X-Serverless-Authorization: Bearer ID_TOKEN
ヘッダーを使用して、サービスへのリクエストの前の手順で取得した ID トークンを含めることができます。両方のヘッダーを指定すると、X-Serverless-Authorization
ヘッダーのみがチェックされます。
Google Cloud の外部からダウンロードしたサービス アカウント キーを使用する
環境で Workload Identity 連携の使用が適切でない場合は、ダウンロードしたサービス アカウント キーを使用して、Google Cloud の外部から認証できます。上記のように、アプリケーションのデフォルト認証情報で認証ライブラリを使用するようにクライアント コードを更新します。
自己署名 JWT を使用して Google 署名付き ID トークンを取得できますが、作業はかなり複雑になり、エラーが発生しやすくなります。基本的な手順は次のとおりです。
target_audience
クレームを受信側サービスまたは構成済みカスタム オーディエンスの URL に設定して、サービス アカウント JWT に自己署名します。カスタム ドメインを使用しない場合、target_audience
値は、特定のトラフィック タグにリクエストを送信する場合でも、サービスの URL として残す必要があります。Google によって署名された ID トークンと自己署名された JWT を交換します。このトークンでは、
aud
クレームに前述の URL が設定されています。Authorization: Bearer ID_TOKEN
ヘッダーまたはX-Serverless-Authorization: Bearer ID_TOKEN
ヘッダーを使用して、サービスへのリクエストに ID トークンを含めます。両方のヘッダーを指定すると、X-Serverless-Authorization
ヘッダーのみがチェックされます。
上記の手順のサンプルについては、この Cloud Run functions の関数の例で確認できます。
認証済みリクエストを受信する
受信側のプライベート サービス内で、Authorization ヘッダーを解析して署名なしトークンによって送信される情報を受信できます。