実践知識の一覧

実践知識 · 04

社内アプリの認可設計

社員がログインできても、すべての業務を許可するわけではありません。役割・対象範囲・条件を組み合わせて、社内アプリの権限を設計します。

Google Cloudで社内アプリを企画・設計する方向け ·

役割・範囲・条件で業務権限を決める

Webサーバーに共通の認可層を加える設計案です。

  1. 入口の管理IAPで社員の入場を制御する
  2. 業務の認可操作と対象データを照合する
  3. 付与の管理グループと期限で運用する

Google Workspace/Cloud Identity で社員を管理する組織を想定します。Entra ID などを使う場合は入口の設計を調整します。

誰が何を管理するか

IAP はアプリへの入場を管理します。業務操作と対象データの認可は、アプリのサーバーで判定します。

利用時の経路と、所属情報を権限に対応付ける経路を分けます。

提案する責任分担。既存のWebサーバーに共通の認可層を組み込みます。

アクセス署名付き情報操作・対象許可所属を同期割当を参照
社員ブラウザから利用
IAP本人確認・入場許可
React Router署名検証・本人特定
共通の認可層役割・範囲・条件を判定
データ操作Drizzle → PostgreSQL
社員情報所属グループ
権限の割当役割・範囲・有効期限
この図をテキストで読む

構成図「入口と業務の認可を分担する」。ブロック7個、つながり6本。 枠: Google 側の管理(ブロック2個)、社内アプリ側の責任(ブロック4個)。 【ブロック】 - 社員: ブラウザから利用 - IAP: 本人確認・入場許可 - React Router: 署名検証・本人特定 - 共通の認可層: 役割・範囲・条件を判定 - データ操作: Drizzle → PostgreSQL - 社員情報: 所属グループ - 権限の割当: 役割・範囲・有効期限 【図の符号】緑の淡い塗り=効果・良い点 / 墨の囲み枠=守られた内側 / 灰色の破線の囲み枠=外部の領域 【流れ】 - 利用時の判定: 社員 → 〔アクセス〕 → IAP → 〔署名付き情報〕 → React Router → 〔操作・対象〕 → 共通の認可層 → 〔許可〕 → データ操作 - 所属と権限の対応: 社員情報 → 〔所属を同期〕 → 権限の割当 → 〔割当を参照〕 → 共通の認可層

業務承認者に、Google Cloud の Editor 権限を与える必要はありません。

所属情報は別途つなぐ

IAP の情報からグループ一覧を得られるとは限りません。所属情報を別途取得・同期し、アプリの役割に対応付けます。

認可方式は何が違うか

役割で操作を決め、対象範囲と属性の条件で絞ります。案件参加や文書の共有が中心なら、関係に基づく判定も加えます。

違いは「何を基準に判断するか」です。

観点
RBAC
役割で判断
ABAC
属性で判断
ReBAC
関係で判断
ACL
個別の許可
基準
どの役割か
担当者・承認者
どんな条件か
部署・金額・状態
対象との関係
参加者・共有先
許可先の一覧
対象ごとに指定
具体例
承認者は承認可能
操作の基本権限
30万円以下
本人の申請は除外
案件の参加者
その案件を閲覧
資料を個別共有
佐藤さんだけ追加
使いどころ
最初の土台
少数の役割に整理
業務条件を追加
範囲を細かく制限
共有を中心に設計
階層の継承にも対応
例外の共有
件数増加に注意
この図をテキストで読む

比較表「役割・属性・関係は組み合わせて使う」。4列 × 3行。 【列】 1. RBAC(役割で判断) 2. ABAC(属性で判断) 3. ReBAC(関係で判断) 4. ACL(個別の許可) 【比較】(観点ごとに) ■ 基準 - RBAC: どの役割か / 担当者・承認者 - ABAC: どんな条件か / 部署・金額・状態 - ReBAC: 対象との関係 / 参加者・共有先 - ACL: 許可先の一覧 / 対象ごとに指定 ■ 具体例 - RBAC: 承認者は承認可能 / 操作の基本権限 - ABAC: 30万円以下 / 本人の申請は除外 - ReBAC: 案件の参加者 / その案件を閲覧 - ACL: 資料を個別共有 / 佐藤さんだけ追加 ■ 使いどころ - RBAC: 最初の土台 / 少数の役割に整理 - ABAC: 業務条件を追加 / 範囲を細かく制限 - ReBAC: 共有を中心に設計 / 階層の継承にも対応 - ACL: 例外の共有 / 件数増加に注意

一般的な社内業務は、役割を土台に対象範囲と属性条件を加える形から始めます。

どのように権限を付けるか

役割と対象範囲を一組として付与します。通常はグループ経由で付け、代理担当などの例外は個人に期限付きで付与します。

架空例:田中さんは東京営業部の承認者です。30万円以下・承認待ち・自己承認不可を条件にします。

同じ承認者でも、部署・金額・申請者によって結果が変わります。

要件を満たす要件から外れる
役割承認者
対象範囲東京営業部
追加条件金額・状態・申請者
認可判定すべての要件を照合
承認を許可20万円・同部署・他人
操作を拒否他部署/自己申請など
この図をテキストで読む

構成図「役割・対象範囲・条件をそろえて判定する」。ブロック6個、つながり5本。 【ブロック】 - 役割: 承認者 - 対象範囲: 東京営業部 - 追加条件: 金額・状態・申請者 - 認可判定: すべての要件を照合 - 承認を許可: 20万円・同部署・他人 - 操作を拒否: 他部署/自己申請など 【図の符号】橙の淡い塗り=注意・課題 / 緑の淡い塗り=効果・良い点

