KeycloakのAuthorization Servicesは、resource / scope / policy / permission という4つの部品で集中認可を組み立てる仕組みです。本記事では各要素の関係、decision strategyの挙動、UMAのRPT取得フロー、そしてpolicy enforcerのキャッシュや性能設計まで、エンタープライズの実構築で押さえるべき勘所を整理します。
Keycloakを「ログインとトークン発行の箱」として使っている現場は多いですが、Authorization Services(認可サービス)まで踏み込むと、アプリ側に散らばりがちな認可ロジックをKeycloakに集約できます。本記事では、resource / scope / policy / permission の4要素を軸に、UMA的な集中認可、RBAC/ABACの実装、そして性能設計までを実務目線で掘り下げます。バージョン差の激しい領域なので、細かい挙動は必ず稼働バージョンの公式ドキュメントで確認する前提で読んでください(本記事は新しめのバージョン基準です)。
014つの部品:resource / scope / policy / permission
Authorization Servicesを有効にしたクライアント(confidential + Authorization有効)は「resource server」になります。認可はこの上で、次の4部品の組み合わせで表現します。
- resource(リソース):保護対象。
Documentや/orders/{id}のような、アプリ内の守りたいモノ。type(リソース種別)を付けられ、テンプレート的な扱いが可能です。 - scope(スコープ):リソースに対して行える操作。
read/write/deleteのような動詞が典型ですが、リソースの属性を表現する使い方も許容されています。 - policy(ポリシー):許可の条件。役割・グループ・時刻・JavaScriptなど「どういう場合にOKか」を定義します。permissionとは独立して作り、再利用します。
- permission(パーミッション):resource/scope と policy を結びつけるもの。「このリソース(スコープ)には、これらのポリシーを適用する」という紐付けです。
ここで効いてくる設計思想が「ポリシーとパーミッションの分離」です。公式のAuthorization Services Guideでも強調されているとおり、policyは条件だけを表す再利用可能な部品で、どのリソースに効かせるかはpermissionが決めます。条件の変更(例:営業時間の変更)はpolicyを1箇所直せば全permissionに波及し、適用範囲の変更はpermission側で行う、という関心の分離ができます。
02permissionは2種類:resource-based と scope-based
permissionには2タイプあります。使い分けが認可設計の粒度を決めます。
- resource-based permission:リソース(または「リソースタイプ」)に対してポリシーを適用します。
Apply To Resource Typeを使うと、同じtypeを持つ全リソースに一括でポリシーを効かせられます。「全ドキュメントは所有者のみ編集可」のような横断ルールに向きます。 - scope-based permission:リソース上の特定スコープ(操作)に対して適用します。
read は全社員、write は編集者ロールのように、操作ごとに条件を変えたいときはこちらです。
実務では「粗い制御はresource-based、動詞レベルの制御はscope-based」と割り切ると見通しが良くなります。scope-basedを多用すると柔軟ですが、permission数が爆発しやすいので、まずresource typeで大枠を締めてから、例外的にscope-basedで穴を開ける/絞る、という順番が管理しやすいです。
02policyの種類:role / js / time / aggregate ほか
policyは条件の表現手段が複数あります。よく使うものを挙げます。
- role-based:realm/clientロールの保有を判定。ロールを「required」にすると全保有必須にできます(既定はrequiredではない点に注意)。
- group-based:グループ所属で判定。
Extend to Childrenで子グループまで含めるか選べます。 - user / client-based:特定ユーザー、特定クライアントに限定。
- time-based:開始・終了時刻や、月・日・時・分の繰り返し条件。全条件のAND評価です。メンテナンス時間帯の締め出しなどに。
- regex-based:IDトークン等の属性(ネストしたJSONクレームもドット記法・配列添字で)を正規表現でマッチ。ABAC寄りの判定に有効です。
- aggregated(集約):「ポリシーのポリシー」。個別policyを部品化し、決定戦略付きで束ねられます。循環参照は作成時に防止されます。
- JavaScript-based:
$evaluationオブジェクト経由でidentity/context/realmにアクセスして任意条件を書けます。
JavaScriptポリシーには重要なバージョン依存の注意があります。新しめのバージョンでは、管理コンソールからのインラインJSアップロードは既定で無効化されており、公式ガイドも「JS Policiesはサーバへ直接デプロイ(JavaScript Providers)せよ」と明記しています。つまりJSポリシーはJARとしてビルド時にサーバへ載せる運用が基本です。ビルド時/実行時設定の考え方は ビルド時・実行時設定 の整理も参考にしてください。なお、いずれのpolicyもlogic(positive/negative)で評価結果を反転でき、「このロールでない場合」といった否定条件を逆ポリシーを作らずに表現できます。
03decision strategy:unanimous / affirmative / consensus
1つのpermissionに複数policyを紐付けたとき、最終判定をどうまとめるかがdecision strategyです。
- unanimous(既定):全policyがpositiveで初めて許可。ANDに近い、最も厳しい挙動。
- affirmative:1つでもpositiveなら許可。ORに近い。
- consensus:positiveの数がnegativeを上回れば許可。多数決。
既定がunanimousである点は必ず意識してください。「roleAとroleBのどちらか一方でOK」にしたいのに、1つのpermissionへ両方のrole-based policyを付けると、既定のunanimousでは両方必須になってしまいます。OR条件が欲しい場合は、affirmativeにするか、aggregated policyで束ねて意図を明示します。aggregatedはそれ自体に決定戦略を持てるため、複雑な論理を「部品化された小さなpolicy+集約」で組み立てるのがKeycloak流のdivide-and-conquerです。
04RBAC/ABACの実装マッピング
Authorization Servicesは、RBACとABACの両方をカバーできます。実装の対応づけは次のとおりです。
- RBAC:role-based / group-based policy が中心。「編集者ロールなら write スコープ許可」といった素直な役割ベース制御。ロール・グループ設計そのものは ロール・グループ・属性設計 の整理とセットで考えると破綻しません。
- ABAC:regex-based policy(属性マッチ)やJavaScript policy、time-based policyで、ユーザー属性・環境属性・リソース属性を条件化します。「部署属性がリソースの所属部署と一致する場合のみ」といった関係性判定はここに載せます。
- ReBAC的な所有者判定:Protection APIでリソース作成時に
ownerを設定しておき、JS policyで「リクエスト主体=リソース所有者」を評価する、という定番パターンで表現できます。
現実のエンタープライズ要件は「基本はロール、例外は属性」という混在がほとんどです。KeycloakはRBACをベースにABACを重ねられるため、この混在を1つの認可基盤に集約できるのが強みです。組織横断の権限統制という観点では マルチアカウント統制 の考え方とも接続します。
05UMA的な集中認可:permission ticket と RPT
Authorization ServicesはUMA 2.0に準拠したフローを備えます。中心は、トークンエンドポイントの urn:ietf:params:oauth:grant-type:uma-ticket グラントで取得するRPT(Requesting Party Token)です。RPTには、評価済みのpermission(どのリソースのどのスコープが許可されたか)が入ります。
典型的なフローはこうです。クライアントが保護リソースへアクセス → resource serverがpermission ticket(要求リソース/スコープとコンテキストを表す不透明な構造)を発行 → クライアントがそのticketをKeycloakのトークンエンドポイントへ送る → ポリシー評価の結果としてRPTが返る、という流れです。permission ticketを介さず、audience にresource serverのクライアントIDを指定してインクリメンタルにpermissionを要求するentitlement的な使い方もできます。詳細な要求構文は authz-clientのドキュメントで確認できます。
06policy enforcer:PEPとキャッシュ
アプリ側で認可を効かせる部品がpolicy enforcer(PEP)です。リクエストを傍受し、Keycloakが与えたpermissionに応じてアクセス可否を判断します。policy enforcerのドキュメントによれば、enforcementには3モードあります。
- enforcing(既定):リソースにpolicyが紐付いていなくても、既定で拒否。安全側。
- permissive:policyが無ければ許可。段階導入時に有効。
- disabled:評価を止めて全許可(ただしAuthorization Contextから許可情報は取得可能)。
性能面で重要なのがpath-cacheです。パスとKeycloakリソースの対応をキャッシュし、サーバへの過剰な問い合わせを抑えます。既定でlifespanは30,000ミリ秒、max-entriesは1,000件です(0で無効、-1で無期限)。リソース定義が安定している本番では、このキャッシュが実効レイテンシを大きく左右します。段階導入では、まずpermissiveで挙動を観測し、リソース/permissionの穴を潰してからenforcingへ切り替えるのが安全な進め方です。
07性能設計と設計判断の勘所
Authorization Servicesは強力ですが、リクエストごとにポリシー評価が走る以上、設計を誤るとレイテンシに直結します。実構築で効いたポイントを挙げます。
- 評価はできるだけRPTにまとめる:エンドポイントごとに個別評価するより、必要なpermissionをRPTへ一括で載せ、以後はRPT検証で済ませる方が往復が減ります。
- permission爆発を避ける:resource typeとaggregated policyで論理を集約し、個別permissionの数を抑える。数が増えるほど評価も管理も重くなります。
- JS policyの多用に注意:宣言的policyより評価コストとレビューコストが高くなりがち。宣言的に書ける条件はそちらへ寄せる。
- PEPキャッシュを活かす:path-cacheのlifespan/max-entriesを本番の変更頻度に合わせて調整する。
- 評価はEvaluateタブで先に検証:本番前にPolicy Evaluationツール(identity/context/permissionを与えて評価をシミュレート)で意図どおりか確認する。Red Hat build of Keycloakのガイドにも手順があります。
もう一段引いた設計判断として、「認可をどこまでKeycloakに寄せるか」があります。全アプリの認可をKeycloakへ集約すると統制と監査は効きますが、Keycloakが認可のクリティカルパスに乗ります。ドメインロジックに密結合した細粒度の認可はアプリ側に残し、横断的・組織的な権限統制をKeycloakへ寄せる、という切り分けが現実的です。
—まとめ
Authorization Servicesは、resource / scope / policy / permission の4部品と、unanimousを既定とするdecision strategy、そしてUMAのRPTフローで、認可をKeycloakに集約する仕組みです。RBACをベースにregex/JS/timeでABACを重ねられる柔軟性が魅力ですが、その分「既定のunanimous」「JSポリシーはサーバへ直接デプロイ」「PEPのpath-cache」といったバージョン依存の勘所を外すと、意図しない挙動や性能劣化を招きます。細かい仕様は稼働バージョンの公式ドキュメントで必ず確認し、まずpermissiveで観測してからenforcingへ、という段階導入をおすすめします。Keycloakでの認証・認可基盤の実構築については 導入事例 も参考にしてください。
—参考(一次情報)
- Keycloak — Authorization Services Guide(公式ドキュメント)
- Keycloak — Policy Enforcer(公式ドキュメント)
- Keycloak — Authorization Client(公式ドキュメント)
- Red Hat build of Keycloak 26.4 — Evaluating and testing policies