Google Cloud Identity-Aware Proxy(Cloud IAP)でWebアプリに認証を追加する
ども、takiponeです。
先日サンフランシスコで開催されたGoogle Cloud Next '17ではGCP(Google Cloud Platform)の多くの新機能が発表されました。その中で個人的にツボだったのがCloud Identity-Aware Proxy(以下Cloud IAP)でした。既にベータ版として触ることができたので、その様子をレポートします。
Cloud Identity-Aware Proxy(IAP:ID認証プロキシ)とは
Cloud IAPは、Googleアカウントの認証機能を提供するリバースプロキシサービスです。OSSのgateのas a Service版という説明が近いと思います。Google認証に対応するIDaaSと比べてOpenID/OAuth2のフローを意識する必要がないため、既存のWebアプリケーションやWeb APIに手軽に組み込むことができます。
図ではプロキシ先がERP/CRMとなっていますが、以下のサービスをサポートします。
- Google App Engine(GAE)
- Google Compute Engine(GCE)
- Google Container Engine(GKE)
GCEおよびGKEでは、HTTPSロードバランサのオプションとして動作します。
検証環境
今回は以下の構成で試してみました。
- リージョン : us-west1-b
- GCE : f1-micro 1台
- SSL証明書 : Let's Encrypt
- Webアプリケーション : Blystad/http-server-header-dump
まずはVMインスタンスでWebアプリを起動、インスタンスグループとHTTPSロードバランサを作成、DNSをロードバランサに向けておいて、Webブラウザでアクセスします。
リクエストヘッダをダンプした、シンプルなレスポンスが表示されます。
Cloud IAPのセットアップ
それでは、HTTPロードバランサでCloud IAPオプションを有効にします。GCP Webコンソール画面では、[IAMと管理] - [ID認証プロキシ]を選択します。
中央のペインにある「ID認証プロキシ」にCloud IAPの対象リソースがリストされます。ロードバランサ単位ではなくバックエンドサービス単位なのがポイントで、画像など公開データをホストするバックエンドサービスはOFF、HTMLやJSONなど制限したいデータをホストするバックエンドサービスでONにするといった使い分けができそうです。
ロードバランサの既定の設定では、スクリーンショットにあるように[設定]列がバリデーションでエラー(赤丸のエクスクラメーションマーク)になりました。[ファイヤーウォール]のリンクをクリックすると、以下のダイアログが表示されます。
どうやらロードバランサを経由せずにVMインスタンスの80番ポートに直接アクセスできる状態がダメなようで、以下のようにdefault-allow-http
ルールのソースIP範囲をロードバランサのIPに絞ることで解消できました(VMインスタンスのタグを変更し他のファイヤーウォールルールが適用されるように変更しましたが、エラーは解消されませんでした。ちょっとバグっぽい動きかな)。
気を取り直して、リソースの[IAP]のスイッチをONにします。
ドメイン名入力のダイアログが表示されるので、HTTPSロードバランサに向いているドメイン名を入力し、[有効にする]をクリックします。
続いて、アクセスを許可するGoogleアカウントを指定します。画面右側の[Access]ペインの「追加」をクリックします。
メンバーの追加ダイアログが開きます。どんな指定ができるかは[?]マークにマウスオーバーすると以下のように表示されます。
今回はGmailのメールアドレスを入力し、[追加]で登録しました。
動作確認
再度Webブラウザでアクセスしてみると...
先ほどのレスポンス表示ではなく、見慣れたGoogleアカウントの認証画面にリダイレクトしました。先ほど指定したメールアドレス、パスワードを順に入力し、認証が完了すると...
先ほどと同じ、リクエストヘッダを含む、レスポンスが表示されました。正しく認証機能が動作しました。認証なしのときに加えてHTTPロードバランサが以下のヘッダを追加しています。
X-Goog-Authenticated-User-Email
: 認証したメールアドレスX-Goog-Authenticated-User-ID
: 認証したGoogleアカウントIDX-Goog-Authenticated-User-JWT
: JWT署名付きトークン
これらはバックエンドのWebアプリで活用できそうですね。Basic認証の代替として、X-Goog-Authenticated-User-Email
をWebサーバーのカスタムログに書き込むとか良さそうです。
JWT署名付きトークンの検証
Cloud IAPが付与するJWT署名付きトークンを検証してみました。この辺りはドキュメントに解説があります。
まずは、https://jwt.io/ のデバッガにトークンを貼り付けて紐解いてみます。
ペイロードに先ほどのメールアドレスのほか、タイムスタンプなどが含まれているのが分かります。正当性を検証するために、公開鍵を入手します。Googleが公開する鍵は、以下のURLでJSON形式の3種類があります。
$ curl https://www.gstatic.com/iap/verify/public_key
{
"1aDm7w" : "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE4rtreuHTI2mgFh63My3FgpR4w5tA\nKlLSqdu5UlMKSMhX7OXyqUOKlhdCJmCGcvJyCeC9c+HooIJClaUiJmYi8A==\n-----END PUBLIC KEY-----\n",
"Ci2qZQ" : "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE+nR06xvnL4hanbFlNYKXrmfWJ1oX\nuGkgBorc3neV769qFdRWQJphHH4u8nYiNmYTcfAq+YCuBTf+3H37ZxXCeQ==\n-----END PUBLIC KEY-----\n",
"N2_6BA" : "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEuGY5UNVDiwDt5Z7IPwvPM2Oi2J25\noFvgqEJngZk57YFLpWz8+2sNRnagAjw40x3kuzKu9I60xEj1Ba/XLJYcFA==\n-----END PUBLIC KEY-----\n"
}
$
どの鍵が対応するかは、ヘッダのkid
で指定されます。今回はN2_6BA
だったので、以下のコマンドラインで公開鍵を取得します。
$ curl -s https://www.gstatic.com/iap/verify/public_key | jq -r '.["N2_6BA"]'
-----BEGIN PUBLIC KEY-----
MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEuGY5UNVDiwDt5Z7IPwvPM2Oi2J25
oFvgqEJngZk57YFLpWz8+2sNRnagAjw40x3kuzKu9I60xEj1Ba/XLJYcFA==
-----END PUBLIC KEY-----
$
これをデバッガに貼り付けると...
検証が通りました!バックエンドのWebアプリケーションで署名付きトークンを検証することで、Cloud IAPが付与した認証情報の正当性が確認できます。
まとめ
Googleの認証機能を追加できるCloud IAPの様子をご紹介しました。既存のWebアプリケーションに認証機能を追加する、良いサービスだと思います。
AWSにもCognite User Poolと連動する認証プロキシサービスが欲しいところです(^^