【AWS Summit Japan 2022】SaaS の認証認可について改めて考える〜 アーキテクチャーパターンと実装例 〜(AWS-33)
2022.6.1
はじめに
この記事は AWS Summit Japan 2022 5月26日(木) のセッション「 AWS-33:SaaS の認証認可について改めて考える〜 アーキテクチャーパターンと実装例 〜 」に参加した時のレポートになります!
セッション概要
タイトル
SaaS の認証認可について改めて考える〜 アーキテクチャーパターンと実装例 〜(AWS-33)
SaaS アプリケーションではテナント横断的なリソースを共有するアーキテクチャを採用することによって、 コスト最適化、 デプロイの俊敏性、 運用の効率化を図ることができます。 一方で、 いかにリクエスト元のテナントを識別してアクセスを分離するかはセキュリティ上重要な考慮事項であり SaaS ならではの実装が必要です。そこで本セッションでは、アプリケーションのマルチテナント化の検討や、SaaS アプリケーションの設計・実装をされている方向けに、SaaS における認証認可・テナント分離のための実践的なアーキテクチャーパターンと AWS での実装方法についてご説明いたします。
スピーカー
AWS 技術統括本部 ISV/SaaSソリューション本部 ソリューションアーキテクト
柴田 龍平 氏
セッション内容
【 SaaS アプリケーションにおける認証認可の課題とプラクティス 】
- エンドユーザーが SaaS に期待するもの
- 使い始めが簡単
- サブスクリプションモデルでの支払い
- 改善や革新の速度
- IT資産管理をしなくても済む
- SaaS開発に求められていること
- 変化の絶え間ないビジネスモデルに対応できるよう製品開発方法の見直し
- 一度作って終わりではなく、リリースしてからがスタート
- ビジネスの差別化 – サービス価値向上
- 製品について、「実験」「傾聴」「反復」のイノベーションサイクルを繰り返し回す
- イノベーションサイクルを回すための手段として活用できる技術
- Infrastructure as Code
- CI/CDパイプライン
- マイクロサービス
- コンテナ
- サーバレス
【 SaaS アプリケーションの認証認可の要件 】
- 要件
- 高い可用性・信頼性
- 複数サービスでのID共通化
- エンドユーザーのID基盤との連携やフェデレーション
- 最小限のパフォーマンス影響
- 別テナントによるアクセスからの保護
- 開発者に負荷をかけない
別のテナントからアクセスを保護するのはコンプライアンス上重要です。
ただし、他ID基盤とのフェデレーションの面で利便性は確保しなければいけないということは、セキュリティとアジリティのバランスが取れた柔軟な基盤が必要となります。
今回のテーマとなっている SaaS の面から、開発者が苦労なしに使うことができるといったことも要件としては挙げられていますね。
柔軟なアクセス制御ができる基盤というと 「OpenID」、「Auth0」、「AWS Cognito」 や 「Okta」 等考えられそうです。
【 SaaS における認証のプラクティス 】
- 認証を専用サービスのアイデンティティプロバイダに移譲して、一元化された ユーザー管理/フェデレーション 機能を実現
- JSON Web Token (JWT)を使い、ユーザ情報にテナントの属性を加えることで、データベースへのアクセスが不要にする
ユーザー管理を一元化することは初回登録の手間も軽減されるので、ユーザにとっても効果的なプラクティスですね。
利便性を上げる上では欠かせないですね。
【 AWSでのアイデンティティプロバイダの選択肢 】
- Amazon Cognito ( クォータは要確認 )
- IDaaS
- Okta
- OneLogin
- Ping Identity
- パッケージ
- OSS や 商用パッケージを 「 EC2 」「 Fargate 」で稼働
- ライブラリを使って独自実装
- アプリの 1 機能として実装
Amazon Cognito や IDaaS といったマネージドサービスを使うことで、運用負荷を抑えた認証基盤が構築できるので最適ですね。
パッケージや独自実装は認証基盤を保守していかないといけないので、よほどの理由がない限り使うのはお勧めできなさそうです。
【 Amazon Cognito でのマルチテナント設計 】
Amazon Cognito で「テナント」を作るためのマルチテナント設計
テナント要件に応じて4つの設計パターンがある。
- カスタム属性ベース
テナント情報をカスタム属性としてユーザーのプロファイルに保存- 選択に適したシナリオ
- マネージドな機能で認可しつつ、テナント分離をする
- テナント毎にパスワードポリシーやフェデレーション要件がない
- 選択に適したシナリオ
- グループベース
ユーザーテナントの紐づけをユーザープールグループとして保存- 選択に適したシナリオ
- Amazon Cognito IDプールの機能でユーザーに IAM Role を割り当てる
- IAMの機能やアクセストークンによる認可を行う
- 選択に適したシナリオ
- アプリクライアントベース
テナント毎にアプリクライアントを作成- 選択に適したシナリオ
- 特定テナントで外部 IdP を利用したフェデレーションログインをする
- 選択に適したシナリオ
- ユーザープールベース
テナント毎にユーザープールを分離- 選択に適したシナリオ
- テナント毎にパスワードポリシーや MFA 設定を変更する
- ユーザーが同一の情報(メールアドレス等)で複数テナントに所属
- テナント間で異なる役割を持つ複雑な要件がある
- 選択に適したシナリオ
【 実装時の留意事項 】
- 悪意あるユーザーが別テナントを装ってアクセスできないようにする
- ユーザーとテナントのマッチングに利⽤する値がユーザーや管理者によって別テナントのものに変更不可能であることを保証する
- ユーザーのメールアドレスドメインを⽤いてテナント識別を⾏う場合は、当該メールアドレスがアプリケーションや外部 IdP によって検証されている場合のみ信頼する
- 認証後、アプリケーションでテナント識別に利⽤する tenant_id などのカスタム属性をユーザー、テナント管理者が変更できない設定(イミュータブル)にする
- 外部 IdP とのフェデレーションにより⾃動的に別テナントにログインされてしまわないようにする
- 外部 IdP を利⽤した Amazon Cognito セッション Cookie を持っているユーザーは、同じ IdPを利⽤する他のアプリクライアントでもアクセスが可能。外部 IdP を利⽤する場合は、あるテナントの外部 IdP を他のテナントで利⽤するアプリクライアントに紐付けないようにする
ここで記載されていることは、冒頭に触れた「別のテナントからアクセスを保護」と同じようなことですね。
【 パッケージの使用 】
マネージドサービス や IDaaS で「時間当たりの認証要求数」等要件を満たせない場合、
OSS や パッケージの利用を検討する。
- AWS Fargate や Amazon Aurora Serverless を用いた Keycloak を稼働するサンプル実装
【 SaaS におけるレイヤー毎のアクセス制御 】
- クライアント – 「PC」, 「スマートフォン」
- ゲートウェイ – 「Amazon API Gateway」,「AWS AppSync」
識別したトークンで API のアクセスを制御 ( 認可 )- 認証済みのユーザーのみ許可
- 契約プランに応じた API 呼び出しのみを許可
- テナント毎のスロットリング
- コンピュート – 「Amazon EC2」,「AWS Fargate」,「AWS Lambda」
テナントを識別してビジネスロジックを処理 ( 認可 or テナント分離 )- テナントリソースの読み書き
- アプリケーション機能の制限
- ゲートウェイ相当の処理
- ストレージ / DB – 「Amazon S3」,「Amazon OpenSearch Service」,「Amazon DynamoDB」,「Amazon Aurora」
各サービスの機能でテナント毎のデータアクセスを分離 ( テナント分離 )- テナント毎の prefix のみアクセスを許可
- 行レベルセキュリティでテナントアクセスを分離
【 テナント分離のためのデプロイモデル 】
- サイロモデル
- テナント専用のインフラストラクチャを保有
- テナントデータの処理や補完はテナント占有リソースで実施
- 認証やオンボーディング等は、サイロでも共有サービスとして作成することが望ましい
- プールモデル
- テナント同士がリソースをシェア
- テナントデータの処理や補完はアプリケーションによる論理的分離
- ブリッジモデル
- 一部リソースをサイロとして分割
- 一部リソースはプールにする
それぞれのモデルは、直接キーワードの意味をイメージするとわかりやすいですね。
【 ゲートウェイレイヤーでのアクセス制御 】
- Amazon API Gateway REST API
- COGNITO_USER_POOLS オーソライザー
- Lambda オーソライザー
- Amazon API Gateway HTTP API
- JWT オーソライザー
- Lambda オーソライザー
- AWS AppSync
- AWS_LAMBDA
- OPENID_CONNECT
- AMAZON_COGNITO_USER_POOLS
実装には様々な種類があることが伺えます。
【 ストレージ / DB レイヤーでのアクセス制御 】
- Amazon S3
- バケットの分割 ( サイロ )
- テナント専用プレフィックスによる分離 ( プール )
- Amazon OpenSearch Service
- ドメインの分離 ( サイロ )
- インデックスの分離 ( サイロ )
- パーティションキーによる分離 ( プール )
- Amazon DynamoDB
- テーブルの分割 ( サイロ )
- 行レベルセキュリティによる分割 ( プール )
- Amazon Aurora PostgreSQL
- インスタンスの分割 ( サイロ )
- スキーマ / テーブルの分割 ( ブリッジ )
- 行レベルセキュリティによる分割 ( プール )
サービス毎にユニークなアクセス制御方法があり面白いです。
【 セッションのまとめ 】
- SaaS アプリケーションの認証認可のプラクティス
- アイデンティティプロバイダの利⽤
- トークンによるテナント情報の表現
- 要件に応じて適切なアイデンティティプロバイダを選択する
- Amazon Cognitoを⽤いる場合は最適な⽅法を選択
- 要件によってはパートナーソリューションやパッケージの利⽤も検討
- テナントの属性を⽤いて認可とテナント分離を実施
- レイヤーや分離モデル毎の⽅法が存在
- 複数レイヤーで分離を実装し、サービスデベロッパーの負荷を軽減
まとめ
内容としては、ベストプラクティスの他、モデルや実装の種類まで濃い内容でしたね。
構成に Lambda が使えて、アプリケーション上で扱いやすくできるのも魅力的でした。
本格的な構成を「いつかやる」という意識を持って勉強していくことで、より魅力のある構成を提案していってみたいですね。
テックブログ新着情報のほか、AWSやGoogle Cloudに関するお役立ち情報を配信中!
Follow @twitterRecommends
こちらもおすすめ
Special Topics
注目記事はこちら
データ分析入門
これから始めるBigQuery基礎知識
2024.02.28
AWSの料金が 10 %割引になる!
『AWSの請求代行リセールサービス』
2024.07.16