Amazon Web Services ブログ

AWS 上のマルチテナント SaaS 環境におけるセキュリティプラクティス

この記事は Security practices in AWS multi-tenant SaaS environments を訳したものです。

SaaS (Software-as-a-service) アプリケーションのセキュリティ保護は、すべてのアプリケーションアーキテクトと開発者にとって最優先事項です。複数のテナントによって共有される環境のセキュリティ保護は、特に困難な場合があります。アイデンティティフレームワークとその概念を理解するには時間がかかることがあり、これらの環境でテナント分離を形成するには、さまざまなツールやサービスを深く理解する必要があります。セキュリティはあらゆるソフトウェアアプリケーションの基本要素ですが、SaaS アプリケーションには SaaS 特有の考慮事項があります。この記事では、アマゾンウェブサービス (AWS) 上のマルチテナント SaaS 環境を保護するための課題、機会、ベストプラクティスについて詳しく説明します。

SaaS アプリケーションのセキュリティに関する考慮事項

シングルテナントアプリケーションは特定の顧客向けに展開されることが多く、通常はこの単一のエンティティのみを扱います。このような環境でもセキュリティは重要ですが、脅威シナリオには他のお客様による潜在的なアクセスは含まれません。マルチテナント SaaS アプリケーションには、シングルテナントアプリケーションと比較した場合、独自のセキュリティ上の考慮事項があります。
マルチテナント SaaS アプリケーションでは特にアイデンティティ (ID) とテナントの分離に特別な注意を払う必要があります。これらの考慮事項は、すべてのアプリケーションが講じなければならないセキュリティ対策に追加されるものです。このブログ記事では、アイデンティティ (ID) とテナントの分離に関する概念と、SaaS プロバイダーが安全なアプリケーションを構築するために AWS がどのように役立つかについて説明します。

アイデンティティ (ID)

SaaS アプリケーションは、個々のプリンシパル (ユーザーと呼ばれることが多い) によってアクセスされます。これらのプリンシパルによるアクセスは、対話型 (Web アプリケーション経由など) またはマシンベース (API 経由など) の場合があります。各プリンシパルは一意に識別され、通常、メールアドレス、名前、ロール、その他のメタデータなど、プリンシパルに関する情報に関連付けられます。
SaaS アプリケーションには、個々のプリンシパルが一意に識別されるだけでなく、テナントという別の構成要素があります。マルチテナントに関する論文では、「テナントとは、使用するアプリケーションについて同じビューを共有する 1 人以上のユーザーのグループ」として定義されています。このビューは、テナントによって異なる場合があります。1 対 1 のマッピングだけであっても、個々のプリンシパルはテナントに関連付けられます。テナントは一意に識別され、テナント管理者に関する情報、請求情報、その他のメタデータが含まれます。
プリンシパルが SaaS アプリケーションにリクエストを送信する際には、プリンシパルはテナントとユーザー ID を提供します。SaaS アプリケーションはこの情報を検証し、リクエストを許可するかどうかの判断を行います。適切に設計された SaaS アプリケーションでは、この認可のステップは中央集権型の認証サービスに依存すべきではありません。中央管理された認証サービスは、アプリケーションにおける単一障害点となり得ます。認証サービスが障害を起こした場合、またはリクエスト過多によりダウンした場合、SaaS アプリケーション全体がリクエストを処理できなくなります。
SaaS アプリケーションでこれを実現するためには、ID プロバイダー (IdP) の使用と、トークンを用いてアイデンティティを表現するという 2 つの重要なテクニックが必要となります。

アイデンティティプロバイダ (IdP) の使用

従来型の Web アプリケーションでは、ユーザー情報をリレーショナルデータベーステーブルに格納するということがよく行われていました。プリンシパルが正常に認証されると、アプリケーションはセッション ID を発行し、プリンシパルに応答します。それ以降のリクエストでは、プリンシパルは都度セッション ID をアプリケーションに渡します。アプリケーションは、このセッション ID に基づいてリクエストを許可するかどうかを決定します。図 1 に、この構成例を示します。

レガシーアプリケーション認証の例

図 1 — レガシーアプリケーションでの認証の例

