課題と判断基準
2026年9月26日時点
A社の社員としてログインして注文を開くとB社の注文が見えます。ログインは成功しAPIも正常応答しました。この設計例で問うのはパスワードではなく、サーバーがその社員にその注文へのその操作を許可してよいか判断したかです。
マルチテナント試験は利用者と役割の変更だけで終えません。利用者・役割 × テナント × オブジェクト × 操作を組み合わせ、詳細画面からファイル・バックグラウンドまで同境界を確認します。ログイン成功や有効トークンはオブジェクト許可の十分条件ではありません。[1][2]
本記事は複数顧客組織が使うSaaS注文システムを例にします。アカウント・注文・方針は合成した設計例で、実顧客・事故ではありません。所有者が許可した隔離環境だけで検証します。
ログイン、役割、注文、組織の境界を別に問う
認証は誰かを確認し、認可はどの資源にどの操作を許すか決めます。本記事のテナントは組織別データ・権限の境界です。同じ基盤でも組織間制限を明示設計します。[1][3]
注文APIでは次を分けます。
| 区分 | 確認する問い | 欠落時の例 |
|---|---|---|
| 認証・セッション | 主体を信頼できるか、セッションは有効か | 未ログイン要求を処理 |
| 役割・機能 | 削除・エクスポートを実行できるか | 閲覧者が管理者エクスポートを実行 |
| オブジェクト | この注文を読む・変える権利があるか | 同組織の他社員注文を無許可参照 |
| テナント | この組織で行動でき、対象もその範囲か | A管理者がB注文を削除 |
OWASP API Security Top 10 2023はオブジェクト権限のBOLAと機能権限のBFLAを分けます。注文参照機能の利用許可は全注文の閲覧許可ではありません。UUIDのように推測困難なIDでも検査は必要です。[2][4]
全体を許可しても属性境界が残ります。注文は読めても内部メモは不可、メモ編集は可能でもtenant_id・owner_id変更不可という場合です。BOPLA(オブジェクト属性レベル認可不備)はこうした読書き制限を扱います。[5]
製品の文脈を保ち、実行規模を調整 — 固定リードが基準と履歴を引き継ぎ、期間ごとのスクワッドの実行結果を判断の根拠にまとめます。
先にサービスの許可規則を固定する
「他社員の注文をすべて遮断」も普遍的正解ではありません。共同担当や組織管理者に必要なら正常アクセスです。許可規則なしに拒否だけ増やすと正常業務も止める実装を合格させます。
OWASP ASVS 5.0.0 V8は機能・データ・属性規則の文書化・適用とテナント間制御を分けます。表に移す際は役割名よりどの関係で許可するかを記す方が有用です。[6]
設計例:注文システムの方針と合成データ
Aには会員U_A1・U_A2、管理者ADM_A、閲覧者VIEW_A、Bには会員U_B1と管理者ADM_Bがいます。O_A1・O_A2・O_B1は対応会員の所有で該当テナントに属します。全件が試験用下書きで、検索名に「合成」を含めます。会員・組織管理者・閲覧者への応答はorder_id・status・memoだけです。
会員は自分の注文参照・作成・メモ編集を許可します。管理者は自テナントの参照・メモ編集・下書き削除・エクスポートを行えます。閲覧者は割当注文だけ読み、VIEW_AにはO_A1だけ割り当てます。同テナントでも会員間で自動共有しません。
支援担当SUPPORT_Xは既定アクセスなしです。別承認の有効期間だけO_A1のIDと状態を読め、変更・削除・エクスポートは不可です。広い支援権限が必要なら別承認範囲として文書化します。
一般更新でテナント・所有者は変えられません。一括更新では一件でも無権限なら全件拒否を選びます。各例は初期データへ復元して独立確認します。
利用者・役割 × テナント × 対象 × 操作を表にする
以下は方針から導く代表検証例で、標準全項目や実行済み結果ではありません。OWASPは役割・機能・データの表と複数アカウントでの検証を提案しており、それを注文・顧客境界へ具体化します。[7][8]
詳細参照と変更
| 例 | 利用者・役割 | テナント・対象 | 操作 | 期待結果・証拠 |
|---|---|---|---|---|
| M01 | U_A1・会員 | A・自分のO_A1 | 参照 | 許可。order_id=O_A1、status、memoだけで他注文なし |
| M02 | U_A1・会員 | A・他会員のO_A2 | 参照 | 拒否。注文本文・所有者情報なし |
| M03 | ADM_A・管理者 | A・O_A2 | 参照 | 許可。管理者の正常業務を止めない |
| M04 | U_B1・同じ会員役割 | A・O_A1 | 参照 | 拒否。同役割でも他テナントは不可 |
| M05 | ADM_B・管理者 | A・O_A1 | 参照 | 拒否。B権限はAへ広がらない |
| M06 | VIEW_A・閲覧者 | A・割当O_A1 | 参照 | 許可。非所有でも明示割当が適用 |
| M07 | VIEW_A・閲覧者 | A・O_A1 | メモ編集 | 拒否。メモと業務イベントは不変 |
| M08 | U_A1・会員 | A・自分のO_A1 | メモ編集 | 許可。指定メモのみ変更し所有者・テナント維持 |
| M09 | U_A1・会員 | A・他会員のO_A2 | メモ編集 | 拒否。応答だけでなく保存値も不変 |
| M10 | ADM_A・管理者 | B・O_B1 | 削除 | 拒否。注文・添付・業務状態を維持 |
| M11 | ADM_A・管理者 | A・下書きO_A2 | 削除 | 許可。O_A2だけ削除し他二件を維持 |
一覧、一括処理、作成、支援アクセス
| 例 | 利用者・役割 | テナント・対象 | 操作 | 期待結果・証拠 |
|---|---|---|---|---|
| M12 | U_A1・会員 | A・「合成」で三件一致 | 一覧・検索 | O_A1のみ、許可総数1。他二件の題名・集計なし |
| M13 | ADM_A・管理者 | A・O_A1、O_A2 | 一括メモ編集 | 許可。二件のみ変更、O_B1不変 |
| M14 | ADM_A・管理者 | A・B混在、O_A1、O_B1 | 一括編集 | 全拒否。例の原子的方針で両方不変 |
| M15 | U_A1・会員 | 無権限Bを選択 | 作成 | 拒否。Bに行・ファイル・イベントなし |
| M16 | U_A1・会員 | 権限のあるA | 作成 | 許可。サーバー確認AとU_A1所有で一件、Bにはなし |
| M17 | U_A1・会員 | A・自分のO_A1 | tenant_id・owner_id変更 | 拒否。一般更新で移転できず旧値維持 |
| M18 | SUPPORT_X・有効承認 | A・承認O_A1 | 参照 | 許可。ID・状態のみ。監査に実担当と承認ID |
| M19 | SUPPORT_X・同承認 | A・範囲外O_A2 | 参照 | 拒否。同テナントの他注文へ広がらない |
| M20 | SUPPORT_X・同承認 | A・O_A1 | エクスポート | 拒否。参照承認はダウンロード・出力承認ではない |
M14全拒否はこの例の選択です。部分成功なら許可対象だけ処理し、拒否対象の内容・変更・副作用なしという別期待を定めます。先頭一件だけ検査して残りを処理する方式はどちらにも適しません。
拒否を403か存在を隠す404にするかはAPI方針で決めます。状態コード一つを合格基準にはしません。 データが残る応答や変更済み保存庫なら拒否できていません。WSTGも役割別の非公開応答と実動作を確認します。[9]
クライアントのtenant_idは選択値で、権限証拠ではない
複数組織の利用者が画面で組織を選ぶのは正常です。問題はサーバーが無検証で信じることです。URL・本文・ヘッダーのIDは選択組織を示すだけで行動権を証明しません。認証主体の現在メンバーシップ・サービス権限と結び付けて検証します。[10]
言語に依存しない設計順序の例は次です。
セッション・トークン検証 → 選択テナントの現権限 → 操作と対象関係 → 許可属性決定 → 参照・変更 → 許可結果のみ返却
照会には対象IDだけでなく検証済みテナントと所有・割当条件を適用します。組織別に権限を確認し、A管理者役割をBへ持ち込みません。所属確認不能・文脈欠落では全データへ広げず失敗させます。
Next.js App Router公式認証ガイドはProxyの簡易事前検査とDALの権限検査を分けます。Server Actionsも公開API同様の考慮と独自検査が必要です。ボタンを隠しても直接呼出しを防いだとは言えません。セッション・役割例を適用しても注文所有・テナント所属規則は追加が必要です。[11]
権限変更後、同じセッションで確認する
再ログイン後だけでは古い権限の残存を見逃します。発行後に所属・役割を変え、既存セッション・トークンを維持した要求で確認します。ASVS 5.0.0 8.3.2は判断値の変更反映を扱い、自己完結トークン等の遅延への補完制御も情報流出を取り消せないとします。[6]
本例は変更確定後に開始する次の検査から新方針を適用します。実行中要求と配信済みデータは別です。伝播遅延があるなら許容時間・リスク・遮断装置を先に定め、その境界を試験します。理由なくトークン満了まで許可しません。
| 例 | 変更条件 | 維持する要求条件 | 期待結果 |
|---|---|---|---|
| T01 | U_A1のA所属削除 | 以前のトークンでO_A1参照・編集 | 全拒否。アカウントが有効でもAには不可 |
| T02 | ADM_Aを閲覧者へ下げO_A1だけ割当 | 旧管理者セッションで参照・編集・出力 | O_A1参照のみ許可。他操作とO_A2参照は拒否 |
| T03 | U_A1をAから削除しB会員へ | 旧Aトークンと正しいB文脈要求を別確認 | AのO_A1拒否。Bで新作成した本人所有O_B2許可、O_B1拒否。注文を自動移転しない |
| T04 | SUPPORT_X承認満了・撤回 | 以前有効な要求を再実行 | O_A1も拒否。満了・手動撤回を別試験 |
| T05 | ADM_Aが出力要求後A権限喪失 | 待機していた利用者委任処理を実行 | 現権限再確認方針では拒否。ファイル作成・送付なし |
支援では顧客になりすまして痕跡を消さず、実担当と代理範囲が分かる監査にします。テナント、対象、操作、承認満了・撤回を合わせて検証します。
リリース判断につながる検証 — 主要フローを検証し、実行結果と残る条件をリリース判断の根拠につなげます。
詳細画面の外にも同じ規則を追う
表の完成後に各経路を確認します。以下はM01–M20とT01–T05の経路別検証設計です。同じAPI方針を宣言しただけで他経路を省略しません。[1]
| 経路 | 追加条件 | 確認結果 |
|---|---|---|
| 一覧・検索 | フィルター、並び、次ページ、候補、総数・集計 | 許可対象だけで欠落なし。制限対象が題名・総数・ページ情報へ出ない |
| 一括参照・更新・削除 | 同テナント非所有と別テナントを混在 | 個別判定。全拒否・部分成功方針と保存結果が一致 |
| ファイル・添付 | プレビュー、原本、変換版、URL発行 | IDだけで読めない。注文と実ファイルの権限一致 |
| エクスポート | 要求、状態参照、結果一覧、受取 | 要求者範囲のみ。他者がjob IDで状態・結果・位置を得ない |
| 非同期 | 待機中権限変更、再試行、次jobのテナント変更 | 主体・テナント・範囲維持。前A文脈が次Bへ残らない |
| キャッシュ | 正常利用者が埋めた値、他者・他組織、権限回収 | ヒットでも同じ許可・拒否 |
| 監査・外部副作用 | 拒否された変更・削除・出力 | 業務データ・決済呼出し・送信なし。拒否監査は残しトークン・秘密URLは残さない |
この非同期出力は利用者の代理作業です。workerのDB全権限は利用者の全データ出力権限ではありません。ASVS 8.3.3は仲介サービス権限を元要求者の代わりに使わないよう求めます。[6]
クリックと無関係の定期精算・バックアップなどサービス自身の作業は別方針になり得ます。その場合は主体、対象テナント、範囲、受取人を別承認します。「バックグラウンドだから管理者」という一規則にまとめない提案です。
キャッシュキーを分けても権限検査は残る
保護キャッシュを読む前に認可します。値・範囲がテナント別ならキーにも区分が必要で、同テナントでも利用者・許可属性・権限版で結果が変わります。一方、全員共通の公開基準データまで利用者別複製は不要です。[10]
検証設計例: U_A1が自注文を読んでキャッシュを埋め、U_A2・U_B1で同合成対象を要求して混在を確認します。次にU_A1所属を削除し、キャッシュを残して再要求します。冷えたキャッシュだけではこの条件を検証できません。
これはアプリの権限境界です。ブラウザー・CDNの保存許可、TTL、再検証まで一設定で解決すると仮定しません。
署名付きダウンロードリンクは別アクセス経路
S3 presigned URLは所持者が使えるbearer tokenの性質を持ち、有効中は複数回使えます。満了時刻に加え署名認証と権限が有効性へ影響します。[12]
ここからの設計上の注意は明確です。アプリのA所属削除だけで既存S3リンクも無効とはしません。新規発行APIの遮断と発行済みリンクでの受取は別試験です。
権限回収後の新ダウンロードも即時停止する必要があれば、毎回現権限を確認する経路か実効ある失効制御を設計・検証します。短い満了だけで即時遮断は保証できません。S3は要求開始時に満了を確認するため、以前に始めた転送は続き得ます。取得済みコピーも回収できません。[12]
DBのRLSは補強であり全経路の自動解決ではない
PostgreSQL 17のRLSは行アクセスを制限しますがsuperuserとBYPASSRLSは迂回します。表所有者も通常迂回し、FORCE ROW LEVEL SECURITYで変えられます。読取りと変更条件も異なるため、管理者だけでなくアプリの実DB役割・方針で参照・挿入・更新を確認します。[13]
RLSでも外部へ複製済みの検索結果・キャッシュ・ファイル権限は自動証明できません。一方、RLSなしを本記事だけで脆弱とも判定できません。一貫したアプリ方針、スキーマ・DB分離など選択構造が要求境界を満たすか検証するのが先です。
応答と実結果を一緒に残す
所有者と対象システム・アカウント・時間・許可操作を合意します。本番コピーでなく合成データを使い、決済・メール・Webhookは試験受取先へ向けます。対象IDは準備データから取り、実他者IDを列挙・推測しません。
拒否と近い許可を対で確認します。M02拒否にはM01正常参照、M14拒否にはM13正常一括を添えます。認証失敗で全要求が止まる環境を安全な認可と誤認しないためです。未ログイン・ログアウト後も別セッション試験に加えます。[9]
方針・ビルド・データ版、主体・テナント、対象、操作、期待、実応答、保存前後差、後続イベントを結びます。他注文不在だけでなく許可注文が正確に出るかも確認します。M14では変更行と業務イベントは0ですが、必要な拒否監査までゼロとはしません。
認可自体を偽承認関数にしたテストだけで終えません。実認証・権限経路とアプリDB役割を通る統合検証を含め、外部副作用だけを制御する環境を作ります。修正後は失敗要求だけでなく、同方針を共有する参照・変更・ファイル・jobと正常アクセスを回帰対象にします。
選択ケースと除外理由は変更別回帰テスト範囲決定ワークブックへ結べます。本記事の表は期待動作の例、ワークブックは実行・除外の記録です。
合格はログイン済みでなく許可範囲との一致
現方針と合成データを用意できれば既存ツールで始められます。新製品購入は表作成の前提ではありません。複雑な委任、サービス間伝播、即時失効が必要なファイル配信など、境界を説明できない部分は追加設計確認とします。
リリース判断の提案は、他顧客データの露出・変更を全体合格率で相殺しないことです。原因と影響経路を直し、拒否と正常アクセスを再確認します。未確認経路は合格でなく残余リスクとします。この実施と全脆弱性不在の保証は別です。
外部チームとシナリオ・範囲を検討する場合はIXC QAアウトソーシングサービスを確認できます。アカウント、データ境界、経路、成果物は着手前に合意します。



