Keycloak コンテナがめっちゃ便利だったのでついでに https 化もした

関連記事
【Keycloak】Apache の VirtualHost で分けられた複数のサイトをまとめてシングルサインオンしよう
https://qiita.com/thirdpenguin/items/1136c755560eea51b5b1

---

公式にリリースされているコンテナイメージによる Keycloak 導入があまりにも簡単すぎて感動したので、ついでに Keycloak コンテナの https 化もやってみました。

github リポジトリにやり方がありました。
https://github.com/keycloak/keycloak-containers/tree/master/server#setting-up-tlsssl

上記を要約すると、「```/etc/x509/https``` に 秘密鍵 tls.key と 証明書 tls.crt をくれると後はよろしくやるよ！でもボリュームマウントで置くとファイルのオーナーが root になるから、適切な所有者が読み取り可能になるようイメージを直してね！」とのことです。ボリュームマウントによるオーナーの変更は、 root 以外のユーザで Keycloak を動かす時には留意する必要がありそうですね。

ではやっていきましょう。 1 章では Keycloak の導入から始めるので、もう Keycloak コンテナの準備が終わっている方は 2 章からどうぞ。

## バージョン情報
- Keycloak サーバ (IdP)
- OS: CentOS8 (8.1.1911)
- podman: 1.6.4
- podman-compose: 0.1.7.dev0


## 1. Keycloak コンテナの準備
公式 github リポジトリ keycloak-containers の docker-compose ファイルのサンプルを podman-compose に流用して、Keycloak コンテナと、連携する DB となる PostgreSQL コンテナを一気に建てます。
関連記事と同じ作業内容なので、もう終わっている方は読み飛ばしてしまって結構です。

1. podman のインストール

```
# dnf -y install podman
```
　
2. podman-compose のインストール
podman-compose のインストールに pip3 が必要なので、 pip3 を同梱している python3 系列をインストールもします。

```
# dnf install -y python36
# pip3 install https://github.com/containers/podman-compose/archive/devel.tar.gz
```
　
3. git リポジトリ keycloak-containers をクローン
適当なディレクトリをローカルリポジトリにして、keycloak-containers リポジトリを引っ張ってきます。

```
# mkdir localrepo
# cd localrepo
# git init
# git clone https://github.com/keycloak/keycloak-containers.git
# cd keycloak-containers
# ls
CONTRIBUTING.md  License.html  README.md  adapter-wildfly  docker-compose-examples  docs  gatekeeper  keycloak-init-container  openshift-examples  server  set-version.sh
```
　
## 2. HTTPS 化作業

1. 証明書の設置

