RBACを単なる「ログイン後の表示切り替え」とは考えていませんか?
AIエージェントがコードを書き、管理画面を操作し、複数の業務フローをまたいで処理する時代では、本当に重要なのは次の4つです。
- 誰が実行するのか
- どのアプリ境界から来た操作なのか
- どの操作まで許すのか
- どのデータ範囲に触れてよいのか
この4つを、実装として明示し続けることが大事だと考えています。
先に結論
自分たちのプロダクトでやっていることを一言でまとめると、RBACを「人に役割を付ける仕組み」ではなく、システムの事故半径を小さくするための境界設計として扱うことです。
特に意識しているのは次の4点です。
- 認証と認可を分ける
- ユーザーロールだけでなく、アプリ境界でも権限を切る
- 機微操作は path 単位でさらに絞る
- ルールをコードの単一情報源に寄せ、逸脱を静的に検出する
AIエージェント時代に怖いのは、「少し強すぎる権限」が人間の1クリックではなく、連続した業務実行権に変わることです。だからこそ、粗いロールだけではなく、操作単位まで権限を刻む必要があります。
自分たちのプロダクトで意識していること
1. 認証と認可を分離する
自分たちは、認証基盤には主にセッション管理を担わせ、RBACそのものはドメイン側で持つようにしています。
考え方としては、
- 認証基盤は「その人が本人か」を扱う
- 認可基盤は「その人が何をしてよいか」を扱う
という分離です。
認証ライブラリにロール設計まで寄せてしまうと、ビジネス上の権限モデルが製品都合に引っ張られやすくなります。逆に、認可をドメイン側に置けば、将来ロール体系を変えても、意味づけをアプリケーションの内部で保ちやすいです。
AIエージェント時代は、認証方式の選定よりも「どこまで実行させるか」の設計のほうが重要です。なので、この分離はかなり大事だと思っています。
2. 権限をユーザーだけでなくアプリ境界でも切る
自分たちのプロダクトでは、権限判定を「ユーザーのロール」だけで決めないようにしています。
アプリごとに、
- 読み取りのみ許すドメイン
- 読み書きを許すドメイン
- 一切アクセスさせないドメイン
をアクセスマトリクスとして持っています。
これはかなり重要です。
同じユーザーでも、
- 外部向けアプリからの操作
- 業務向けアプリからの操作
- 管理コンソールからの操作
では、許される範囲が違うはずです。
ここをユーザーロールだけで吸収しようとすると、
- 権限が過剰に広がる
- BFFやフロントエンドの境界が意味を失う
- 誤って別用途の画面から危険操作を呼べてしまう
という問題が出やすくなります。
AIエージェントに管理画面を触らせるなら、なおさらです。人には見えている「このアプリは閲覧用」「このアプリは管理用」という文脈を、機械はロール名だけでは理解しません。だからこそ、アプリ境界そのものを認可条件に入れるようにしています。
3. 機微な操作は path 単位でさらに絞る
ドメイン単位の権限だけだと、まだ粗いです。
そこで自分たちは、個別の procedure や path に対して例外ルールを置けるようにしています。つまり、
- 普段はドメイン単位の既定権限でさばく
- ただし PII、商用データ、状態遷移を伴う操作だけは個別に allow-list する
という二段構えです。
実務で危険なのは「そのドメイン全体」ではなく、
- 特定の検索 API だけが機微情報を返す
- 特定の更新だけが状態遷移を起こす
- 特定の一覧だけが内部情報や金額を含む
というケースです。
権限が弱いシステムでは、この粒度を BFF の分岐や画面側の出し分けで吸収しがちです。でもそれでは、別の呼び出し経路が生えた瞬間に破綻します。
なので自分たちは、例外を例外として中央管理することを強く意識しています。
4. ロールを一段ではなく、多層で考える
自分たちの権限モデルは、少なくとも次のような層を持つ前提で設計しています。
- システム全体のロール
- 組織内メンバーシップのロール
- 部署内ロール
- Role / Permission / RolePermission
- Scope の概念
つまり、「全員に対して同じ ADMIN / MEMBER を付ける」だけではなく、
- システム管理者としての権限
- 組織に対する所有者 / 管理者 / 一般メンバー権限
- 部署や職務に紐づく権限
- 自分自身だけ
- 自組織だけ
- 全体
のような広がりを最初から想定しています。
ここはAIエージェント時代に特に大事です。必要なのは、強い管理者を少人数に配ることではなく、実行可能範囲を細かく切ることだからです。
「更新できる」ではなく、
- 自分の担当範囲だけ更新できる
- 自組織のデータだけ更新できる
- 全体を横断して更新できる
の違いが、事故時の被害を大きく左右します。
実装として特に重視していること
1. unknown を許さない fail-closed
自分たちの設計では、分からないものは通さないことをかなり重視しています。
例えば、
- 未知の
appIdは拒否 -
x-app-idがない呼び出しは拒否 - 信頼できない
x-user-idは権威として扱わない - IP allowlist の設定が壊れていたら、緩めるのではなく全拒否
- リダイレクト先がホワイトリスト外なら拒否
といった振る舞いです。
AIエージェントが絡むと「想定外の経路」が増えるので、例外時に fail-open してしまう設計は特に危険です。なので、分からないものは止める方向に寄せています。
2. defense in depth を入れる
危険操作を1か所のチェックに依存させないことも意識しています。
例えば概念的には、
- 認証済みであること
- そのアプリから呼んでよいこと
- そのロールを持っていること
- 場合によっては内部スタッフ文脈であること
を別々の層で確認します。
これはAIエージェント運用と相性が良いです。1つの条件を書き漏らしても、他の層が止めてくれるからです。
3. 権限ポリシーを SSOT に寄せる
自分たちは、権限判定を handler の中に好き勝手書ける状態を避けたいと思っています。
思想としては、
- 認可ルールは中央のマトリクスに集約する
- 例外は path override に集約する
- 逸脱した書き方は lint や guard で検出する
という形です。
これはAIエージェント時代にかなり効きます。
エージェントは局所最適の修正を入れるのが得意なので、何も縛らないと、各所に if (ctx.appId !== 'admin-app') のような場当たり的なチェックを増やしやすいからです。そうなると、人間も機械も「本当の権限ルールがどこにあるか」を追えなくなります。
権限ルールは、人間が読めるだけでなく、機械が迷わない形で1か所に置くべきだと思っています。
4. 監査と redaction をセットで考える
自分たちは、認可だけでなく監査もセットで考えています。
- 誰が
- どの procedure を
- 成功 / 失敗どちらで
- どの入力で実行したか
を残す設計にしつつ、ログ入力には redact を入れます。
さらに、監査ログでは「PII は既定で記録しない」「sensitive 項目は fail-closed で弾く」という方針を取っています。
権限は、設定するだけでは足りません。後から追えることまで含めて初めて運用可能になります。
おわりに
自分たちのプロダクトでやっているのは、RBACを「役職テーブル」ではなく、システム境界の設計として扱うことです。
特にAIエージェント時代は、権限設定の甘さがそのまま自動実行の広さになります。
だからこそ必要なのは、
- 誰が
- どのアプリから
- どの操作を
- どの範囲に対して
実行してよいのかを、コードとテストで固定することです。
RBACは、エージェントを賢く動かすための機能ではありません。
エージェントが賢く動きすぎたときに、壊せる範囲を狭めるための設計です。