ストーリー
田
田中VPoE
認証で「あなたは誰か」を確認した。次は認可 —「あなたは何ができるか」を制御する仕組みだ
あなた
RBACは使っています。admin、editor、viewerのようなロールを定義して、APIごとに必要なロールをチェックしています
あ
田
田中VPoE
基本的なRBACは良いが、BtoB SaaSではそれだけでは不十分な場面がある。例えば「テナントAの管理者はテナントBのデータにアクセスできない」。これはロールだけでは制御できない。リソースレベルの認可が必要だ
田
田中VPoE
そうだ。さらに複雑な要件になると「ドキュメントの作成者とそのチームメンバーだけが編集できる」のような関係ベースの認可(ReBAC)も必要になる。Google DriveやGitHubの権限モデルがこれだ
認可モデルの比較
4つの主要モデル
| モデル | 正式名称 | 判定基準 | 適用場面 | 複雑度 |
|---|
| RBAC | Role-Based Access Control | ロール | 社内システム、シンプルなAPI | 低 |
| ABAC | Attribute-Based Access Control | 属性の組み合わせ | 条件付きアクセス | 中 |
| PBAC | Policy-Based Access Control | ポリシー(ルール) | クラウドリソース(AWS IAM) | 中〜高 |
| ReBAC | Relationship-Based Access Control | リソース間の関係 | ファイル共有、SNS、マルチテナント | 高 |
RBAC(ロールベースアクセス制御)
RBAC モデル:
ユーザー ──→ ロール ──→ パーミッション
例(PayConnect):
User: alice ──→ Role: admin ──→ Permissions: [create, read, update, delete]
User: bob ──→ Role: viewer ──→ Permissions: [read]
User: carol ──→ Role: editor ──→ Permissions: [create, read, update]
判定:
can(alice, "delete", "invoice") → true(admin は delete 可能)
can(bob, "delete", "invoice") → false(viewer は read のみ)
| 利点 | 制限 |
|---|
| シンプルで理解しやすい | テナント分離ができない |
| 実装が容易 | リソース単位の制御が困難 |
| 管理コストが低い | ロール爆発(細かい権限=大量のロール) |
ABAC(属性ベースアクセス制御)
ABAC モデル:
判定 = f(ユーザー属性, リソース属性, 環境属性, アクション)
ポリシー例:
IF user.role == "editor"
AND resource.tenant_id == user.tenant_id ← テナント分離
AND environment.time IN business_hours ← 時間帯制約
AND action IN ["read", "update"]
THEN ALLOW
例:
can(alice{tenant:A, role:editor}, "update", invoice{tenant:A})
→ true(同一テナント + editor ロール)
can(alice{tenant:A, role:editor}, "update", invoice{tenant:B})
→ false(テナント不一致)
ReBAC(関係ベースアクセス制御)
ReBAC モデル:
判定 = ユーザーとリソースの「関係」に基づく
関係の定義:
document:annual-report#owner@user:alice
document:annual-report#editor@team:finance
team:finance#member@user:bob
team:finance#member@user:carol
判定ロジック:
can(alice, "edit", "annual-report")
→ alice は owner → edit 可能 ✓
can(bob, "edit", "annual-report")
→ bob は finance の member
→ finance は annual-report の editor
→ edit 可能 ✓
can(dave, "edit", "annual-report")
→ dave は関係なし → edit 不可 ✗
認可エンジンの選定
| ツール | モデル | 特徴 | 適用場面 |
|---|
| OPA(Open Policy Agent) | PBAC | Rego言語、汎用、Kubernetes統合 | インフラ、API認可 |
| Cedar(AWS) | ABAC + RBAC | Rust実装、高速、AWS Verified Permissions | AWS環境 |
| OpenFGA | ReBAC | Google Zanzibar inspired、OSS | ファイル共有、複雑な権限 |
| SpiceDB(Authzed) | ReBAC | Zanzibar準拠、高パフォーマンス | 大規模BtoB SaaS |
| Casbin | RBAC/ABAC/ReBAC | 多言語対応、軽量 | 小〜中規模アプリ |
OPA(Open Policy Agent)による認可
# OPA ポリシー例(PayConnect)
package payconnect.authz
default allow = false
# 管理者は全操作が可能
allow {
input.user.role == "admin"
input.resource.tenant_id == input.user.tenant_id
}
# エディターは読み取りと更新が可能
allow {
input.user.role == "editor"
input.resource.tenant_id == input.user.tenant_id
input.action in ["read", "update"]
}
# ビューアーは読み取りのみ可能
allow {
input.user.role == "viewer"
input.resource.tenant_id == input.user.tenant_id
input.action == "read"
}
# テナント不一致は常に拒否(暗黙のデフォルト deny)
マルチテナント認可のパターン
マルチテナント認可の実装パターン:
パターン1: テナントIDフィルタリング(シンプル)
SELECT * FROM invoices
WHERE tenant_id = :current_user_tenant_id
AND id = :requested_invoice_id
パターン2: Row Level Security(PostgreSQL)
CREATE POLICY tenant_isolation ON invoices
USING (tenant_id = current_setting('app.current_tenant')::uuid);
パターン3: 認可エンジン(OPA/Cedar)
// API ミドルウェアで認可チェック
const allowed = await opa.evaluate({
user: req.user,
action: "read",
resource: { type: "invoice", id: invoiceId, tenant_id: tenantId }
});
if (!allowed) return res.status(403).json({ error: "Forbidden" });
認可のベストプラクティス
| プラクティス | 説明 |
|---|
| デフォルト拒否 | 明示的に許可されない限り、すべてのアクセスを拒否する |
| 一元的な認可ロジック | 各APIに個別実装ではなく、認可エンジンに集約する |
| 認可の監査ログ | 全ての認可判定(許可/拒否)をログに記録する |
| テスト可能な認可 | ポリシーに対する自動テストを書く |
| 権限の定期レビュー | 四半期ごとにアクセス権限を棚卸しする |
まとめ
| ポイント | 内容 |
|---|
| 4つの認可モデル | RBAC(ロール)、ABAC(属性)、PBAC(ポリシー)、ReBAC(関係) |
| テナント分離 | RBACだけでは不十分。ABACやRLSでテナント分離を実現 |
| 認可エンジン | OPA、Cedar、OpenFGA等を活用し、認可ロジックを集約 |
| ベストプラクティス | デフォルト拒否、一元管理、監査ログ、テスト、定期レビュー |
チェックリスト
次のステップへ
次は「フェデレーションとSSO」を学びます。複数のIdPやサービスを横断するID連携の設計方法を身につけましょう。
推定読了時間: 30分