用意しておいた秘密鍵と証明書を任意のディレクトリに配置します。
[参考](https://qiita.com/thirdpenguin/private/85d05c93116d824a88d9#%E5%8F%82%E8%80%83)記事に自己署名書の取得手順があります。

```
# mkdir certs
# cp /path/to/your.key certs/tls.key
# cp /path/to/your.crt certs/tls.crt
```
　
2. keycloak-postgres.yml の編集
さて、Keycloak コンテナの https 化のためには……
所定のディレクトリ ```/etc/x509/https``` に鍵と証明書を適切なパーミッションで設置する必要があるのでした。
~~yml へ1行追記するだけで楽なので~~ 今回はバインドマウントでやってみます。

あとはポートフォワーディングの設定を変える必要もあるはずです。
http は 8080 で listen してましたが https はまた別のポートになるでしょう。
しかしはて、 https の listen ポートは一体どこへ。このイメージの [dockerfile](https://github.com/keycloak/keycloak-containers/blob/master/server/Dockerfile) に手がかりがあるのでは？

```:github.com/keycloak/keycloak-containers/blob/master/server/Dockerfileより抜粋
EXPOSE 8080
EXPOSE 8443

ENTRYPOINT [ "/opt/jboss/tools/docker-entrypoint.sh" ]

CMD ["-b", "0.0.0.0"]
```

 ```EXPOSE 8443``` の記述があるのでおそらくこれっぽいです。
念のため起動ログを漁って裏も取ったのですが、その話は後にして、とりあえず yml ファイルを編集します。
 

```
# cd docker-compose-examples
# vi keycloak-postgres.yml
```

```vim:keycloak-postgres.yml
version: '3'

volumes:
  postgres_data:
      driver: local

services:
  postgres:
      image: postgres
      volumes:
        - postgres_data:/var/lib/postgresql/data
      environment:
        POSTGRES_DB: keycloak
        POSTGRES_USER: keycloak
        POSTGRES_PASSWORD: password
  keycloak:
      image: quay.io/keycloak/keycloak:latest
      volumes: # ←追加
        - /<証明書の絶対パス>:/etc/x509/https # ←追加
      environment:
        DB_VENDOR: POSTGRES
        DB_ADDR: postgres
        DB_DATABASE: keycloak
        DB_USER: keycloak
        DB_SCHEMA: public
        DB_PASSWORD: password
        KEYCLOAK_USER: admin
        KEYCLOAK_PASSWORD: Pa55w0rd
        # Uncomment the line below if you want to specify JDBC parameters. The parameter below is just an example, and it shouldn't be used in production without knowledge. It is highly recommended that you read the PostgreSQL JDBC driver documentation in order to use it.
        #JDBC_PARAMS: "ssl=true"
      ports:
        - 8080:8080
        - 8443:8443 # ←追加
      depends_on:
        - postgres
```

Keycloak コンテナにバインドマウントするボリュームの追加と、ポート 8443 のフォワーディング設定のため3行ファイルに書き加えました。
　
3. サービス起動

鍵と証明書の設置、そして yml ファイルの編集が終わったらいよいよ起動です。

```
# cd docker-compose-examples
# podman-compose -f keycloak-postgres.yml up -d
using podman version: podman version 1.6.4
podman pod create --name=docker-compose-examples --share net -p 8443:8443 -p 8080:8080
96f023c108904557f7c953cc1896271bbfec1e9526583d9300d47cde3b1889d5
0
podman volume inspect docker-compose-examples_postgres_data || podman volume create docker-compose-examples_postgres_data
podman run --name=docker-compose-examples_postgres_1 -d --pod=docker-compose-examples --label io.podman.compose.config-hash=123 --label io.podman.compose.project=docker-compose-examples --label io.podman.compose.version=0.0.1 --label com.docker.compose.container-number=1 --label com.docker.compose.service=postgres -e POSTGRES_DB=keycloak -e POSTGRES_USER=keycloak -e POSTGRES_PASSWORD=password -v docker-compose-examples_postgres_data:/var/lib/postgresql/data --add-host postgres:127.0.0.1 --add-host docker-compose-examples_postgres_1:127.0.0.1 --add-host keycloak:127.0.0.1 --add-host docker-compose-examples_keycloak_1:127.0.0.1 postgres
046eec4c0a2619de953e35bd2940a00f43ac95ff87df955a55c07fe831492a23
0
podman run --name=docker-compose-examples_keycloak_1 -d --pod=docker-compose-examples --label io.podman.compose.config-hash=123 --label io.podman.compose.project=docker-compose-examples --label io.podman.compose.version=0.0.1 --label com.docker.compose.container-number=1 --label com.docker.compose.service=keycloak -e DB_VENDOR=POSTGRES -e DB_ADDR=postgres -e DB_DATABASE=keycloak -e DB_USER=keycloak -e DB_SCHEMA=public -e DB_PASSWORD=password -e KEYCLOAK_USER=admin -e KEYCLOAK_PASSWORD=Pa55w0rd --add-host postgres:127.0.0.1 --add-host docker-compose-examples_postgres_1:127.0.0.1 --add-host keycloak:127.0.0.1 --add-host docker-compose-examples_keycloak_1:127.0.0.1 quay.io/keycloak/keycloak:latest
8241eb401a36880c0d3850a2230ae7c15510b9eedfe20478c6357972c597da6a
0
```

ポッド作成、ボリューム作成、コンテナ作成のコマンドが実行され、正常に終われば上記のように終了コード 0 が 3 回返ります。
失敗したら、```podman-compose -f keycloak-postgres.yml down``` で一度ポッドとコンテナを削除し、問題を修正した後にもう一度実行してください。

## 3. 接続テスト
ブラウザから https://<podman ホストのIP>:8443 に接続して Keycloak の管理コンソールに接続できれば作業終了です！おつかれさまでした。自己証明書だとこの画面にたどり着く前に証明書関連のエラーが出ると思います。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/320878/03d487a6-5ce6-e7a6-5e9b-edbfb322731a.png)


## 余談
本当に 8443 を https の listen ポートとして使用して良かったのだろうか、ということで Keycloak コンテナの起動ログを漁ってみました。


inspect  コマンドの LogPath 行を見て、ログファイルの保存場所を確認して……

```
# podman container inspect  docker-compose-examples_keycloak_1 | grep LogPath
        "LogPath": "/var/lib/containers/storage/overlay-containers/b9e422a609e4def892dc6d64688834585fb43a98ad63b3fa1ce9126cc3792033/userdata/ctr.log",
```

それっぽいワードで検索してみます。

```
# grep HTTP /var/lib/containers/storage/overlay-containers/b9e422a609e4def892dc6d64688834585fb43a98ad63b3fa1ce9126cc3792033/userdata/ctr.log
2020-07-01T01:46:56.731772928-04:00 stdout F 05:46:56,725 INFO  [org.wildfly.extension.undertow] (MSC service thread 1-4) WFLYUT0006: Undertow HTTP listener default listening on 0.0.0.0:8080
2020-07-01T01:46:57.459785836-04:00 stdout F 05:46:57,458 INFO  [org.wildfly.extension.undertow] (MSC service thread 1-2) WFLYUT0006: Undertow HTTPS listener https listening on 0.0.0.0:8443
```

Undertow という何かが 8443 を listen してますね。Undertow ってなんでしょう？

>Undertow is a flexible performant web server written in java, providing both blocking and non-blocking API’s based on NIO.
http://undertow.io/

なるほど、どうやら Java EE アプリケーションサーバである Wildfly や Jboss の拡張機能として動作する web サーバみたいです。コンテナ構築だと特に意識することはありませんでしたが、Keycloak は Wildfly 上で動作する Java アプリケーションです。ブラウザから指定の IP:Port へ接続したときに ```/auth``` に自動で飛ばされていたのは Undertow の働きだったわけですね。

## 参考
自己署名証明書の作成の際に参考にさせていただきました。ありがとうございます。

オレだよオレオレ認証局で証明書つくる
https://qiita.com/ll_kuma_ll/items/13c962a6a74874af39c6
Apache httpdで作るHTTPSサーバ
https://qiita.com/jinnai73/items/638dcc1434d47b12e6ba