第7章 ユーザーストレージ SPI
ユーザーストレージ SPI を使用して拡張機能を Red Hat Single Sign-On に書き込み、外部のユーザーデータベースおよび認証情報ストアに接続することができます。組み込み LDAP および ActiveDirectory サポートは、この SPI 動作を実装したものです。追加設定なしで、Red Hat Single Sign-On はローカルデータベースを使用して、ユーザーおよびクレデンシャルの作成、更新、および検証を行います。多くの場合、組織には Red Hat Single Sign-On のデータモデルに移行できない既存の外部プロプライエタリーユーザーデータベースがあります。このような状況では、アプリケーション開発者は User Storage SPI の実装を作成し、外部ユーザーストアと、内部のユーザーオブジェクトモデルとの橋渡しをして、Red Hat Single Sign-On がユーザーのログインと管理を行えるようにします。
Red Hat Single Sign-On ランタイムがユーザーログイン時など、ユーザーを検索する必要がある場合は、複数の手順を実行してユーザーを特定します。まず、ユーザーキャッシュにユーザーが含まれているかどうかを確認します。ユーザーが見つかった場合にはユーザーがそのインメモリー表現を使用しているかを確認します。次に、Red Hat Single Sign-On のローカルデータベース内でユーザーを検索します。ユーザーが見つからない場合は、ランタイムが探しているユーザーをいずれかの実装が返すまで、User Storage SPI プロバイダー実装全体をループして、ユーザークエリーを実行し続けます。プロバイダーは、ユーザーの外部ユーザーストアをクエリーし、ユーザーの外部データ表現を Red Hat Single Sign-On のユーザーメタモデルにマップします。
User Storage SPI プロバイダー実装は、複雑な基準クエリーの実行、ユーザーへの CRUD 操作の実行、認証情報の検証および管理、または多数のユーザーの一括更新を実行することもできます。これは、外部ストアの機能により異なります。
User Storage SPI プロバイダー実装は、Jakarta EE コンポーネントと同様にパッケージ化およびデプロイされます。これらはデフォルトでは有効になっていませんが、管理コンソールの User Federation
タブでレルムごとに有効および設定する必要があります。
ユーザープロバイダーの実装で、ユーザー属性をユーザーアイデンティティーのリンク/確立のためのメタデータ属性として使用している場合は、ユーザーが属性を編集できないようにし、対応する属性が読み取り専用になっていることを確認してください。この例は LDAP_ID
属性で、内蔵の Red Hat Single Sign-On LDAP プロバイダーが LDAP サーバー側でユーザーの ID を保存するために使用しています。詳細については、脅威モデルの軽減の章 を参照してください。
7.1. プロバイダーインターフェイス
User Storage SPI の実装を構築する場合は、プロバイダークラスとプロバイダーファクトリーを定義する必要があります。プロバイダークラスインスタンスは、プロバイダーファクトリーによってトランザクションごとに作成されます。プロバイダークラスは、ユーザー検索やその他のユーザー操作で負荷が大きい作業をすべて行います。org.keycloak.storage.UserStorageProvider
インターフェイスを実装する必要があります。
package org.keycloak.storage; public interface UserStorageProvider extends Provider { /** * Callback when a realm is removed. Implement this if, for example, you want to do some * cleanup in your user storage when a realm is removed * * @param realm */ default void preRemove(RealmModel realm) { } /** * Callback when a group is removed. Allows you to do things like remove a user * group mapping in your external store if appropriate * * @param realm * @param group */ default void preRemove(RealmModel realm, GroupModel group) { } /** * Callback when a role is removed. Allows you to do things like remove a user * role mapping in your external store if appropriate * @param realm * @param role */ default void preRemove(RealmModel realm, RoleModel role) { } }
UserStorageProvider
インターフェイスはほんのわずかであると思われるかもしれません。本章では後で、ユーザー統合のサポート向けにプロバイダーが実装する可能性のあるさまざまなインターフェイスが他にあることを説明します。
UserStorageProvider
インスタンスは、トランザクションごとに 1 度作成されます。トランザクションが完了すると、UserStorageProvider.close()
メソッドが呼び出され、インスタンスはガベージコレクションされます。インスタンスはプロバイダーファクトリーによって作成されます。プロバイダーファクトリーは org.keycloak.storage.UserStorageProviderFactory
インターフェイスを実装します。
package org.keycloak.storage; /** * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a> * @version $Revision: 1 $ */ public interface UserStorageProviderFactory<T extends UserStorageProvider> extends ComponentFactory<T, UserStorageProvider> { /** * This is the name of the provider and will be shown in the admin console as an option. * * @return */ @Override String getId(); /** * called per Keycloak transaction. * * @param session * @param model * @return */ T create(KeycloakSession session, ComponentModel model); ... }
プロバイダーファクトリークラスは、UserStorageProviderFactory
を実装する際に、具体的なプロバイダークラスをテンプレートパラメーターとして指定する必要があります。これはランタイムがこのクラスをイントロスペクションしてその機能 (実装する他のインターフェイス) をスキャンするため必要です。たとえば、プロバイダークラスの名前が FileProvider
の場合、ファクトリークラスは以下のようになります。
public class FileProviderFactory implements UserStorageProviderFactory<FileProvider> { public String getId() { return "file-provider"; } public FileProvider create(KeycloakSession session, ComponentModel model) { ... }
getId()
メソッドは、User Storage プロバイダーの名前を返します。この ID は、特定のレルムのプロバイダーを有効にする際に管理コンソールのユーザーフェデレーションページに表示されます。
create()
メソッドは、プロバイダークラスのインスタンスを割り当てます。org.keycloak.models.KeycloakSession
パラメーターを取ります。このオブジェクトは、その他の情報およびメタデータを検索し、ランタイム内の他のコンポーネントへのアクセスを提供するために使用できます。ComponentModel
パラメーターは、プロバイダーが特定のレルム内でどのように有効および設定されたかを表します。これには、有効化されたプロバイダーのインスタンス ID と、管理コンソールで有効にした場合に指定できる設定が含まれます。
UserStorageProviderFactory
には他の機能があり、この後、本章で取り上げます。