実践知識 · 04
社内アプリの認可設計
社員がログインできても、すべての業務を許可するわけではありません。役割・対象範囲・条件を組み合わせて、社内アプリの権限を設計します。
Google Cloudで社内アプリを企画・設計する方向け ·
役割・範囲・条件で業務権限を決める
- 入口の管理IAPで社員の入場を制御する
- 業務の認可操作と対象データを照合する
- 付与の管理グループと期限で運用する
Google Workspace/Cloud Identity で社員を管理する組織を想定します。Entra ID などを使う場合は入口の設計を調整します。
誰が何を管理するか
IAP はアプリへの入場を管理します。業務操作と対象データの認可は、アプリのサーバーで判定します。
利用時の経路と、所属情報を権限に対応付ける経路を分けます。
提案する責任分担。既存のWebサーバーに共通の認可層を組み込みます。
この図をテキストで読む
構成図「入口と業務の認可を分担する」。ブロック7個、つながり6本。 枠: Google 側の管理(ブロック2個)、社内アプリ側の責任(ブロック4個)。 【ブロック】 - 社員: ブラウザから利用 - IAP: 本人確認・入場許可 - React Router: 署名検証・本人特定 - 共通の認可層: 役割・範囲・条件を判定 - データ操作: Drizzle → PostgreSQL - 社員情報: 所属グループ - 権限の割当: 役割・範囲・有効期限 【図の符号】緑の淡い塗り=効果・良い点 / 墨の囲み枠=守られた内側 / 灰色の破線の囲み枠=外部の領域 【流れ】 - 利用時の判定: 社員 → 〔アクセス〕 → IAP → 〔署名付き情報〕 → React Router → 〔操作・対象〕 → 共通の認可層 → 〔許可〕 → データ操作 - 所属と権限の対応: 社員情報 → 〔所属を同期〕 → 権限の割当 → 〔割当を参照〕 → 共通の認可層
所属情報は別途つなぐ
IAP の情報からグループ一覧を得られるとは限りません。所属情報を別途取得・同期し、アプリの役割に対応付けます。
認可方式は何が違うか
役割で操作を決め、対象範囲と属性の条件で絞ります。案件参加や文書の共有が中心なら、関係に基づく判定も加えます。
違いは「何を基準に判断するか」です。
この図をテキストで読む
比較表「役割・属性・関係は組み合わせて使う」。4列 × 3行。 【列】 1. RBAC(役割で判断) 2. ABAC(属性で判断) 3. ReBAC(関係で判断) 4. ACL(個別の許可) 【比較】(観点ごとに) ■ 基準 - RBAC: どの役割か / 担当者・承認者 - ABAC: どんな条件か / 部署・金額・状態 - ReBAC: 対象との関係 / 参加者・共有先 - ACL: 許可先の一覧 / 対象ごとに指定 ■ 具体例 - RBAC: 承認者は承認可能 / 操作の基本権限 - ABAC: 30万円以下 / 本人の申請は除外 - ReBAC: 案件の参加者 / その案件を閲覧 - ACL: 資料を個別共有 / 佐藤さんだけ追加 ■ 使いどころ - RBAC: 最初の土台 / 少数の役割に整理 - ABAC: 業務条件を追加 / 範囲を細かく制限 - ReBAC: 共有を中心に設計 / 階層の継承にも対応 - ACL: 例外の共有 / 件数増加に注意
どのように権限を付けるか
役割と対象範囲を一組として付与します。通常はグループ経由で付け、代理担当などの例外は個人に期限付きで付与します。
架空例:田中さんは東京営業部の承認者です。30万円以下・承認待ち・自己承認不可を条件にします。
同じ承認者でも、部署・金額・申請者によって結果が変わります。
この図をテキストで読む
構成図「役割・対象範囲・条件をそろえて判定する」。ブロック6個、つながり5本。 【ブロック】 - 役割: 承認者 - 対象範囲: 東京営業部 - 追加条件: 金額・状態・申請者 - 認可判定: すべての要件を照合 - 承認を許可: 20万円・同部署・他人 - 操作を拒否: 他部署/自己申請など 【図の符号】橙の淡い塗り=注意・課題 / 緑の淡い塗り=効果・良い点
- 入退社を扱う担当
- 業務の責任者
- 代理担当の例外
どこで権限を強制するか
共通の認可層を loader/action/API と業務処理に適用します。一覧・件数・集計・CSV・生成AIにも同じ範囲を適用します。
一覧を読む場合と、権限外の操作を要求した場合を追います。
この図をテキストで読む
シーケンス図「画面・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 を検討します。
以下は今回の構成に対する採用判断です。製品の人気順位ではありません。
この図をテキストで読む
比較表「規模と共有の仕組みから選ぶ」。3列 × 3行。 【列】 1. TypeScript(アプリ内の共通モジュール) 2. Cerbos(役割・属性のポリシー) 3. OpenFGA(共有関係のモデル) 【比較】(観点ごとに) ■ 採用する条件 - TypeScript: 小さく始める / 最初の1アプリ - Cerbos: 共通基盤を育てる / 複数の社内アプリ - OpenFGA: 共有が業務の中心 / 案件・文書・階層 ■ 一覧との連携 - TypeScript: 検索条件を実装 / 判定との整合性が必要 - Cerbos: Drizzle向け連携 / 認可条件をSQLへ変換 - OpenFGA: 対象IDを列挙 / モデル・量で性能が変化 ■ 管理するもの - TypeScript: コードと割当情報 / 型・テストを共通化 - Cerbos: ポリシーと実行基盤 / 配布・稼働を管理 - OpenFGA: 関係データとモデル / 同期・整合性を管理
この資料の構成例
構成例は React Router 8+Drizzle+PostgreSQL です。既存のWebサーバーに共通の認可層を組み込みます。
運用で権限を保つ
異動・退職に追従するため、所属の同期と利用停止を設計します。グループ変更の反映遅延を見込み、緊急停止の経路も用意します。
誰が誰に何を付与したかを記録します。他部署・自己承認・期限切れなどの拒否ケースをテストします。
- 所属と有効期限
- 緊急の利用停止
- 監査と拒否テスト
導入する際の境界
公開サイトと社内アプリは別の Cloud Run サービスに分ける案が自然です。必要に応じてDBの行レベル制御も加えます。