「東京の承認者」「大阪の承認者」を別ロールにせず、同じ役割と異なる範囲を付与します。
入退社を扱う担当
社員アカウントと所属グループを管理します。
業務の責任者
承認者・対象範囲・限度額を決めます。
代理担当の例外
個人への追加権限に期限と理由を残します。

どこで権限を強制するか

共通の認可層を loader/action/API と業務処理に適用します。一覧・件数・集計・CSV・生成AIにも同じ範囲を適用します。

一覧を読む場合と、権限外の操作を要求した場合を追います。

申請一覧を要求閲覧できる範囲を判定東京営業部に限定部署条件付きで検索許可範囲の行だけ返す申請一覧を表示権限外の申請を承認要求本人・操作・対象を照合拒否と理由を返す操作不可を通知・更新なし
利用者画面・API・生成AI
WebサーバーReact Router・業務処理
共通の認可層利用者・操作・対象
DBPostgreSQL
この図をテキストで読む

シーケンス図「画面・API・生成AIで共通の判定を通す」。参加者4人、ステップ10個。 【参加者】(左から右) - 利用者: 画面・API・生成AI - Webサーバー: React Router・業務処理 - 共通の認可層: 利用者・操作・対象 - DB: PostgreSQL 【流れ】(上から下へ) ── 一覧:見える範囲を検索条件にする ── 1. 利用者 → Webサーバー: 申請一覧を要求 2. Webサーバー → 共通の認可層: 閲覧できる範囲を判定 3. 共通の認可層 → Webサーバー: 東京営業部に限定(応答) 4. Webサーバー → DB: 部署条件付きで検索 5. DB → Webサーバー: 許可範囲の行だけ返す(応答) 6. Webサーバー → 利用者: 申請一覧を表示(応答) ── 更新:権限外の操作は実行前に止める ── 7. 利用者 → Webサーバー: 権限外の申請を承認要求 8. Webサーバー → 共通の認可層: 本人・操作・対象を照合 9. 共通の認可層 → Webサーバー: 拒否と理由を返す(応答) 10. Webサーバー → 利用者: 操作不可を通知・更新なし(応答)

画面の表示制御と、サーバーで強制する認可をそろえます。

承認は専用の業務操作として守る

更新では対象の部署・所有者・状態をサーバーで確認します。汎用の更新APIから承認処理を迂回できないようにします。

実装方式をどう選ぶか

最初の小さなアプリは共通 TypeScript モジュールが候補です。複数アプリの共通基盤なら Cerbos、共有関係が中心なら OpenFGA を検討します。

以下は今回の構成に対する採用判断です。製品の人気順位ではありません。

観点
TypeScript
アプリ内の共通モジュール
Cerbos
役割・属性のポリシー
OpenFGA
共有関係のモデル
採用する条件
小さく始める
最初の1アプリ
共通基盤を育てる
複数の社内アプリ
共有が業務の中心
案件・文書・階層
一覧との連携
検索条件を実装
判定との整合性が必要
Drizzle向け連携
認可条件をSQLへ変換
対象IDを列挙
モデル・量で性能が変化
管理するもの
コードと割当情報
型・テストを共通化
ポリシーと実行基盤
配布・稼働を管理
関係データとモデル
同期・整合性を管理
この図をテキストで読む

比較表「規模と共有の仕組みから選ぶ」。3列 × 3行。 【列】 1. TypeScript(アプリ内の共通モジュール) 2. Cerbos(役割・属性のポリシー) 3. OpenFGA(共有関係のモデル) 【比較】(観点ごとに) ■ 採用する条件 - TypeScript: 小さく始める / 最初の1アプリ - Cerbos: 共通基盤を育てる / 複数の社内アプリ - OpenFGA: 共有が業務の中心 / 案件・文書・階層 ■ 一覧との連携 - TypeScript: 検索条件を実装 / 判定との整合性が必要 - Cerbos: Drizzle向け連携 / 認可条件をSQLへ変換 - OpenFGA: 対象IDを列挙 / モデル・量で性能が変化 ■ 管理するもの - TypeScript: コードと割当情報 / 型・テストを共通化 - Cerbos: ポリシーと実行基盤 / 配布・稼働を管理 - OpenFGA: 関係データとモデル / 同期・整合性を管理

共通の社内アプリ基盤を作る目的なら、Cerbos と実際の一覧画面で小さく検証します。

この資料の構成例

構成例は React Router 8+Drizzle+PostgreSQL です。既存のWebサーバーに共通の認可層を組み込みます。

運用で権限を保つ

異動・退職に追従するため、所属の同期と利用停止を設計します。グループ変更の反映遅延を見込み、緊急停止の経路も用意します。

誰が誰に何を付与したかを記録します。他部署・自己承認・期限切れなどの拒否ケースをテストします。

所属と有効期限
グループ変更の反映と期限切れを管理します。
緊急の利用停止
同期を待たずに止める経路を用意します。
監査と拒否テスト
付与の理由・変更者と、拒否の挙動を確認します。

導入する際の境界

公開サイトと社内アプリは別の Cloud Run サービスに分ける案が自然です。必要に応じてDBの行レベル制御も加えます。

実践知識の一覧へ