Skip to content
Published on

Keycloak 26.7 — SCIM がプレビューに昇格、外部 Infinispan 不要のマルチクラスター v2、そしてアップグレードで踏みやすい落とし穴

シェア
Authors

はじめに — 四半期に一つずつ、今回は26.7

Keycloakは最近、およそ3か月間隔でマイナーバージョンを出しています。GitHubのリリース日ベースで、26.5.0が2026年1月6日、26.6.0が4月8日、そして26.7.0が7月9日に出ました。マイナーが出るたびリリースノートをざっと眺めるだけで済ませたいところですが、今回は運用者として引っかかる点が多い回です — 長らく待たれていた機能2つ(SCIM、外部キャッシュ不要のマルチクラスター)がプレビューに乗り、アップグレードガイドのbreaking/notableの一覧も特に長くなっています。

本稿は、公式リリースノートとリポジトリの原文adoc(リリースノートアップグレードガイド)、そして機能フラグの実際の定義であるProfile.javaを突き合わせて整理した、運用視点の読み解きです。Keycloak 26のアーキテクチャ自体が初見なら、先にKeycloak 26 アーキテクチャ徹底解説を読んでおくほうがいいでしょう。

SCIM API — 4年開いていたイシューがコアへ(プレビュー)

SCIM(System for Cross-domain Identity Management)は、ユーザーやグループのようなアイデンティティリソースをシステム間で標準REST APIとして読み書きするプロトコルです(スキーマはRFC 7643、プロトコルはRFC 7644)。OktaやEntra IDのような商用IdPでは当たり前とされる機能ですが、Keycloakのコアにはありませんでした。2022年8月に開かれたSCIMサポートのイシューはリアクション300件を集めながら今も開いたままで、その間この空白はscim-for-keycloakのようなサードパーティ拡張が埋めてきました。

今回、その空白がコアで埋まり始めました。タイムラインをコードで追うとこうです — scim-api機能フラグは26.6.0のProfile.javaにexperimentalとしてひっそり入り(26.6.0のリリースノートには言及がありません)、26.7.0でプレビューに昇格しました。デフォルトは無効なので--features=scim-apiで有効化する必要があり、有効化した後もrealm設定でrealmごとに再度トグルする必要があります。

実装範囲は管理ガイドのSCIM章によれば次のとおりです。

  • ユーザー・グループの作成/参照/更新/PATCH/削除の全操作と、グループメンバーシップ管理
  • SCIMフィルタ構文の全体とページネーション
  • Enterprise User拡張(RFC 7643 4.3節)とUser Profile属性マッピングによるカスタムスキーマ拡張
  • スキーマディスカバリーエンドポイント

エンドポイントはrealm単位で開かれます。

/realms/<realm-name>/scim/v2/ServiceProviderConfig
/realms/<realm-name>/scim/v2/ResourceTypes
/realms/<realm-name>/scim/v2/Schemas
/realms/<realm-name>/scim/v2/Users
/realms/<realm-name>/scim/v2/Groups

権限モデルは新設せず、Admin REST APIと同じrealm-managementロールをそのまま使います。ユーザーの書き込みはmanage-users、読み取りはview-users、検索はquery-users/query-groupsです — すでにAdmin API用のサービスアカウントがあれば、追加設定なしにSCIMも使えます。呼び出しはconfidentialクライアントのみ許可され、publicクライアントは拒否されます。

設計で目を引くのは管理者リソースの保護です。SCIMクライアントは通常、広範な管理権限で動くため、侵害されたプロビジョニングクライアントが管理者アカウントを削除したり管理者グループにユーザーを押し込んだりするシナリオを、ドキュメントが明示的に防いでいます — 管理ロールを持つユーザー・グループをSCIMで参照すると最小限の表現(id、schemas、userName程度)しか返らず、書き込みは403で拒否されます。管理者アカウントはAdminコンソールとAdmin REST APIからしか操作できません。

