ロール・権限定義書とは
ロール・権限定義書は、RBAC(Role-Based Access Control: ロールベースアクセス制御)の設計を具体化した文書です。「誰が(アクター)」「どの機能に対して(機能)」「何ができるか(CRUD権限)」を定義し、機能設計書・画面設計書のアクセス制御実装の基準として使用します。
💡 RBAC vs ABAC vs PBAC
アクセス制御モデルには RBAC(役割ベース)・ABAC(属性ベース)・PBAC(ポリシーベース)があります。多くの業務システムでは RBAC が最も実装しやすく管理しやすい選択です。ただし「所属部署のデータのみ閲覧可」のようなデータスコープ制御は、RBAC にテナント制御・オーナーシップチェックを組み合わせて実装します。
① アクター(ユーザー種別)の定義
システムを利用するすべての人物の種別(アクター)を定義します。
| アクターID | アクター名 | 概要・特性 | 想定人数 | 認証方式 |
|---|---|---|---|---|
| ACT-01 | システム管理者 | システム全体を管理。ユーザー管理・システム設定・マスタ管理すべての権限を持つ。人数は最小限に制限 | 2〜3名 | パスワード + MFA(必須) |
| ACT-02 | 業務管理者 | 各業務ドメイン(営業・仕入・在庫)のデータ管理権限を持つ。部門マネージャー相当 | 5〜10名 | パスワード + MFA(任意) |
| ACT-03 | 一般ユーザー(営業) | 受注・見積の作成・更新が可能。自部門のデータのみ参照可能 | 50〜80名 | パスワード(SSO連携) |
| ACT-04 | 一般ユーザー(仕入) | 発注・仕入の作成・更新が可能。自部門のデータのみ参照可能 | 10〜20名 | パスワード(SSO連携) |
| ACT-05 | 閲覧専用 | 全データを参照のみ。データ変更不可。レポート・帳票出力は可 | 20〜30名 | パスワード(SSO連携) |
| ACT-06 | 外部パートナー | 発注書・納品書のみ参照可能。自社に関するデータのみアクセス可能 | 〜100社 | パスワード(招待メール) |
| ACT-07 | システム(バッチ) | 夜間バッチ処理用のサービスアカウント。画面は使用しない | — | サービスアカウントトークン |
② ロール定義とロール階層
アクターに割り当てるロールを定義します。1人のユーザーに複数ロールを付与できる設計にします。
| ロールID | ロール名 | ロールコード | 説明 |
|---|---|---|---|
| ROL-01 | システム管理者 | ROLE_SYS_ADMIN | すべての機能・データへのフルアクセス。ユーザー管理・システム設定を含む |
| ROL-02 | 業務管理者 | ROLE_BIZ_ADMIN | マスタ管理・全業務データへのCRUD。ユーザー管理・システム設定は不可 |
| ROL-03 | 営業担当 | ROLE_SALES | 受注・見積・顧客情報のCRUD。自部門データのみ操作可能 |
| ROL-04 | 仕入担当 | ROLE_PURCHASE | 発注・仕入・在庫のCRUD。自部門データのみ操作可能 |
| ROL-05 | 在庫担当 | ROLE_INVENTORY | 在庫・入出庫データのCRUD。他部門データは参照のみ |
| ROL-06 | 閲覧専用 | ROLE_VIEWER | 全データ参照のみ。帳票・レポート出力可。データ変更不可 |
| ROL-07 | 外部パートナー | ROLE_PARTNER | 発注書・納品書の参照のみ。自社に関するデータのみアクセス可能 |
③ 権限マトリクス(機能×ロール)
各機能に対して各ロールが持つCRUD権限を一覧化します。C=作成 / R=参照 / U=更新 / D=削除 / ×=権限なし
| 機能カテゴリ / 機能名 | SYS_ADMIN | BIZ_ADMIN | SALES | PURCHASE | INVENTORY | VIEWER | PARTNER |
|---|---|---|---|---|---|---|---|
| ユーザー管理 / ユーザー一覧・検索 | CRUD | R | × | × | × | × | × |
| ユーザー管理 / ユーザー作成・編集 | CRUD | × | × | × | × | × | × |
| 受注管理 / 受注一覧・検索 | CRUD | CRUD | CR(自部門) | R | R | R | × |
| 受注管理 / 受注登録・編集 | CRUD | CRUD | CRU(自部門) | × | × | × | × |
| 発注管理 / 発注一覧・検索 | CRUD | CRUD | R | CRUD | R | R | R(自社分) |
| 発注管理 / 発注登録・編集 | CRUD | CRUD | × | CRU | × | × | × |
| 在庫管理 / 在庫一覧 | CRUD | CRUD | R | R | CRUD | R | × |
| マスタ管理 / 商品マスタ | CRUD | CRUD | R | R | R | R | × |
| マスタ管理 / 取引先マスタ | CRUD | CRUD | R | R | × | R | × |
| 帳票出力 / 受注帳票・見積書 | ○ | ○ | ○(自部門) | × | × | ○ | × |
| 帳票出力 / 発注書・納品書 | ○ | ○ | × | ○ | ○ | ○ | ○(自社分) |
| システム設定 / 全設定 | CRUD | × | × | × | × | × | × |
④ データスコープ制御
同じロールのユーザー間でも、アクセスできるデータの範囲(スコープ)を制御する設計です。
| スコープ種別 | 対象ロール | 実装方針 |
|---|---|---|
| 部門スコープ | SALES / PURCHASE / INVENTORY | ユーザーが所属する部門IDに紐づくデータのみ取得。全APIでWHERE句にdepartment_id = {user.department_id}を付与 |
| 全社スコープ | SYS_ADMIN / BIZ_ADMIN / VIEWER | 部門制限なし。全データにアクセス可能 |
| 取引先スコープ | PARTNER | 自社(取引先)に関するデータのみ取得。全APIでWHERE句にpartner_id = {user.partner_id}を付与 |
⑤ 承認フロー設計
金額・リスクの高い操作には承認フロー(申請→承認→実行)を設計します。
| 対象操作 | 申請者 | 承認者 | 承認条件 |
|---|---|---|---|
| 受注登録(100万円以上) | SALES | BIZ_ADMIN(営業管理者) | BIZ_ADMIN 1名の承認で実行可能 |
| 発注登録(50万円以上) | PURCHASE | BIZ_ADMIN(仕入管理者) | BIZ_ADMIN 1名の承認で実行可能 |
| マスタ削除(全件) | BIZ_ADMIN | SYS_ADMIN | SYS_ADMIN 1名の承認で実行可能 |
| ユーザー削除 | SYS_ADMIN | 別のSYS_ADMIN | 本人以外のSYS_ADMIN 1名の承認が必要(二重チェック) |
⑥ ロール管理運用ルール
- 最小権限の原則: 業務上必要な権限のみを付与する。デフォルトロールは VIEWER(閲覧専用)とし、追加権限は申請・承認を経て付与
- 定期棚卸し: 四半期に1回、ロール割り当て一覧をシステム管理者がレビューし、不要な権限を削除
- 退職・異動時の対応: 退職日(または異動日)当日にシステム管理者がアカウント無効化およびロール削除を実施。人事システムとの連携自動化を推奨
- SYS_ADMINの最小人数制限: SYS_ADMINは2〜3名に厳格に制限。増員には上長の承認が必要
Python Tips — DjangoのRBAC設定を自動検証するスクリプト
"""
DjangoのグループとパーミッションのDB設定が権限マトリクスの定義通りか検証するスクリプト。
python manage.py shell で実行するか、management commandとして組み込む。
権限マトリクスをYAMLで管理し、実際のDB設定と突合する。
"""
import yaml
from django.contrib.auth.models import Group, Permission
from django.contrib.contenttypes.models import ContentType
from dataclasses import dataclass
# 権限マトリクスのYAML定義例
PERMISSION_MATRIX_YAML = """
ROLE_SALES:
order: [view, add, change] # 受注: 参照・作成・更新(削除不可)
product: [view] # 商品マスタ: 参照のみ
customer: [view, add, change] # 顧客: 参照・作成・更新
ROLE_BIZ_ADMIN:
order: [view, add, change, delete]
product: [view, add, change, delete]
customer: [view, add, change, delete]
purchase: [view, add, change, delete]
ROLE_VIEWER:
order: [view]
product: [view]
customer: [view]
purchase: [view]
"""
@dataclass
class ValidationError:
role: str
model: str
permission: str
error_type: str # "MISSING" | "EXTRA"
def get_current_permissions(group_name: str) -> dict[str, set[str]]:
"""DBから現在のグループのパーミッション設定を取得する"""
try:
group = Group.objects.get(name=group_name)
except Group.DoesNotExist:
return {}
result = {}
for perm in group.permissions.select_related("content_type").all():
model = perm.content_type.model
# "view_order" → "view" に変換
action = perm.codename.replace(f"_{model}", "")
result.setdefault(model, set()).add(action)
return result
def validate_permissions() -> list[ValidationError]:
"""権限マトリクスYAMLとDB設定を突合して差異を検出する"""
matrix = yaml.safe_load(PERMISSION_MATRIX_YAML)
errors = []
for role_name, model_permissions in matrix.items():
current = get_current_permissions(role_name)
for model, expected_actions in model_permissions.items():
expected_set = set(expected_actions)
actual_set = current.get(model, set())
# 定義されているが設定されていない権限
for missing in expected_set - actual_set:
errors.append(ValidationError(
role=role_name, model=model,
permission=missing, error_type="MISSING"
))
# 設定されているが定義されていない権限(過剰権限)
for extra in actual_set - expected_set:
errors.append(ValidationError(
role=role_name, model=model,
permission=extra, error_type="EXTRA"
))
return errors
def apply_permissions(dry_run: bool = True) -> None:
"""権限マトリクスYAMLに基づいてDjangoグループとパーミッションを設定する"""
matrix = yaml.safe_load(PERMISSION_MATRIX_YAML)
for role_name, model_permissions in matrix.items():
group, created = Group.objects.get_or_create(name=role_name)
action = "作成" if created else "更新"
target_perms = set()
for model_name, actions in model_permissions.items():
try:
ct = ContentType.objects.get(model=model_name)
for act in actions:
codename = f"{act}_{model_name}"
perm = Permission.objects.get(content_type=ct, codename=codename)
target_perms.add(perm)
except (ContentType.DoesNotExist, Permission.DoesNotExist) as e:
print(f" ⚠️ 権限が見つかりません: {model_name}.{act} — {e}")
if dry_run:
print(f"[DRY RUN] {action}: {role_name} ({len(target_perms)}件の権限)")
else:
group.permissions.set(target_perms)
print(f"✅ {action}: {role_name} ({len(target_perms)}件の権限を設定)")
if __name__ == "__main__":
print("=== 権限設定バリデーション ===")
errors = validate_permissions()
if not errors:
print("✅ すべての権限設定が権限マトリクス通りです")
else:
for e in errors:
mark = "❌ 不足" if e.error_type == "MISSING" else "⚠️ 過剰"
print(f" {mark}: {e.role} / {e.model} / {e.permission}")
print("\n=== 権限設定の適用(dry run)===")
apply_permissions(dry_run=True)
✅ 権限設定のCI/CDへの組み込み
このバリデーションスクリプトをCIパイプラインに組み込み、DjangoのGroup・Permission設定が権限マトリクスYAMLから乖離していないかを自動検証できます。権限マトリクスはYAMLで管理してGitでバージョン管理し、PRレビューで権限変更の意図を確認する運用が理想的です。