これは何?
- AWS が公開している Cognito を使用したマルチテナント環境構成 QuickStart のデプロイメントガイドを日本語訳ながら読み進めたメモ
Amazon Cognito を使用した SaaS のアイデンティティと隔離 – Quick StartQS ランディングページテンプレート
https://aws.amazon.com/jp/quickstart/saas/identity-with-cognito/
SaaS Identity and Isolation with Amazon Cognito on the AWS Cloud
https://aws-quickstart.s3.amazonaws.com/saas-identity-cognito/doc/saas-identity-and-isolation-with-cognito-on-the-aws-cloud.pdf
aws-quickstart/saas-identity-cognito: AWS Quick Start Team
https://github.com/aws-quickstart/saas-identity-cognito
要約
- マルチテナント SaaS を実現するためのリファレンスアーキテクチャの説明
- SPA + マイクロサービス
- 1つ の Cognito User Pool でユーザーを管理
- ユーザーのカスタム属性として、該当するテナントを管理する
- API Gateway における Lambda オーソライザー機能を使用することで柔軟なアクセスコントロールが可能
- Cognito User Pool におけるカスタム属性は ID Token に含まれているため、デコードすれば判定に使用可能
- なので SPA クライアントからアプリケーションへのアクセスは API Gateway を経由するよう構成する
- 認証後リクエスト時には HTTP リクエストヘッダーにて ID Token を連携する
- テナントごとのアクセス権限は IAM ポリシーによって実現している
- テナントを作成する際に IAM API によって IAM ポリシーを作成
- DynamoDB を使用する権限ポリシーの場合、条件キーとして
dynamodb:LeadingKeys
を使用することでパーションキーと一致する条件付が実現できる- テナント ID をベースに DynamoDB のパーティションを作成するよう設計しておくことで、シンプルなポリシーでのアクセス制御が可能となる
- DynamoDB を使用する権限ポリシーの場合、条件キーとして
- Cognito User Pool によってユーザー認証が成功した後、 Cognito ID Pool 経由で作成したテナントごとの IAM ポリシーが適用されている IAM Role のクレデンシャルを取得する
- 各マイクロサービスが DynamoDB 等の AWS サービスに対する操作を行う際に、上記で取得した IAM Role のクレデンシャルを使用する
- テナントを作成する際に IAM API によって IAM ポリシーを作成
- 認証済みユーザーがアクションする際には ID Token を API Gateway に連携し、 ID Token からテナント ID を判別し、マイクロサービス側ではテナント ID に紐づく IAM 権限を使用することで、ユーザー並びにテナントの管理と、権限の分離を実現することが可能となっている
TOC
- これは何?
- 要約
- TOC
- SaaS Identity and Isolation with Amazon Cognito on the AWS Cloud
- Contents
- Overview
- Architecture
- Planning the Deployment
- Deployment Steps
- Walkthrough
- Implementation Details
- FAQ
- Additional Resources
- GitHub Repository
- Document Revisions
SaaS Identity and Isolation with Amazon Cognito on the AWS Cloud
Contents
About This Guide
- この Quick Start リファレンスデプロイメントガイドは、 AWS 上で Cognito を使用した SaaS の Identity と Isolation のソリューションをデプロイするためのステップバイステップの手順を提供する
- SaaS アーキテクトは、このガイドの情報を使用して、認証と認可のコアとなる構成要素とユーザーロールを定義し、クロステナントアクセスを防止する IAM ポリシーを統合したエンドツーエンドのソリューションを構築するためのベストな方法を検討することができる
- この Quick Start に含まれるコードは、 SaaS 開発者に向けて独自の SaaS identity ソリューションを構築するための明確な出発点を提供する
About Quick Starts
- Quick Start は、 CloudFormation テンプレートを使用して、ベストプラクティスに従って AWS 上に特定のワークロードやソリューションをデプロイするための自動化されたリファレンスデプロイメント
Quick Links
skip
Costs and Licenses
skip
Overview
- この Quick Start では、 Cognito をシステムの基礎となる Identity Provider として使用し、 SaaS の Identity と Isolation の基礎を構築するためのアーキテクチャ戦略を示すリファレンスソリューションを SaaS ISV (Independent Software Vendor) に提供する
- 目的としては、 AWS 上に堅牢な SaaS Identity Model を構築する際に、一般的なユーザーとシステムの要求事項のすべてに上手く対応するため、各 SaaS プロバイダーがオーケストレーションする必要のある全ての構成要素を組み合わせること
- この Quick Start では、コアとなる Identity の概念を自社の SaaS アプリケーションに導入するための基盤となる一連のビルディングブロックを提供する
- この Quick Start のコードと、デプロイされるインフラストラクチャを使用することで、マルチテナント SaaS 環境における Identity と Isolation に関連する全ての基本的な概念を接続するアプリケーションによって SaaS Identity のベストプラクティスを直接見ることができるようになる
Core SaaS Identity and Isolation Concepts
- このセクションでは、この Quick Start でデプロイされたソリューションを形作るコアコンセプトのいくつかを探っていく
- 堅牢で効率的な Identity と Isolation モデルを構築するためのアプローチに、マルチテナントがどのように影響するかを理解することが重要
- 従来のシングルテナント環境では Identity のスコープは狭く、ユーザーのクレデンシャルと個人情報 (PII: Personally Identifiable Information) の管理にフォーカスされる傾向がある
- これらのシングルテナントソリューションは、通常、アプリケーションの認証・認可モデルを実装するために ID ブローカーや ID プロバイダーに依存している
- 一方で、マルチテナント環境では、ユーザーは、ユーザー自身のテナントに関するコンテキストを正確に解決するため、追加の ID データを必要とする
- 次の図は、これらのコンセプトを概念的にマッピングしたもの
- ユーザー ID とテナント ID は明確に区別する
- このソリューションのゴールは、これら2つの概念を統合して SaaS Identity と呼ぶ Identity の概念を作成すること
- これらの Identity を結合することで、システムのコンポーネントがテナントとユーザーのコンテキストに完全にアクセスできるようになる
Figure 1: Creating a SaaS identity
- SaaS システム全体で Identity のコンテキストがどのように伝達されるかを考えるだけでなく、リソースへのアクセスを制限するために Identity がどのように使用されるか考慮する必要がある
- マルチテナントシステムでは、アーキテクチャの一部として共有リソースを利用していることが多く、これらのリソースへのクロステナントアクセスを排除するために、各ユーザーにポリシーとロールを関連付けて、システムのビューを制御する必要がある
- 次の図は、これらのコンセプトを強調したもの
- 2つのテナントが一連の AWS リソースにアクセスしている
- セキュリティポリシーでは、各テナントは自分のリソースへのアクセスのみを許可する必要がある
Figure 2: Preventing cross-tenant access
- ここで重要なポイントは、 Identity だけでは SaaS 環境のセキュリティ要件を完全に満たすことは出来ないという点
- 認証されていることは1つのバリアとなりますが、特定のテナントが他テナントのリソースにアクセスできないように制御するためには、ポリシーの追加レイヤーを用いる必要がある
- SaaS の Identity に関する議論では、ロールについても触れなければならない
- SaaS 環境では、ユーザーに関連付けられたロールについて考える際に考慮しなければならないポイントがある
- 例えば、ユーザーはシステムユーザーであったり、テナントユーザーであったりする
- システムユーザーは SaaS プロバイダーの管理者であり、全ての管理者にアクセスできる
- テナントユーザーは、一部の設定やデータにアクセスを制約される
- 次の図は、これらのシステムロールとテナントロールを概念的に表したもの
- テナントユーザーを管理する個々のテナント管理者が存在する
- それぞれのテナント管理者が異なるロールを持つ可能性もある
- システムロールも存在し、システムユーザーの追加タイプ(運用、サポートなど)を提供するために使用される
- システムロールのユーザーは、システムの一部である全てのテナントにアクセスできる
- これらのロールの正確な性質はシステムごとに変わる可能性があるが、 Identity プロビジョニングと Isolation のアプローチは、異なるユーザーやロールの様々ニーズに対応する必要がある
- テナントユーザーを管理する個々のテナント管理者が存在する
Figure 3: System and tenant user roles
- Quick Start 環境の詳細を掘り下げると、テナントのライフサイクルとアクセスプロファイルには、いくつかの特別な考慮事項があることがわかる
- これらの異なるロールがどのようにプロビジョニングされるか、これらのロールが Identity と Isolation モデルの基礎となる実装にどのような影響を与えるのか探っていく
Applying Roles
- ほとんどのアプリケーションには、ユーザーロールの概念が含まれている
- これらのロールは、各ユーザーがアクセスするコンテキストと範囲を定義し、システム機能やリソースへのアクセスを制御する
- SaaS では、システムユーザーとテナントユーザー両方の多様なニーズに対応しなければならないロールが必要となり、このモデルに複雑さが加わる
- これらのロールの性質を明確にするために Quick Start が提供する環境では、システムユーザーとテナントユーザーの小さなコレクションをサポートしている
- これらのユーザーは、アプリケーションの機能やリソースへのアクセス制御をするために使用できるアプローチを強調するためにコレクションに含まれており、以下のセクションで掘り下げる
System Users
- システムユーザーは、全てのテナントへのアクセスを必要とするユーザー
- これらのユーザーは自社の SaaS テナントに様々なタイプの管理、監視、サポートを提供する ISV を代表している
- このカテゴリには通常、システム管理者、運用担当者、カスタマーサポートスタッフなど、様々なレベルでのアクセス権を持つユーザーが含まれる
- 今回の Quick Start には、システムレベルでのアクセスを制御するための基本的なことを解説するため、2つの具体的なロールが含まれている
System administrator
- このロールは新しい System user を導入する機能を含め、全てのテナント環境へのフルアクセスが可能
- このロールは、他の人が見ることができないシステムのヘルスデータにもアクセスすることができる
System user
- このロールは、システムのデータへのアクセスが制限されているサポートレベルのユーザーを表す
- このユーザーには、ユーザー管理や、システムのヘルスを閲覧する機能はなく、カスタマーの問題に対するトラブルシューティングをサポートするためにアプリケーションデータを表示することしかできない
Tenant Users
- テナントユーザーは、特定テナントにスコープされたユーザー
- これらのユーザーは、テナント構成を管理するために使用される個々のテナントロールを表し、特定アプリケーションのドメイン固有の様々な役割を想定している
- 最初のテナントユーザーは、よくオーナーを呼ばれ、登録プロセス中に作成される
- その後の全ユーザーは、このオーナーアカウントによって作成される
- この Quick Start では、以下の2つのロールを設定して、テナントアクセスのバリエーションを強調している
Tenant administrator
- このロールは、システムに新しいテナントユーザーを導入する機能を含め、テナント環境へのフルアクセスが可能
- アプリケーション機能にもアクセス可能
Tenant user
- このロールは、テナントデータと機能へのアクセスが制限されたアプリケーションレベルのユーザーを表す
- このユーザーにはユーザー管理機能は無く、アプリケーション機能へのアクセスも制限されている
The Reference Application
- 前のセクションで説明したコンセプトを効果的に説明するために、この Quick Start ではエンドツーエンドの SaaS Identity と Isolation を提供するリファレンスアプリケーションをデプロイする
- リファレンスアプリケーションは、軽量な SaaS 注文管理システム
- 製品カタログを管理するための基本的な機能と、それらの製品の注文を作成するためのサポートを提供
- この機能は、前のセクションで説明したロールにまたがる Identity と Isolation の様々な側面を強調するのに役立つ
- 製品カタログを管理するための基本的な機能と、それらの製品の注文を作成するためのサポートを提供
- この Quick Start をデプロイしたあとは、 walkthrough のステップに沿って、アプリケーションでサポートされているフローを探索することができる
Architecture
- この Quick Start では、デフォルトのパラメーターを使用して新規 VPC をデプロイし、以下のような SaaS identity と isolation 環境を構築する
Figure 4: Deployed application architecture
- この Quick Start のアーキテクチャには、2つの Availability Zone にまたがる VPC にコンテナベースのアプリケーションをデプロイするためのベストプラクティスに準拠した、拡張性が高く可用性の高いソリューションを作成するための、多くの AWS サービスと構成が含まれている
- まず S3 を使ってデプロイされたリファレンスアプリケーションを見てみる
- この AngularJS アプリケーションの全アセットは S3 バケットにデプロイされ、 S3 バケットから提供されている
- デプロイされた Web アプリケーションは、 API Gateway を経由してルーティングされた RESTful コールを通して、アプリケーションのバックエンドサービスと連携する
- API Gateway は、 SaaS 環境でサービスを自然に公開する方法を提供し、環境へのアクセスを計測してスロットルをかけることを可能にする
- また、サービスにアクセスしようとする度にシステムのトークンを検証できる Lambda オーソライザーもサポートしている
- このオーソライザーは Lambda 関数として実装されており、 API Gateway を通過するリクエストに対してカスタムした認可ロジックを作成することができる
- アーキテクチャは、 VPC 内で個別の Availability Zone にデプロイされた NAT ゲートウェイを採用している
- これらの NAT ゲートウェイは VPC のパブリックサブネットにホストされており、カスタマーのプライベートサブネットから他の AWS サービスやインターネットに流れるトラフィックの高可用性ルーティングを提供する
- アプリケーションサービスのコアは、 VPC のプライベートサブネットにホストされている
- ECS クラスターが、システムのマイクロサービスを実行するコンテナをホストしている
- このクラスターには 7つ の Node.js マイクロサービスがデプロイされている
- このクラスターは基本的な高可用性のために AutoScaling を採用している
- このクラスターを更にチューティングして、テナントの負荷の変化に動的に対応し、需要に応じてスケールアップやスケールダウンを行うことができる
- アーキテクチャ図の右側には、アプリケーションが利用する様々な AWS サービスが表示されている。たとえば・・・
- DynamoDB テーブルは、ストレージを必要とするサービスの一部にプロビジョニングされている
- IAM はアプリケーションの Isolation ポリシーとロールを管理・適用する
- Cognito は ID プロバイダーとして機能する
- SNS はユーザー登録プロセス中に検証メールを発行する
- このアーキテクチャは継続的なデプロイメントもサポートしている
- CodePipeline, CodeBuild, S3, ECR を組み合わせて、新しいアプリケーション機能のビルドとデプロイを管理している
Planning the Deployment
Prerequisites
- この Quick Start をデプロイする前、次の AWS サービスに触れておくことを推奨
- VPC
- ECS
- API Gateway
- DynamoDB
- IAM
- Cognito
Deployment Options
- この Quick Start は2つのデプロイオプションを提供している
- Quick Start を新しい VPC にデプロイする (エンドツーエンドデプロイ)
- このオプションでは、 VPC, Subnet, NAT Gatewa, Security Group 等のインフラストラクチャコンポーネントで構成される新しい AWS 環境を構築し、この新しい VPC に Quick Start をデプロイします
- Quick Start を既存の VPC にデプロイする
- このオプションでは、既存の AWS インフラストラクチャに Quick Start をプロビジョニングする
- Quick Start を新しい VPC にデプロイする (エンドツーエンドデプロイ)
- この Quick Start では、後述する追加設定を使用することもできる
Deployment Steps
- skip
Step 1. Prepare Your AWS Account
Step 2. Launch the Quick Start
Step 3. Test the Deployment
Walkthrough
- skip
Onboarding Tenants
Managing Tenant users
Managing the Catalog
Managing Orders
Performing System Administrator Functions
Implementation Details
Conceptual Architecture
- アプリケーションフローとロールについて説明したところで、これらの機能をサポートする基本的な設計と実装をみていく
- この Quick Start では、 SaaS Identity と Isolation に焦点を当てているが、必要に応じてクラウドネイティブアプリケーションモデルにも対応しているので ECS コンテナ内で動作するマイクロサービスのセットも含まれている
- Figure 12 は、アーキテクチャの高度に概念化されたバージョンを示している。(詳細なアーキテクチャ図については Figure 1 を参照)
Figure 12: Conceptual architecture
- このアーキテクチャは AWS 技術を使用する
- リファレンスアプリケーションは、 S3 バケットから直接コンテンツを提供する AngularJS を使用している
- アプリケーションからのリクエストは API Gateway を経由してルーティングされ、アプリケーションをサポートする各マイクロサービスに送られる
- Node.js で開発されたマイクロサービスは ECS のコンテナクラスタで実行される
- これらのサービスの中には、ストレージとして DynamoDB を使用しているものもある
- 他のサービスは、直接所有するストレージを持たない
- Cognito はシステム全体で使用されており、基本的なユーザー管理インフラを提供している
- Lambda オーソライザーが API Gateway に設定されており、このエクスペリエンスを通過するトークンの検証を行っている
Orchestarting Onboarding
- ここではテナントのオンボーディングプロセスが、システム内に新しいテナントを作成するために、システムアーキテクチャの可動パーツをどのように編成するのかを見ていく
- Figure 13 は、 Quick Start アーキテクチャの様々な要素間における相互作用の概要を示している
Figure 13: Orchestrating Onboarding
- オンボーディングのワークフローは、以下のステップで構成されている
- 新規テナントが登録フォームに必要事項を入力してサブミットする
- Tenant Registration Service は、ユーザーが存在しないことを確認する
- User Management Service は、ローカルデータベースに新しいユーザーを作成する
- User Management Service は、 Cognito に新しいユーザープールとカスタムクレームを作成する
- Tenant Management Service は新しいテナントを作成する
- Tenant Registration Service は、各テナントロールのポリシーを規定する
- このプロセスが終了すると、新しいテナントの全ての可動パーツが正常にプロビジョニングされる
- これでテナントユーザーが存在し、 Cognito での認証準備が整った
- これでテナントと必要なポリシーが全てプロビジョニングされた
Orchestrating Authentication
- ユーザーを作成したら、そのユーザーがシステムによってどのように認証されるのかを見る必要がある
- 認証プロセスは、ユーザーをテナントに接続し、ユーザーのリソースへのアクセスを制限・制御するコンテキストを取得する
Figure 14: Orchestrating authentication
- 幸いなことに、このプロセスのほとんどは Enhanced (Simplified) Flow と呼ばれるものを使用して、 Cognito API への一連の呼び出しによって編成することが可能
- Figure 14 は、この Quick Start で実装された、このフローの図
- 認証フローは、システムの Authentication Service によって編成され、以下のステップから構成されている
- Authentication Service は、ユーザーが存在するかを判断し、存在する場合には割り当てられた User Pool ID を決定する
- システムは Cognito から、その User Pool に関する情報を取得する
- この段階では、サービスは特定の User Pool に対してユーザーを認証するために必要なパラメーターを持っている
- ユーザーは割り当てられた User Pool に対して認証され、認証に成功すると ID Token が返される
- ID Token を使って Cognito から Cognito ID を取得する
- Cognito は STS から一時的な STS トークンの要求を受け、供給された Cognito ID を STS トークンと交換し、そのトークンを Authentication Service に返す
- Authentication Service は、 ID Token と Access Token として使用した STS トークンをクライアントに返す
- ID Token はクライアントにユーザーに関するクレームデータへのアクセスを提供する
- ID Token と STS トークンの両方は、ダウンストリームサービスへの呼び出しで渡される
- これらのトークンは、ユーザーのためのテナントコンテキストと、 AWS リソースへのアクセスに使用されるアクセス ID とシークレットキーの両方を提供する
Binding Identity to Tenant and Policies
- このオンボーディングプロセスでは、この Quick Start がデプロイする SaaS Identity と Isolation に不可欠な基本的なバインディングが作成される
- Figure 15 は、この関係の 3つ のコンポーネントを示している
Figure 15: Binding tenants and roles to identity
- Cognito では、ユーザー ID を作成し、その ID にテナントとの関係を記述する属性を導入する
- この場合、 Quick Start は各ユーザーにテナント ID とロールを用意して入力する
- テナント ID は、この ID を介してユーザーと接続される
- これにより、課金やステータス (active/inactive) などのテナント属性にユーザーが接続される
- テナント ID は、ユーザーとテナントをテナント Isolation を強制する IAM ポリシーのコレクションに接続する
- この場合、 Quick Start は各ユーザーにテナント ID とロールを用意して入力する
- これらの 3つ の概念を 1つ の統一されたモデルに接続する能力は、この Quick Start ソリューションの重要なポイント
- ユーザーとテナントの関係を識別し、それを強制可能なポリシーにマッピングすることで、開発者はこのガイドで説明した Identity と Isolation の目標の多くに対処することができる
Connecting The Dots
- 次のセクションでは、この Quick Start がシステムの重要な要素をどのように実装しているかについて詳細に説明する
Provisiong Policies
- この Quick Start では、システムはテナントを、テナントの AWS リソースへのアクセス範囲を決定する一連のポリシーにバインドすることができる
- 新しいテナントがオンボードされると、システムはテナントのポリシーをプロビジョニングする
- この Quick Start では DynamoDB を使用して、これらの生成されたポリシーを使用してどのように Isolation を実証することができるのかを説明している
- 各テナントのデータは一連の DynamoDB テーブルに保存される
- これらのテーブルでは、各テナントのデータが各テーブル内の他テナントデータを一緒に存在する、プールされたマルチテナントモデルを使用している
- このモデルでは、これらのテーブル内のデータを Isolation して、クロステナントアクセスを防止する方法が必要となる
- Isolation 目標を達成するためのポリシーをシステムがどのように作成できるかを考えてみる
- DynamoDB では、 DynamoDB テーブル内の特定アイテムへのアクセスをフィルタリングするポリシーを定義する IAM Service の機能を使用する
- Figure 16 は、テーブル内アイテムへのテナントアクセスを制限するポリシーのサンプルを示している
{
"Sid": "TenantReadOnlyOrderTable",
"Effect": "Allow",
"Action": [
"dynamodb:GetItem",
"dynamodb:BatchGetItem",
"dynamodb:Query",
"dynamodb:DescribeTable"
],
"Resource": [
"arn:aws:dynamodb:us-east-1:123456789012:table/Order"
],
"Condition": {
"ForAllValues:StringEquals": {
"dynamodb:LeadingKeys": [
"5bd24c40d66c4755819d28ceab9f0826"
]
}
}
}
Figure 16: Scoping tenant access with policies
- この例では、システムの Order テーブルで実行できる操作の概要を説明する
- 注目すべきキーアイテムは
dynamodb:LeadingKeys で、これにはテナント ID が含まれている
- この値は、テーブルのパーティションキー値のプレフィックスとして、一致するテナント ID を持つテーブル内のアイテムにのみ、データの表示を制限する
- 注目すべきキーアイテムは
- ポリシーの肥大化を抑え、環境を管理しやすくするために、この Quick Start では、各テナントに固有のポリシーとロールのセットを導入している
- これにより、テナント毎に個別のポリシーを用意する必要がなくなり、フットプリントが小さくなります
- この Quick Start では DynamoDB テーブルの Isolation を実証することにフォーカスしている点に注意
- より完全なシステムでは、これらのポリシーをより広範囲な AWS リソースに拡張する必要があり、それぞれのリソースで Isolation を実現するための独自のモデルが必要になる
Defining Custom Claims
- この Quick Start では、テナント情報を各ユーザーに関連付ける属性を表すためにクレームを使用する
- これらのクレームは、エンコードされた JWT にパッケージ化されて転送される
- これらのトークンには、テナントの Cognito User Pool で定義された属性から引き出されたデータが含まれる
- Cognito は OpenID Connect プロトコルの全ての実装でサポートされている標準の属性セットをサポートしている
- しかし、これらの標準属性には、ユーザーをテナントに関連付けるために必要な項目の一部が含まれていない
- これらの追加データ要素は、カスタム属性として導入する必要があり、認証プロセスで返される JWT のカスタムクレームとして伝達される
- カスタム属性は、各テナントがシステムにオンボードされたときにプロビジョニングされ、設定される
- この Quick Start ソリューションでは、まずテナントの User Pool を作成し、必要な属性をこの User Pool に追加する
- 登録プロセスでは、これらの属性のデータを収集して生成し、ユーザーのプロビジョニングプロセスに注入する
- その後、ユーザーが認証されると、これらの属性はエンコードされ、 ID Token として返される
- カスタムクレームは OpenID Connect 標準でサポートされていますが、 SaaS ソリューションにカスタムクレームを使用することはトレードオフになる
- カスタムクレームを使用すると、ソリューションは単一の ID プロバイダにバインドされる(この場合は Cognito)
- 何らかの理由で、 LinkedIn や Facebook といった他プロバイダに変更したい場合、新しいプロバイダはこれらのカスタムクレームを認識しない
- そのため、カスタムクレームはテナント属性を伝えるための自然なメカニズムを提供するものの、この制限を想定して設計を行う必要がある
- 場合によっては、ユーザーの Identity をテナントにバインドするために、別のパターンに頼る必要があるかもしれない
Using Tokens
- この Quick Start ソリューションでは、トークンを使用して、テナントとそのアクセス権限に関する情報を連携する
- 認証に成功すると ID Token と Access Token の2つのトークンが生成される
- これらのトークンは、 JWT 形式でクライアントに返され、クライアントとの間で渡される際にエンコードされる
- 各コンシューマは、トークンの内容をデコードして、トークンに関連付けられた属性を含む JSON オブジェクトにアクセスする
- 次のコードは、クライアントアプリケーションが受信した ID Token をデコードして表示する方法の例を示している
$rootScope.bearerToken = response.data.token;
var decodedToken = jwtHelper.decodeToken($rootScope.bearerToken);
$rootScope.userDisplayName = decodedToken['given_name'] + ' ' + decodedToken['family_name'];
$rootScope.userRole = decodedToken['custom:role']
Figure 17: Decoding tokens on the client
- これらのトークンは、アプリケーションのサービスに送信される各 HTTP リクエストのヘッダーにも挿入される
- リクエストを処理する各サービスは、 ID Token を参照してテナントコンテキストを取得する
- サービスが AWS リソースにアクセスする必要がある場合には、アクセストークンから AWS クレデンシャルを抽出する必要がある
- Figure 18 のコードは、これらのトークンがアプリケーションサービスによってどのように処理されるかの例
- このコードでは、 Product 情報を管理するための基本的な REST 操作を提供する Product Service にフォーカスしている
app.use(function(req, res, next) {
res.header("Access-Control-Allow-Origin", "*");
res.header("Access-Control-Allow-Methods", "GET, POST, OPTIONS, PUT, PATCH, DELETE");
res.header("Access-Control-Allow-Headers", "Content-Type,Access-Control-Allow-Headers,Authorization,X-Requested-With");
bearerToken = req.get('Authorization');
if (bearerToken) {
tenantId = tokenManager.getTenantId(req);
}
next();
});
Figure 18: Extracting the tenant ID from the ID token
- このコードは、サービスに送信される様々なリクエストを処理する
- これはベアラートークンからのテナント ID 抽出を一元化する
- このアプローチを使用すると、サービスによって実装された各エントリポイントで参照されるテナント ID を取得するためのコードブロックを1つに集約できる
- この関数はテナント ID を取得するために
tokenManager
に依存している- この関数はアプリケーションによるトークン情報の処理を簡素化して統一するために、集中化されたヘルパーモジュールにパッケージ化されている
- また、プロダクト用の DynamoDB テーブルにアクセスするためのクレデンシャルも必要
- Figure 19 は Quick Start ソリューションはこれらのクレデンシャルを取得する方法の例を示している
app.get('/product/:id', function(req, res) {
winston.debug('Fetching product: ' + req.params.id);
tokenManager.getCredentialsFromToken(req, function(credentials) {
// init params structure with request params
var params = {
tenantId: tenantId,
productId: req.params.id
}
// << remaining Get code >>
});
});
Figure 19: Getting tenant-scoped credentials
- この function はプロダクト REST サービスの GET メソッドを実装している
getCredentialsFromToken()
function はベアラートークンを含む HTTP リクエストを渡す- この function はヘッダからトークンを抽出してデコードし、 DynamoDB API の呼び出しに必要な属性を保持するクレデンシャルオブジェクトを返す
- このプロセスに流れるトークンは、 IAM ポリシーによってスコープされるクレデンシャルとともに、アクセスのスコープに必要なテナントコンテキストを提供する
- これらの要素が配置されていると、最小限のオーバーヘッドでシステムの全サービスにコンテキストを流すことができる再利用可能なメカニズムができる
- 他サービスを経由してこのコンテキストを解決することに関連するレイテンシも排除される
Using the Custom Authorizer
- アプリケーションが認証プロセスでトークンを取得した後も、バックエンドサービスへのリクエストを行う際には、そのトークンを検証する必要がある
- API Gateway は、カスタムオーソライザーと呼ばれるカスタム処理ロジックを注入して、この検証を処理するための自然なメカニズムを提供する
Figure 20: Custom authorizer flow
- Figure 20 は Quick Start リファレンスアプリケーションで、このカスタム検証がどのように実装されているかの概要を示している
- クライアントからの各リクエストは API Gateway を介してルーティングされ、 API Gateway はこれらの呼び出しを対応するマイクロサービス関数にマッピングする
- このマッピングを作成するには、 API Gateway の HTTP エントリポイントを、アプリケーションのバックエンドサービスの特定のメソッドに接続する必要がある
- この構成中に HTTP メソッド要求の設定を構成して、認証用のカスタムオーソライザーオプションを選択することで、カスタムオーソライザーを導入して構成できる
- Figure 21 に API Gateway コンソールから、これらのオプションにアクセスする方法を示す
Figure 21: Selecting custom authorization
- カスタム認証先プションを選択した後、 Figure 22 に示すように、その認証先の設定を編集することができる
- これには、各リクエストに関連付けられたトークンを検証するために使用される Lambda 関数の設定が含まれる
Figure 22: Configuring a custom authorizer
- この Quick Start のオーソライザーを実装する Lambda 関数は、生成された JWT に署名するために最初に使用された Cognito User Pool の PEM 証明書をダウンロードする
- オーソライザーは PEM 証明書をダウンロードした後、クレームを解読し、発行者、トークンのタイプ、提供された ID Token の署名検証を行い、指定されたリソースメソッドの承認を行う
- このソリューションは、テナント User Pool の PEM 証明書のキャッシングをサポートしていない
- 本番環境でこのソリューションを使用している場合は、この最適化を追加する必要があるでしょう
- カスタムオーソライザーのパフォーマンスを向上するために ElastiCache を活用するのは自然な選択
- カスタムオーソライザーは現在、 API の全てのメソッドに対して
*
にポリシーが設定されており、メソッドごとに呼び出されている - エンドポイントに特定の IAM ポリシーを割り当てることで、ポリシーのフットプリントを最小限に抑えることを推奨
Putting it All Together
- これらの詳細が、全体的な identity と isolation モデルにどのように適合するかを簡単に見る
- Figure 23 は、先程説明したコアコンセプト間のつながりを強調したもの
Figure 23: Mapping Flows to Activities
- サンプルアプリケーションの 3つ の主要なワークフローを左図に、各フローに関するアクティビティを右図に示す
- テナントのオンボーディングと登録プロセスでは、テナントとそれに対応するポリシーを規定する
- また、ユーザーとテナントにバインドする必要のあるカスタム属性も作成する
- 認証では、テナントのアクセス権と権限を伝える適切な ID Token と Access Token でユーザーを関連付ける
- これらのトークンは、エンコードされた JWT 形式でクライアントに返される
- 3番目のデータフローでは、これらのトークンはアプリケーションサービスへのサービスコールに注入される
- ID Token と Access Token は HTTP ヘッダーで各サービスに渡され、 API Gateway によって検証され、マイクロサービスによってデコードされ、現在のテナントコンテキストを解決し、 AWS リソースにアクセスするためのクレデンシャルを取得するために使用される
- これらのクレデンシャルは、コードが呼び出されるたびに DynamoDB などの各 AWS サービスクライアントに直接わたされる
- テナントのオンボーディングと登録プロセスでは、テナントとそれに対応するポリシーを規定する
Considerations for Production Environments
- この Quick Start では、完全なエンドツーエンドの identity と isolation ソリューションをまとめています。ただし、本番環境でこのコードを使用する場合は、以下の機能追加を検討することをお勧めします
- クライアント証明書
- 完全なセキュリティを確保するには、認証にクライアント証明書を使用することをオススメします
- AutoScaling
- 現在のソリューションは、高可用性を実現するために Multi-AZ モデルが採用されています
- しかし、サービスの負荷変化を測定して対応する AutoScaling モデルにはポリシーがアタッチされていません
- ドメイン内サービスの特定スケーリングディメンションに基づいて、このドメインをチューニングすることを検討すると良いでしょう
- JWT encoding
- システムを通過するトークンは現状暗号化されていません
- トークンの内容をより安全にするためには、暗号化ライブラリを使用することをお勧めします
- API keys
- サービスによっては、開発者 API の一部としてメソッドを公開する場合があります
- これらのエントリポイントは API Gateway でサポートしている API キーで保護する必要があります
- Microservice communications
- 現在の実装では、クライアントからマイクロサービスへのインタラクションは全て API Gateway を通過します
- しかし、マイクロサービス間の呼び出しの中には、直接 HTTP 呼び出しとして処理されるものもあります
- システムの拡張性を高めるには、これらのコールを API Gateway を介してルーティングして返すか、 SQS を使用して非同期に処理することを検討してください
- クライアント証明書
Application Libraries
Node.js Modules
- Async
- amazon-cognito-identity-js
- Config
- Winston
- UUID
- body-parser
- aws-sdk
- amazon-cognito-js
- Express
- Randomstring
- Request
- jsonwebtoken
- jwk-to-pem
- jwt-decode
AngularJS Modules
- Augular
- Bootstrap
- angular-route
- angular-jwt
- angular-mocks
- Grunt
- Karma
- phantomjs-prebuilt
- time-grunt
- autoprefixer-core
Python Modules
- JSON
- Requests
- cfn-response
- Boto 3
FAQ
skip
Additional Resources
skip
GitHub Repository
skip
Document Revisions
skip