正直に限界を書くと — 今回入ったのはKeycloakがSCIMサーバーになる方向のみです。 HRシステムやアイデンティティガバナンスプラットフォームがKeycloakにユーザーを出し入れするインバウンドプロビジョニングはこれで対応できます。逆に、KeycloakがSCIMクライアントとなり外部SCIMプロバイダーからユーザーを連携してくることは別のイシューとしてまだ開いており、ドキュメントも外部SCIMサービスプロバイダーからのユーザー連携とプッシュベースのリアルタイムイベントを今後のリリース計画としてのみ記載しています。Keycloakからダウンストリームアプリへ押し出すアウトバウンドプロビジョニングも今回のスコープ外です — それは依然として拡張の領域です。そしてプレビューはプレビューです。サポート対象ではなく、最終形が変わる可能性もあります。

マルチクラスター v2 — 外部Infinispanなしで(プレビュー)

これまでKeycloakのマルチサイトHA(v1)は、サイト間セッションレプリケーションのために外部Infinispan(Data Grid)クラスターを別途デプロイ・運用する必要があり、自動フェイルオーバーのためのベンダー固有のfencingインフラまで要求していました — Keycloak Kubernetes HA 運用で扱った構成です。運用したことがある人なら分かる通り、認証サーバーのHAのためにキャッシュクラスターというもう一つの分散システムを世話するコストは小さくありません。

26.7のマルチクラスターv2は、その外部依存をまるごと取り除きます。アーキテクチャはこう変わります。

  • Keycloakインスタンス同士が組み込みのInfinispanキャッシュでクラスター間を直接接続します。
  • 同期レプリケーションされるデータベースが単一の真実の源(single source of truth)になります。機能フラグの名前がstatelessなのはこのためです — Profile.javaの定義そのままに、認証セッション・アクショントークン・ログイン失敗データをDBに保存し、複数クラスターがDBだけでつながるようにします。
  • サイト間のキャッシュ無効化は、DBベースのoutboxパターンで処理されます。
  • ロードバランサーが外部fencingなしでサイトダウンを検知します。

ここまで聞くと地理的なDRまでできそうに聞こえますが、公式ガイドが釘を刺している制約をそのまま移すとこうなります。

  • 単一リージョン、あるいはそれに準ずる低レイテンシ環境専用です。 同期レプリケーションされる高可用データベースが必須で、クラスターからDBまでの読み書き・コミットのレイテンシは5ms未満が推奨、10ms未満が必須です。大陸間のアクティブ-アクティブDRは期待できません。
  • チームが定期テストしている構成(ベンダー自己測定)は、同一AWSリージョン内のシングルAZ OpenShift(ROSA HCP)クラスター2つ + アベイラビリティゾーン間で同期レプリケーションするリーダーを持つAurora PostgreSQL 17.5 + AWS Global Acceleratorで、テスト負荷はユーザー100万人・秒間300リクエストです。この範囲を超える規模は自分で検証するよう明記されています。
  • 障害シナリオによっては数分のダウンタイムがあり得て、DBベンダーによっては手動介入が必要になることもあります。ノード障害の検知はデフォルト設定で1分以内です。

運用視点でもう一つ — Profile.javaではこの機能はFeatureUpdatePolicy.SHUTDOWNとして宣言されています。フラグのオン・オフにローリングが使えず、クラスター全体のシャットダウンが必要という意味です。すでに稼働中のプロダクションに無停止で組み込めるような類の機能ではありません。

まとめると、v2は「外部Infinispan運用をなくしたリージョン内マルチクラスター可用性」であって、「遠く離れた2つのデータセンター」ではありません。その代わりに得られるものははっきりしています — 管理すべき分散システムが一つ減り、KubernetesやAWSのような特定環境への依存も消えます。負荷がテスト範囲内で、DBを同期レプリケーションで運用できる組織であれば、v1の運用複雑度と引き換える価値のあるトレードです。

余談を一つ。タグ時点のリリースノート原文は、この機能をハイライトではプレビュー、本文の見出しではexperimentalと記す不一致があり(mainブランチではプレビューに整理されました)、コードのProfile.javaは最初からPREVIEWでした。リリースノートとコードが食い違うときは、コードが正しいです。

Organizations — マルチテナンシー委任が現実的に

マルチテナントSaaSのSSO設計で扱った通り、KeycloakのOrganizationsは一つのrealmの中で複数のテナント(組織)を管理する機能です。ところがこれまで組織を管理するにはmanage-realmという高権限ロールが必要でした — テナント管理者にrealm全体の管理権限を渡すことになり、委任と呼ぶには気恥ずかしい構造でした。

