認可は多層で設計する — XACML・ABAC・ReBAC と実装パターンの整理

認可を複数の粒度で設計するためのフレームワーク(XACML、NIST ABAC、Zanzibar/ReBAC)を整理し、JWT groups + AVP/Cedar の実装パターンとの対応関係をまとめる。

はじめに

「このユーザーはこのエンドポイントにアクセスできるか」と「このユーザーはこのリソースを操作できるか」は、同じ「認可」でも粒度が違います。

実際のシステムでは、1 つの認可メカニズムですべてをカバーするのは難しく、複数の粒度を組み合わせるのが一般的です。この記事では、認可の多層設計に関するフレームワークと実装パターンを整理します。

認可の粒度

認可には大きく 4 つの粒度があります。

粒度判定内容
API レベルこのアプリに何を許可するかOAuth 2.0 Scopes
ロールレベルこのユーザーは何者かJWT groups / RBAC
属性レベル条件を満たすかABAC(時刻、部署、リソース属性)
関係性レベル誰と何の関係があるかReBAC(owner、editor、viewer)

下に行くほど細かい判定ができますが、実装の複雑さも上がります。実際のシステムでは上の層で大部分をフィルタし、必要な場所だけ下の層で細かく判定するのが定石です。

フレームワーク別の解説

XACML(OASIS 標準)

eXtensible Access Control Markup Language。認可の多層設計を最も体系的にアーキテクチャ化した標準です。

XACML は認可を 4 つのコンポーネントに分解します。

コンポーネント役割実装例
PEP (Policy Enforcement Point)認可判定を「実行」する場所API ミドルウェア、Gateway
PDP (Policy Decision Point)認可判定を「下す」エンジンCedar/AVP、OPA
PAP (Policy Administration Point)ポリシーを「管理」する場所管理画面、ポリシー CRUD API
PIP (Policy Information Point)判定に必要な「属性を提供」する場所ユーザーDB、Cognito

重要なのは、PEP は複数のレイヤーに配置できるという設計思想です。

        ┌─────┐
        │ PAP │  ポリシー管理
        └──┬──┘

        ┌─────┐
        │ PDP │  判定エンジン
        └──┬──┘

    ┌──────┼──────┐
    ▼      ▼      ▼
  ┌─────┐┌─────┐┌─────┐
  │ PEP ││ PEP ││ PEP │  実行ポイント
  └─────┘└─────┘└─────┘
  API GW  App層  DB層

API Gateway 層で粗い PEP(ロールチェック)を置き、アプリ層で細かい PEP(リソースレベルの判定)を置く、という構成が自然に表現できます。

NIST ABAC(SP 800-162)

Attribute-Based Access Control のガイドライン。「ロールだけでなく、あらゆる属性で認可判定する」モデルです。

判定に使える属性は 4 種類に分類されます。

属性の種類
Subject 属性ロール、所属部署、資格、クリアランスレベル
Resource 属性機密度、所有者、作成日、ステータス
Action 属性read / write / delete / approve
Environment 属性時刻、IP アドレス、デバイス種別

RBAC(ロールベース)が Subject 属性の 1 つだけで判定するのに対し、ABAC は 4 種類の属性を組み合わせて判定します。

例: 以下のすべてを満たす場合に許可
  - Subject: lawyer ロール
  - Resource: 担当案件
  - Action: view
  - Environment: 営業時間内

AWS の Cedar(Amazon Verified Permissions で使われるポリシー言語)は ABAC エンジンの一種です。

permit(
  principal in Common::Role::"lawyer",
  action == Site::Action::"view",
  resource
) when {
  resource.assignedTo == principal &&
  context.time.hour >= 9 &&
  context.time.hour <= 18
};

Google Zanzibar / ReBAC

Google が内部で使っている Relationship-Based Access Control システム。Google Drive、YouTube、Google Maps 等で使われています。2019 年に論文が公開されました。

ReBAC はオブジェクト間の関係性を大量に保持し、それを辿って認可判定します。

