PodmanではじめるRed Hatのミドルウェア製品:Keycloak(2)

Red Hatでソリューションアーキテクトをしている田中司恩(@tnk4on)です。 前回記事の続きになります。前回記事ではRed Hat build of Keycloak(RHBK)のサポート構成やPodmanを使ったテスト実行について紹介しました。 今回はPodmanで実行したコンテナレジストリのユーザー認証基盤としてRed Hat build of Keycloakを使う方法を紹介します。

(前回記事はこちら) rheb.hatenablog.com

-目次-


Distribution Registryとは

Distributionプロジェクトのロゴ
Distributionプロジェクトのロゴ

かつてPythonで書かれた「Docker Registry」*1というOSSプロジェクトがありました。 Docker Hubやその他のコンテナレジストリの基礎となるOSSプロジェクトでしたが、その後のコンテナエコシステムの標準化の流れでCNCFに寄贈されました。

詳細はDocker社のブログ記事を参照ください。

このプロジェクトはCNCFに寄贈された以降は「Distribution」に名称が変更されました。このDistributionプロジェクトの中のコンポーネントの1つが「Distribution Registry」で、現在はGoで書き直されています。このDistribution RegistryはOCI Distribution spec*2に基づいて実装が行われています。

DistributionプロジェクトのWebサイトとGitHubリポジトリ

ネットのさまざまなところではDocker Registryという名前を見ることが多いですが、その情報はすでに古く、Distribution Registryまたは単にRegistryと呼ぶのが正しいです。この際に覚えておきましょう。

Distribution Registryのコンテナイメージ

このDistribution Registryはコンテナイメージが公開されていますので、すぐにコンテナ環境で実行できます。 なお、Docker HubにあるRegistryのDocker公式イメージはDistribution Registryのコンテナイメージです。 これは「Docker HubにホストされているDistribution Registry」であり「Docker Registry」ではありませんのでお間違えないように。

registry - Official Image | Docker Hub

podman runコマンドで実行する場合はこんな感じです。これだけでローカル環境にシンプルなコンテナレジストリが立ち上がります。

% podman run -d -p 5000:5000 --name registry docker.io/library/registry:2

registry:2の2となっているのは現在のDistribution Registryのメジャーバージョンのv2をタグとして指定しています。なお現時点のDistribution Registryの最新版はv2.8.3ですが、2、2.8、2.8.3はすべて同じイメージを指すようにタグ付けされています。

保管するコンテナイメージを永続化したい場合はコンテナ内の/var/lib/registryにバインドマウントします。

% mkdir registry
% podman run -d -p 5000:5000 --name registry -v ./registry:/var/lib/registry:Z docker.io/library/registry

ローカル環境でテスト的に使いたい場合ははこれくらいを覚えておけば基本的には十分です。もう少し高度に使いたい場合は環境変数を追加して実行できます。

Distribution Registryのドキュメントにいくつか例があるので参考にしてください

次のセクションではRed Hat build of Keycloakを認証基盤として利用する方法を紹介します。 Distribution Registryは別の手段で実行しますので、テストで起動したコンテナは削除しておいてください。

% podman rm -f -t 0 registry 

Red Hat build of KeycloakをDistribution Registryの認証基盤として利用する

Distribution Registry自体にはユーザーを作成したり管理する機能はありません。その代わりにsilly、token、htpasswdの認証プロバイダをサポートしています。 今回はRed Hat build of Keycloakをtoken方式の認証基盤として利用します。

Red Hat build of KeycloakをDistribution Registryの認証基盤として利用する
Red Hat build of KeycloakをDistribution Registryの認証基盤として利用する

実行するコンテナと公開ポートの構成はこちらです。

実行するコンテナと公開ポートの構成
実行するコンテナと公開ポートの構成

Red Hat build of Keycloakの実行

ここから構築方法について解説します。製品ドキュメントは下記を元にしていますが、ドキュメントの内容だけでは情報が足りないので本記事の内容をしっかりと確認してください。

第4章 Red Hat build of Keycloak を使用するための Docker レジストリー設定 | Red Hat Product Documentation

作業の順番は下記の通りです

  1. 管理者ユーザーでログインする
  2. 新規のレルムを作成する
  3. 新規のクライアントを作成する
  4. Docker Compose YAMLをダウンロードする
  5. 新規ユーザーを作成する
  6. 不要な属性の必須設定をオフにする

まずは前回と同じくpodman runコマンドでRed Hat build of Keycloakを起動します。今回の構築用に若干オプションを変更しています。