26.7がこれを手直ししました。

  • 専用のrealm管理ロールが3つ新設されました: manage-organizations(組織全体の読み書き)、view-organizations(読み取り専用)、query-organizations(一覧・検索のみ)。既存のquery-users/query-clientsパターンと同じ路線です。manage-realmは後方互換のため引き続き組織管理権限を含みます。
  • 組織がFine-Grained Admin Permissionsの第一級リソースタイプになりました。特定の組織一つだけを管理できる委任管理者を作れるようになり、FGAPが有効な場合は組織メンバー一覧の参照もユーザーレベルの権限を尊重し、閲覧を許された分だけを返します。
  • 組織グループにrealm/clientロールをマッピングできるようになりました。組織グループにロールを一度付与すると全メンバーのrealm_access/resource_accessクレームに自動反映され、Organization Group Membershipプロトコルマッパーのオプションを有効にすればorganizationクレーム内に組織別に整理して入れることもできます。数百人規模のテナントで、メンバーごとにロールを付けるのではなくグループ単位で管理せよ、という話です。

breaking変更も一つ付いてきました。組織メンバー一覧APIがデフォルトでbrief表現を返すようになりました。フルユーザー表現が必要な場合はクエリパラメータで明示する必要があります。

GET /admin/realms/{realm}/organizations/{id}/members?briefRepresentation=false

組織招待一覧のemail/firstName/lastNameフィルタも部分一致から大文字小文字を無視した完全一致に変わりました — 部分一致が必要ならsearchパラメータを使うよう案内されています。これらのAPIに依存する自動化があるなら、レスポンスとフィルタの挙動が変わっていないか先に確認してください。

アップグレードで踏みやすいもの

今回のアップグレードガイドから、運用者が実際に踏みそうなものを選びました。全体の一覧はアップグレードガイド原文を見てください。

PostgreSQLの非同期コミットがデフォルトで有効になります。 persisted user sessions、client sessions、login failures、eventsのような揮発性テーブルだけを更新するトランザクションは、今後PostgreSQLの非同期コミット(async commit)で処理されます(ログアウトは引き続き同期コミットを強制)。パフォーマンスのための選択ですが、意味を正確に理解しておく必要があります — PostgreSQLのドキュメントによれば、非同期コミットはWALがディスクにフラッシュされる前にコミット成功を返し、サーバーがクラッシュするとその間のコミットは失われます。ロスト・ウィンドウは最大でwal_writer_delay(デフォルト200ms)の3倍です。データが壊れるわけではなく、失われるのは直近1秒未満のセッション・イベント書き込みであり、ユーザーから見れば再ログインで済む話です。ただしeventsテーブルが含まれる点は注目に値します — クラッシュ直前のログインイベントが監査ログから抜け落ちる可能性があるということなので、監査要件が厳しい環境では--spi-connections-jpa--quarkus--async-commit=falseでオプトアウトするか判断が必要です。

X.509クライアント認証にCA Subject DNオプションができ、事実上必須になります。 mTLSでクライアントを認証している場合、管理コンソールで信頼アンカーCAのsubject DNを指定するオプションが強制されるようになりました。既存の設定は当面動作しますが、次のメジャーからサーバー側の検証が入り、このオプションのない作成・更新・インポートは拒否されます。正確なDNの代わりに正規表現で証明書をマッチさせていたオプションも同時に廃止予告されています。TLS終端プロキシの後ろでヘッダー経由で証明書を渡す構成の場合、truststoreがクライアント証明書チェーンを検証できるようになっているかも再確認が必要です。

セルフ登録フローが変わります。 realmでセルフ登録とVerify Emailを併用している場合、登録フォームからパスワードフィールドがデフォルトで消えます。ユーザーはプロフィールのみを登録し、メールを検証した後にパスワード(またはOTP、パスキー)を設定します。検証されていないメールでクレデンシャルから先に作る順序を逆にした変更で、登録UXとドキュメント・スクリーンショットが丸ごと変わります。以前の挙動に戻すスイッチはありますが、deprecatedと表示されています。

