Google Cloud Platform

Cloud Identity-Aware Proxy におけるアクセス制御の仕組み

Google Cloud Next '17 において、私たち Google は Cloud Identity-Aware Proxy(Cloud IAP)のベータ版を発表しました。Cloud IAP を使用すると、Google Cloud Platform(GCP)上のウェブ アプリケーションへのアクセスを制御できます。

Cloud IAP に関する前回の投稿では、Cloud IAP の概要と、Cloud IAP によるアクセス制御が、従来の LAN や VPN などにおける境界ベースのアクセス制御よりも簡単で安全なことを説明しました。今回はさらに踏み込んで、Cloud IAP の仕組みと、その開発過程で私たちが行った技術上の決定について解説します。

Cloud IAP の仕組み

リクエストが App EngineCloud Load Balancing HTTP(S) に送信されると、これらのプロダクトを支えるインフラストラクチャの内部コードが、App Engine アプリまたは Google Compute Engine バックエンド サービスで Cloud IAP が有効になっているかどうかをチェックします。有効になっていたら、インフラストラクチャは Cloud IAP の認証サーバーに対して、リクエスト ヘッダまたはクッキーに含まれる、保護対象リソースに関する情報(GCP プロジェクト番号、リクエスト URL、Cloud IAP の資格情報など)の確認を求めます。

有効な資格情報がリクエストに含まれていたら、認証サーバーはそれらの資格情報を使用して、ユーザーの ID(電子メール アドレスとユーザー ID)を取得します。そして、その ID 情報を基に Cloud Identity & Access Management(Cloud IAM)への問い合わせを行い、ユーザーがリソースへのアクセスを許可されているかどうかをチェックします。

OpenID Connect による認証

Cloud IAP が使用する資格情報は OpenID Connect(OIDC)トークンです。このトークンは、クッキー(GCP_IAAP_AUTH_TOKEN 1)か Authorization: bearer ヘッダに含まれます。

OIDC トークンの取得に必要なフローを開始するには、Cloud IAP は OAuth2 クライアント ID およびシークレットを必要とします。Cloud Console で Cloud IAP を有効にすると、GCP 側でプロジェクト内に OAuth2 クライアントを作成します。さらに、これを使用するよう Cloud IAP を構成します。GCP API や Cloud SDK を使って Cloud IAP を有効にする場合は、OAuth2 クライアントを手動で構成する必要があります。

Cloud IAP で保護されたアプリケーションとのやり取りをウェブ ブラウザで行うユーザーは、資格情報を含むクッキーを受け取ります。Cloud IAP 認証サーバーは、資格情報が含まれていないリクエストや無効な資格情報を含むリクエストを検出すると、そのユーザーを Google の OIDC フローにリダイレクトします。ユーザーは OIDC フローを使って、どのアプリケーションに自分の ID を見せるかを管理できます。認証サーバーは OAuth リダイレクトを処理し、OIDC フローを完了させます。

認証サーバーはユーザーを OAuth フローにリダイレクトする際、クロスサイト リクエスト フォージェリ(CSRF)攻撃を防ぐためにランダム ノンス(使い捨て乱数)も生成します。認証サーバーはそのノンスを GCP_IAAP_XSRF_NONCE クッキーに保存するとともに、認証サーバーの秘密鍵で署名して OAuth フローの state パラメータにも保存します(ユーザーがリクエストしたオリジナル URL も署名して保存されます)。認証サーバーは OAuth リダイレクトを処理する際、state パラメータの署名を確認し、そのノンス値がクッキーに含まれるものと一致するかどうかチェックします。

ロボット パレード

スクリプトやプログラムからのアクセスをサポートするために、認証サーバーは Authorization ヘッダの OIDC トークンも検索します。OAuth2 トークンを付与された OIDC トークンや、サービス アカウントの秘密鍵を取得するプロセスは、少々複雑です。

Cloud IAP のドキュメントには、サービス アカウントやモバイル アプリからの認証を行うサンプル コードが記載されています。Cloud IAP の舞台裏で何が行われるのかを知りたい方や、独自の認証を行いたい方のために、サンプル コードで自動化されるステップを以下に示します。

  1. 以下のクレームを含む JWT(JSON Web Token)を作成します。
  2. aud: https://www.googleapis.com/oauth2/v4/token
  3. exp: 将来のいずれかの時点
  4. iat: 現在の時刻
  5. iss: サービス アカウントの電子メール アドレス
  6. target_audience: ベース URL(プロトコル、ドメイン、オプション ポート。パスなし)または Cloud IAP で保護されたアプリケーションの OAuth2 クライアント ID(これは OIDC トークンの aud クレームを管理します。Cloud IAP はこのクレームを検証し、あるアプリケーションで使用されるよう意図されたトークンが別のアプリケーションで使用されるのを防ぎます)。
  7. サービス アカウントの秘密鍵を持っている場合、それを使って JWT に署名します。アクセス トークンしか持っていない場合は、App Engine standard environment の App Identity APICloud IAM の signBlob API を使って署名します。
  8. サーバー間のやり取りを行うアプリケーション向けに、OAuth 2.0 を使用して JWT を aud クレームの URL に POST します。