Red Hat build of Keycloakのコンテナイメージの取得にはregistry.redhat.ioへのログインが必要です。 Red Hat build of Keycloakが含まれる製品の有効なサブスクリプションをお持ちのRed Hatアカウント、または評価版を使用中のRed Hatアカウント、等が必要です

% podman login registry.redhat.io
% podman run -d -p 8080:8080 -e KEYCLOAK_ADMIN=admin -e KEYCLOAK_ADMIN_PASSWORD=admin --name keycloak -e KC_FEATURES=docker keycloak-rhel9:24-10 start-dev
  • -d:デタッチモードでバックグラウンド実行する
  • --name keyclaok:コンテナにkeycloakという名前をつける
  • -e KC_FEATURES=docker:コンテナ実行時に環境変数「KC_FEATURES」を追加し、パラーメーターをdockerにセットする

今回使用するDocker認証はデフォルトでは無効化されています。そのため、Red Hat build of Keycloakの起動時に有効化するオプションを追加します。 この環境変数KC_FEATURESについては製品ドキュメントにチラッとだけ出てきます。製品ドキュメントではほとんど解説がないのでご注意ください。

3.8. 関連するオプション | Red Hat Product Documentation

podman runコマンドで実行した後にpodman logsコマンドでコンテナ名を指定してRed Hat build of Keycloakが起動したかどうか確認します。 正常に起動すると下記のようなログが出力されます。

% podman run -d -p 8080:8080 -e KEYCLOAK_ADMIN=admin -e KEYCLOAK_ADMIN_PASSWORD=admin --name keycloak -e KC_FEATURES=docker keycloak-rhel9:24-10 start-dev
% podman logs -f keycloak
...
2024-06-14 01:35:44,461 INFO  [io.quarkus] (main) Keycloak 24.0.5.redhat-00001 on JVM (powered by Quarkus 3.8.4.redhat-00002) started in 16.594s. Listening on: http://0.0.0.0:8080
2024-06-14 01:35:44,462 INFO  [io.quarkus] (main) Profile dev activated.
2024-06-14 01:35:44,462 INFO  [io.quarkus] (main) Installed features: [agroal, cdi, hibernate-orm, jdbc-h2, keycloak, narayana-jta, reactive-routes, resteasy-reactive, resteasy-reactive-jackson, smallrye-context-propagation, vertx]
2024-06-14 01:35:44,468 WARN  [org.keycloak.quarkus.runtime.KeycloakMain] (main) Running the server in development mode. DO NOT use this configuration in production.

コンテナレジストリ向けの認証設定

ここからはRed Hat build of Keycloakの管理画面での操作になります。

まず、Red Hat build of Keycloakのコンテナ起動時に指定した管理者ユーザーのユーザー名とパスワードでログインします。ブラウザでlocalhost:8080へアクセスします。

管理者ユーザーでログインする
管理者ユーザーでログインする

管理者ユーザーでログイン直後はmasterレルムが表示されます。レルムとはKeycloakにおけるマルチテナント機能のようなものです。masterはサーバー自体の管理ができるレルムになります。 アプリケーション用途には別のレルムを作ってそちらを使います。 ここではServer infoのタブを開きDocker機能が有効化されているか確認します。Enable featuresにDockerが見つかれば正常に有効化できています。

masterレルム
masterレルム

Server infoでDocker機能の有効化を確認する
Server infoでDocker機能の有効化を確認する

次に新規でレルムを作成します。Red Hat build of Keycloakと書いてあるプルダウンメニューを選択しCreate realmを押します。

新規でレルムの作成を実行する
新規でレルムの作成を実行する

レルムの作成画面ではレルム名を入力してCreateを押します。ここではレルム名は「registry」にします。

レルム名を入力して作成を実行する
レルム名を入力して作成を実行する

レルムの作成が成功するとプルダウンメニューの表示が作成したレルム名(registry)に変更されます。 左のClientsメニューを選択します。

Clientsの一覧画面
Clientsの一覧画面

新規でクライアントを作成します。Client typeはプルダウンから「docker-v2」を選択します。Client IDには任意の名前を入力します。ここでは「docker-auth」とします。「Next」を押します。

クライアントとはユーザーの認証を要求できるエンティティーのことでKeycloakに接続するアプリケーションの管理単位です。コンテナレジストリにログインする際のユーザー(後ほど作成)とは別の管理単位になりますので混同しないようにご注意ください

クライアントの作成。Client typeはdocker-v2を選択する。
クライアントの作成。Client typeはdocker-v2を選択する。