残りは圧縮して列挙します。

  • シャットダウンタイムアウトが1秒から10秒に延び、分散キャッシュのリバランス完了を待ってから落ちるようになりました。オーケストレーターの終了猶予(terminationGracePeriodSecondsなど)と合わせておいてください。shutdown-timeoutオプションで調整可能です。
  • 新規生成されるクライアントシークレットが常に86文字になります(HS512のエントロピー確保が目的)。既存シークレットはそのままですが、シークレットを保存する側に最大長の制約があるなら伸ばす必要があります。
  • セッションクッキーのハッシュがSHA-256からSHA-384へ、新規生成されるaes-generatedキーのデフォルトサイズが128ビットから256ビットへ上がりました(いずれもCNSA 2.0への整合が目的で、既存セッション・既存realmには影響しません)。
  • 26.5.4で導入直後からdeprecatedだったview-system管理ロールが、セキュリティ上の理由で削除されました。サーバー全体の情報参照は、今後master realmのmanage-realm保有者に限定されます。
  • FreeMarkerのデフォルトが2.3.32に上がりました。レガシーディレクティブや?apiのような内部アクセスに依存していたカスタムログインテーマは、アップグレード後に必ずテストしてください。ログインテーマのボタン配置も変わりました。
  • DPoPがimplicit/hybridフローで拒否されます。フロントチャネルにアクセストークンが出ていくフローではsender-constrainedモデルが成立しないという理由で、その組み合わせは今後エラーになります。
  • Admin REST APIでIDによるユーザー参照時にサービスアカウントが含まれなくなり、Identity Providerのaliasは作成後変更不可になりました。
  • Authorization Servicesのリソースuriテンプレート検証が厳しくなりました。パス中間のワイルドカードのように元々動作していなかったパターンが今後は作成・更新時に拒否されるため、アップグレード前にリソースのurisフィールドを点検するよう、ガイドは事前点検クエリまで提供しています。

廃止レーダー — 今すぐ切るか乗り換えるもの

  • Identity Brokering API V1がdeprecatedになりました。 代替のV2は、ユーザーにbrokerロールを付ける代わりにクライアント単位の認可(外部トークン参照の許可スイッチ + IdP許可リスト)に切り替わり、confidentialクライアントのみを許可し、POST + 標準JSONレスポンスを使います。V2は今回のリリースでサポートされますがデフォルト無効で、V1はまだデフォルト有効です — 将来のリリースでV1が削除されV2がデフォルトになる予定なので、外部IdPトークンを取り出して使っているアプリケーションがあるなら、今からV2に移行するのが妥当です。
  • Twitter Identity Brokerが削除予告されました。 レガシーなOAuth 1.0aエンドポイントに依存しているためです。XのOAuth 2.0エンドポイントに対してgeneric OAuth v2 IdPを設定する形に乗り換え、使っていないなら--features-disabled=twitter-brokerで今から無効化できます。
  • OIDCクライアントのBearer-onlyスイッチがdeprecatedになりました。 コンソールからはすでに消えており、RESTでのみ設定可能でしたが、それも塞がれる予定です。グラントなしのOIDCクライアントで同じ目的を達成できます。
  • WebAuthnポリシーのRequire Discoverable CredentialオプションがDeprecatedになりました。 新しいDiscoverable CredentialオプションはWebAuthn仕様のresidentKey値(required/preferred/discouraged)をそのままサポートします — Yes/Noの強制では表現できなかったpreferredは、iCloud Keychain、Google Password Manager、1Passwordのようなパスキープロバイダーとの互換性にとって重要です。パスキーのエコシステムが今どこまで来ているかは、パスキー・クレデンシャル・エクスチェンジのまとめで扱いました。
  • SHA-1がKeycloak 27で全面削除されます。 NISTのSHA-1退役計画(2030年に完全退役)を根拠に、アップグレードガイドはKeycloak内ではSHA-1をすでに退役したものとみなし、SHA-2/SHA-3系列へ今すぐ移行するよう明記しています。SAMLの署名アルゴリズムや古い連携でSHA-1を使っているなら、27が出る前に整理する必要があります。

その他の標準実験 — 一段落ずつ

