マルチテナントセキュリティ
このドキュメントの目的
マルチテナントSaaSにおけるデータ分離以外のセキュリティを理解し、テナント間の安全性を確保する設計ができるようになることが目標です。
データパーティション化とテナント分離ではデータの分離方法(RLS等)を、テナント別設定管理とテナントカスタマイズパ ターンではテナントごとの挙動制御を学びました。本記事では、認証分離、権限設計、監査、レート制限、インシデント対応などデータ分離以外のセキュリティ全般に焦点を当てます。
具体例について: 本記事ではIDサービスを題材にした例(OAuth トークン、セッション分離等)を使用していますが、マルチテナントセキュリティの原則はSaaS全般に共通です。
テナント間の認証分離
セッション分離
マルチテナント環境では、あるテナントのセッションが別のテナントで利用されてはなりません。
正しいセッション分離:
Tenant A: Session-A ──> Tenant Aのリソースにのみアクセス可能
Tenant B: Session-B ──> Tenant Bのリソースにのみアクセス可能
クロステナント攻撃(防止すべき):
攻撃者: Session-A ──> Tenant Bのリソースにアクセス(NG!)
セッション分離の実装方法:
| 方式 | 説明 | セキュリティレベル |
|---|---|---|
| セッションにテナントIDを紐付け | セッション作成時にtenant_idを記録し、リクエスト時に検証 | 基本 |
| Cookie Domain分離 | テナントごとに異なるドメイン(tenant-a.example.com) | 高 |
| セッションストア分離 | テナントごとに異なるセッションストアを使用 | 最高 |
トークンスコープの分離
OAuth 2.0トークンには、テナント情報を含めてクロステナントアクセスを防止します。
アクセストークンの構造:
{
"sub": "user-123",
"tenant_id": "tenant-a", ← テナントの明示
"scope": "read:users",
"iss": "https://tenant-a.example.com",
"aud": "https://api.example.com"
}
検証フロー:
リクエスト受信
│
▼
┌──────────────────┐
│ 1. トークン検証 │ ← 署名、有効期限
├──────────────────┤
│ 2. テナントID検証 │ ← トークンのtenant_idとリクエスト先が一致
├──────────────────┤
│ 3. スコープ検証 │ ← 操作に必要なスコープがあるか
└──────────────────┘
│
▼
アクセス許可 or 拒否
クロステナント攻撃の防止
主要な攻撃パターンと対策:
| 攻撃パターン | 説明 | 対策 |
|---|---|---|
| テナントID改ざん | リクエストのテナントIDを書き換え | トークン内のtenant_idと照合 |
| セッション固定攻撃 | 他テナントのセッションを利用 | セッションにtenant_idを紐付け |
| IDOR(Insecure Direct Object Reference) | 他テナントのリソースIDを推測 | リソースアクセス時にtenant_idを検証 |
| JWT混同攻撃 | 異なるテナントのJWTを流用 | issuer(iss)をテナント単位で検証 |
| 認可コード横取り | 他テナントの認可コードを利用 | 認可コードにtenant_idを紐付け |
テナント管理者の権限設計
ロールベースアクセス制御(RBAC)
テナント内の権限はロールで管理します。システム管理者とテナント管理者を明確に区別します。
権限の階層:
┌──────────────────────────────────────────┐
│ システム管理者(SaaS運営者) │
│ │
│ ・全テナントの管理 │
│ ・テナントの作成・削除 │
│ ・システム設定の変更 │
│ ・プラン・課金の管理 │
├──────────────────────────────────────────┤
│ テナント管理者(顧客の管理者) │
│ │
│ ・自テナント内のユーザー管理 │
│ ・自テナントの設定変更 │
│ ・自テナントの監査ログ閲覧 │
│ ・他テナントへのアクセスは一切不可 │
├──────────────────────────────────────────┤
│ テナントユーザー(顧客のエンドユーザー) │
│ │
│ ・自分のプロファイル管理 │
│ ・許可されたリソースへのアクセス │
│ ・管理機能へのアクセスは不可 │
└──────────────────────────────────────────┘
最小権限の原則
テナント管理者には必要最小限の権限のみを付与します。
権限マトリック ス:
操作 │ システム管理者 │ テナント管理者 │ テナントユーザー
────────────────────────┼───────────────┼───────────────┼────────────────
テナント作成・削除 │ ○ │ × │ ×
テナント設定変更 │ ○ │ ○ │ ×
ユーザー作成・削除 │ ○ │ ○ │ ×
ユーザープロファイル閲覧 │ ○ │ ○ │ 自分のみ
監査ログ閲覧 │ 全テナント │ 自テナント │ ×
他テナントデータ閲覧 │ ○ │ × │ ×
権限エスカレーション防止
テナント管理者が自分の権限をシステム管理者レベルに昇格させることを防ぎます。
防止すべきパターン:
1. テナント管理者が自分にシステム管理者ロールを付与
→ 対策: ロール付与APIで上位ロールの付与を禁止
2. テナント管理者が他テナントの管理者ロールを取得
→ 対策: ロール操作は自テナント内に限定
3. テナント管理者がAPI直接呼び出しで権限チェックを回避
→ 対策: 全APIエンドポイントでサーバーサイド権限チェック
実装のポイント:
- ロール付与は「自分と同じか下位のロール」のみ許可
- テナント境界を越えるロール操作は一律拒否
- 権限チェックはクライアントサイドではなくサーバーサイドで実施