内部ツールのRBACとABAC:拡張できる権限の選び方
内部ツール向けにRBACとABACの使い分けを解説。サポート、経理、マネージャーの具体例、レコードレベルのルール、そして実用的な判断マトリクスで拡張可能な権限設計を学びます。

内部ツールで権限がややこしくなる理由
内部ツールはビジネスで最も機微な部分に近い場所にあります:顧客レコード、返金、請求書、給与メモ、取引金額、そして内部の非公開コメント。すべてを誰でも見られてよいわけではなく、編集できる人はさらに限られます。
権限は通常は単純に始まります:「サポートはチケットを閲覧できる」「経理は返金を承認できる」「マネージャーはチームの実績を見られる」。しかし組織が成長し、プロセスが変わると、ツールが例外のパッチワークになります。
この「あとで爆発する」パターンはよくあります:
- ロールの肥大化:Support を追加し、次に Support - Senior、Support - EU、Support - EU - Night Shift と増えていき、誰も各ロールの含意を覚えていない状態になります。
- 例外の累積:数人が「ちょっとだけ追加権限が必要」と言うと、一時的な切り替えが積み重なります。
- 偶発的な露出:画面が再利用され、アクセスチェックがされないまま給与メモや顧客の個人情報、収益レポートが見えてしまうことがあります。
- 壊れたワークフロー:ユーザーがレコードを見られても次のステップを実行できない(あるいは文脈を見ないまま実行できてしまう)ことがあります。
- つらい監査:「$1,000 を超える返金を誰が承認できるか?」に手作業で答えなければならないのは苦痛です。
RBAC か ABAC を早く選ぶ目的は、画面をロックするだけでなく、新しいチームや地域、ポリシーが現れてもルールが理解しやすく保てることです。
良い権限モデルは四つの性質を持ちます:説明しやすい、レビューしやすい、誤用しにくい、そして変更が速い。
RBAC を簡単に(役割とその解放内容)
RBAC(ロールベースアクセス制御)は「職種名」アプローチです。ユーザーは1つ以上のロール(Support Agent、Admin)を与えられ、各ロールはそのロールが見たりできることの固定セットを持ちます。同じロールを持つ二人は同じアクセスを得ます。
RBAC は、チームが日常的にほぼ同じやり方で動き、主な疑問が「この画面を使えるか?」や「このアクションを実行できるか?」といった機能レベルのときにうまく機能します。
サポートコンソールの例:
- Support Agent:チケットの閲覧、顧客への返信、内部ノートの追加
- Support Lead:エージェントの操作に加え、チケットの再割り当てやチーム指標の閲覧
- Admin:ユーザー管理、システム設定の変更、権限ルールの編集
ポイントは、ロールは個人にではなく責任に対応するということです。責任が安定していればロールも安定し、モデルは説明しやすくなります。
RBAC が適しているのは:
- 組織図が明確なとき(チーム、リード、管理者)
- ほとんどのアクセス判断が「この機能を使えるか?」で済むとき
- オンボーディングを予測可能にしたいとき(ロールXを割り当てれば完了)
- 監査が重要なとき(ロールが何をできるかを一覧にしやすい)
RBAC が問題になるのは現実がややこしくなったときです。内部ツールには例外が集まります:返金できるサポート担当、特定地域のみ見られる経理担当、顧客のPIIを見られない契約社員など。例外ごとに新しいロールを作るとロール爆発が起きます。
実用的なサインは、毎週「特別ロール」を追加し始めることです。
ABAC を簡単に(属性に基づくルール)
ABAC(属性ベースアクセス制御)は役職だけでなくルールでアクセスを決めます。「Finance ロールは何ができるか?」ではなく、「その人は誰で、そのレコードは何で、今何が起きているかに基づいて許可するか?」と問います。
属性は既に追跡している事実です。ルールの例:
- 「サポート担当は自分の地域のチケットを閲覧できる」
- 「マネージャーは営業時間内に$5,000未満の経費を承認できる」
多くのABACシステムは次の属性カテゴリを使います:
- ユーザー属性:部門、地域、マネージャーかどうか
- データ属性:レコードの所有者、チケットの優先度、請求書のステータス
- コンテキスト属性:時刻、デバイス種別、ネットワークの場所
- アクション属性:閲覧か編集かエクスポートか
具体例:サポート担当がチケットを編集できるのは、(a) 優先度が critical ではない、(b) チケットが自分に割り当てられている、(c) 顧客の地域が自分の地域と一致する、という条件を満たすときだけ、のようにできます。これにより Support - EU - Noncritical といった別々のロールを作らずに済みます。
トレードオフは、例外が積み重なるとABACのルールが考えにくくなる点です。数か月で「誰が請求書をエクスポートできるか?」の答えが長い条件の連鎖を読まないとわからなくなることがあります。
良いABACの習慣は、ルールを少数に保ち、一貫させ、平易な言葉で名前をつけることです。
レコードレベルアクセス:失敗が最も起きやすい場所
多くのチームは権限を「この画面を開けるか?」として扱います。それは第一層に過ぎません。レコードレベルアクセスは別の問いに答えます:画面を開けても、どの行を見たり変更したりできるか?
サポート担当と経理担当が同じCustomersページにアクセスすることがあり得ます。画面レベルだけで対処すると全員に全てを見せてしまうリスクがあります。レコードレベルルールは、そのページ内で読み込まれるデータを絞ります。
一般的なレコードレベルルール:
- あなたの顧客のみ(assigned_owner_id = current_user.id)
- あなたの地域のみ(customer.region IN current_user.allowed_regions)
- あなたのコストセンターのみ(invoice.cost_center_id IN current_user.cost_centers)
- あなたのチームのチケットのみ(ticket.team_id = current_user.team_id)
- あなたが作成したレコードのみ(created_by = current_user.id)
レコードレベルアクセスはUIだけでなく、データ取得と修正が行われる場所で強制されなければなりません。実務では、クエリ層、APIエンドポイント、ビジネスロジックでの適用を意味します。
典型的な失敗モードは「ページはロックされているがAPIは開いている」ことです。ボタンが非表示でもエンドポイントが全レコードを返す場合があります。アプリにアクセスできる誰かがリクエストを再利用したりフィルタをいじったりしてその呼び出しをトリガーすることがあります。
モデルの健全性をチェックする質問:
- ユーザーがエンドポイントを直接呼べる場合でも、許可されたレコードだけが返るか?
- 一覧、詳細、エクスポート、カウントのエンドポイントは同じルールを適用しているか?
- 作成、更新、削除は(読み取りと別に)チェックされているか?
- 管理者は意図的にルールをバイパスするのか、それとも誤ってバイパスしているのか?
画面権限は部屋に入れるかどうかを決めます。レコードレベルアクセスは入った後にどの引き出しを開けるかを決めます。
実例:サポート、経理、マネージャー
目標は「完全無欠のセキュリティ」ではなく、今の人が理解でき、将来ワークフローを壊さずに変えられる権限です。
サポートチーム
サポートはレコードレベルルールが必要になることが多いです。「全チケットを見せる」は滅多に正しくありません。
シンプルなモデル:エージェントは自分に割り当てられたチケットと自分のキュー内のものを開いて更新できる。チームリードはチケットを再割り当てし、エスカレーションに介入できる。マネージャーは編集権限なしにダッシュボードを見ることが多い。
バルク操作とエクスポートがよく問題になります。多くのチームは一括クローズを許可し、一括再割り当てを制限し、エクスポートはリードやマネージャーに限定してログを残す、といった対応をします。
経理チーム
経理のアクセスは主に承認の流れとクリーンな監査記録が重要です。
一般的な設定:AP(買掛)担当は請求書を作成して下書きを保存できるが、承認や支払いはできない。コントローラーは承認と支払いの解放ができる。監査担当は添付ファイルを含め読み取り専用で、ベンダー情報を変更できない。
現実的なルール例:「AP担当は自分が作成した下書きを編集できる。提出されたらコントローラーだけが変更できる。」これはステータスと所有者に基づくレコードレベルのルールであり、多くの場合追加のロールを作るよりABACが適しているケースです。
マネージャー
多くのマネージャーは広い可視性を必要としますが編集権限は限定されるべきです。
実用的なパターン:マネージャーは多くの運用データを見られるが、編集は自分のチームや直属部下に結び付くレコードだけにする(休暇申請、目標、評価メモなど)。team_id、manager_id、employment_status のような属性は、部門ごとに別ロールを作るより明確です。
これらのグループに共通して必要なもの:
- サポート:割り当て/キューによる可視性、エクスポートの慎重な制御、再割り当ての管理
- 経理:ステータスベースのルール(下書き→提出→承認)、厳格な承認、監査に耐える読み取りアクセス
- マネージャー:広い閲覧、狭い編集(チーム所有か直属部下に紐づく場合)
判断マトリクス:ロール、属性、レコードレベルルール
「どちらが優れているか」を議論する代わりに、アクセスのどの部分がどのモデルに適しているかを考えてください。多くのチームはハイブリッドになります:幅広いアクセスはロールで、例外は属性で、「自分のものだけ」はレコードフィルタで。
| 評価項目 | ロール (RBAC) | 属性 (ABAC) | レコードレベルフィルタ |
|---|---|---|---|
| チーム規模 | 小〜中規模で職務が明確な場合に最適。 | チームが成長し職務境界が曖昧になると有用。 | 所有権が重要な場合は規模に関係なく必要。 |
| 例外の頻度 | 「〜以外の全員」が増えると破綻しやすい。 | 「region = EU かつ tier = contractor の場合」など、ロールを増やさず扱える。 | 「自分に割り当てられたチケットのみ」や「自分のコストセンターの請求書のみ」を扱う。 |
| 監査要件 | 「Finance ロールは請求書をエクスポートできる」など説明が簡単。 | ルールを明確に文書化すれば監査対応可能。 | 特定データに対するスコープを証明できるため監査上よく必要とされる。 |
| 組織再編リスク | 組織図に合わせすぎるとリスクが高い。 | department_id や employment_type など安定した属性を使えばリスクは低め。 | 所有権フィールドが正確なら中程度のリスクで耐えられる。 |
権限ロジックは月々の請求のように扱ってください。余分なロールやルール、例外はテスト、説明、デバッグのコストがかかります。今日の現実的なシナリオをカバーする最小限に留めましょう。
実用的なデフォルト:
- 広いレーンにはまずRBACを使う(Support、Finance、Manager)。
- 繰り返し現れる条件にはABACを追加する(地域、シニアリティ、顧客ティア)。
- ユーザーが「自分のもの」を見るべきときはレコードレベルルールを追加する。
ステップバイステップ:画面を作る前に権限を設計する
UI を作ってから権限を決めると、たいていロールが増えすぎたり例外が積み上がったりします。簡単な計画で継続的な改修を防げます。
1) 画面ではなくアクションから始める
各ワークフローで人が実際に行うことを書き出します:
- 閲覧(read)
- 作成(create)
- 編集(edit)
- 承認(approve)
- エクスポート(export)
- 削除(delete)
返金フローでは Approve は Edit と同じアクションではありません。この1点の違いが厳格なルールが要るかロールだけで済むかを決めることがよくあります。
2) 職務に合うロールを定義する
会議なしで人が認識できるロール名を選んでください:Support Agent、Support Lead、Finance Analyst、Finance Manager、Auditor、Admin。"Support Agent - Can edit VIP notes" のようなロールはすぐに増えてしまいます。
3) 実際の例外を生む属性をリストアップする
ABAC は価値を生むところだけに追加します。典型的な属性は地域、チーム、顧客ティア、所有権、金額です。
例外が月に1回未満なら、恒久的な権限ルールを作る代わりに手動承認ステップを検討してください。
4) レコードレベルルールを一文ポリシーで書く
レコードレベルアクセスは多くの内部ツールが壊れる箇所です。非技術的なマネージャーに見せられるようなルールを書いてください:
「Support Agents は自分の地域のチケットを閲覧できる。」
「Finance Analysts は承認されるまでは自分が作成した請求書の下書きを編集できる。」
「Managers は$500超の返金を自分のチームに対してのみ承認できる。」
一文で表現できないルールは、たいていプロセスに曖昧さがあります。
5) 画面を作る前に5人でテストする
以下のような実シナリオを歩いてみてください:
- VIP 顧客を扱うサポート担当
- 請求書を修正する経理担当
- 高額返金を承認するマネージャー
- メンテナンスをする管理者
- 履歴は見られるが変更できない監査担当
ここで混乱を直しておけば、権限迷路になるのを防げます。
よくある落とし穴(と回避法)
多くの権限失敗は RBAC と ABAC のどちらを選ぶかで起きるのではなく、小さな例外が積み重なって誰も誰が何をできるか説明できなくなることから起きます。
ロール爆発は通常「Support Lead に1つだけボタンが必要」から始まり、1つだけ違う25個のロールになります。ロールは職務形に広めに保ち、繰り返すエッジケースは少数のルールベース例外で処理してください。
読みにくい属性ロジックは ABAC 版の同じ問題です。「department == X AND region != Y」のような条件がそこかしこにあると監査は推測作業になります。ポリシーに名前を付け(ドキュメント内でもよい)「RefundApproval ポリシー」のように参照できるようにしましょう。
エクスポート、レポート、一括操作は漏えいが起きやすい場所です。画面のビューをロックしても、エクスポート CSV や一括更新が同じチェックをスキップしていないか確認してください。
注視すべき落とし穴:
- 例外ごとに新ロールを作ること
- 読みにくく名前のない属性ルール
- チェックをスキップするエクスポートやスケジュールレポート
- 同じアクセス判定をツールごとに別々にしていること
- レコードレベルルールが一箇所でしか適用されていないこと
最も安全な対処は、ロール、属性、レコードレベルルールの単一の信頼できるソースを作り、バックエンドロジックで一貫して強制することです。
出荷前の簡単チェックリスト
モデルが説明しにくいなら、誰かが「その顧客を見られるはずだ」と言ったときにデバッグが難しくなります。
ほとんどのサプライズを防ぐ5つのチェック:
- 実際のユーザーが自分のアクセスを一文で説明できるか(例:「私は Support、region = EU、地域のチケットを閲覧できるがエクスポートはできない」)。できなければルールが散らばりすぎです。
- 「誰がエクスポートできるか」「誰が承認できるか」に明確な答えがあるか。エクスポートと承認は高リスクとして扱ってください。
- レコードレベルルールはボタンを隠すだけでなく、APIエンドポイント、レポート、バックグラウンドジョブのすべてで強制されているか?
- デフォルトはセンシティブな操作に対して安全になっているか(デフォルト拒否)。新しいロールや属性、画面が強力な権限を継承してしまわないように。
- 「この特定のレコードを誰が見られているか、そしてなぜか」を1分以内に単一の真実のソース(ロール、属性、所有権/ステータス)で答えられるか?
例:経理はすべての請求書を閲覧できるが、承認者だけが承認でき、マネージャーだけがベンダー一覧をエクスポートできる。サポートはチケットを閲覧できるが内部ノートはチケット所有チームだけが見られる、等。
既存の仕組みを壊さずに権限を変更する方法
権限は退屈な理由で変わります:新しいマネージャーが着任する、経理がAPとARに分かれる、買収で別チームが加わるなど。変更に備えて、アップデートを小さく、可逆的でレビューしやすくしておきましょう。
大きな「スーパー・ロール」にアクセスを結びつけないようにし、新しいアクセスはロール、属性、あるいは狭いレコードルールとして追加して、実際のタスクでテストしてください。
全面設計を壊さずにアクセスを追加する方法
新しい部門が現れたとき(または買収でチームが加わったとき)は、基礎ロールは安定させ、周辺に層を追加します。
- 基本ロールは少数に保ち(Support、Finance、Manager)、そこに小さなアドオン(Refunds、Export、Approvals)を追加する。
- 組織変更には属性(team、region、cost_center)を使うと新グループに新ロールを作る必要が減る。
- 所有権や割り当てにはレコードレベルルールを使う(ticket.assignee_id、invoice.cost_center)。
- 敏感な操作には承認ステップを追加する(支払い、貸倒処理など)。
- エクスポートはほぼすべての場所で独立した権限として扱う。
休暇カバーやインシデント対応の一時アクセスは恒久的なロール変更にしないでください。「48時間の Finance Approver」など、終了日時と理由を必須にして自動で取り消せるようにします。
監査リズムと調査に即答できるログ
シンプルなレビュー頻度を使ってください:高リスク権限は月次、その他は四半期ごと、組織再編や買収の後は追加レビュー。
誰が何を、どのレコードに対して、なぜ許可されたかを答えられるように十分なログを残してください:
- 誰が閲覧、編集、承認、エクスポートしたか
- いつそれが起きたか(可能ならどこからか)
- どのレコードが対象だったか(ID、タイプ、編集の前後)
- なぜそれが許可されたか(ロール、属性、レコードルール、一時付与)
- 誰がアクセスを付与したか(および有効期限)
維持できるモデルを実装するための次のステップ
小さくて地味な権限モデルから始めてください。それが数ヶ月の変化に耐えます。
良いデフォルトはシンプルなRBAC:実際の職務に合わせた少数のロール(Support Agent、Support Lead、Finance、Manager、Admin)を用意し、画面の大きな扉や開始できるワークフロー、利用可能なアクションをそのロールで制御します。
そして、同じ例外が繰り返し出る場所だけにABACを追加してください。「後で役に立つかもしれない」だけでABACを導入するのは待ちましょう。ABAC は金額制限、地域制限、所有権、ステータスなど条件が重要な場合に威力を発揮しますが、慎重なテストと明確な責任者が必要です。
まずはルールを平易な一文で書いてください。一文で言いづらいルールは保守が難しいです。
実際の内部ツールでこれを素早く試したいなら、AppMaster (appmaster.io) のようなノーコードプラットフォームを使って、ロール、owner/team/status のようなデータフィールド、そしてバックエンドで強制されるワークフローを早期にモデル化できます。UI 決定が危険な仮定を固める前に試行できます。
よくある質問
デフォルトでは、アクセス判断が主に機能(画面)に関するもので、職務が安定しているならRBACを選びます。役割と同じ役割でも地域・所有権・金額・ステータス・顧客ティアによってアクセスが変わる場合はABACを検討してください。毎週「特別ロール」を作っているなら、RBACだけでは既に限界です。
ハイブリッドがもっとも保守しやすいことが多いです。RBACで Support、Finance、Manager、Admin のような大きなレーンを定義し、地域や承認上限などの繰り返し発生する条件にはABACを追加し、さらにレコードレベルのフィルタでユーザーが見る行を限定します。こうすることでオンボーディングは簡単に保て、例外が大量のロールに変わるのを防げます。
役割が例外をコード化し始めたときがサインです。例えば「Support - EU - Night Shift - Can Refund」のようなロールが増えると役割の爆発が進行しています。対処法は、役割を職務に近い名前に戻し、可変部分は属性(region、team、seniority)やワークフロー(承認)に移すことです。
画面レベルの権限はページに入れるかどうかを決めます。レコードレベルのアクセスは、同じページ内でどの行を読んだり変更したりできるかを決めます。多くの情報漏えいは、画面をロックしてもAPIやクエリが返すデータをスコープしていないことから起きます。
ボタンを隠すだけでは不十分です。エクスポート用のエンドポイント、レポートジョブ、バルク操作にも同じ権限チェックを適用し、エクスポートは明示的な高リスクの権限として扱ってください。画面で見られる以上にエクスポートできる人がいるならコントロールは不完全です。
退屈で一貫したモデルを保つことです:小さなロールセット、名前付きポリシーの少数、そして一箇所での強制。読み取り、編集、承認、削除、エクスポートをすべてログに残し、アクター、レコード、許可された理由を記録してください。「誰が$1,000超の返金を承認できるか」を即答できなければ、モデルの見直しが必要です。
デフォルトは広範な閲覧、編集は限定するのがよいです。マネージャーはチームや業績データを幅広く見られるが、編集は直属の部下やチーム所有の項目に限定する、といったパターンです。manager_id や team_id のような属性を使うと、部門ごとに別ロールを作る必要が減ります。
一時的なアクセスは恒久的なロール変更にしてはいけません。終了日時と理由を必須にした期間限定付与にし、ログで追跡可能かつ自動で取り消せるようにします。これにより緊急アクセスがそのまま長期特権になるのを防げます。
まず各ワークフローでのアクション(view, edit, approve, export など)を一覧にし、それぞれどのロールが行うか決めます。次に、ロール爆発を防げる明確なケースでのみ属性を追加し、レコードレベルルールは非技術的なマネージャーにも説明できる一文ポリシーで書きます。UIを作り込む前に実シナリオでテストしてください。
ロールをユーザーフィールドとしてモデル化し、チーム、地域、コストセンター、所有権、ステータスなど必要な属性を保存し、ルールはインターフェースだけでなくバックエンドのロジックで強制してください。AppMaster (appmaster.io) のようなノーコードツールでは、データ構造を定義し、承認やチェックのためのビジネスプロセスを作り、一覧・詳細・エクスポートのエンドポイントが同じルールを適用するようにできます。目標は、組織やワークフローが変わっても素早く変更できる一貫した真実のソースです。