今回のリリースにはexperimentalタグの付いた標準実装がやけに多く含まれています。すべてデフォルト無効で、experimentalはプレビューよりもさらに手前の段階だという前提で目を通してください。

  • Shared Signals Framework送信側(ssf): ログアウト・クレデンシャル変更・アカウント無効化のようなセキュリティイベントを、署名付きSET(RFC 8417)としてダウンストリームへほぼリアルタイムでプッシュします。CAEP 1.0とRISC 1.0のプロファイル、push(RFC 8935)/poll(RFC 8936)配送の両方をサポートし、再起動してもイベントを失わないよう耐久性のあるoutboxで設計されています。トークンリフレッシュまでセッション無効化が分からない古典的な空白を狙った機能です。
  • AuthZEN Evaluation API(authzen): OpenID AuthZEN 1.0のPDPの役割を実装しました。subject/resource/actionを送るとpermit/denyを既存のAuthorization Servicesポリシーで返します。単発・バッチ評価の両方に対応します。
  • Identity Assertion JWT Grant(identity-assertion-jwt): 組織間で認証サーバーをまたぐ際に再認証なしでトークンを受け取るID-JAGドラフトの部分実装です。現状は受信側の役割のみが実装されており、フルフローはまだ動きません。
  • トークン交換委任(token-exchange-delegation): ゲートウェイがダウンストリームでユーザーに代わって振る舞う委任シナリオ向けで、delegationパラメータ化されたスコープがユーザー同意を要求し、リフレッシュのたびに再評価されます。トークン交換の背景はRFC 8693 トークン交換と委任を参照してください。
  • Admin API v2(client-admin-api:v2): 厳格な検証と正確なOpenAPI仕様を備えた新しい管理APIの最初のリソースとして、クライアント管理が入りました。OperatorがこれをKeycloakOIDCClient/KeycloakSAMLClientカスタムリソースでクライアントを宣言的に管理するために使います。既存Admin REST APIの緩い検証と不正確な仕様という長年の不満への回答が始まったと言えます。

プレビューから正式サポートに昇格したのは、SAMLクライアントのstep-up認証一つです。OIDCにしかなかった認証コンテキスト要求がSAML SPにも開かれました。

だからいつ上げて、何を有効にするか

まとめると、こう判断します。

  • アップグレード自体はマイナーリリースであり、上記の一覧はすべて管理可能な水準なので、先送りする理由はありません。ただし上げる前に、X.509 CA Subject DNの追加、クライアントシークレットの長さ制約、カスタムテーマのテスト、非同期コミットのオプトアウトの要否、セルフ登録フローの変化という4~5点はチェックリストに入れてください。
  • SCIMプレビューはステージングで試す価値が十分にあります。特にAdmin REST APIでプロビジョニングスクリプトを組んで使ってきた組織なら、標準プロトコル + 既存の権限モデル + 管理者保護までそろったこの方向は長期的に正しい選択です。ただしプロダクション依存はpreviewがsupportedに昇格してからが妥当で、Keycloakがクライアントになる方向(外部SCIM連携、ダウンストリームプッシュ)はまだ存在しないことを前提に設計してください。
  • マルチクラスターv2は、今v1(外部Infinispan)の運用に疲れており、単一リージョン + 同期レプリケーションDBという条件を満たせる組織にとって実質的な単純化です。逆に地理的DRが要件なら、この機能は答えではありません — 10ms未満のDBレイテンシ要求がその線を引いています。オン・オフの際に全体シャットダウンが必要な点まで計画に入れてください。
  • 組織管理ロール3つはプレビューではなく、今回のリリースの静かな実利です。テナント管理者にmanage-realmを渡していたなら今すぐ回収し、manage-organizations以下に絞り込むことが、今回のアップグレードで得られる最も確実なセキュリティ改善です。

おわりに

Keycloak 26.7はヘッドライン(SCIM、マルチクラスターv2)だけ見るとプレビューの祭典ですが、その下に流れる方向は一貫しています — サードパーティ拡張と外部インフラが埋めてきた空白をコアの標準実装に吸収し(SCIM、SSF、AuthZEN)、高権限ロールを分割し(組織管理ロール、view-systemの削除)、古い緩みを締め直す(X.509 CA DN、URIテンプレート検証、SHA-1退役予告)。自前でIdPを運用している立場からすると歓迎すべき方向で、その代償はアップグレードガイドが長くなることだけです。リリースノートだけ読んで済ませず、アップグレードガイドをチェックリスト代わりに一度通すことをお勧めします。

参考資料