単純な Web アプリケーションよりも大きなアプリケーションでは、このパターンは最適ではありません。通常、リクエストごとにデータベースクエリまたはキャッシュの検索が少なくとも 1 回発生し、ユーザー情報またはセッション情報を保持するデータストアにボトルネックが生じます。さらに、アプリケーションとそのユーザー管理が緊密に結合しているため、外部 ID プロバイダーとのフェデレーションが困難になります。
SaaS アプリケーションを設計するときは、Amazon Cognito、Auth0、Okta のような ID プロバイダーの使用の検討が推奨されます。ID プロバイダーを使用すると、フェデレーションなどのユーザー認証を外部で処理することで、ID の管理に必要な負担を軽減できます。図 2 は、図 1 に示すセルフマネージドソリューションの代わりに SaaS プロバイダーが ID プロバイダーを使用する方法の例を示しています。

ID プロバイダーが関与する認証フローの例

図 2 — ID プロバイダーが関与する認証フローの例

ユーザーが ID プロバイダーで認証されると、ID プロバイダーは標準化されたトークンを発行します。このトークンは、ユーザーの認証方法に関係なく同じです。つまり、テナントが使用する複数の異なる認証方法に対するサポートをアプリケーションに組み込む必要はありません。
ID プロバイダーは、一般的にフェデレーテッドアクセスもサポートしています。フェデレーテッドアクセスとは、サードパーティが ID を保持しており、ID プロバイダがこのサードパーティと信頼関係を持つということを意味します。顧客がサードパーティが管理する ID を使用してログインしようとすると、SaaS アプリケーションの ID プロバイダーがサードパーティ ID プロバイダーとの認証トランザクションを処理します。
この認証トランザクションでは通常、Security Assertion Markup Language (SAML) 2.0 などのプロトコルが使用されます。SaaS アプリケーションの ID プロバイダーは、テナントの ID プロバイダーとの対話を管理します。SaaS アプリケーションの ID プロバイダーは、SaaS アプリケーションが理解できる形式でトークンを発行します。図 3 は、SaaS アプリケーションが ID プロバイダーを使用してフェデレーションをサポートする方法の例を示しています。

テナントが提供する ID プロバイダーを使用する認証の例

図 3 — テナントが提供する ID プロバイダーを使用する認証の例

こちらの例については、「Azure AD を使用してフェデレーション認証用に Amazon Cognito をセットアップする方法」を参照してください。

トークンによるアイデンティティの表現

アイデンティティは通常、署名付きトークンで表されます。ID プロバイダによって発行される JSON Web Signature (JWS) は JSON Web Token (JWT) とも呼ばれ、Web アプリケーションから利用できる署名付き JSON オブジェクトです。リクエスト元が特定のリソースにアクセスする権限があることを示すために使用されます。これらの JSON オブジェクトは ID プロバイダーによって署名され、中央管理されたデータベースやサービスに対してクエリを行わなくても検証できます。
トークンには、ID プロバイダーによって発行されるクレームと呼ばれるキーと値のペアがいくつか含まれています。トークンの発行と有効期限に関するいくつかのクレームに加えて、トークンには個々のプリンシパルとテナントに関する情報も含めることができます。

アクセストークンクレームのサンプル

以下の例は、Amazon Cognito が JWT 形式で発行する一般的なアクセストークンのクレームセクションを示しています。

{
  "sub": "aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee",
  "cognito:groups": ["TENANT-1"
  ],
  "token_use": "access",
  "auth_time": 1562190524,
  "iss": "https://cognito-idp.us-west-2.amazonaws.com/us-west-2_example",
  "exp": 1562194124,
  "iat": 1562190524,
  "origin_jti": "bbbbbbbbb-cccc-dddd-eeee-aaaaaaaaaaaa",
  "jti": "cccccccc-dddd-eeee-aaaa-bbbbbbbbbbbb",
  "client_id": "12345abcde"
}

プリンシパルとプリンシパルが関連付けられているテナントは、ユーザー ID (sub クレーム) と cognito:groups クレーム内のテナント ID の組み合わせによってこのトークンで表されます。この例では、SaaS アプリケーションはテナントごとに Cognito グループを作成して、テナントを表します。他の ID プロバイダーでは、アクセストークンに反映されるカスタム属性をユーザーに追加できる場合があります。
SaaS アプリケーションがリクエストの一部として JWT を受け取ると、アプリケーションはトークンを検証し、その内容をアンパックしてリクエストを許可するかの決定を行います。トークン内のクレームによって、テナントコンテキストと呼ばれる状態が設定されます。環境変数がコマンドラインアプリケーションの処理に影響を与えるのと同じように、テナントコンテキストは SaaS アプリケーションによるリクエストの処理方法に影響します。
JWT を使用することで、SaaS アプリケーションは、外部 ID プロバイダーやその他の中央集権型のサービスを頻繁に参照することなく、リクエストを処理できます。