次のページのCapability configは空白なのでそのまま「Save」を押します。

Capability configは空白のままSaveを押す
Capability configは空白のままSaveを押す

さらに次のLogin settingsもそのまま「Save」を押します。

Login SettingsもそのままSaveを押す
Login SettingsもそのままSaveを押す

クライアント「docker-auth」が作成されました。

新規クライアント「docker-auth」の作成完了
新規クライアント「docker-auth」の作成完了

クライアント「docker-auth」のActionプルダウンから「Download adapter config」を選択します。

Download adapter configを選択する
Download adapter configを選択する

Download adaptor configsの画面でFormat optionが「Docker Compose YAML」になっていることを確認し「Download」を押します。

Docker Compose YAMLをダウンロードする
Docker Compose YAMLをダウンロードする

ダウンロードしたファイルは「keycloak-docker-compose-yaml.zip」として保存されます。これは後でDistribution Registryの実行時に使用します。

次はコンテナレジストリへログインするときに使用するユーザーを作成します。 左のメニューからUsersを選択し、「Create new user」を押します。

新規ユーザーの作成
新規ユーザーの作成

ユーザー名を入力し「Create」を押します。ここではユーザー名「tnk4on」を指定します。

ユーザー名を入力しユーザーの作成を完了する
ユーザー名を入力しユーザーの作成を完了する

ユーザーのパスワードを作成します。User datailsの画面からCredentialsタブを選択し、「Set password」選択します。

Credentialsの作成
Credentialsの作成

パスワードを入力し、Temporaryのチェックを外し「Save」を押します。

パスワードを入力しTemporaryのチェックを外す
パスワードを入力しTemporaryのチェックを外す

もう一度確認画面が出てくるので「Save password」押します。これでユーザーのパスワードがセットされました。

再度確認画面でSave passwordを押す
再度確認画面でSave passwordを押す

コンテナレジストリの認証に不要なemail,firstName,lastName要素の必須設定をオフにします。 左のメニューからRealm settingsを選択し、User Profileタブを選択します。ますはemailのリンクを選択します。

不要な属性の必須設定をオフにする
不要な属性の必須設定をオフにする

Required fieldをオフにし「Save」を押します。残りのfirstName,lastNameも同様に行います。この設定がemail,firstName,lastNameすべてでオフになっていないとpodman loginを実行したときにエラーになります。ご注意ください。

Required fieldをオフにして保存する
Required fieldをオフにして保存する

Distribution Registryの実行

先ほどの手順でダウンロードしたファイル「keycloak-docker-compose-yaml.zip」を展開すると下記のファイル一覧が出てきます。

% tree
.
├── README.md
├── certs
│   ├── localhost.crt
│   ├── localhost.key
│   └── localhost_trust_chain.pem
├── data
└── docker-compose.yaml

3 directories, 5 files

docker-compose.yamlを使ってDistribution Registryを起動するのですが、このままではComposeの実行時でエラーになります。

<ダウンロードしたdocker-compose.yaml>

registry:
  image: registry:2
  ports:
    - 127.0.0.1:5000:5000
  environment:
    REGISTRY_STORAGE_FILESYSTEM_ROOTDIRECTORY: /data
    REGISTRY_HTTP_TLS_CERTIFICATE: /opt/certs/localhost.crt
    REGISTRY_HTTP_TLS_KEY: /opt/certs/localhost.key
    REGISTRY_AUTH_TOKEN_REALM: http://localhost:8080/realms/registry/protocol/docker-v2/auth
    REGISTRY_AUTH_TOKEN_SERVICE: docker-auth
    REGISTRY_AUTH_TOKEN_ISSUER: http://localhost:8080/realms/registry
    REGISTRY_AUTH_TOKEN_ROOTCERTBUNDLE: /opt/certs/localhost_trust_chain.pem
  volumes:
    - ./data:/data:z
    - ./certs:/opt/certs:z

正常に起動する修正を加えたのが下記です。

<修正を加えたdocker-compose.yaml>>

version: '3'
services:
  registry:
    image: registry:2
    ports:
      - 127.0.0.1:5000:5000
    environment:
      REGISTRY_STORAGE_FILESYSTEM_ROOTDIRECTORY: /data
      REGISTRY_HTTP_TLS_CERTIFICATE: /opt/certs/localhost.crt
      REGISTRY_HTTP_TLS_KEY: /opt/certs/localhost.key
      REGISTRY_AUTH_TOKEN_REALM: http://localhost:8080/realms/registry/protocol/docker-v2/auth
      REGISTRY_AUTH_TOKEN_SERVICE: docker-auth
      REGISTRY_AUTH_TOKEN_ISSUER: http://localhost:8080/realms/registry
      REGISTRY_AUTH_TOKEN_ROOTCERTBUNDLE: /opt/certs/localhost_trust_chain.pem
    volumes:
      - ./data:/data:z
      - ./certs:/opt/certs:z

