🐣

Keycloak にカスタム User Storage Provider を追加する

2023/05/15に公開

Keycloak のクイックスタートに用意されているユーザーストレージ SPI プロバイダーの一つを Keycloak に追加する作業を通じて、 Keycloak を拡張する一連の手順を確認しました。
本記事ではプロバイダーを Keycloak に適用する手順を扱いますが、プロバイダーの開発には触れません。

動作環境

WSL バージョン: 1.2.5.0
Docker version 23.0.5, build bc4487a
Keycloak version 21.1.1

使用したクイックスタート

今回は user-storage-simple というクイックスタートを使用しました。このクイックスタートで提供されているのは、ローカルのプロパティファイルをユーザーストレージとして用いるシンプルなユーザーストレージ SPI のカスタムプロバイダーです。
https://github.com/keycloak/keycloak-quickstarts/tree/latest/user-storage-simple

プロパティファイルには、以下のように = を区切り文字としてユーザ名とパスワードのペアが平文で保存されています。 tbrady がユーザ名、 superbowl がパスワードです。

users.properties
tbrady=superbowl

設定

カスタムプロバイダの組み込みは以下の流れで行います。
今回は、2~3は Docker イメージの作成の中で行います。

  1. カスタムプロバイダーを jar ファイルとして作成する
  2. jar ファイルを providers ディレクトリに配置する
  3. kc.sh build を実行する
  4. Keyclaok 管理コンソールでレルムにカスタムプロバイダーを追加する

jar ファイルの作成

クイックスタートのリポジトリをクローンして、対象の Maven プロジェクトをビルドします。

git clone https://github.com/keycloak/keycloak-quickstarts.git
cd keycloak-quickstarts/user-storage-simple
mvn clean install

jar を組み込んだ Docker イメージの作成

公式ガイドに載っているサンプルを参考に、 Dockerfile を作ります。
COPY 命令で user-storage-properties-example.jar を /opt/keycloak/providers ディレクトリに配置しているのが、 SPI プロバイダーの組み込みに該当します。

Dockerfile
FROM quay.io/keycloak/keycloak:latest as builder

WORKDIR /opt/keycloak
# for demonstration purposes only, please make sure to use proper certificates in production instead
RUN keytool -genkeypair -storepass password -storetype PKCS12 -keyalg RSA -keysize 2048 -dname "CN=server" -alias server -ext "SAN:c=DNS:localhost,IP:127.0.0.1" -keystore conf/server.keystore
RUN /opt/keycloak/bin/kc.sh build

FROM quay.io/keycloak/keycloak:latest
COPY --from=builder /opt/keycloak/ /opt/keycloak/

COPY --chown=keycloak:keycloak user-storage-properties-example.jar /opt/keycloak/providers/user-storage-properties-example.jar

ENV KC_HOSTNAME=localhost

ENV KEYCLOAK_ADMIN=admin
ENV KEYCLOAK_ADMIN_PASSWORD=admin

ENTRYPOINT ["/opt/keycloak/bin/kc.sh"]

Docker イメージをビルドします。

docker build . -t mykeycloak

レルムにカスタムプロバイダーを追加する

Docker イメージからコンテナを起動します。

docker run --name mykeycloak -p 8080:8080 \
        mykeycloak \
        start-dev

ホストから Keycloak の管理コンソール (今回は http://localhost:8080/admin) にアクセスして、 Dockerfile で指定した管理者のユーザ名とパスワードでログインします。

User Fedearation のメニューを選択すると、今回の作業で追加された二つのカスタムプロバイダーが表示されました。
User Fedearation の設定
プロバイダーの一覧にカスタムプロバイダーが表示された

[Add Readonly-property-file provider] を選択して、 master レルムにカスタムプロバイダーを追加します。このカスタムプロバイダーでは、必須項目として UI Display Name という管理コンソールに表示される名前を設定する必要があるので、適当な表示名を設定します。今回は "Readonly-property-file provider" としました。

Readonly-property-file provider の設定

[Save] して、レルムへのプロバイダーの追加は完了です。

動作確認

管理コンソールの Users には何が表示される?

まずは master レルムのユーザー一覧を見てみます。管理コンソールの説明を信じると、 [Search User] に "*" を入れて検索するとフェデレーテッドプロバイダーも含めユーザーの一覧が表示されるとのことなので、試してみます。

master レルムのユーザー一覧

予想とは異なり、 admin しか表示されませんでした。これは、今回追加したプロバイダに UserQueryProvider インターフェースが実装されていないためと思われます。公式のガイドに以下の説明がありました。

SPI: org.keycloak.storage.user.UserQueryProvider
Description: Defines complex queries that are used to locate one or more users. You must implement this interface if you want to view and manage users from the administration console.

カスタムプロバイダーによるログイン

ログインも試してみました。
挙動は通常のユーザ名/パスワードのログインと変わりませんでした。

ログインの挙動は内部データべースで管理されているユーザーと変わらない

Keycloak 内部のユーザーストアに同じユーザ名のユーザーは作れる?

作れませんでした。作ろうとすると、 同じ username のユーザーが存在する、と怒られます。

既存のユーザーとユーザー名が重複するユーザーは作れない

Keycloakは複数のユーザーデータベース間でのユーザー名やメールアドレスの重複を良しとしていません。その思想に則った挙動だと思います。

When a Storage Provider lookup fails, Keycloak does not fail over because user databases often have duplicate usernames or duplicate emails between them. Duplicate usernames and emails can cause problems because the user loads from one external data store when the admin expects them to load from another data store.
https://www.keycloak.org/docs/latest/server_admin/#dealing-with-provider-failures

まとめ

ユーザーストレージ SPI のカスタムプロバイダーを Keycloak に組み込む手順を確認しました。 jar を provider ディレクトリに配置して kc.sh build するだけでした。

Discussion