OPEN

SaaS のテナント分離戦略について

  • The isolation mindset

    https://docs.aws.amazon.com/whitepapers/latest/saas-tenant-isolation-strategies/the-isolation-mindset.html

    • 分離はオプショナルではない
      • 分離は SaaS の基本的な構成要素である
      • マルチテナント型 SaaS のプロバイダは、テナントのリソースを分離するための方策を取る必要がある
    • 認証/認可と分離は別物
      • ログイン管理/アクセス管理を下からと言ってリソースを分離したことにはならない
      • 分離というパズルのピースの一つであるけど、それだけで充分ではない
    • 分離の実装/強制は SaaS 利用者に委ねてはならない
      • 分離を侵害するようなコードを書くとは思わないが、確実ではない。
      • そもそもそのようなことが起こらないように、アクセススコープの管理は分離規則を管理する共通の処理によって行われるべき
        • SaaS 利用者に委ねない、ということ
    • 分離のための既存のソリューションがなければ自作する必要がある
      • AWS Identity や IAM など、テナント分離を容易にするソリューションは多数存在する
      • これらを組み合わせることでテナント分離をある程度シンプルに実現できることもある
      • しかし、既存のソリューションが適さない場合ももちろんある。
      • だからといってそれがテナント分離の要件を引き下げる理由になってはならない。なければ自作すること
    • 分離はリソースレベルの構成要素ではない
      • マルチテナントと分離の文脈では、分離を具体的なインフラリソースの境界と見る向きもある
        • これはDB、ECS、VPCなどのインフラ全体をテナント毎に運用することに繋がる
        • 確かにこれはよくある分離の形態のひとつであるが、テナント分離の実現方法はこれだけではない
      • 各種リソースを共用するような場合においても、テナント分離は実現できる
        • このようなリソース共有型のモデルでも、分離は論理的な構成要素として、ランタイムに実現可能
      • 要点: 分離はリソースのサイロ化によってのみ実現するものではない
    • 事業ドメインによっては特定の分離要件がある
      • テナント分離のアプローチは様々あるが、事業ドメインによっては特定のアプローチが必要な場合もある
      • 例えば高いコンプライアンスが求められる業界では、ポリシーベースの分離では不十分で、テナント毎にDBを用意する必要があるかもしれない。
  • Isolation: Security or noisy neighbor?

    https://docs.aws.amazon.com/whitepapers/latest/saas-tenant-isolation-strategies/isolation-security-or-noisy-neighbor.html

    • 分離というトピックはカテゴリ分けしづらい
    • 一般的にはセキュリティやコンプライアンスという文脈で考慮されることが多い
      • テナント間のリソースアクセスを制限する境界をつくるため
    • これは重要な要素である一方、「ノイジー・ネイバー」やパフォーマンス問題を解決するための分離、という観点もある
    • このペーパーでは、セキュリティによる重きを置きつつも、両方の観点をカバーしていく

    ノイジー・ネイバー: 共有リソースを一部のテナントが大量に消費して、別のテナントに悪影響(パフォーマンス下がるとか)がでる問題

  • https://docs.aws.amazon.com/whitepapers/latest/saas-tenant-isolation-strategies/silo-isolation.html

    Core isolation concepts - Silo isolation

    • テナント毎に個別のリソーススタックを用意する
      • E2E で完全に分離されたテナント分離を実現する
    • Pros
      • 厳しいコンプライアンスモデルのサポート
      • ノイジー・ネイバーの懸念なし
      • テナント毎のコスト計算
      • 障害の影響範囲が狭い
    • Cons
      • ビジネスのスケール
        • 作成できるアカウントの数に限りがある
        • アカウントが増えたときのメンテコスト
      • コスト
        • 全アカウントが個別の環境を持つのでコスト高い
      • フットワークの軽さ
        • 非中央集権的なサイロ型はメンテナンスコストが高いので、プロダクトの迅速な進化の足かせとなる可能性がある
      • 管理と監視の非中央集権化
        • すべてのテナントの活動を単一のツールで管理・監視できるようにしたい
        • しかしサイロ化したマルチテナントでは、各テナントのインフラからデータを集計しなければならないので、難易度が高い
          • 実現可能ではあるけども、比較的コストが高い
  • https://docs.aws.amazon.com/whitepapers/latest/saas-tenant-isolation-strategies/pool-isolation.html

    Core isolation concepts - Pool isolation

    • サイロ型は分離という観点ではとてもわかり易いし効果的
    • しかし、SaaS を作りたい企業は、テナント間でリソース/インフラを共有することによる効率さとか機敏さ、コスト効率も求めているはず
    • プール型はインフラを共有するアプローチ
    • プール型では、全テナントが共通のインフラを利用する
      • 計算資源だけでなく、DBも共有している
        • テーブルはテナントIDによってインデックスされている
    • このモデルは、SaaS プロバイダー的には効率がいいものの、テナント分離という観点では物事を複雑にしている
      • リソースが共有されているので、テナント分離の実装が何を意味するのか不明瞭
      • 典型的なネットワークや IAM による境界定義が行えない
    • 実装はよりチャレンジングではあるが、だからといって テナント分離の要件を緩和する言い訳にしてはならない
      • プール型では、別テナントのデータにアクセスしてしまう危険性は高まる
        • そのため、リソースの分離を確実にすることに特に注意を払う必要がある
    • Pros
      • 開発の機敏さ
        • よりシンプルになるので、開発速度が上がる
        • 管理する環境が一つになるので、サイロ型のようなテナント毎に必要な作業がなくなる
      • コスト
        • プール型にすることで、インフラはテナント全体の利用に応じてスケールするようになる。
      • 管理/運用がシンプル
      • イノベーション
        • 運用/管理がシンプルになるので、より機能にフォーカスできる→イノベーションが生まれる
    • Cons
      • ノイジー・ネイバー
        • リソースを共有すればするほど、テナント間で計算資源の奪い合いになる可能性が上がる
        • 良いマルチテナントアーキテクチャはこの影響を最小限に抑えようとするが、プール型だとこの影響を完全に取り除くことはできない
      • テナント毎のコスト計算
        • より細かいデータの集計が必要
      • 障害の影響範囲
        • 障害は基本的に全テナントに影響する
        • 障害を特定し、表面化し、障害からうまく回復できるレジリエントな環境の構築に、さらに深く取り組む必要がある。
      • コンプライアンス
        • ロジック的にテナント分離は実現されていても、インフラを共有するため、顧客がこの運用を嫌がる可能性がある
        • これはコンプライアンスの遵守や規制が厳しい事業ドメインで特に顕著
          • このような場合は、システムの一部をサイロ化する必要あり
            • ブリッジ型を参照のこと
  • https://docs.aws.amazon.com/whitepapers/latest/saas-tenant-isolation-strategies/the-bridge-model.html

    Core isolation concepts - The bridge model

    • サイロ型やプール型は分離に対して非常に明確なアプローチであるが、SaaS プロバイダ的には分離の見方はそれほど絶対的なものではない
    • 実際のアプリケーションを見てシステムをより小さなサービスに分解していくと、サイロ型とプール型両方のアプローチが混在が必要なことがわかる
      • これをブリッジ型と呼ぶ
    • 図(元サイト参照のこと)だと
      • Web層は共通
      • ビジネスロジックのあるアプリケーション層とDBは個別
    • このモノリスをマイクロサービスに分割しようと思うと、各種マイクロサービスはサイロ型とプール型が混在するだろうことが想像できる
    • AWS の各機能を利用してどの用にサイロ型やプール型を実装していくかについては、また別の項で説明する
    • 重要なことは、サイロとプールの見方は、様々な分離要件を持つサービスの集まりに分解された環境では、より細かくなるということ
    • Pros and Cons
      • ブリッジ型はサイロ型とプール型のハイブリッドで、それぞれの機能に適した実装を選択することができる
      • サイロ型の価値観や信条はシステムの各領域に依然として適用される
      • Pros and Cons を考える歳は、アーキテクチャの各リソースやレイヤについて、サイロ型・プール型のトレードオフを考える必要がある
  • https://docs.aws.amazon.com/whitepapers/latest/saas-tenant-isolation-strategies/tier-based-isolation.html

    Core isolation concepts - Tier-based isolation

    • プランに応じてサイロ型/プール型を提供する
    • アプリのアーキテクチャというよりは、サービスのパッケージング寄りの考え方
    • 基本的に、プール型と同じバージョンをサイロ型でも使う
      • この時サイロ型の環境はプール型のクローンで、たまたま1テナントだけが使ってるのでサイロ型になっている、という状態
  • https://docs.aws.amazon.com/whitepapers/latest/saas-tenant-isolation-strategies/identity-and-isolation.html

    Core isolation concepts - Identity and isolation

    • アイデンティティがどの用に分離と結びついているか考えるのも必要
    • テナントの分離を検討しているのであれば、現在 SaaS 環境のリソースにアクセスしているテナントを表し、識別することが必要になる
    • 多くの場合、アイデンティティは他の構成要素と組み合わせて、分離スキームのコアとなるスコープ・ルールやポリシーを取得するために使われる
    • このポリシーの定義や適用方法は各分離モデルやサービスによって異なる
    • しかし、アプローチの基本は図5(元サイト参照のこと)のようになる
    • この図はアイデンティティがより広い分離モデルのストーリーの中にどの用に組み込まれるかを一般化したもの
      • ユーザが認証されると、システムはテナント・コンテキストをアプリケーションに返す
        • ユーザの属するテナント情報と、そのテナントを分離するためのポリシーを含む
      • このコンテキストはすべてのインタラクションを通じてアクセスでき、SaaS 環境の顆粒の要素によってリソース(この場合はDB)へのアクセスを限定するために使われる
    • スコープの取得や適用は分離モデルや利用するリソースによって異なるが、中核となる概念は同じ
    • 重要なバリエーションとして、テナント・スコープの決定方法がある
      • このスコーピング・コンテキストはデプロイ時に決定されることもあるし、ランタイムに取得されることもある
      • それぞれの詳細は様々なアーキテクチャにおける具体的な分離の特徴を見ながら触れていく
  • https://docs.aws.amazon.com/whitepapers/latest/saas-tenant-isolation-strategies/subnet-silo-isolation.html

    Implementing silo isolation - Subnet silo isolation

    • VPC の中の個別の subnet で管理する
    • ネットワークのルーティング周りでテナント間アクセスを防ぐ
    • 有効ではあるが、おすすめしない
      • メンテナンスコスト、スケール上の課題ですぐに破綻する

    Targeted silo isolation

    • 一部のマイクロサービスだけサイロ型にする
    • TBD
  • https://docs.aws.amazon.com/whitepapers/latest/saas-tenant-isolation-strategies/silo-compute-considerations.html

    Implementation silo isolation - Silo compute considerations

    • (前述のマイクロサービスのような)アプリケーションをサイロ化する場合、様々な計算資源の分離モデルが、どの用にアプローチに影響するか考える必要がある。
    • 様々なAWSコンピュートサービスのユニークな属性は、リソースが適切に分離されることを保証するために特定の手段を取ることを要求するかもしれない
    • コンテナを使ってサイロ化する場合
      • 悪意のあるコードや設定不十分な環境がコンテナをすり抜け、あるテナントが別のテナントの情報にアクセスできるパーミッションがあるとみなしてしまうケースがある
      • コンテナは適切に使用されれば堅牢な分離モデルを実装することができる
      • テナント間のアクセスを防ぐ機構は、AWS のコンテナサービスによって異なる
        • ECS では、サイロ分離を実現するためにテナント毎にクラスタを作る必要がある
        • ECK では、EKS クラスタ内でリソースをサイロ化する追加の仕組みがある
          • 図10
            • EKS namespace を利用してテナントを分けている
            • しかし namespace だけで完全なサイロ化を実現することはできない
            • たとえば AWS App Mesh や Tigera Calico のようなソリューションと併用する
    • AWS Lambda を使う場合
      • Lamba function はそもそも分離されている、と考えるかもしれないが、 Lambda function が前テナントをサポートする実行ロールでデプロイされている場合はその限りではない。
      • プールはこれを回避する方法を提供してくれる
        • しかしこれは、この関数が他のテナントからは実行できない、ということを意味している
        • 図11 は Lambda で完全な分離を実現する方法の例
          • テナントの分離を実現するため、テナント毎に個別の Lambda fucntion をデプロイしている。
            • テナント専用の実行ロールで
          • 説得力のあるソリューションに見えるが、扱いにくく、 AWS Lambda の制限を超える可能性がある
            • 1K のテナントがあるときの管理・デプロイを想像すると…
            • SaaS の機敏さを損なう可能性
            • 一部のプレミアムプランでのみ提供、ならあり得るかも
    • 要点: サイロ型の実装を検討する際は、採用するAWSサービスによって個別の実現方法を検討する必要がある
  • https://docs.aws.amazon.com/whitepapers/latest/saas-tenant-isolation-strategies/silo-for-any-resource.html

    Implementation silo isolation - Silo for any resource

    • どのようなリソースであってもサイロ型でデプロイ可能
    • 利用する AWS サービスを分離するストラテジーや機構はものによって異なる
      • DynamoDB ならテーブルを分けるかも
      • 別のストレージサービスなら、テナント毎に個別のクラスタが必要かも
      • SQS や EventBridge はまた別のアプローチが必要
      • → 要件によってサイロ化すべきものを適切に選別するべき
    • 基本的には、あらゆるリソースについて、ノイジー・ネイバーやセキュリティプロファイルを評価することが必要
      • サイロ化することで得られるメリットとデメリットを比較検討する
  • https://docs.aws.amazon.com/whitepapers/latest/saas-tenant-isolation-strategies/implementing-pool-isolation.html

    Implementing pool isolation

    • SaaS プロバイダにとってプール型は魅力的
      • 効率性、機敏さ、コストなど、事業者が SaaS モデルを提供しようとした動機づけになるものが多い
    • もちろん、リソースを共有モデルに移行するとより困難な分離の問題に直面する
    • 分離を実現するツールや仕組みと、共有リソースを消費するテナントの間には、根本的なミスマッチが存在する
    • プール型で共有したい各リソースについて、分離を実現するためにはそれぞれ異なるアプローチが必要になりうる、という点も問題を複雑にしている
    • これらの困難は実際に存在するが、これを動機に分離要件を緩和するべきではない
      • 単にプール型でリソース分離を実現するために、ツールや構成要素の組み合わせを見つけるためにより頑張らなければならない、というだけ

    • 具体的なプール型の分離テクニックを掘り下げる前に、プール型が分離へのアプローチをどのように変えるかを明確にイメージしよう
    • 一般的に AWS リソースの分離について話す場合、IAM を利用してどのようにリソース間のインタラクションを管理するか、に焦点を当てる
    • 事実サイロ型では、IAM はテナント分離ポリシーを表現するのに最適である
    • プール型では、IAM の利用はもう少し複雑
    • 図12(元サイト参照のこと)はサイロ型とプール型のマインドセットの違いを表している
      • IAM ポリシーをそれぞれのモデルでアクセスを限定するためにどう適用しているか
      • 左には2つのサイロ型デプロイがあり、テナントはそれぞれのインフラで稼働している
        • これらのテナントはどちらも他のリソース(ストレージ)にアクセスしている
        • これらのインスタンスがデプロイされた時、各テナントに個別の IAM インスタンスプロファイルが設定される
        • これはデプロイ時に作成されるため、核テナントが別テナントのリソースにアクセスできないようにすることができる
      • 右にはプール型でデプロイした compute node がある
        • これらのノードは、すべてのテナントに代わって実行される
        • この事実はここにデプロイされているノードに対する IAM プロファイルのスコープに直接影響する
        • ノードを特定のテナントに制限するかわりに、すべてのテナントをサポートするのに充分オープンなプロファイルで、ノードをデプロイする必要がある
        • この広いスコープがプール型の本当の問題を引き起こす
        • 実装しようとしている SaaS ソリューションによって矯正されるアクセスの制限を実装する、新しい方法を考え出す必要がある

    • これらプール型分離のユニークな側面を考慮すると、プール型で分離を実現するための選択肢はそれぞれ大きく異なることがわかる
    • すべての組み合わせについて調べることは本稿の範囲を超えているが、よく適用される様々な戦略についてより良い感触を得るためにいくつかの一般的なパターンを調べることはできる
    • 以下のセクションではこれらの戦略の概要を説明する
  • https://docs.aws.amazon.com/whitepapers/latest/saas-tenant-isolation-strategies/run-time-policy-based-isolation-with-iam.html

    Implementing pool isolation - Run-time, policy-based isolation with IAM

    • プール型の環境では、リソースを分離する戦略を見つけるために IAM を利用するのが一般的
    • しかし上述したように、プール型で分離を実現するためには、 IAM の適用方法に工夫が必要
    • コンビュート・ノードの IAM スコープを継承するかわりに、プール型分離モデルを実行時に矯正するためのコードを書く必要がある
    • 図13(元サイト参照のこと)はこのモデルの概念図
      • この図では、いくつかの下流リソース(DB, S3バケットなど)へのアクセスが必要なマイクロサービスがある
      • このマイクロサービスはプール型でデプロイされ、複数テナントのリクエストを処理する
      • このマイクロサービスの仕事は、リクエストを処理する時に、テナントが別のテナントのリソースへの境界を超え内容に製薬を適用すること
      • この図では、マイクロサービスが分離マネージャと連携して、マイクロサービス内のコードによってアクセスされるリソースを制御するために使用されるスコープ・コンテキストを取得していることがわかる
      • この概念モデルで、未確定要素をある程度見渡すことができる
      • しかしこれを実際に見るには、このコンテキストがどのひょうに表現されて起用されるかを説明する、より具体的な戦略を考えていく必要がある
    • 図14(元サイト参照のこと)はテナント・リソースへのアクセスの実行時制限の一部として、IAM がどのように利用できるかを詳しく示している
      • 実行時にポリシーの設定と適用を行う場合のライフサイクル全体を見ることができる
      • 最初のステップでは、テナントがシステムにオンボードする
        • このプロセスでは、テナントのユーザと IAM ポリシーを設定する(step 2-3)
      • テナントがオンボードしたら、アプリケーションのマイクロサービスに通知する(step 4)
        • このマイクロサービスはプール型で実行されているため、全テナントのリソースにアクセスできる広範な IAM スコープでデプロイされている
        • 我々の仕事は、このサービスに送信されるリクエストを見て、そのリクエストのスコープを単一のテナントに絞り込むこと
        • これを分離マネージャに現在のテナントの認証セットを要求することで実現する(step 5)
        • 分離マネージャはテナントの IAM ポリシーを検索する(step 6)
        • そしてテナントにスコープされた認証情報セットを生成し、呼び出し元のマイクロサービスに返す
        • 最後に、マイクロサービスは返却された認証情報を使って DB にアクセスする(step 7)
        • これらのテナントにスコープされた新しい認証情報により、マイクロサービスのコードは別テナントのリソースにアクセスできないようになる
    • このモデルでは、基本的にマイクロサービスが他のリソースにアクセスしようとするたびに、このテナントコンテキストが適用されることになる
    • この制約は、「マイクロサービスは、各テナントのリソースにアクセスする前に新しい認証情報を取得する」という規約の結果として適用される
  • https://docs.aws.amazon.com/whitepapers/latest/saas-tenant-isolation-strategies/scaling-and-managing-pool-isolation-policies.html

    Implementing pool isolation - Scaling and managing pool isolation policies

    • IAM ポリシーは強力な分離構造を提供する一方で、SaaS プロバイダにスケーリング上の課題を突きつけることもある
    • システム上に多数のテナントがあり、ポリシーの母数が多い場合、 IAM サービスの限界を超える可能性がある
    • テナントの数やポリシーの複雑さが増すにつて、これらのポリシー管理が難しくなる可能性もある
    • こういった場合、一部の SaaS プロバイダは実行jIに IAM ポリシーを生成して管理する方法について、別のアプローチを試みる

    • この課題へのアプローチの一つは、IAM ポリシーをランタイムに生成するモデルへの移行である
      • 現在の呼び出しコンテキストを調べ、必要な IAM ポリシーをその場で生成する仕組みをシステムに実装する、というアイデア
      • これにより、ポリシーは IAM から移動し(一過性であるため)、すべてのテナントをサポートするのに必要なポリシー数の潜在的な制限に対処できるようになる
      • 図15(元サイト参照のこと)は、このポリシー動的生成機構の概要を示している
        • このフローは、先程の例と同じ分離マネージャから始まる
        • しかし直接 IAM にアクセスし、アクセス・スコープの制限に必要なポリシーを取得するのではなく、一連のステップを踏んでポリシーを生成する
        • 分離マネージャはまず、トークン自動販売機にリクエストを行い、テナント・スコープのトークンを取得する(step 1)
        • テナント分離モデル用に事前に定義したテンプレートにアクセスするのはトークン自動販売機の責務(step 2)
          • これらは従来の IAM ポリシーの動的な部分を設定できるテンプレートファイルだと考えられる
          • ファイルの重要な要素(テナントのコンテキストを表す要素)は記入されていない
          • たとえば、DynamoDB のテーブル名やテーブルのキー条件をテナント識別子で埋めることができる
        • 必要なテンプレートが取得できたら、次はトークン生成機にトークンをリクエストする(step 3)
          • このステップでは、テナント・コンテキストを渡す
          • トークン生成機はテナントの詳細情報をテンプレートに埋め込み、完全に hydrated な IAM ポリシーを作成する(step 4-5)
          • 最後にトークン生成機はこのポリシーを利用して、ポリシーに則ったスコープを付与されたトークンを生成する
          • トークンは分離マネージャに戻され、各テナントのリソースにアクセス可能になる(step 6-7)
        • これらのポリシーをテンプレートに移行することで、これらのポリシーがテナント分離要件を実施することを保証する責任を、あなたが負うことになる
        • 理想的には、このメカニズムの詳細は開発者の視界にほとんど入らないため、何か問題が発生する可能性は低くなる
    • このモデルの利点の一つは管理面
      • 各テナントごとに個別のポリシーを作成する必要がないため、隔離ポリシーを変更する場合、その変更を適用するための経路がより簡単になる
      • また、これらのポリシー・テンプレートのコンテンツ・ライフサイクル(独自のパイプラインを通じたバージョン管理とデプロイ)を管理することができる