# 関係性の定義
document:readme#owner@user:alice
folder:docs#viewer@team:engineering
folder:docs#parent@document:readme

# クエリ
check: user:alice は document:readme を view できるか?
→ alice は readme の owner → owner は view を含む → 許可

特徴は関係性の伝播です。「フォルダの viewer は、その中のドキュメントも viewer」のような階層的なアクセス制御が自然に表現できます。

OSS 実装:

OAuth 2.0 Scopes

認可の中で最も粗い粒度。**「このアプリに何を許可するか」**を制御します。

scope=openid email profile

Scopes は「ユーザーの認可」ではなく「アプリの認可」です。ユーザーが admin ロールでも、アプリに write scope がなければ書き込みはできない。

これは他の認可レイヤーとは直交する概念で、組み合わせて使います。

多層認可の実装パターン

パターン: JWT groups + ABAC エンジン

最も実用的な多層パターンの一つ。粗い認可は JWT だけで完結し、細かい認可だけ外部エンジンに問い合わせます。

リクエスト


[ミドルウェア] JWT の groups を確認
  │  lawyer じゃなければ → 403


[ハンドラー] ビジネスロジック
  │  リソースレベルの判定が必要


[認可サービス] ABAC エンジン (Cedar/AVP) に問い合わせ
  │  「このユーザーはこの案件の担当者か?」


レスポンス
レイヤー粒度レイテンシXACML での名前
JWT groupsロールレベル0ms(トークンに含まれてる)PEP(粗い)
ABAC エンジン属性/関係性レベル数 ms(API 呼び出し)PEP(細かい)+ PDP

大部分のリクエストは JWT groups で通過/拒否できるので、ABAC エンジンへの問い合わせは本当に必要な場面だけに限定できます。

XACML の用語で整理

レイヤーやってることXACML
JWT groups(ミドルウェア)RBACPEP(粗い)
認可サービス(AVP 等)ABACPEP(細かい)+ PDP
ポリシー管理 APIポリシー CRUDPAP
ユーザーストア(Cognito 等)ユーザー属性提供PIP

Linux との類似性

実はこの多層構造は Linux のアクセス制御にも見られます。

Linux認可システム
group (www-data, docker)JWT groups(ロールレベル)
file permission (770)エンドポイントレベルの認可
ACL (setfacl -m u:alice:rx)リソースレベルの ABAC/ReBAC
SELinux / AppArmorポリシーエンジン(PDP)

Linux でも「group でざっくり制御 + ACL で細かく制御 + SELinux でポリシーベースの強制」という多層構造になっています。

どのフレームワークを選ぶか

要件適したフレームワーク
API ごとのアクセス制御だけOAuth 2.0 Scopes + RBAC
ロールベースで十分RBAC(JWT groups)
リソースの属性で判定したいABAC(Cedar / OPA)
階層的な共有・権限継承があるReBAC(SpiceDB / OpenFGA)
上記の組み合わせXACML アーキテクチャで整理

重要なのは、いきなり細かい粒度から始めないことです。

推奨の導入順序:

1. RBAC(JWT groups)← ほとんどのケースはこれで足りる
2. 必要な箇所だけ ABAC を追加
3. 階層的な共有が必要になったら ReBAC を検討

注意点

認可の判定は必ずサーバーサイドで

クライアント側で「groups に admin があるからボタンを表示する」のは UI の最適化としては OK ですが、認可の判定そのものはサーバーサイドで行う必要があります。JWT はクライアントが読めるので、UI の出し分けにしか使えません。

キャッシュ戦略

ABAC エンジンへの問い合わせは毎回行うとレイテンシが積みます。一般的な戦略:

ポリシーの可視化

多層になると「結局このユーザーは何ができるのか」が見えにくくなります。管理画面やデバッグツールで「このユーザーの有効な権限一覧」を出せるようにしておくと、運用が楽です。

まとめ

← Back to all posts