この Codelab について
1. はじめに
ウェブアプリではユーザー認証が必要になることが多く、通常はアプリで特別にプログラミングする必要がありますが、Google Cloud Platform アプリでは、ユーザー認証を Identity-Aware Proxy サービスに任せることができます。選択したユーザーのみにアクセスを制限する場合は、アプリケーションを変更する必要はありません。アプリケーションがユーザー ID を認識する必要がある場合(ユーザー設定をサーバーサイドで保持する場合など)、Identity-Aware Proxy では最小限のアプリケーション コードを使用してそれを実現します。
Identity-Aware Proxy とは
Identity-Aware Proxy(IAP)は Google Cloud Platform のサービスです。アプリケーションに送信されたウェブ リクエストをインターセプトし、リクエストを送信したユーザーを Google の ID サービスを使用して認証し、認証されたユーザーからのリクエストのみを通過させます。さらに、リクエスト ヘッダーを変更して認証されたユーザーに関する情報を含めることができます。
この Codelab では、独自のアプリケーションを作成し、アプリケーションへのアクセスを制限して、IAP からユーザー ID を取得する手順について説明します。
作業内容
この Codelab では、Google App Engine を使用して最小限のウェブ アプリケーションを構築し、Identity-Aware Proxy を使用してアプリケーションへのアクセスを制限し、ユーザー ID 情報を提供するさまざまな方法を見ていきます。作成するアプリの機能は次のとおりです。
|
学習内容
- Python 3.7 を使用して簡単な App Engine アプリを作成してデプロイする
- アプリへのアクセスを制限する IAP を有効または無効にする
- ユーザー ID 情報を IAP からアプリに取り込む
- なりすましを防ぐために IAP からの情報を暗号的に検証する
必要なもの
- 最新のウェブブラウザ(Chrome など)
- Python プログラミング言語の基本的な知識
この Codelab では、Google App Engine と IAP を中心に説明します。関連のない概念やコードブロックについては詳しく触れず、コードはコピーして貼るだけの状態で提供されています。
2. 設定方法
Cloud Shell コマンドライン環境で作業します。まず、その環境を開いてサンプルコードを取得します。
コンソールと Cloud Shell を起動する
ラボページの左上にある [Google コンソールを開く] ボタンをクリックします。ボタンの下に表示されるユーザー名とパスワードを使用してログインする必要があります。 |
この Codelab のすべてのコマンドは、作成されて開いたプロジェクトの Cloud Shell 内で実行されます。コンソール ページのヘッダーの右側にある「Cloud Shell をアクティブにする」アイコンをクリックして Cloud Shell を開きます。ページの下半分では、コマンドを入力して実行できます。コマンドは自分の PC から実行することもできますが、まず必要な開発ソフトウェアをインストールして構成する必要があります。Cloud Shell には、必要なソフトウェア ツールがすべて揃っています。 |
コードをダウンロードする
コマンドを入力できるように Cloud Shell のコマンドラインの領域をクリックします。GitHub からコードを取得して、コードフォルダに移動します。
git clone https://github.com/googlecodelabs/user-authentication-with-iap.git
cd user-authentication-with-iap
このフォルダには、この Codelab のステップごとに 1 つのサブフォルダが含まれています。ステップごとに適切なフォルダに移動します。
3. ステップ 1 - アプリケーションをデプロイして IAP で保護する
これは Python 3.7 で記述された App Engine スタンダード アプリケーションで、単に「Hello, World」とだけ表示されます。ようこそ。デプロイしてテストした後、IAP を使用してアクセスを制限します。
アプリケーション コードを確認する
メインのプロジェクト フォルダから、このステップのコードが含まれている 1-HelloWorld
サブフォルダに変更します。
cd 1-HelloWorld
アプリケーション コードは main.py
ファイルにあります。Flask ウェブ フレームワークを使用し、テンプレートの内容を利用してウェブ リクエストに応答します。そのテンプレート ファイルは templates/index.html
にあり、このステップではプレーン HTML のみが含まれています。2 つ目のテンプレート ファイルには、templates/privacy.html
の簡単なプライバシー ポリシーのサンプルが含まれています。
他にファイルは 2 つあります。requirements.txt
はアプリケーションが使用するデフォルト以外の Python ライブラリをすべてリストし、app.yaml
は Python 3.7 App Engine アプリケーションであることを Google Cloud Platform に通知します。
次のような cat コマンドを使用してシェル内の各ファイルを一覧表示できます。
cat main.py
または、Cloud Shell ウィンドウの右上にある鉛筆アイコンをクリックして、Cloud Shell コードエディタを開き、その方法でコードを調べることもできます。
このステップでは、どのファイルも変更する必要はありません。
App Engine にデプロイする
Python 3.7 用の App Engine スタンダード環境にアプリをデプロイします。
gcloud app deploy
デプロイ先のリージョンの選択を求められる場合があります。近くで「support Standard」と表示されているデバイスを選択してください。続行を確認するメッセージが表示されたら、「Y
」(はい)と入力します。
数分後にデプロイが完了し、gcloud app browse
でアプリケーションを表示できるというメッセージが表示されます。次のコマンドを入力します。ブラウザで新しいタブが開かない場合は、表示されているリンクをクリックして新しいタブで開くか、必要に応じて手動で開いた新しいタブにコピーします。このアプリを実行するのは今回が初めてなので、クラウド インスタンスが起動するのに数秒かかり、それから以下のウィンドウが表示されます。
インターネットに接続されていれば、どのパソコンからも同じ URL でそのウェブページにアクセスできます。アクセスはまだ制限されていません。
IAP を使用してアクセスを制限する
Cloud コンソール ウィンドウで、ページの左上にあるメニュー アイコンをクリックし、[セキュリティ]、[Identity-Aware Proxy] の順にクリックします。 | |
このプロジェクトの認証オプションを有効にするのは今回が初めてであるため、IAP を使用するには OAuth 同意画面を構成する必要があるという内容のメッセージが表示されます。 | |
[同意画面を構成] ボタンをクリックします。同意画面を構成するための新しいタブが開きます。 |
下記の必須項目に適切な値を入力してください。
アプリケーション名 | IAP の例 |
サポートメール | 。すでに入力されている場合があります。 |
承認済みドメイン | アプリケーションの URL のホスト名部分(例:iap-example-999999.appspot.comこれは、先ほど開いた Hello World ウェブページのアドレスバーで確認できます。URL の先頭の |
[アプリケーション ホームページ] リンク | アプリの表示に使用された URL |
[アプリケーション プライバシー ポリシー] リンク | アプリ内のプライバシー ページへのリンク。ホームページのリンクの末尾に /privacy を追加したもの |
[保存] をクリックします。認証情報の作成を求めるメッセージが表示されます。この Codelab の認証情報を作成する必要はないので、このブラウザタブを閉じます。
[Identity-Aware Proxy] に戻ってページを更新します。保護できるリソースのリストが表示されます。[App Engine アプリ] 行の [IAP] 列の切り替えボタンをクリックして IAP を有効にします。 | |
IAP によって保護されるドメイン名が表示されます。[オンにする] をクリックします。 | |
ブラウザタブを開き、アプリの URL に移動します。アプリにアクセスするためのログインを求める「Google でログイン」画面が表示されます。 | |
Google アカウントまたは G Suite アカウントでログインします。アクセス拒否の画面が表示されます。 |
アプリは IAP で正常に保護されていますが、どのアカウントを通過させるのかを IAP にまだ指示していません。
コンソールの [Identity-Aware Proxy] ページに戻り、[App Engine] アプリの隣にあるチェックボックスをオンにすると、ページの右側にサイドバーが表示されます。 | |
アクセスを許可する必要がある各メールアドレス(または Google グループ アドレス、または G Suite ドメイン名)をメンバーとして追加する必要があります。[メンバーを追加] をクリックします。メールアドレスを入力し、そのアドレスに割り当てる Cloud IAP/IAP で保護されたウェブアプリ ユーザーロールを選択します。同じ方法で追加のアドレスや G Suite ドメインを入力できます。 |
[Save] をクリックします。「ポリシーを更新しました」というメッセージがウィンドウの下部に表示されます。
アプリに戻ってページを再読み込みします。承認されたユーザーですでにログインしているので、ウェブアプリが表示されるはずです。ただし、「アクセス権がありません」というメッセージが引き続き表示されることがあります。IAP が承認を再確認しない場合があるためです。その場合は次のステップに従います。
- ウェブブラウザでホームページ アドレスを開き、
https://iap-example-999999.appspot.com/_gcp_iap/clear_login_cookie
のように、URL の末尾に/_gcp_iap/clear_login_cookie
を追加します。 - アカウントがすでに表示された状態で、新たに「Google でログイン」画面が表示されます。アカウントをクリックせずに、[別のアカウントを使用] をクリックして認証情報を再入力ます。
- これで、IAP によりアクセス権が再確認されたので、アプリケーションのホーム画面が表示されます。
別の有効な Gmail アカウントや G Suite アカウントをお持ちのうえで、別のブラウザを利用できる場合、またはブラウザでシークレット モードを使用できる場合は、そのブラウザを使ってアプリケーションのページに移動し、他のアカウントでログインしてみてください。アカウントは承認されていないため、アプリの代わりに「アクセス権がありません」の画面が表示されます。
4. ステップ 2 - ユーザー ID 情報にアクセスする
アプリが IAP で保護されると、通過するウェブ リクエスト ヘッダーで IAP により提供される ID 情報を使用できるようになります。このステップでアプリケーションが取得するのは、ログイン ユーザーのメールアドレスと、Google Identity Services によってそのユーザーに割り当てられた永続的な一意のユーザー ID です。そのデータはウェルカム ページでユーザーに表示されます。
これはステップ 2 です。最後のステップは、iap-codelab/1-HelloWorld
フォルダで Cloud Shell を開いて終了しました。次のステップのフォルダに移動します。
cd ~/iap-codelab/2-HelloUser
App Engine にデプロイする
デプロイには数分かかるため、まず Python 3.7 の App Engine スタンダード環境にアプリをデプロイすることから始めます。
gcloud app deploy
続行を確認するメッセージが表示されたら、「Y(はい)」と入力します。デプロイは数分で完了します。待っている間に、以下の説明のようにアプリケーション ファイルを調べることができます。
デプロイの準備が整うと、gcloud app browse
でアプリケーションを表示できるというメッセージが表示されます。次のコマンドを入力します。ブラウザで新しいタブが開かない場合は、表示されているリンクをコピーして貼り付けると、通常は新しいタブで開きます。次のようなページが表示されます。
アプリケーションが旧バージョンから新しいバージョンに置き換わるまで、数分かかる場合があります。必要に応じてページを更新して上記のようなページを表示します。
アプリケーション ファイルを調べる
このフォルダにはステップ 1 と同じファイルセットが含まれていますが、ファイルのうち main.py
と templates/index.html
は変更されています。プログラムは、IAP によってリクエスト ヘッダーに提供されるユーザー情報を取得するように変更されました。また、テンプレートにそのデータが表示されるようになりました。
IAP 提供の ID データを取得する main.py
には、次の 2 行が含まれています。
user_email = request.headers.get('X-Goog-Authenticated-User-Email')
user_id = request.headers.get('X-Goog-Authenticated-User-ID')
X-Goog-Authenticated-User-
ヘッダーは IAP によって提供されます。名前の大文字と小文字は区別されないため、必要に応じてすべて小文字または大文字で指定できます。render_template ステートメントにこれらの値が含まれるようになったので、表示が可能です。
page = render_template('index.html', email=user_email, id=user_id)
index.html テンプレートでこれらの値を表示するには、二重の中かっこで名前を囲みます。
Hello, {{ email }}! Your persistent ID is {{ id }}.
ご覧のとおり、提供されたデータには先頭に accounts.google.com
: が付き、情報の出所を示します。必要な場合、アプリケーションではコロンまでのすべてを削除して未加工の値を取得できます。
IAP を無効にする
IAP が無効になっている場合、または、なんらかの理由で(同じクラウド プロジェクトで実行されている他のアプリケーションなどによって)バイパスされている場合にこのアプリがどうなるのかを確認するために IAP を無効にします。
Cloud コンソール ウィンドウで、ページの左上にあるメニュー アイコンをクリックし、[セキュリティ]、[Identity-Aware Proxy] の順にクリックします。App Engine アプリの隣にある IAP 切り替えスイッチをクリックして、IAP を無効にします。 |
すべてのユーザーがアプリにアクセスできるようになることを示す警告が示されます。
アプリケーションのウェブページを更新します。同じページが表示されますが、ユーザー情報は表示されなくなります。
アプリケーションが保護されなくなったため、ユーザーは IAP を経由したと思われるウェブ リクエストを送信できます。たとえば、Cloud Shell から次の curl コマンドを実行して、この操作を行うことができます(<your-url-here> の部分は、アプリの正しい URL に置き換えてください)。
curl -X GET <your-url-here> -H "X-Goog-Authenticated-User-Email: totally fake email"
ウェブページは次のようにコマンドラインに表示されます。
<!doctype html> <html> <head> <title>IAP Hello User</title> </head> <body> <h1>Hello World</h1> <p> Hello, totally fake email! Your persistent ID is None. </p> <p> This is step 2 of the <em>User Authentication with IAP</em> codelab. </p> </body> </html>
IAP が無効になっていたりバイパスされていたりすることをアプリケーションが認識する手段はありません。潜在的なリスクがある場合は、ステップ 3 で解決策が示されます。
5. ステップ 3 - 暗号検証を使用する
IAP がオフであったりバイパスされたりするリスクがある場合、アプリでは受信した ID 情報が有効であることを確認できます。ここでは、IAP によって追加された X-Goog-IAP-JWT-Assertion
という 3 つ目のウェブ リクエスト ヘッダーを使用します。ヘッダーの値は暗号で署名されたオブジェクトで、ユーザー ID データも含まれています。アプリケーションはそのデジタル署名を検証し、そのオブジェクトの中で提供されたデータを使用します。そのデータは IAP から改変されずに提供されたものです。
デジタル署名の検証には、最新の Google 公開鍵セットの取得などの追加のステップがいくつか必要です。アプリケーションでこれらの追加のステップが必要かどうかは、他のユーザーが IAP を無効にしたりバイパスしたりできる可能性があるか、またはアプリケーションの機密性などに基づいて決めることができます。
これはステップ 3 です。最後のステップは、iap-codelab/2-HelloUser
フォルダで Cloud Shell を開いて終了しました。次のステップのフォルダに移動します。
cd ~/iap-codelab/3-HelloVerifiedUser
App Engine にデプロイする
Python 3.7 の App Engine スタンダード環境にアプリをデプロイします。
gcloud app deploy
続行を確認するメッセージが表示されたら、「Y(はい)」と入力します。デプロイは数分で完了します。待っている間に、以下の説明のようにアプリケーション ファイルを調べることができます。
デプロイの準備が整うと、gcloud app browse
でアプリケーションを表示できるというメッセージが表示されます。次のコマンドを入力します。ブラウザで新しいタブが開かない場合は、表示されているリンクをコピーして貼り付けると、通常は新しいタブで開きます。
ステップ 2 で IAP を無効にしたため、IAP データがアプリケーションに提供されていません。次のようなページが表示されます。
前のタスクと同様、最新バージョンが有効になって新しいページが表示されるまでに、場合によっては数分待つ必要があります。
IAP が無効になっているため、参照できるユーザー情報はありません。ここで IAP を有効に戻します。
Cloud コンソール ウィンドウで、ページの左上にあるメニュー アイコンをクリックし、[セキュリティ]、[Identity-Aware Proxy] の順にクリックします。App Engine アプリの隣にある IAP 切り替えスイッチをクリックして、IAP を再びオンにします。 |
ページを更新すると、次のようになります。
検証方法で提供されるメールアドレスには、先頭に accounts.google.com:
が付いていないことに注意してください。
IAP がオフになっているかバイパスされている場合、検証されたデータは有効な署名を使用できないため紛失または無効になります。ただし、Google の秘密鍵の所有者がそのデータを作成した場合を除きます。
アプリケーション ファイルを調べる
このフォルダには手順 2 と同じ一連のファイルが含まれ、そのうちの 2 つは変更されたファイル、1 つは新しいファイルです。新しいファイルは auth.py
です。これは、暗号で署名された ID 情報を取得して検証するための user()
メソッドを提供します。変更されたファイルは main.py
と templates/index.html
で、それぞれこのメソッドの結果を使用します。比較のために、手順 2 で見つかった未確認のヘッダーも表示されます。
新機能は主に user()
関数に含まれています。
def user():
assertion = request.headers.get('X-Goog-IAP-JWT-Assertion')
if assertion is None:
return None, None
info = jwt.decode(
assertion,
keys(),
algorithms=['ES256'],
audience=audience()
)
return info['email'], info['sub']
assertion
は、指定されたリクエスト ヘッダーで提供される暗号で署名されたデータです。コードはライブラリを使用して、このデータを検証およびデコードします。検証では、署名されたデータを確認し、そのデータが(基本的には保護されている Google Cloud プロジェクト用に)準備されていることを対象に知らせるために Google 提供の公開鍵を使用します。ヘルパー関数の keys()
と audience()
は、これらの値を収集して返します。
署名付きオブジェクトには、検証済みのメールアドレスと一意の ID 値(サブスクライバーの場合は、sub
に指定)の 2 つのデータが必要です。
これでステップ 3 は完了です。
6. 概要
App Engine ウェブ アプリケーションをデプロイしました。ステップ 1 では、選択したユーザーのみにアプリケーションへのアクセスを制限しました。ステップ 2 では、IAP がアプリケーションへのアクセスを許可したユーザーの ID を取得して表示し、IAP が無効化またはバイパスされた場合にその情報が偽装される可能性があることを確認しました。ステップ 3 では、なりすましが不可能な、暗号で署名されたユーザー ID のアサーションを検証しました。
7. クリーンアップ
この Codelab で使用した Google Cloud Platform リソースは、App Engine インスタンスのみです。アプリをデプロイするたびに新しいバージョンが作成され、削除されるまで存在し続けます。ラボを終了して、プロジェクトとその中のすべてのリソースを削除します。