テナントの分離

テナントの分離は、すべての SaaS アプリケーションの基本です。各 SaaS アプリケーションは、あるテナントが別のテナントのリソースにアクセスできないようにする必要があります。SaaS アプリケーションは、あるテナントを別のテナントから適切に分離する境界を作成する必要があります。
何をもって十分な分離とするかは、お客様のドメイン、デプロイモデル、および適用されるコンプライアンスフレームワークによって異なります。テナントを相互に分離する手法は、使用する分離モデルとアプリケーションによって異なります。このセクションでは、テナント分離戦略の概要を説明します。

デプロイモデルが分離に影響する

アプリケーションのデプロイ方法は、テナントの分離方法に影響します。SaaS アプリケーションでは、サイロ、プール、ブリッジの 3 種類の分離を使用できます。

サイロモデル

サイロモデルは、テナントごとに 1 セットのインフラストラクチャを展開するモデルを意味します。アプリケーションによっては、テナントごとの Virtual Private Cloud (VPC) 、テナントごとのコンテナ群、またはテナントごとにデプロイされるその他のリソースを意味する場合があります。このモデルでは通常テナントごとにデプロイが行われますが、テナント横断での管理用の共有インフラストラクチャがある場合もあります。図 4 は、テナント単位の VPC モデルを使用するサイロ化されたデプロイメントの例を示しています。

テナントごとに VPC をプロビジョニングするサイロ化されたデプロイメントの例

図 4 — テナントごとに VPC をプロビジョニングするサイロ化されたデプロイメントの例

プールモデル

プールモデルは、すべてのテナントに対してインフラストラクチャが共有されるモデルを意味します。テナントの分離は、アプリケーションレベルの構成により、論理的に実装されます。テナントごとにリソースを分割するのではなく、アプリケーション内で分離が強制されます。図 5 は、サーバーレス技術を使用したプールデプロイメントモデルの例を示しています。

サーバーレス技術を使用したプールデプロイモデルの例

図 5 — サーバーレス技術を使用したプールデプロイモデルの例

図 5 では、すべてのテナントが共有する Amazon DynamoDB テーブルから項目を取得する AWS Lambda 関数は、AWS Security Token Service に一時的な認証情報の発行を要求します。この認証情報により、リクエスタは、リクエストを行ったテナントに属するテーブル内の項目にのみアクセスできます。リクエスタは、AWS Identity and Access Management (IAM) ロールを引き受けることで、これらの認証情報を取得します。これにより、SaaS アプリケーションは、テナント同士を分離したまま、基盤となるインフラストラクチャを共有できます。このパターンの詳細については、後述の「サービス機能を利用した分離の実施」を参照してください。

ブリッジモデル

ブリッジモデルは、サイロモデルとプールモデルの両方の要素を組み合わせたものです。一部のリソースはテナントごとに分かれている場合もあれば、一部はテナント間で共有されているものもあります。たとえば、アプリケーションに共有アプリケーションレイヤー と、テナントごとに Amazon Relational Database Service (RDS) インスタンスがあるモデルが考えられます。アプリケーション層は各要求を評価したうえで、リクエストを行ったテナントの専用データベースに接続します。
このブリッジモデルは、各テナントが一定の応答時間を必要とし、一部のリソースがボトルネックとなる場合に役立ちます。RDS の例では、アプリケーション層はテナントによって発行されるリクエストを処理できますが、1 つの RDS インスタンスでは処理できないという状況でした。
どの分離モデルを実装すべきかの決定は、お客様の要件、コンプライアンス要件、または業界のニーズによって決まります。プールモデルで導入できるお客様もいれば、規模の大きいお客様では専用のサイロのデプロイが必要な場合もあります。
テナント階層化 (Tiering) の戦略が使用する分離方法にも影響する場合もあります。たとえば、ベーシック階層 (Tier) の顧客はプールされたインフラストラクチャを利用し、エンタープライズ階層の顧客にはサイロ化されたインフラストラクチャを別途用意するということも検討可能です。
テナント分離モデルの詳細については、テナント分離戦略に関するホワイトペーパーをご参照ください。

サービス機能を利用した分離の実施

