ドメインで制限された共有の適用時にパブリック Cloud Run サービスを作成する方法
Google Cloud Japan Team
※この投稿は米国時間 2022 年 9 月 27 日に、Google Cloud blog に投稿されたものの抄訳です。
この投稿では、お客様の組織がドメインで制限された共有を有効にしている場合でも、Cloud Run サービスで未認証リクエストを許可し、allUsers ID を使用する方法を説明します。セキュリティを重視する多くの大規模なお客様がこの方法を実践しています。
ドメインで制限された共有は、Google Cloud プロジェクトの権限を外部ユーザーに意図せず付与しないようにするためのセキュリティ機能です。たとえば、外部の @gmail.com アカウントに VM インスタンスの作成(または削除)の権限を付与する必要はないでしょう。ドメインで制限された共有により、信頼できるドメインからのユーザーのみに権限を付与できるようになっています。
デフォルトでは、ドメインで制限された共有も有効にしている場合、Cloud Run サービスに対する未認証リクエストは許可できません。許可しようとすると、「IAM ポリシーの更新に失敗しました」というエラーが発生します。このエラーを解決する方法は複数あります。この投稿では、インフラストラクチャ管理を専門とするプラットフォーム チームを持つ大規模な企業にも有効なソリューションをご紹介します。
Cloud Run アクセス管理の 2 つのレイヤについて
このエラーに対するソリューションを掘り下げる前に、そもそもなぜこのエラーが発生するのか、Cloud Run のアクセス制御を理解することから始めましょう。Cloud Run のアクセス制御には、上り(内向き)設定と Identity and Access Management(IAM)ポリシーの 2 つのレイヤがあります。
上り(内向き)設定
上り(内向き)設定により、送信元ネットワークに基づいてリクエストをフィルタリングできます。一例としては、Google Cloud プロジェクトに対する内部ソースからのリクエストのみを許可することが挙げられます。また、Google Cloud ロードバランサを経由するリクエストや内部ソースからのリクエスト、あるいはインターネットを含むあらゆる場所からのリクエストも許可して、Cloud Run HTTPS エンドポイントに到達させることもできます。
IAM ポリシー
IAM ポリシーを使用すると、送信者の ID に基づいてリクエストをフィルタリングできます。一般的に、IAM ポリシーはユーザーまたはサービス アカウントなどの ID にロールをバインディングし、ロールは設定された権限を保持します。ID は、その Cloud Run サービスに対する run.invoker ロールがある場合、Cloud Run HTTPS エンドポイントにしか到達できません。すべての(未認証)リクエストを許可するには、allUsers にサービスに対する run.invoker ロールを付与する IAM ポリシーを作成します。
ドメインで制限された共有(DRS)について
多くの組織がドメインで制限された共有(DRS)を使用して、ドメインに基づくリソース共有を制限することでクラウド環境のセキュリティを維持しています。より具体的に説明すると、DRS とは組織が IAM ポリシーで使用できる ID のセットを制限できるようにする組織のポリシーのことです。
Google Workspace ドメインの example.org を持つ組織が DRS を有効にすると、alice@example.org は Google Cloud プロジェクトの一つでプロジェクト編集者ロールを持つことができますが、他の Google Workspace ドメイン(bob@mystore.org や @gmail.com アカウントを含む)ではそれができません。
また、DRS ポリシーも allUsers ID に影響を与えます。DRS ポリシーが有効化されると、allUsers ID はどの IAM ポリシーにも使用できません。これは Cloud Run IAM ポリシーでも同様で、run.invoker ロールを付与すると、「IAM ポリシーの更新に失敗しました」というエラーが発生します。
多くのサービスで未認証リクエストを受け入れる必要がある
DRS ポリシーを有効にすることはベスト プラクティスであり、外部ユーザーに不要な権限を付与することを回避できます。しかし、DRS ポリシーは次のような例を含め、allUsers ID を必要とするいくつかの有効なシナリオもブロックしてしまいます。
Cloud Run でホストされる店舗検索サイトなどの公開ウェブサイト。
認証と認可がサービスによって処理されるパブリック Cloud Run サービス。
内部の上り(内向き)のみを介して公開され、内部ソースからのリクエストのみを受け取るべき内部の Cloud Run サービス。
先に説明したように、Cloud Run のアクセス制御のレイヤに従って、DRS は IAM レイヤのみに影響し、上り(内向き)設定はそれとは独立したものとなっています。
DRS が適用されているときに未認証リクエストを許可する方法
DRS ポリシーが設定されているときに引き続き allUsers が特定の Cloud Run サービスを呼び出せるようにするために、プラットフォーム管理者は DRS ポリシーを無効にし、allUsers を含む IAM ポリシーを設定し、最後に DRS ポリシーを再び有効にできます。(その方法を確認するにはこちらのドキュメントを参照してください)。この手順が有効なのは、組織のポリシーが過去に溯って評価および適用されることがないからです。ポリシーは、有効になっている場合にのみ更新をブロックします。変更のたびに手動で DRS をオフにしたりオンにしたりすると、大規模な組織はスケーリングできず、デプロイ中にセキュリティのメカニズムが無効になります。
より明示的な代替方法としては、条件付きの組織のポリシーを Resource Manager タグと併用できます。そうすることで、リソースに特定のタグが添付されている場合でも、条件付きポリシーはリソースに影響しません。この方法で、プラットフォーム管理者は特定の Cloud Run サービスを DRS から除外するタグを付けることができます。起動元のロールは、引き続き組織全体の DRS 設定の制約を受けながらも、それらの特定のサービスに対して allUsers に割り当てることができます。
インターネットから Cloud Run サービスへの公開アクセスを許可するという考えに抵抗がある場合は、さらに制限を加えることもできます。たとえば、上り(内向き)設定が内部リクエストのみを受け入れるように設定されている場合、未認証リクエストのみを許可できます。その方法については、この記事の後半で説明します。
実際の例
IAM ポリシーの更新に失敗するというエラーに直面しつつ、それを解決したお客様一社をご紹介します。その組織(ここでは example.org と呼びます)には、プラットフォーム チームとプロジェクト チームがあります。両チームのタスクは以下のとおりです。
プラットフォーム チーム
プラットフォーム チームは、Google Cloud 組織とセットアップ全体を管理しています。プラットフォーム全体のセキュリティの責任を担い、Google Cloud の組織レベルでドメイン制限共有ポリシーを有効にして、Google Workspace ドメイン(example.org)の ID のみに権限を付与しています。
プロジェクト チーム
プロジェクト チームは、オープンではあるものの Cloud Run でホストされている内部ウェブサイトで作業をします。そのようなサービスでは、上り(内向き)設定を内部に設定し、allUser を使用した IAM ポリシーに対してすべての受信と内部トラフィックを許可する必要があります。チームはドメイン制限の共有ポリシーによって allUsers の使用が禁止されており、「IAM ポリシーの更新に失敗しました」というエラーが表示されます。
Resource Manager タグと条件付き DRS ポリシーを使用する
プロジェクト チームが Cloud Run サービスで allUsers に対して run.invoker ロールを付与する IAM ポリシーを作成できるようにするためには、以下に示すように、リソースタグに基づいた条件付き DRS ポリシーをセットアップします。まず、プラットフォーム チームは、Google Cloud の組織レベルで以下のコマンドを使用してタグキーとタグ値を作成します。タグキーとして allUsersIngress
を使用し、タグ値として True を使用します。必要な組織リソース ID(ORGANIZATION_ID
)は、組織リソースの一意の識別子です。
$ gcloud resource-manager tags keys create allUsersIngress \
--parent=organizations/ORGANIZATION_ID
Waiting for TagKey [allUsersIngress] to be created...done.
name: tagKeys/TAG_ID
namespacedName: ORGANIZATION_ID/allUsersIngress
parent: organizations/ORGANIZATION_ID
shortName: allUsersIngress
$ gcloud resource-manager tags values create True \
--parent=ORGANIZATION_ID/allUsersIngress \
--description="Allow for allUsers for internal Cloud Run services"
Waiting for TagValue [True] to be created...done.
name: tagValues/TAGVALUE_ID
namespacedName: ORGANIZATION_ID/allUsersIngress/True
parent: tagKeys/TAG_ID
shortName: 'True'
プラットフォーム チームは組織全体の DRS ポリシーとその例外を管理する責任を担っており、このタグ値を管理して、任意のリソースに添付できるのはこのチームのみです。Google Cloud コンソールは、タグとその値へのアクセスを管理するのに使用できるため、プロジェクト チームのメンバーは自分でタグを適用することができず、プラットフォーム チームにタグをリクエストする必要があります。
プラットフォーム チームは、allUsersIngress タグの値が「True」に一致しないリソースにのみ適用される条件付き DRS ポリシーを作成します。このコマンドは、独自のドメインから ID を許可するため、Google Workspace お客様 ID(DIRECTORY_CUSTOMER_ID
とも呼ばれます)が必要です。必要な場合は、複数の Google Workspace お客様 ID を使用できます。
条件付き DRS ポリシーを設定するには、まず次のコンテンツを使用した drs-policy.yaml という名前のポリシー ファイルを作成します。
次に以下の gcloud コマンドを実行してポリシーを設定し、drs-policy.yaml
を参照します。
$ gcloud org-policies set-policy drs-policy.yaml
プラットフォーム チームは、ORGANIZATION_ID/allUsersIngress
というタグと True
の値を、次の gcloud コマンドを使用して特定の Cloud Run サービスに添付できます。
$ gcloud resource-manager tags bindings create \
--tag-value=ORGANIZATION_ID/allUsersIngress/True \
--parent=//run.googleapis.com/projects/PROJECT_ID/locations/REGION/services/SERVICE \
--location=REGION
条件付きの組織のポリシーが作成された時点で、プロジェクト チームはタグ付けされた Cloud Run サービスの allUsers ID に run.invoker 権限を付与できるようになります。
さらに多くの制約のための条件付き Cloud Run 上り(内向き)ポリシーの使用
お客様のプラットフォーム チームは、Cloud Run サービスが一般公開されることが絶対にないようにしたいと考えていました。公開サービスでは上り(内向き)が all に設定され、IAM ポリシーが allUser に設定されていました。これを別の条件付きの組織のポリシーを追加することで解決しました。DRS と同様に、Cloud Run の上り(内向き)設定にも組織のポリシーがあります。
run.allowedIngress 組織ポリシーは、Cloud Run サービスに対して許可される上り(内向き)設定を定義します。この制約が適用されると、許可された値のいずれかに一致する上り(内向き)設定がサービスで必要になります。組織のポリシーの run.allowedIngress を同じタグの条件とすることで、上り(内向き)設定を内部のみにとどめる制限と allUser での IAM ポリシーの許可を同時に実行できます。
プロジェクト チームに特定のタグ付き Cloud Run サービスの設定を強制し、内部の上り(内向き)設定にとどめるには、allowedIngress-policy.yaml
という名前のポリシー ファイルを次のコンテンツを使用して作成します。
次に以下の gcloud コマンドを実行してポリシーを設定し、allowedIngress-policy.yaml を参照します。
$ gcloud org-policies set-policy allowedIngress-policy.yaml
組織のポリシーは、新しい構成の更新に対してのみ、その制約の評価と適用を行います。既存のリソース構成の評価と適用は行いません。この遡及的動作のため、タグを添付する前に正しい内部の上り(内向き)が設定されている必要があります。そうでない場合、プロジェクト チームが変更できるのは IAM run.invoker 権限のみとなり、上り(内向き)は引き続き all または internal-and-cloud-load-balancing に設定されたままとなり、内部の上り(内向き)の前提条件を遵守しません。
条件付きの組織のポリシーが作成された時点で、プロジェクト チームはこの Cloud Run サービスの allUsers ID に run.invoker 権限を付与できるようになります。また、プロジェクト チームは上り(内向き)設定を all または internal-and-cloud-load-balancing に戻すことはできません。
まとめ
この記事では、組織がドメインで制限された共有を有効にしている場合でも、Cloud Run サービスの allUsers ID に run.invoker ロールを付与する方法について説明しました。allUsers を使用できる Cloud Run サービスをタグ付けするために、条件付き DRS ポリシーと Resource Manager タグを併用しました。また、同じタグを持つ Cloud Run サービスの内部以外の上り(内向き)を設定できないようにする 2 つ目の組織ポリシーを追加する方法をご紹介しました。
条件付きポリシーはフォルダやプロジェクト レベルでも設定でき、ポリシーの階層的な評価を尊重します。これにより、このソリューションをより複雑な組織やフォルダ構造にも拡張できます。
関心をお持ちの方は、以下のリソースをご活用ください。