Cognito を使ったマルチテナント構成についてメモ
- Cognito を使ったマルチテナント構成について、新しい公式情報が追加されていたので確認したメモ
- マルチテナント構成には 4つのパターンがあるので、ユースケースに応じて検討する感じ
- User Pool ベースにマルチテナント
- テナント毎に User Pool を作成する
- テナント毎に MFA 設定やパスワードポリシーを管理したい場合に適している
- テナント、つまり User Pool 毎にユーザーはサインアップする必要がある
- ハイレベルな分離が可能だが開発・運用がツラめ
- アプリクライアントベースにマルチテナント
- テナント毎にアプリクライアントを作成する
- User Pool 自体は 1つ なので、ユーザーが管理するアカウントも 1つ で良い
- 1つ のユーザーに対して複数のアプリクライアントが使用できる
- ホストされた UI を使う場合、各アプリクライアントでセッション Cookie が共有されるので注意
- 複数のアプリケーションがある場合、ホストされた UI を使うことで SSO チックな動作が可能
- 外部 IdP でのフェデレーションを使用する場合、アプリクライアントで意図しない外部 IdP が使用できないように管理する必要がある
- Client Credential Grant を使うことで B2B, マシーン間での認可にも使える
- アプリクライアントが所属するテナントについては、アプリケーション側でロジックや情報を持つ必要がある
- User Pool グループベースにマルチテナント
- テナント毎に User Pool グループを作成する
- 旧来から存在する RBAC
- カスタム属性ベースにマルチテナント
- ユーザーが持つカスタム属性で所属テナントを管理する
- 旧来から存在するマルチテナント構成
- 所属テナントを管理するカスタム属性について、ユーザー側での上書きができないようにアプリクライアント側で write 権限を与えないように注意
元来の Cognito を使ったマルチテナント構成
Amazon Cognito を使用した SaaS のアイデンティティと隔離 – Quick StartQS ランディングページテンプレート
https://aws.amazon.com/jp/quickstart/saas/identity-with-cognito/
元来上記の QuickStart にてリファレンスアーキテクチャが公開されていた
ざっくり要約すると以下のような感じ
- 1つ の Cognito User Pool でユーザーを管理
- カスタム属性でテナントを管理
- テナント毎のアクセス権限については DynamoDB や IAM ポリシー条件
dynamodb:LeadingKeys
を使用することで実現- Cognito User Pool で認証を行い、認証したユーザーに対しては Cognito ID Pool を用いてテナント毎の IAM ポリシーが適用された IAM クレデンシャルを発行する
- API Gateway をフロントエンドアプリからのリクエスト先として、 Lambda オーソライザーを用いて、カスタム属性を確認してユーザーが属するテナントを判別して処理を行う
精読と英語勉強を兼ねて、昔 gist に日本語訳したものがある
SaaS Identity and Isolation with Amazon Cognito on the AWS Cloud の日本語訳
https://gist.github.com/noid11/61f89741da2c6a55db98de5b7d223d20
新しい Cognito を使ったマルチテナント構成
Multi-tenant application best practices - Amazon Cognito
https://docs.aws.amazon.com/cognito/latest/developerguide/multi-tenant-application-best-practices.html
新しくドキュメントにマルチテナントに関する情報が追加されていたので、読んだ
User Pool ベースのマルチテナンシー
- テナント毎に User Pool を作成する
- Pros
- テナント毎に異なる設定を実装できる
- ユーザーとテナントのマッピングを柔軟に行うことができる
- 同じユーザーに複数のプロファイルを許可することもできる
- Cons
- 各ユーザーは、アクセスできるテナントごとに個別にサインアップする必要がある
- オススメのシナリオ
- アプリがテナント毎に異なる設定をもつ
- データレジデンシー要件、パスワードポリシー、 MFA 設定など
- アプリにユーザーからテナントへの複雑なロールマッピングがある
- 1人 のユーザーがテナント A の学生であり、同じユーザーがテナント B の教員であるなど
- アプリがネイティブユーザーのプライマリ認証方法としてホストされた UI を使用する
- アプリには、各テナントが使用するための完全なインフラインスタンスを取得する必要がある(?)
- エフォートレベル
- 開発と運用にかかる労力は高い
- Cognito API の操作および自動化ツールを使用するアプリケーションに、テナントのオンボーディングや管理コンポーネントを組み込む必要がある
- これらのコンポーネントは、各テナントに必要なリソースを作成するために必要
- テナントに一致するユーザーインタフェースを実装する必要がある
- ユーザーが対応するテナントの User Pool にサインアップしてサインインできるようにするロジックをアプリケーションに実装する必要がある
アプリクライアントベースのマルチテナンシー
- テナントごとにアプリクライアントを作成する
- Pros
- ユーザーのプロファイルを再作成することなく、同じユーザーを複数のテナントにマッピングできる
- ホストされた UI が使用されている場合、認証されたユーザーのセッションを維持するためにセッション Cookie が作成される
- セッション Cookie は同じユーザープール内のアプリクライアント間の SSO も提供する
- Cons
- ホストされた UI を使用してネイティブアカウントでユーザーを認証する場合、ユーザー名、パスワードなどに関する追加の考慮事項が必要
- オススメのシナリオ
- アプリ設定は全テナントで同じ
- データレジデンシーとかパスワードポリシーとか
- アプリには、ユーザーとテナントの間で 1対多 のマッピングがある
- 1人のユーザーが、同じプロファイルを使用して複数のテナントにアクセスできる
- テナントが常に外部 IdP を使用してサインインする、フェデレーション専用のマルチテナントアプリケーションがある
- B2B マルチテナントアプリケーションがあり、テナントのバックエンドサービスはクライアント認証情報許可を使用してサービスにアクセスする
- テナント毎にアプリクライアントを作成して、クライアント ID とシークレットをテナントのバックエンドサービスを共有してマシン間での認可を行うことができる
- これは OAuth 2.0 の Client Credential Grant のことだと思われる
- エフォートレベル
- 開発作業が多くなる
- ユーザーをテナントのアプリクライアントに一致させるには、テナントマッチングのロジックとユーザーインタフェースを実装する必要がある
グループベースのマルチテナンシー
- テナントごとに User Pool Group を作成する
- 普通に RBAC (Role Based Access Control)
- ID Pool 使って IAM クレデンシャル使ってもよいし、 User Pool が発行する Access Token, ID Token にもグループ情報が JWT payload として付与されているので、それを使っても良い
Role-Based Access Control - Amazon Cognito
https://docs.aws.amazon.com/cognito/latest/developerguide/role-based-access-control.html
カスタム属性ベースのマルチテナンシー
- テナント識別データをカスタム属性として使う
- tenant_id のようなカスタム属性を設定して使う
- アプリケーションやバックエンドサービスで全てのマルチテナンシーロジックを処理する
- Pros
- 全てのユーザーに対して統一されたサインアップおよびサインインのエクスペリエンスを提供できる
- カスタム属性を確認することで、アプリケーションでユーザーのテナントを識別することもできる
マルチテナンシーの考慮事項
- 検証されていない email を使用して、ドメインの一致に基づいてテナントへのユーザーアクセスを許可しないようにする
- email, phone_number はアプリケーションによって検証するか、外部からの検証の証明が確認できない限り、信頼しない
- アプリクライアントの属性のアクセス許可とスコープ設定などを精査すること
- テナントを識別するために使用されるユーザープロファイル属性が、管理者が変更できる属性または不変な属性か確認する
- アプリクライアントは、これらの属性への read only アクセス権を持っている必要がある
- アプリクライアント側で write 権限を与えてしまうとユーザー側で所属テナントを変更できてしまうので
- 不正なクロステナントアクセスを防ぐために、外部 IdP とアプリクライアントの間に 1:1 のマッピングがあることを確認する
- ユーザーが有効な Cognito セッション Cookie を持っていて、その外部 IdP が複数のアプリクライアントで許可されている場合に発生する可能性があるので注意
- アプリケーションにテナント照合および認可ロジックを実装する場合、テナントへのユーザーアクセスを認可するために使用される基準がユーザー自身によって変更されないようにする
- 外部 IdP がフェデレーションに使用されている場合、テナント ID プロバイダーの管理者がユーザーアクセスを変更できないようにする
- 外部 IdP の管理者がユーザーのテナント属性を書き換えられてしまうため