金色の配線パターンが広がる基板の接写
現場の実践

権限判定がエンドポイントごとに散らばる設計、クラウド移行後に障害の温床になる理由

目次を見る

オンプレのモノリスをクラウドに移行し、マイクロサービス(機能ごとに小さく分割したサービス群)に分割した際、権限チェックのコードもサービスごとにコピーされていくケースがあります。移行直後は動いていても、半年後に「なぜこの権限だけ通ってしまうのか」という障害調査で時間を溶かす原因になります。

本記事は、クラウド移行やマルチテナント化を進めているインフラ・バックエンド担当者に向けて、権限判定(authorisation、認可とも呼ばれる)のロジックが分散したときに何が起きるか、どう検知し、どう直すかを整理します。運用監視や障害対応の観点から実務的に使える確認手順を中心にまとめました。

何が起きるか

権限判定がエンドポイントごとの条件分岐(if 文の羅列)に散らばると、サービスが増えるたびに矛盾が生まれます。

たとえば「invoice.approve(請求書の承認)」という業務操作が、API Gateway 経由のサービス A では組織単位でチェックされ、バッチ処理を担うサービス B ではユーザー単位でしかチェックされていない、という状態です。

この状態でクラウド移行時にサービス B だけ先にコンテナ化してデプロイすると、旧オンプレ環境では発生しなかった「テナントを越えたデータ参照」が本番で起きます。監視ログにはただの 200 OK が並ぶだけなので、アクセスログの異常検知だけでは発見できません。

影響範囲は単純な不具合では済みません。マルチテナント(複数の顧客企業のデータを同じ基盤で扱う構成)の SaaS では、他社のデータが見える・消せる状態がインシデントレポートの対象になります。障害対応のポストモーテム(事後検証)でも「どのサービスのどの分岐が権限を通したか」の特定に時間がかかり、MTTR(平均復旧時間)が伸びる原因になります。

なぜ起きるか

原因は段階的に分解できます。

第一に、認証(authentication、本人確認)と認可(authorisation、操作の許可判定)が同じ処理として扱われがちです。ログインが通ったユーザーを「何でもできるユーザー」として扱ってしまう実装は、クラウド移行時にサービスが増えるほど危険度が上がります。

第二に、権限判定がビジネスルールの検証と混同されます。「承認済みの請求書を編集できるか」はワークフロー状態の検証であり、「Alice が請求書 #123 を承認できるか」という権限判定とは別の問いです。この二つを 1 つの if 文にまとめると、権限漏れとロジック不備が同じ場所で混在し、根本原因分析(RCA)が難しくなります。

第三に、クライアント側チェック(フロントエンドでのボタン非表示など)を認可の代替として扱ってしまう設計です。API を直接叩けば通ってしまうため、サーバーサイドでの強制がなければ意味を持ちません。

第四に、サービス分割時に「同じ質問を同じ形で問う」という一貫性が失われます。権限判定は本来「principal(誰が)が action(何を)を resource(どのリソースに)context(どの状況で)行えるか」という 1 つの型で統一されるべきですが、サービスごとに HTTP メソッドや UI ラベルを基準にした個別実装が増えると、判定基準がずれていきます。

自分のプロジェクトが該当するか確認する方法

該当するかどうかは、次の観点でコードとインフラ構成を洗い出すと判断できます。

  • 複数サービス・複数エンドポイントで同じ業務操作(例: 請求書承認)に対する権限チェックが存在するか、コードベースを grep で横断検索する
  • テナント・組織・チームなど境界をまたぐリソースアクセスがある場合、境界チェックが共通関数化されているか確認する
  • ロール名(admin, member など)だけで判定し、リソースの状態や関係性を見ていない箇所がないか確認する
  • 権限判定のロジックが、DB のクエリ条件(WHERE 句)や行レベルセキュリティだけに依存し、アプリケーション層に判定コードが存在しないか確認する
  • クラウド移行でサービスを段階的に切り出した場合、切り出し前と後で同じ操作の権限判定結果が一致するか、ステージング環境で突き合わせテストを行う
# 権限チェックのパターンを横断検索する例
grep -rn "role ==" --include="*.py" ./services/ | wc -l
grep -rn "if.*role" --include="*.ts" ./services/ | sort | uniq -c

このコマンドで検出件数がサービス数より明らかに多い場合、判定ロジックが集中化されていない可能性が高いです。1 つの業務操作に対して複数の書き方が存在するなら、統一されていない証拠になります。

対策の手順

1. 権限判定マトリクスを業務観点で作る

フレームワークのルート定義からではなく、業務ドメインから権限マトリクスを作成します。principal(例: staff member)、action(例: case.view)、resource(例: 所属組織内のケース)、条件(例: 在籍中であること)、期待される結果(Allow/Deny)を表にまとめます。これが監視すべき「正解」の基準になります。

2. 判定を1箇所に集約する

すべての権限判定を「principal が action を resource に対して context 内で行えるか」という統一形式に揃えます。サービスをまたぐ場合は、共有ライブラリ関数や、ポリシーエンジン(OPA など、ルールを外部で評価する仕組み)の導入を検討します。ただし、シンプルな管理者/一般ユーザーの区別しかない小規模ツールにポリシーエンジンを入れるのは過剰投資です。ルールが複雑化し、複数サービスで共有され、コンプライアンス上の説明責任が求められる場合に検討する、という順序が妥当です。

3. デフォルト拒否で監視ポイントを作る

権限判定は「何も許可されていない」状態を初期値にします。データを読む・状態を変える・特権的な外部連携を呼ぶ・機微なエクスポートを生成する、この4種類の処理経路すべてに強制ポイント(enforcement point)を置きます。監視設計としては、この強制ポイントを通過しなかったリクエストをログに残し、異常なパターン(テナント ID の不一致など)をアラート条件に加えます。

4. 移行時の突き合わせテストを組み込む

サービスをクラウドに段階移行する際は、旧環境と新環境で同じリクエストに対する権限判定結果が一致するかを、CI パイプラインまたはステージング環境で検証します。結果が一致しない項目はリリースをブロックする運用にすると、本番でのテナント越境のような重大インシデントを未然に防げます。

まとめ

権限判定の分散は、クラウド移行やマイクロサービス化のタイミングで一気に表面化します。

確認の第一歩は、コードベースを横断検索して同じ業務操作に対する判定ロジックが何パターンあるかを数えることです。パターンが多いほど、監視やインシデント対応の負荷も比例して増えます。

業務観点の権限マトリクスを作り、判定を1箇所に集約し、デフォルト拒否を徹底し、移行時に突き合わせテストを行う、この4段階を踏むことで、権限まわりの障害を事後調査ではなく事前検知に変えていけます。

参考

Permissions and Authorisation: A Practical Playbook

この記事について: 本記事は AI を活用して作成し、forva AI 編集部が内容を確認・監修しています。

AI 駆動開発のご相談は forva AI へ。まずはお気軽にどうぞ。