ではこのdocker-compose.yamlファイルを使ってDistribution Registryのコンテナを実行します。

Podman v4.7.0以降はpodman composeコマンドが実装されています。podman composeコマンドは、ローカルホストにインストールされたdocker-composeコマンドを参照実行するラッパーコマンドです。 本家のdocker-composeコマンドをインストールし、docker.sockからpodman.sockへシンボリックリンクを作成するだけでPodmanでdocker-composeがそのまま使えます。 詳細は拙作の著書「Podman Advanced Pod-01:DockerからPodmanへの移行」を参照ください。

podman composeコマンドを-dオプションをつけて実行します。

% cd keycloak-docker-compose-yaml
% podman compose up -d
>>>> Executing external compose provider "/usr/local/bin/docker-compose". Please refer to the documentation for details. <<<<

[+] Running 1/1
 ✔ Container keycloak-docker-compose-yaml-registry-1  Started                   

podman psコマンドを実行し、keycloak-docker-compose-yaml-registry-1というコンテナが正常に起動していれば成功です。

% podman ps -a
CONTAINER ID  IMAGE                                         COMMAND               CREATED         STATUS         PORTS                                       NAMES
e3ed196f344b  registry.redhat.io/rhbk/keycloak-rhel9:24-10  start-dev             15 minutes ago  Up 15 minutes  0.0.0.0:8080->8080/tcp, 8080/tcp, 8443/tcp  keycloak
54f837e4c325  docker.io/library/registry:2                  /etc/docker/regis...  12 seconds ago  Up 13 seconds  127.0.0.1:5000->5000/tcp, 5000/tcp          keycloak-docker-compose-yaml-registry-1

PodmanからDistribution Registryを利用する

コンテナレジストリを利用する環境が整ったのでPodmanを使って各種操作を行います。

ログイン/ログアウト

コンテナレジストリにログインするにはpodman loginコマンドを使います。注意点としては、実稼働環境のコンテナレジストリではhttps://でアクセスを行いますが今回はテスト環境なのでhttp://でアクセスを行います。 http://でアクセスする場合はpodman loginコマンドに--tls-verify=falseオプションを追加して実行します。

% podman login localhost:5000 --tls-verify=false

ユーザー名とパスワードを入力し、Login Succeeded!が出ればログイン成功です。

% podman login localhost:5000 --tls-verify=false
Username: tnk4on
Password:
Login Succeeded!

ログイン済みのコンテナレジストリからログアウトをする場合はpodman logoutコマンドを使います。ログアウトの場合--tls-verify=falseオプションは不要です。 Removed login credentials forが表示されればログアウト成功です。ローカルに保存されていた認証情報は削除されます。

% podman logout localhost:5000
Removed login credentials for localhost:5000

コンテナイメージのPushとPull

コンテナレジストリにログインし、そのユーザー専用のリポジトリとしてコンテナをPushしてみます。

サンプルでビルドしたコンテナをコンテナレジストリにPushします。podman pushコマンドの実行の場合も--tls-verify=falseをつけて実行します。

% cat > Containerfile <<EOF
FROM ubi9
RUN echo "hello" | tee hello.txt
EOF
% podman build -t registry-test .
% podman login localhost:5000 --tls-verify=false
Username: tnk4on
Password:
Login Succeeded!
% podman push registry-test localhost:5000/tnk4on/registry-test --tls-verify=false
Getting image source signatures
Copying blob sha256:32c72c1609374470f063a4a8d190512eedd824b0aa644575c3a75d0e466a6426
Copying blob sha256:0abe35b0d2bf06d260396dfc129715dae9736b6c91f3d861492982a0f7daa5c2
Copying config sha256:d7d811c318f6237a9dbc97dc15fc31cc92605b0c2166a4b66b4bdfbde727ea1f
Writing manifest to image destination

コンテナがコンテナレジストリに登録されたかを確認します。Skopeoを使ってコンテナレジストリ上のコンテナイメージの詳細を確認します。

skopeo inspectコマンドを実行します。コンテナレジストリ上のコンテナを直接調べる場合はdocker://(Dockerトランスポート)を指定します。またこの場合も--tls-verify=falseオプションを追加します。

