Keycloak.Xのプロパティ設定方法[2020.12]

(株)日立製作所 研究開発グループ サービスコンピューティング研究部の井出です。

先日，[OpenShift.Run Winter 2020](https://openshift.connpass.com/event/191402/)にて、[Keycloak.X](https://github.com/keycloak/keycloak-community/tree/master/design/keycloak.x)の背景やビルド方法、コンテナ化、性能評価を紹介させていただきました。

[Keycloak on Quarkus - Speakerdeck](https://speakerdeck.com/ido_kara_deru/keycloak-on-quarkus)

本記事は発表時にあまり触れられなかったKeycloak.Xのプロパティ設定方法について改めてまとめたいと思います。なお、2020年12月現在、keycloak.Xの仕様はまだドラフト版であるため、記事の内容から変更される可能性があります。最新の情報は[Keycloak.X Server Configuration](https://github.com/keycloak/keycloak-community/blob/master/design/keycloak.x/configuration.md)をご参照下さい。

## TL;DR

- Keycloak.Xのプロパティは動的プロパティと静的プロパティに分かれる
- 動的プロパティは環境変数、ファイル、起動オプションにて設定
- 静的プロパティは`kc.sh config`コマンドかビルド時にファイルで設定
- 現状、静的プロパティは`--db`と`--feature`、`--feature-xxx`系が該当
- それ以外に、初期管理者アカウントの設定要
    - 環境変数の`KEYCLOAK_ADMIN`と`KEYCLOAK_ADMIN_PASSWORD`にて設定

## Keycloak.Xとは

Keycloak.XはKeycloakのモダナイズのために、実験的に大胆な変更を追加するプロジェクトです。フレームワークへのQuarkusの採用、設定の容易化、など様々な取り組みを行っています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/542848/417b89dd-394e-29e7-e585-5386696d4277.png)

2020年12月現在、Keycloak.Xの実行ファイルやコンテナイメージは配布されていませんが、[keycloak/keyckoak](https://github.com/keycloak/keycloak/tree/master) のMasterブランチにて [/quarkus](https://github.com/keycloak/keycloak/tree/master/quarkus) ディレクトリをビルドすれば利用可能です。Keycloak.Xの取り組みは、今後、[通常のKeycloakに還元されていく](https://github.com/keycloak/keycloak-community/tree/master/design/keycloak.x#migration-to-keycloak-x)とのことですので、この機会にKeycloak.Xに触れてみてはいかがでしょうか？

## Keycloak.Xのプロパティ

standalone.xmlを用いた設定を行う通常のKeycloakと異なり、Keycloak.Xの設定はプロパティの種類に応じ異なる設定方法が用意されています（下記表）。

|種類|説明|設定方法|
|---|---|---|
|[動的プロパティ](https://github.com/keycloak/keycloak-community/blob/master/design/keycloak.x/configuration.md#dynamic-properties)|サーバ起動時に動的に設定可能なプロパティ|- 環境変数<br>- `kc.sh start`のオプション<br>- `conf/keycloak.properties`ファイル|
|[静的プロパティ](https://github.com/keycloak/keycloak-community/blob/master/design/keycloak.x/configuration.md#static-properties) | サーバのビルド時に設定が必要なプロパティ<br>（全ての動的プロパティは静的プロパティとしても設定可能。動的・静的の両方で同じプロパティが設定されたときは静的プロパティが優先される） |- ビルド時の`keycloak.apprication`<br>- `kc.sh` config コマンド<br>- Auto-Configuration機能<br>（[keycloak/keycloak-containers](https://github.com/keycloak/keycloak-containers/tree/master/server-x)のDockerfileを用いてコンテナ化した場合）|
|その他|動的・静的プロパティ以外の設定項目<br>（本記事独自の定義）|環境変数|

プロパティの一覧はデザインノートの[Keycloak.X Server Configuration](https://github.com/keycloak/keycloak-community/blob/master/design/keycloak.x/configuration.md#config-options)に記載されています。しかし、2020年12月現在、デザインノートには動的プロパティや静的プロパティの区分けの情報は記載されていないため、`kc.sh`のヘルプメッセージからそれぞれのプロパティを探る必要があります。

以降、動的プロパティと静的プロパティをそれぞれ見ていきます。

## 動的プロパティ

### 動的プロパティ一覧

`kc.sh start --help`コマンドから一覧を取得可能です。
以下に、ヘルプメッセージから動的プロパティを抜き出した内容を記載します。

```sh
--cluster=<value>       Specifies clustering configuration. The specified
                        value points to the infinispan configuration
                        file prefixed with the 'cluster-' inside the
                        distribution configuration directory. Supported
                        values out of the box are 'local' and 'cluster'.
                        Value 'local' points to the file cluster-local.
                        xml and effectively disables clustering and use
                        infinispan caches in the local mode. Value
                        'default' points to the file cluster-default.
                        xml, which has clustering enabled for infinispan
                        caches.
--cluster-stack=<value>
                        Specified the default stack to use for cluster
                        communication and node  discovery. Possible
                        values are: tcp, udp, kubernetes, ec2.
--config-file=<path>    Set the path to a configuration file.
--db-password=<value>   The database password.
--db-pool-initial-size=<value>
                        The initial size of the connection pool.
--db-pool-max-size=<value>
                        The maximum size of the connection pool.
--db-pool-min-size=<value>
                        The minimal size of the connection pool.
--db-schema=<value>     The database schema.
--db-url=<value>        The database JDBC URL. If not provided a default
                        URL is set based on the selected database
                        vendor. For instance, if using 'postgres', the
                        JDBC URL would be 'jdbc:postgresql:
                        //localhost/keycloak'. The host, database and
                        properties can be overridden by setting the
                        following system properties, respectively: -Dkc.
                        db.url.host, -Dkc.db.url.database, -Dkc.db.url.
                        properties.
--db-username=<value>   The database username.
--hostname-admin-url=<value>
                        The URL that should be used to expose the admin
                        endpoints and console.
--hostname-force-backend-url-to-frontend-url =<value>
                        Forces backend requests to go through the URL
                        defined as the frontend-url. Defaults to false.
                        Possible values are true or false.
--hostname-frontend-url=<value>
                        The URL that should be used to serve frontend
                        requests that are usually sent through the a
                        public domain.
--http-enabled=<value>  Enables the HTTP listener.
--http-host=<value>     The HTTP host.
--http-port=<value>     The HTTP port.
--https-certificate-file=<value>
                        The file path to a server certificate or
                        certificate chain in PEM format.
--https-certificate-key-store-file=<value>
                        An optional key store which holds the certificate
                        information instead of specifying separate files.
--https-certificate-key-store-file-type=<value>
                        An optional parameter to specify type of the key
                        store file. If not given, the type is
                        automatically detected based on the file name.
--https-certificate-key-store-password=<value>
                        A parameter to specify the password of the key
                        store file. If not given, the default
                        ("password") is used.
--https-certificate-trust-store-file=<value>
                        An optional trust store which holds the
                        certificate information of the certificates to
                        trust.
--https-certificate-trust-store-file-type=<value>
                        An optional parameter to specify type of the trust
                        store file. If not given, the type is
                        automatically detected based on the file name.
--https-certificate-trust-store-password=<value>
                        A parameter to specify the password of the trust
                        store file.
--https-cipher-suites=<value>
                        The cipher suites to use. If none is given, a
                        reasonable default is selected.
--https-client-auth=<value>
                        Configures the server to require/request client
                        authentication. none, request, required.
--https-port=<value>    The HTTPS port.
--https-protocols=<value>
                        The list of protocols to explicitly enable.
--profile=<profile>     Set the profile. Use 'dev' profile to enable
                        development mode.
--proxy=<value>         The proxy mode if the server is behind a reverse
                        proxy. Possible values are: none, edge,
                        reencrypt, and passthrough.
--show-config[=<arg0>]  Print out the configuration options when starting
                        the server.
```

### 動的プロパティの設定方法

動的プロパティの設定方法は以下3種があり、それぞれプロパティのフォーマットが異なります。

- `conf/keycloak.properties`ファイル
- `kc.sh start`コマンド
- 環境変数

`conf/keycloak.properties`ファイルには[Keycloak.X Server Configuration](https://github.com/keycloak/keycloak-community/blob/master/design/keycloak.x/configuration.md)に記載のプロパティ名をそのまま利用可能です。そこから、頭に`--`を付け、`.`を`-`に置き換えると`kc.sh start`コマンドのオプションのフォーマットになります。同様に頭に`KC_`を付け、英語を大文字にし、`-`と`.`を`_`に置き換えると環境変数になります。

以下が各設定方法におけるプロパティ名の例です。

```sh
# Keycloak.X Server Configuration に記載のプロパティ名
#（conf/keycloak.propertiesへの記載方法）
db.pool.initial-size

# kc.sh start コマンドのオプション
--db-pool-initial-size

# 環境変数
KC_DB_POOL_INITIAL_SIZE
```

命名規則の詳細は[how-to-set-configuration](https://github.com/keycloak/keycloak-community/blob/master/design/keycloak.x/configuration.md#how-to-set-configuration)に記載されています。

## 静的プロパティ

### 静的プロパティ一覧

`kc.sh config --help`コマンドにて一覧を取得可能です。静的プロパティは全ての動的プロパティと同名のプロパティを持つため、ここでは重複を排除し、静的プロパティ固有の値のみ記載します。

```sh
--db=<value>            The database vendor. Possible values are: h2-mem, 
                        h2-file, mariadb, postgres95, postgres10.
--features=<value>      Enables a group of features. Possible values are:
                        default,disabled_by_default,preview,experimental,
                        deprecated
--features-account2=<value>
                        Enables the ACCOUNT2 feature. Set enabled to enable
                        the feature or disabled otherwise.
--features-account_api=<value>
                        Enables the ACCOUNT_API feature. Set enabled to
                        enable the feature or disabled otherwise.
--features-admin_fine_grained_authz=<value>
                        Enables the ADMIN_FINE_GRAINED_AUTHZ feature. Set
                        enabled to enable the feature or disabled otherwise.
--features-client_policies=<value>
                        Enables the CLIENT_POLICIES feature. Set enabled
                        to enable the feature or disabled otherwise.
--features-docker=<value>
                        Enables the DOCKER feature. Set enabled to enable
                        the feature or disabled otherwise
--features-impersonation=<value>
                        Enables the IMPERSONATION feature. Set enabled to
                        enable the feature or disabled otherwise.
--features-openshift_integration=<value>
                        Enables the OPENSHIFT_INTEGRATION feature. Set
                        enabled to enable the feature or disabled otherwise.
--features-scripts=<value>
                        Enables the SCRIPTS feature. Set enabled to enable
                        the feature or disabled otherwise.
--features-token_exchange=<value>
                        Enables the TOKEN_EXCHANGE feature. Set enabled to
                        enable the feature or disabled otherwise.
--features-upload_scripts=<value>
                        Enables the UPLOAD_SCRIPTS feature. Set enabled to
                        enable the feature or disabled otherwise.
--features-web_authn=<value>
                        Enables the WEB_AUTHN feature. Set enabled to
                        enable the feature or disabled otherwise.
```

2020年12月現在は、DB種別およびfeature系の設定のみ静的プロパティ固有の値と考えることができます。

### 静的プロパティの設定方法

静的プロパティの設定は以下の3種類があります。

- Keycloak.Xビルド時の [keycloak.properties](https://github.com/keycloak/keycloak/blob/master/quarkus/server/src/main/resources/META-INF/keycloak.properties) 編集
- `kc.sh config`コマンド
- [Auto-Configuration](https://github.com/keycloak/keycloak-containers/tree/master/server-x#auto-configuration)機能

[keycloak.properties](https://github.com/keycloak/keycloak/blob/master/quarkus/server/src/main/resources/META-INF/keycloak.properties)はソースコードの`./quarkus/server/src/main/resources/META-INF`配下にあるファイルです。こちらに動的プロパティの`conf/keycloak.properties`と同様のフォーマットでプロパティを追加することで、設定が可能です。しかし、マシンの性能にもよりますがKeycloak.Xのビルドには1時間前後かかるため、何度も静的プロパティを設定する場合は別の方法がおすすめです。

`kc.sh config`コマンドには動的プロパティの`kc.sh start`コマンド利用時と同様、コマンドオプションとして設定します。フォーマットも動的プロパティの`kc.sh start`コマンド利用時と同様です。ただし、`kc.sh start`コマンドにてKeycloak.Xサーバを起動する前に設定する必要があるため、コンテナとして利用する場合は、`kc.sh config --db=postgres10 && kc.sh start`のようにコマンドを連結して使用するか、起動用のスクリプトを用意すると良いでしょう。

[keycloak/keycloak-containers](https://github.com/keycloak/keycloak-containers/tree/master/server-x)のDockerfileを用いてコンテナを作成した場合は、[Auto-Configuration](https://github.com/keycloak/keycloak-containers/tree/master/server-x#auto-configuration)機能を利用可能です。Auto-Configurationは、起動時のオプションに`--auto-config`を加えると、内部の[docker-entrypoint.sh](https://github.com/keycloak/keycloak-containers/blob/master/server-x/tools/docker-entrypoint.sh)が動的に`kc.sh config`を自動実行する機能です。このため、設定時のフォーマットは`kc.sh config`コマンド利用時と同様です。

## その他プロパティ

Keycloak.X Server Configurationに未記載のプロパティとして、初期管理者アカウントの設定があります。
以下のように環境変数から設定可能です。

```shell
# adminユーザ
export KEYCLOAK_ADMIN=admin
# adminパスワード
export KEYCLOAK_ADMIN_PASSWORD=password
```

今回調査した範囲では、通常のKeycloakにおける`add-user-keycloak.sh`のように後から管理者アカウントを設定する方法をKeycloak.Xにて確認できませんでした。このため、keycloak.Xでは本手法での管理者アカウントを作成する必要があります。

## 設定の注意点

いくつか注意点を列挙します。

- 上述のように、動的・静的の両方で同名のプロパティを設定した場合、静的プロパティが優先されます。
- [Keycloak.X Server Configuration](https://github.com/keycloak/keycloak-community/blob/master/design/keycloak.x/configuration.md)には`metrics.enabled=[true|false]`によりヘルスチェックとメトリクス取得が可能になると記載がありますが、2020年12月現在では、まだ`metrics.enabled`プロパティが有効化できませんでした。

## Kubernetesでの動作を想定したKeycloak.Xのプロパティ設定案

Keycloak.XはQuarkusの採用や環境変数からのパラメータ設定など、コンテナからの利用に適しています。そこで、著名なコンテナオーケストレータのKubernetes上でKeycloak.Xを動作させる際のプロパティ設定に触れたいと思います。

ユースケースにも依存すると思いますが、筆者は保守性・機密性の観点で以下の設定方法が良いと考えます。

1. なるべく動的プロパティを活用し、環境変数か`conf/keycloak.properties`にて設定する
1. クレデンシャル情報はSecretリソース等を使用する
1. 静的プロパティ固有の設定のみAuto-Configuration機能、もしくは起動コマンドにて設定する

以下理由を説明します。

Keycloak.Xのプロパティには`db.password`などのクレデンシャル情報が含まれます。クレデンシャル情報は平文で保持するとセキュリティリスクになることから、KubernetesのSecretリソース等を用いて難読化することが望ましいです[^1]。`kc.sh start`および`kc.sh config`コマンドでの設定はSecretリソースとの連携ができないため、クレデンシャル情報は動的プロパティの環境変数か`conf/keycloak.properties`を利用して設定する必要があります。

環境変数の場合は、クレデンシャル情報のみSecretリソースで設定し、他のプロパティはDeployentリソースに設定可能です。一方で、`conf/keycloak.properties`にてクレデンシャル情報を含む設定をする場合、`conf/keycloak.properties`全体をSecretリソースで難読化してしまうと保守性が下がります。このため、クレデンシャル情報のみ環境変数ので設定し、他のプロパティを`conf/keycloak.properties`のConfigmapリソースとして設定するか、もしくはクレデンシャル情報のみ`conf/keycloak.properties`のSecretリソースで設定し、他は環境変数として設定するなど、設定を使い分けると良いでしょう。

静的プロパティ固有の設定は環境変数や`conf/keycloak.properties`が使えません。設定を後から変更しない場合はビルド時の`keycloak.properties`を用いても問題ありませんが、Keycloak.Xのビルドには相応の時間がかかることから、変更の可能性がある場合はAuto-Configuration機能か`kc.sh config`コマンドの利用が望ましいです。これらの設定は別途スクリプトやinitContainer等の手段を設けない場合はDeploymentリソースの`command`および`args`を用いて行えます。`kc.sh config`を使う場合、例えば以下のように設定可能です。

```sh
containers:
  command: ["/bin/sh","-c"]
  args: ["kc.sh config --db=postgres10 && kc.sh start"]

```

一方で、`command`や`args`はSecretリソースと連携できないため[^2]、クレデンシャル情報の設定は避けたほうが望ましいです。また、`args`の設定がが長くなると可読性が下がります。このことから、静的プロパティの利用は必要最小限にし、動的プロパティで設定した方が保守性に優れます。

[^1]: Secretリソース以外にもパブリッククラウドのクレデンシャル情報管理サービス（例えばAWS Secret Manager）やSealed-SecretのようなKubernetes周辺ツールの利用も考えられます。
[^2]: 環境変数の値を`args`で用いればSecret連携ができますが、`args`を管理が必要な分、保守性は低下します。それなら最初から動的プロパティの環境変数で設定したほうが運用負荷は少ないです。

## まとめ

本記事ではKeycloak.Xの動的・静的プロパティの設定方法を紹介しました。概要は以下の通りです（TL;DRと同文）。

- Keycloak.Xのプロパティは動的プロパティと静的プロパティに分かれる
- 動的プロパティは環境変数、ファイル、起動オプションにて設定
- 静的プロパティは`kc.sh config`コマンドかビルド時にファイルで設定
- 現状、静的プロパティは`--db`と`--feature`、`--feature-xxx`系が該当
- それ以外に、初期管理者アカウントの設定要
    - 環境変数の`KEYCLOAK_ADMIN`と`KEYCLOAK_ADMIN_PASSWORD`にて設定

Keycloak.Xは設定やスケールの容易化やQuarkusの採用など、Kubernetes/OpenShift等のコンテナ基盤に適した特徴を持ち、今後の発展が期待されます。まだ開発中の機能も多いですが、これら機能をいち早く試用し、バグ等をコミュニティにフィードバックする意義は大きいです。こちらで確認した範囲では既にKeycloak.Xの基礎的な動作が可能なため、皆様もこの機会にKeycloak.Xを試してみては如何でしょうか。

本記事がKeycloakのユーザやコミュニティにとって参考になれば幸いです。