ほとんどの SaaS アプリケーションでは、状態やデータを保存する場所が必要です。これには、リレーショナルデータベース、NoSQL データベース、または状態を保持するその他のストレージなどがあります。AWS 上に構築された SaaS アプリケーションは、永続ストレージメディアにアクセスする際に、さまざまなメカニズムを使用してテナントの分離を実施することができます。
IAM は、AWS API に対してきめ細かなアクセスコントロールアクセスを提供します。Amazon Simple Storage Service (Amazon S3) や DynamoDB などの一部のサービスでは、IAM ポリシーを使用して個々のオブジェクトまたは項目へのアクセスを制御できます。可能であれば、IAM の組み込み機能を使用してテナントリソースへのアクセスを制限するようにアプリケーション側で実装するべきです。IAM を用いてテナント分離を行う方法については、「動的に生成された IAM ポリシーで SaaS テナントを分離する」をご参照ください。
AWS IAM には、タグに基づいてリソースへのアクセスを制限する機能もあります。これは属性ベースアクセス制御 (ABAC) と呼ばれます。この手法により、サポートされるリソースにタグを適用し、適用されるタグに基づいてアクセス制御を決定できます。これは、リソースが追加または削除されるたびに IAM ポリシーを変更する必要がないため、ロールベースアクセスコントロール (RBAC) よりもスケーラブルなアクセスコントロールメカニズムです。これを SaaS アプリケーションで利用する方法については「SaaSテナント分離をAWS IAMとABACで実装する方法」を参照してください。
一部のリレーショナルデータベースには、テナント分離を実施できる機能があります。たとえば、PostgreSQL には行レベルセキュリティ (RLS) と呼ばれる機能があります。クエリがデータベースに送信されるコンテキストによっては、テナント固有の項目だけが結果に返されます。PostgreSQLの行レベルセキュリティの詳細については「PostgreSQL の行レベルのセキュリティを備えたマルチテナントデータの分離」を参照してください。
その他の永続ストレージメディアでは、きめ細かな権限モデルを提供していません。ただし、テナントごとに何らかの状態コンテナを提供することができます。たとえば、MongoDB を使用する場合、各テナントには MongoDB ユーザーと MongoDB データベースが割り当てます。ユーザーに関連付けられたシークレットは AWS Secrets Manager に保存できます。テナントのデータを取得する場合、SaaS アプリケーションはまずシークレットを取得し、次に MongoDB で認証します。関連付けられた資格情報には、テナント専用のデータベース内のコレクションにアクセスする権限しかないため、結果的にテナントの分離を実施できます。
一般的に、使用している永続ストレージメディアがテナントの分離を実装できる独自の権限モデルを提供している場合は、その永続ストレージメディアを使用することをお勧めします。これにより、アプリケーションに分離を実装する必要がなくなるためです。ただし、データストアがこのレベルの分離を提供していない場合もあります。この場合、アプリケーションレベルでテナントの分離を実装する必要があります。アプリケーションレベルのテナント分離とは、永続的なストレージメディアの機能ではなく SaaS アプリケーションの機能として、あるテナントが別のテナントのデータにアクセスできないようにすることを意味します。

まとめ

この記事では、マルチテナント SaaS アプリケーションに関連する固有のセキュリティ上の考慮事項に関する課題、機会、ベストプラクティスを確認し、特定の アイデンティティ (ID) に関する考慮事項とテナントの分離方法について説明しました。
上記のトピックについてさらに詳しく知りたい場合は、AWS Well-Architected SaaS レンズセキュリティの柱で SaaS 環境でのパフォーマンス管理について深く掘り下げています。また、SaaS アプリケーションのパフォーマンス効率の設計と改善に役立つベストプラクティスとリソースも提供します。

AWS Well-Architected SaaS Lensを使い始める

AWS Well-Architected SaaS レンズは SaaS ワークロードに重点を置いており、SaaS ワークロードの開発と運用に関する合理的・客観的な考え方を促進することを目的としています。レンズの各質問にはベストプラクティスのリストがあり、各ベストプラクティスには、実装の指針となる改善計画のリストがあります。
レンズは既存のワークロードに適用することも、新しいワークロードに利用することもできます。これを使用して、開発中・運用中のアプリケーションを改善したり、自分の組織やグループで利用されている複数のワークロードを可視化したりすることができます。
SaaS レンズは、AWS Well-Architected Tool が提供されているすべてのリージョンで利用できます。利用できるリージョンの一覧は AWS Regional Services List をご参照ください。AWS Well-Architected ツールの使用に費用はかかりません。
レビューが必要なお客様は AWS Well-Architected パートナーAWS SaaS コンピテンシー取得パートナーからレビューを実施できる AWS パートナーを見つけることができます。

翻訳はソリューションアーキテクト 柴田 が担当しました。原文はこちらです。