Linux以外の環境でskopeo inspectを実行して対象のOSが見つからないエラーになる場合は--override-os=linuxを追加してください。 今回のローカル環境のテストの場合はmacOS版Skopeoを使ってもエラーにならなかったのでオプションは追加していません

% skopeo inspect docker://localhost:5000/tnk4on/registry-test --tls-verify=false
{
    "Name": "localhost:5000/tnk4on/registry-test",
    "Digest": "sha256:cd56949fd637e728a6145d7fb45717baac5dabd52cf440b95b4afcd3b140540b",
    "RepoTags": [
        "latest"
    ],
    "Created": "2024-06-14T02:05:17.827927425Z",
...

コンテナイメージが登録されているのが確認できました。今度はこのイメージをPullします。 ローカルのコンテナストレージ上のコンテナイメージを削除し、コンテナレジストリからPullします。Pullの際も--tls-verify=falseオプションを追加します。

% podman images
REPOSITORY                              TAG         IMAGE ID      CREATED         SIZE
localhost/registry-test                 latest      d7d811c318f6  13 minutes ago  238 MB
registry.access.redhat.com/ubi9         latest      a13af6f8eaac  8 days ago      238 MB
registry.redhat.io/rhbk/keycloak-rhel9  24-10       559c3ef84129  2 weeks ago     461 MB
docker.io/library/registry              2           27031dfcd859  8 months ago    25.5 MB
% podman rmi registry-test:latest
Untagged: localhost/registry-test:latest
Deleted: d7d811c318f6237a9dbc97dc15fc31cc92605b0c2166a4b66b4bdfbde727ea1f
% podman pull localhost:5000/tnk4on/registry-test --tls-verify=false
Trying to pull localhost:5000/tnk4on/registry-test:latest...
Getting image source signatures
Copying blob sha256:e4c264f9fa3197924054e658c77b17936ecf85f6dec74962138da485d7d7b86b
Copying blob sha256:e44751f30cbb5bdc2d04fc32e3df7b09765f21c1db7682159c33cc3398c0e583
Copying config sha256:d7d811c318f6237a9dbc97dc15fc31cc92605b0c2166a4b66b4bdfbde727ea1f
Writing manifest to image destination
6a9eef918b31d10db8fdb774f23a6ef27f91c29cecacd79c227196000cfa481f
% podman images
REPOSITORY                              TAG         IMAGE ID      CREATED         SIZE
localhost:5000/tnk4on/registry-test     latest      6a9eef918b31  14 minutes ago  238 MB
registry.access.redhat.com/ubi9         latest      a13af6f8eaac  8 days ago      238 MB
registry.redhat.io/rhbk/keycloak-rhel9  24-10       559c3ef84129  2 weeks ago     461 MB
docker.io/library/registry              2           27031dfcd859  8 months ago    25.5 MB

podman logoutでローカルの認証情報を削除し、再度コンテナレジストリ上のコンテナイメージをPullしてみます。 今度はコンテナレジストリの認証でエラーになりPullできません。パブリックなコンテナレジストリと同様に、認証の仕組みが機能していることが確認できます。

% podman rmi registry-test:latest
Untagged: localhost:5000/tnk4on/registry-test:latest
Deleted: 6a9eef918b31d10db8fdb774f23a6ef27f91c29cecacd79c227196000cfa481f
% podman logout localhost:5000
Removed login credentials for localhost:5000
% podman pull localhost:5000/tnk4on/registry-test --tls-verify=false
Trying to pull localhost:5000/tnk4on/registry-test:latest...
Error: initializing source docker://localhost:5000/tnk4on/registry-test:latest: Requesting bearer token: invalid status code from registry 400 (Bad Request)

まとめ

Red Hat build of Keycloakを認証基盤として利用するケースの1つとして、コンテナレジストリの認証環境を構築してみました。 Red Hat build of KeycloakはGUIの管理コンソールがあるため簡単に認証の設定を行うことができます。また、ユーザーの追加なども管理コンソール上で行うことができます。

Distribution Registryはローカル環境で簡単に実行できるコンテナレジストリのソリューションですが、ユーザー認証基盤を持たないためRed Hat build of Keycloakと組み合わせることで簡単に認証の仕組みを追加できます。 Red Hat build of Keycloakの基本機能を確認する目的でもローカルのコンテナ環境でサクッとお試しできますので、まずはPodmanを使って手を動かして体験してみることをオススメします。

* 各記事は著者の見解によるものでありその所属組織を代表する公式なものではありません。その内容については非公式見解を含みます。