Cloud IAM による認可

Cloud Console に表示される Cloud IAP のアクセス リストは、プロジェクトの Cloud IAM ポリシーの一部にすぎません。このアクセス リストは Cloud IAM の標準機能で操作可能です。そうした機能には、IAM API や、Cloud IAM 階層のフォルダや組織レベルでの Cloud IAP の役割付与が含まれます。

Cloud IAP へのアクセスを付与する役割は roles/iap.httpsResourceAccessor です。Cloud IAM の他の多くの役割とは異なり、オーナーや編集者のような幅広い役割は、いずれもこの役割に関連する許可を付与しません。

これは、「セキュリティ管理者はアクセス ポリシーの構成に責任を持つが、アプリケーションを使用することは想定されていない」というシナリオをお膳立てすることが目的です(もちろん、セキュリティ管理者は常に自身にアクセスを付与できますが、そのためにはわざわざそうしなければなりません。アプリケーション オーナーが自動的にアクセスを付与されると、アプリケーションにうっかりアクセスしてしまうかもしれません)。

ID の伝達

Cloud IAP で保護される多くのアプリケーションは、追加的なアクセス制御や、ユーザーによる設定を行えるようにするために、ユーザーの ID を知ろうとします。Cloud IAP は、そのための方法をいくつか用意しています。なかでも、以下の 2 つはとてもシンプルです。

  1. Google App Engine standard environment を使用するアプリケーション向けに、Cloud IAP は App Engine Users API をサポートしています。Users API を使用する既存コードは通常、何も変更を加えなくても Cloud IAP による保護の対象となります。また、Cloud IAP も Users API と同じユーザー ID を使用します。
  2. Cloud IAP は 2 つの HTTP ヘッダでユーザーの電子メール アドレスと ID を送信します。

3 つ目の方法は、アプリケーションのセキュリティを最大化するためにいくつかの追加ステップが必要です。Users API を使うことができず、そのために 2 つ目の方法を取る必要があるアプリケーションでは、認証されていない HTTP ヘッダに依存することがセキュリティ リスクとなるからです 2

Cloud IAP をうっかり無効にすると、誰でもアプリケーションに接続し、HTTP ヘッダを任意の値に設定してしまうおそれがあります。アプリケーションが Compute Engine や Container Engine で動作する場合は、アプリケーションが動作する VM に直接接続できる人なら誰でも Cloud IAP をバイパスして、HTTP ヘッダを好きなように設定できてしまう可能性があるのです。

前述したように、Cloud IAP のアクセス制御は HTTP(S) ロード バランサの内部で実行されます。そのため、誰かがロード バランサを回避できるとなったら、Cloud IAP も回避できてしまいます。ファイアウォール ルールを誤って構成した場合や、攻撃者がアプリケーション インスタンスやネットワーク上の別のインスタンスに SSH できた場合、こうした事態が起こるおそれがあります。

そこで Cloud IAP は、3 つ目の HTTP ヘッダを提供します。このヘッダには、Cloud IAP の秘密鍵で署名された JWT が含まれます。JWT は OIDC トークンによく似ていますが、Google アカウント サービスではなく、Cloud IAP で署名されています。私たちは、Cloud IAP がユーザー認証に使用した OIDC トークンにこだわらず、独自のトークンを作ることで、将来、ユーザーの Cloud IAP 認証の方法を自由に追加できるようになると考えたのです。

Cloud IAP の舞台裏の仕組みや、Cloud IAP のシンプルさの一端を理解するうえで、この投稿記事が役に立つことを願っています。また、こちらの IAP クイックスタートも参考にしてください。数分で Cloud IAP の使い方を学ぶことができます。

これからもセキュリティとアイデンティティに関するコンテンツを続々とお届けします。お楽しみに!

1 後述するように、もう 1 つの特別なクッキーも使います。
2 これに対し、Users API は安全です。Cloud IAP は、この API で使用される ID 情報を、保護された内部チャンネルを使って設定します。

* この投稿は米国時間 4 月 20 日、Technical Lead Manager である Matthew Sachs によって投稿されたもの(投稿はこちら)の抄訳です。

- By Matthew Sachs, Technical Lead Manager